diff options
| author | Michael Albinus | 2020-09-26 11:38:23 +0200 |
|---|---|---|
| committer | Michael Albinus | 2020-09-26 11:38:23 +0200 |
| commit | c540f3323da96eadf41ccfa4e23ec2a5124343b8 (patch) | |
| tree | 6f513dd3abad6c8e8a61bd2cc939bd5cd9a9461f | |
| parent | c98c7def046c5f6b1ac50fda46e32545b5e2ba37 (diff) | |
| download | emacs-c540f3323da96eadf41ccfa4e23ec2a5124343b8.tar.gz emacs-c540f3323da96eadf41ccfa4e23ec2a5124343b8.zip | |
Add D-Bus monitor
* lisp/net/dbus.el (dbus-interface-monitoring): New defconst.
(dbus-call-method, dbus-call-method-asynchronously)
(dbus-send-signal, dbus-method-return-internal)
(dbus-method-error-internal, dbus-check-arguments): Accept also
:system-private and :session-private.
(dbus-check-event, dbus-event-path-name)
(dbus-event-interface-name)
(dbus-event-member-name, dbus-property-handler)
(dbus-handle-bus-disconnect): Adapt according to new structure.
(dbus-handle-event): Handle also monitor events.
(dbus-event-destination-name, dbus-event-handler)
(dbus-event-arguments, dbus-register-monitor, dbus-monitor-handler):
New defuns.
* src/dbusbind.c (XD_DBUS_VALIDATE_BUS_ADDRESS, xd_remove_watch)
(Fdbus__init_bus): Accept also :system-private and :session-private.
(xd_read_message_1): Add destination and error_name to
dbus-event. Handle monitor events.
(syms_of_dbusbind): Declare QCsystem_private, QCsession_private
and QCmonitor.
(dbus-registered-objects-table): Fix docstring.
| -rw-r--r-- | lisp/net/dbus.el | 295 | ||||
| -rw-r--r-- | src/dbusbind.c | 139 |
2 files changed, 341 insertions, 93 deletions
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index 86db7cbf18a..da47e5bc7f2 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el | |||
| @@ -144,6 +144,17 @@ See URL `https://dbus.freedesktop.org/doc/dbus-specification.html#standard-inter | |||
| 144 | ;; </signal> | 144 | ;; </signal> |
| 145 | ;; </interface> | 145 | ;; </interface> |
| 146 | 146 | ||
| 147 | (defconst dbus-interface-monitoring (concat dbus-interface-dbus ".Monitoring") | ||
| 148 | "The monitoring interface. | ||
| 149 | See URL `https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-become-monitor'.") | ||
| 150 | |||
| 151 | ;; <interface name="org.freedesktop.DBus.Monitoring"> | ||
| 152 | ;; <method name="BecomeMonitor"> | ||
| 153 | ;; <arg name="rule" type="as" direction="in"/> | ||
| 154 | ;; <arg name="flags" type="u" direction="in"/> ;; Not used, must be 0. | ||
| 155 | ;; </method> | ||
| 156 | ;; </interface> | ||
| 157 | |||
| 147 | (defconst dbus-interface-local (concat dbus-interface-dbus ".Local") | 158 | (defconst dbus-interface-local (concat dbus-interface-dbus ".Local") |
| 148 | "An interface whose methods can only be invoked by the local implementation.") | 159 | "An interface whose methods can only be invoked by the local implementation.") |
| 149 | 160 | ||
| @@ -336,7 +347,8 @@ object is returned instead of a list containing this single Lisp object. | |||
| 336 | 347 | ||
| 337 | (or (featurep 'dbusbind) | 348 | (or (featurep 'dbusbind) |
| 338 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) | 349 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) |
| 339 | (or (memq bus '(:system :session)) (stringp bus) | 350 | (or (memq bus '(:system :session :system-private :session-private)) |
| 351 | (stringp bus) | ||
| 340 | (signal 'wrong-type-argument (list 'keywordp bus))) | 352 | (signal 'wrong-type-argument (list 'keywordp bus))) |
| 341 | (or (stringp service) | 353 | (or (stringp service) |
| 342 | (signal 'wrong-type-argument (list 'stringp service))) | 354 | (signal 'wrong-type-argument (list 'stringp service))) |
| @@ -440,7 +452,8 @@ Example: | |||
| 440 | 452 | ||
| 441 | (or (featurep 'dbusbind) | 453 | (or (featurep 'dbusbind) |
| 442 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) | 454 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) |
| 443 | (or (memq bus '(:system :session)) (stringp bus) | 455 | (or (memq bus '(:system :session :system-private :session-private)) |
| 456 | (stringp bus) | ||
| 444 | (signal 'wrong-type-argument (list 'keywordp bus))) | 457 | (signal 'wrong-type-argument (list 'keywordp bus))) |
| 445 | (or (stringp service) | 458 | (or (stringp service) |
| 446 | (signal 'wrong-type-argument (list 'stringp service))) | 459 | (signal 'wrong-type-argument (list 'stringp service))) |
| @@ -490,7 +503,8 @@ Example: | |||
| 490 | 503 | ||
| 491 | (or (featurep 'dbusbind) | 504 | (or (featurep 'dbusbind) |
| 492 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) | 505 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) |
| 493 | (or (memq bus '(:system :session)) (stringp bus) | 506 | (or (memq bus '(:system :session :system-private :session-private)) |
| 507 | (stringp bus) | ||
| 494 | (signal 'wrong-type-argument (list 'keywordp bus))) | 508 | (signal 'wrong-type-argument (list 'keywordp bus))) |
| 495 | (or (null service) (stringp service) | 509 | (or (null service) (stringp service) |
| 496 | (signal 'wrong-type-argument (list 'stringp service))) | 510 | (signal 'wrong-type-argument (list 'stringp service))) |
| @@ -510,7 +524,8 @@ This is an internal function, it shall not be used outside dbus.el." | |||
| 510 | 524 | ||
| 511 | (or (featurep 'dbusbind) | 525 | (or (featurep 'dbusbind) |
| 512 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) | 526 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) |
| 513 | (or (memq bus '(:system :session)) (stringp bus) | 527 | (or (memq bus '(:system :session :system-private :session-private)) |
| 528 | (stringp bus) | ||
| 514 | (signal 'wrong-type-argument (list 'keywordp bus))) | 529 | (signal 'wrong-type-argument (list 'keywordp bus))) |
| 515 | (or (stringp service) | 530 | (or (stringp service) |
| 516 | (signal 'wrong-type-argument (list 'stringp service))) | 531 | (signal 'wrong-type-argument (list 'stringp service))) |
| @@ -527,7 +542,8 @@ This is an internal function, it shall not be used outside dbus.el." | |||
| 527 | 542 | ||
| 528 | (or (featurep 'dbusbind) | 543 | (or (featurep 'dbusbind) |
| 529 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) | 544 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) |
| 530 | (or (memq bus '(:system :session)) (stringp bus) | 545 | (or (memq bus '(:system :session :system-private :session-private)) |
| 546 | (stringp bus) | ||
| 531 | (signal 'wrong-type-argument (list 'keywordp bus))) | 547 | (signal 'wrong-type-argument (list 'keywordp bus))) |
| 532 | (or (stringp service) | 548 | (or (stringp service) |
| 533 | (signal 'wrong-type-argument (list 'stringp service))) | 549 | (signal 'wrong-type-argument (list 'stringp service))) |
| @@ -545,7 +561,8 @@ This is an internal function, it shall not be used outside dbus.el." | |||
| 545 | 561 | ||
| 546 | (or (featurep 'dbusbind) | 562 | (or (featurep 'dbusbind) |
| 547 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) | 563 | (signal 'dbus-error (list "Emacs not compiled with dbus support"))) |
| 548 | (or (memq bus '(:system :session)) (stringp bus) | 564 | (or (memq bus '(:system :session :system-private :session-private)) |
| 565 | (stringp bus) | ||
| 549 | (signal 'wrong-type-argument (list 'keywordp bus))) | 566 | (signal 'wrong-type-argument (list 'keywordp bus))) |
| 550 | (or (stringp service) | 567 | (or (stringp service) |
| 551 | (signal 'wrong-type-argument (list 'stringp service))) | 568 | (signal 'wrong-type-argument (list 'stringp service))) |
| @@ -1018,19 +1035,29 @@ STRING must have been encoded with `dbus-escape-as-identifier'." | |||
| 1018 | "Check whether EVENT is a well formed D-Bus event. | 1035 | "Check whether EVENT is a well formed D-Bus event. |
| 1019 | EVENT is a list which starts with symbol `dbus-event': | 1036 | EVENT is a list which starts with symbol `dbus-event': |
| 1020 | 1037 | ||
| 1021 | (dbus-event BUS TYPE SERIAL SERVICE PATH INTERFACE MEMBER HANDLER &rest ARGS) | 1038 | (dbus-event BUS TYPE SERIAL SERVICE DESTINATION PATH |
| 1039 | INTERFACE MEMBER HANDLER &rest ARGS) | ||
| 1022 | 1040 | ||
| 1023 | BUS identifies the D-Bus the message is coming from. It is | 1041 | BUS identifies the D-Bus the message is coming from. It is |
| 1024 | either a Lisp symbol, `:system' or `:session', or a string | 1042 | either a Lisp symbol, `:system', `:session', `:systemp-private' |
| 1025 | denoting the bus address. TYPE is the D-Bus message type which | 1043 | or `:session-private', or a string denoting the bus address. |
| 1026 | has caused the event, SERIAL is the serial number of the received | 1044 | |
| 1027 | D-Bus message. SERVICE and PATH are the unique name and the | 1045 | TYPE is the D-Bus message type which has caused the event, SERIAL |
| 1028 | object path of the D-Bus object emitting the message. INTERFACE | 1046 | is the serial number of the received D-Bus message when TYPE is |
| 1029 | and MEMBER denote the message which has been sent. HANDLER is | 1047 | equal `dbus-message-type-method-return' or `dbus-message-type-error'. |
| 1030 | the function which has been registered for this message. ARGS | 1048 | |
| 1031 | are the typed arguments as returned from the message. They are | 1049 | SERVICE and PATH are the unique name and the object path of the |
| 1032 | passed to HANDLER without type information, when it is called | 1050 | D-Bus object emitting the message. DESTINATION is the D-Bus name |
| 1033 | during event handling in `dbus-handle-event'. | 1051 | the message is dedicated to, or nil in case thje message is a |
| 1052 | broadcast signal. | ||
| 1053 | |||
| 1054 | INTERFACE and MEMBER denote the message which has been sent. | ||
| 1055 | When TYPE is `dbus-message-type-error', MEMBER is the error name. | ||
| 1056 | |||
| 1057 | HANDLER is the function which has been registered for this | ||
| 1058 | message. ARGS are the typed arguments as returned from the | ||
| 1059 | message. They are passed to HANDLER without type information, | ||
| 1060 | when it is called during event handling in `dbus-handle-event'. | ||
| 1034 | 1061 | ||
| 1035 | This function signals a `dbus-error' if the event is not well | 1062 | This function signals a `dbus-error' if the event is not well |
| 1036 | formed." | 1063 | formed." |
| @@ -1038,7 +1065,7 @@ formed." | |||
| 1038 | (unless (and (listp event) | 1065 | (unless (and (listp event) |
| 1039 | (eq (car event) 'dbus-event) | 1066 | (eq (car event) 'dbus-event) |
| 1040 | ;; Bus symbol. | 1067 | ;; Bus symbol. |
| 1041 | (or (symbolp (nth 1 event)) | 1068 | (or (keywordp (nth 1 event)) |
| 1042 | (stringp (nth 1 event))) | 1069 | (stringp (nth 1 event))) |
| 1043 | ;; Type. | 1070 | ;; Type. |
| 1044 | (and (natnump (nth 2 event)) | 1071 | (and (natnump (nth 2 event)) |
| @@ -1050,20 +1077,26 @@ formed." | |||
| 1050 | (= dbus-message-type-error (nth 2 event)) | 1077 | (= dbus-message-type-error (nth 2 event)) |
| 1051 | (or (stringp (nth 4 event)) | 1078 | (or (stringp (nth 4 event)) |
| 1052 | (null (nth 4 event)))) | 1079 | (null (nth 4 event)))) |
| 1053 | ;; Object path. | 1080 | ;; Destination. |
| 1054 | (or (= dbus-message-type-method-return (nth 2 event)) | 1081 | (or (= dbus-message-type-method-return (nth 2 event)) |
| 1055 | (= dbus-message-type-error (nth 2 event)) | 1082 | (= dbus-message-type-error (nth 2 event)) |
| 1056 | (stringp (nth 5 event))) | 1083 | (or (stringp (nth 5 event)) |
| 1057 | ;; Interface. | 1084 | (null (nth 5 event)))) |
| 1085 | ;; Object path. | ||
| 1058 | (or (= dbus-message-type-method-return (nth 2 event)) | 1086 | (or (= dbus-message-type-method-return (nth 2 event)) |
| 1059 | (= dbus-message-type-error (nth 2 event)) | 1087 | (= dbus-message-type-error (nth 2 event)) |
| 1060 | (stringp (nth 6 event))) | 1088 | (stringp (nth 6 event))) |
| 1061 | ;; Member. | 1089 | ;; Interface. |
| 1062 | (or (= dbus-message-type-method-return (nth 2 event)) | 1090 | (or (= dbus-message-type-method-return (nth 2 event)) |
| 1063 | (= dbus-message-type-error (nth 2 event)) | 1091 | (= dbus-message-type-error (nth 2 event)) |
| 1064 | (stringp (nth 7 event))) | 1092 | (stringp (nth 7 event))) |
| 1093 | ;; Member. | ||
| 1094 | (or (= dbus-message-type-method-return (nth 2 event)) | ||
| 1095 | (stringp (nth 8 event))) | ||
| 1065 | ;; Handler. | 1096 | ;; Handler. |
| 1066 | (functionp (nth 8 event))) | 1097 | (functionp (nth 9 event)) |
| 1098 | ;; Arguments. | ||
| 1099 | (listp (nthcdr 10 event))) | ||
| 1067 | (signal 'dbus-error (list "Not a valid D-Bus event" event)))) | 1100 | (signal 'dbus-error (list "Not a valid D-Bus event" event)))) |
| 1068 | 1101 | ||
| 1069 | (defun dbus-delete-types (&rest args) | 1102 | (defun dbus-delete-types (&rest args) |
| @@ -1103,28 +1136,36 @@ part of the event, is called with arguments ARGS (without type information). | |||
| 1103 | If the HANDLER returns a `dbus-error', it is propagated as return message." | 1136 | If the HANDLER returns a `dbus-error', it is propagated as return message." |
| 1104 | (interactive "e") | 1137 | (interactive "e") |
| 1105 | (condition-case err | 1138 | (condition-case err |
| 1106 | (let (args result) | 1139 | (let (monitor args result) |
| 1107 | ;; We ignore not well-formed events. | 1140 | ;; We ignore not well-formed events. |
| 1108 | (dbus-check-event event) | 1141 | (dbus-check-event event) |
| 1109 | ;; Remove type information. | 1142 | ;; Remove type information. |
| 1110 | (setq args (mapcar #'dbus-delete-types (nthcdr 9 event))) | 1143 | (setq args (mapcar #'dbus-delete-types (nthcdr 10 event))) |
| 1111 | ;; Error messages must be propagated. | 1144 | (setq monitor |
| 1112 | (when (= dbus-message-type-error (nth 2 event)) | 1145 | (gethash |
| 1113 | (signal 'dbus-error args)) | 1146 | (list :monitor (nth 1 event)) dbus-registered-objects-table)) |
| 1114 | ;; Apply the handler. | 1147 | (if monitor |
| 1115 | (setq result (apply (nth 8 event) args)) | 1148 | ;; A monitor event shall not trigger other operations, and |
| 1116 | ;; Return an (error) message when it is a message call. | 1149 | ;; it shall not trigger D-Bus errors. |
| 1117 | (when (= dbus-message-type-method-call (nth 2 event)) | 1150 | (setq result (dbus-ignore-errors (apply (nth 9 event) args))) |
| 1118 | (dbus-ignore-errors | 1151 | ;; Error messages must be propagated. The error name is in |
| 1119 | (if (eq (car-safe result) :error) | 1152 | ;; the member slot. |
| 1120 | (apply #'dbus-method-error-internal | 1153 | (when (= dbus-message-type-error (nth 2 event)) |
| 1121 | (nth 1 event) (nth 4 event) (nth 3 event) (cdr result)) | 1154 | (signal 'dbus-error (cons (nth 8 event) args))) |
| 1122 | (if (eq result :ignore) | 1155 | ;; Apply the handler. |
| 1123 | (dbus-method-return-internal | 1156 | (setq result (apply (nth 9 event) args)) |
| 1124 | (nth 1 event) (nth 4 event) (nth 3 event)) | 1157 | ;; Return an (error) message when it is a message call. |
| 1125 | (apply #'dbus-method-return-internal | 1158 | (when (= dbus-message-type-method-call (nth 2 event)) |
| 1126 | (nth 1 event) (nth 4 event) (nth 3 event) | 1159 | (dbus-ignore-errors |
| 1127 | (if (consp result) result (list result)))))))) | 1160 | (if (eq (car-safe result) :error) |
| 1161 | (apply #'dbus-method-error-internal | ||
| 1162 | (nth 1 event) (nth 4 event) (nth 3 event) (cdr result)) | ||
| 1163 | (if (eq result :ignore) | ||
| 1164 | (dbus-method-return-internal | ||
| 1165 | (nth 1 event) (nth 4 event) (nth 3 event)) | ||
| 1166 | (apply #'dbus-method-return-internal | ||
| 1167 | (nth 1 event) (nth 4 event) (nth 3 event) | ||
| 1168 | (if (consp result) result (list result))))))))) | ||
| 1128 | ;; Error handling. | 1169 | ;; Error handling. |
| 1129 | (dbus-error | 1170 | (dbus-error |
| 1130 | ;; Return an error message when it is a message call. | 1171 | ;; Return an error message when it is a message call. |
| @@ -1172,13 +1213,21 @@ formed." | |||
| 1172 | (dbus-check-event event) | 1213 | (dbus-check-event event) |
| 1173 | (nth 4 event)) | 1214 | (nth 4 event)) |
| 1174 | 1215 | ||
| 1216 | (defun dbus-event-destination-name (event) | ||
| 1217 | "Return the name of the D-Bus object the event is dedicated to. | ||
| 1218 | The result is a string. EVENT is a D-Bus event, see `dbus-check-event'. | ||
| 1219 | This function signals a `dbus-error' if the event is not well | ||
| 1220 | formed." | ||
| 1221 | (dbus-check-event event) | ||
| 1222 | (nth 5 event)) | ||
| 1223 | |||
| 1175 | (defun dbus-event-path-name (event) | 1224 | (defun dbus-event-path-name (event) |
| 1176 | "Return the object path of the D-Bus object the event is coming from. | 1225 | "Return the object path of the D-Bus object the event is coming from. |
| 1177 | The result is a string. EVENT is a D-Bus event, see `dbus-check-event'. | 1226 | The result is a string. EVENT is a D-Bus event, see `dbus-check-event'. |
| 1178 | This function signals a `dbus-error' if the event is not well | 1227 | This function signals a `dbus-error' if the event is not well |
| 1179 | formed." | 1228 | formed." |
| 1180 | (dbus-check-event event) | 1229 | (dbus-check-event event) |
| 1181 | (nth 5 event)) | 1230 | (nth 6 event)) |
| 1182 | 1231 | ||
| 1183 | (defun dbus-event-interface-name (event) | 1232 | (defun dbus-event-interface-name (event) |
| 1184 | "Return the interface name of the D-Bus object the event is coming from. | 1233 | "Return the interface name of the D-Bus object the event is coming from. |
| @@ -1186,15 +1235,32 @@ The result is a string. EVENT is a D-Bus event, see `dbus-check-event'. | |||
| 1186 | This function signals a `dbus-error' if the event is not well | 1235 | This function signals a `dbus-error' if the event is not well |
| 1187 | formed." | 1236 | formed." |
| 1188 | (dbus-check-event event) | 1237 | (dbus-check-event event) |
| 1189 | (nth 6 event)) | 1238 | (nth 7 event)) |
| 1190 | 1239 | ||
| 1191 | (defun dbus-event-member-name (event) | 1240 | (defun dbus-event-member-name (event) |
| 1192 | "Return the member name the event is coming from. | 1241 | "Return the member name the event is coming from. |
| 1193 | It is either a signal name or a method name. The result is a | 1242 | It is either a signal name, a method name or an error name. The |
| 1194 | string. EVENT is a D-Bus event, see `dbus-check-event'. This | 1243 | result is a string. EVENT is a D-Bus event, see |
| 1195 | function signals a `dbus-error' if the event is not well formed." | 1244 | `dbus-check-event'. This function signals a `dbus-error' if the |
| 1245 | event is not well formed." | ||
| 1196 | (dbus-check-event event) | 1246 | (dbus-check-event event) |
| 1197 | (nth 7 event)) | 1247 | (nth 8 event)) |
| 1248 | |||
| 1249 | (defun dbus-event-handler (event) | ||
| 1250 | "Return the handler the event is applied with. | ||
| 1251 | The result is a function. EVENT is a D-Bus event, see | ||
| 1252 | `dbus-check-event'. This function signals a `dbus-error' if the | ||
| 1253 | event is not well formed." | ||
| 1254 | (dbus-check-event event) | ||
| 1255 | (nth 9 event)) | ||
| 1256 | |||
| 1257 | (defun dbus-event-arguments (event) | ||
| 1258 | "Return the arguments the event is carrying on. | ||
| 1259 | The result is a list of arguments. EVENT is a D-Bus event, see | ||
| 1260 | `dbus-check-event'. This function signals a `dbus-error' if the | ||
| 1261 | event is not well formed." | ||
| 1262 | (dbus-check-event event) | ||
| 1263 | (nthcdr 10 event)) | ||
| 1198 | 1264 | ||
| 1199 | 1265 | ||
| 1200 | ;;; D-Bus registered names. | 1266 | ;;; D-Bus registered names. |
| @@ -1717,7 +1783,7 @@ It will be registered for all objects created by `dbus-register-property'." | |||
| 1717 | 1783 | ||
| 1718 | ;; "Set" needs the third typed argument from `last-input-event'. | 1784 | ;; "Set" needs the third typed argument from `last-input-event'. |
| 1719 | ((string-equal method "Set") | 1785 | ((string-equal method "Set") |
| 1720 | (let* ((value (dbus-flatten-types (nth 11 last-input-event))) | 1786 | (let* ((value (dbus-flatten-types (nth 12 last-input-event))) |
| 1721 | (entry (dbus-get-this-registered-property | 1787 | (entry (dbus-get-this-registered-property |
| 1722 | bus service path interface property)) | 1788 | bus service path interface property)) |
| 1723 | (object (car (last (car entry))))) | 1789 | (object (car (last (car entry))))) |
| @@ -1907,13 +1973,123 @@ It will be registered for all objects created by `dbus-register-service'." | |||
| 1907 | result) | 1973 | result) |
| 1908 | '(:signature "{oa{sa{sv}}}")))))) | 1974 | '(:signature "{oa{sa{sv}}}")))))) |
| 1909 | 1975 | ||
| 1976 | (defun dbus-register-monitor | ||
| 1977 | (bus &optional service path interface member handler &rest args) | ||
| 1978 | "Register HANDLER for monitor events on the D-Bus BUS. | ||
| 1979 | |||
| 1980 | BUS is either a Lisp symbol, `:system' or `:session', or a string | ||
| 1981 | denoting the bus address. | ||
| 1982 | |||
| 1983 | SERVICE is the D-Bus service name of the D-Bus. It must be a | ||
| 1984 | known name (see discussion of DONT-REGISTER-SERVICE below). | ||
| 1985 | |||
| 1986 | PATH is the D-Bus object path SERVICE is registered at (see | ||
| 1987 | discussion of DONT-REGISTER-SERVICE below). INTERFACE is the | ||
| 1988 | name of the interface used at PATH. MEMBER is either a method | ||
| 1989 | name, a signal name, or an error name. | ||
| 1990 | |||
| 1991 | HANDLER is the function to be called when a monitor event | ||
| 1992 | arrives. If nil, the default handler `dbus-monitor-handler' is | ||
| 1993 | applied. It is called with ARGS as arguments." | ||
| 1994 | |||
| 1995 | (let ((bus-private (if (eq bus :system) :system-private | ||
| 1996 | (if (eq bus :session) :session-private bus))) | ||
| 1997 | keyword type rule1 rule2 key key1 value) | ||
| 1998 | (unless handler (setq handler #'dbus-monitor-handler)) | ||
| 1999 | ;; Read arguments. | ||
| 2000 | (while args | ||
| 2001 | (when (keywordp (setq keyword (pop args))) | ||
| 2002 | (cond | ||
| 2003 | ((eq :type keyword) | ||
| 2004 | ;; Must be "signal", "method_call", "method_return", or "error". | ||
| 2005 | (setq type (pop args)))))) | ||
| 2006 | ;; Compose rules. | ||
| 2007 | (setq rule1 | ||
| 2008 | (or | ||
| 2009 | (string-join | ||
| 2010 | (delq nil | ||
| 2011 | (list (when service (format "sender='%s'" service)) | ||
| 2012 | (when path (format "path='%s'" path)) | ||
| 2013 | (when interface (format "interface='%s'" interface)) | ||
| 2014 | (when member (format "member='%s'" member)) | ||
| 2015 | (when type (format "type='%s'" type)))) | ||
| 2016 | ",") | ||
| 2017 | "") | ||
| 2018 | rule2 | ||
| 2019 | (when service | ||
| 2020 | (string-join | ||
| 2021 | (delq nil | ||
| 2022 | (list (format "destination='%s'" service) | ||
| 2023 | (when path (format "path='%s'" path)) | ||
| 2024 | (when interface (format "interface='%s'" interface)) | ||
| 2025 | (when member (format "member='%s'" member)) | ||
| 2026 | (when type (format "type='%s'" type)))) | ||
| 2027 | ","))) | ||
| 2028 | |||
| 2029 | (unless (ignore-errors (dbus-get-unique-name bus-private)) | ||
| 2030 | (dbus-init-bus bus 'private)) | ||
| 2031 | (dbus-call-method | ||
| 2032 | bus-private dbus-service-dbus dbus-path-dbus dbus-interface-monitoring | ||
| 2033 | "BecomeMonitor" | ||
| 2034 | (append `(:array :string ,rule1) (when rule2 `(:string ,rule2))) | ||
| 2035 | :uint32 0) | ||
| 2036 | |||
| 2037 | (when dbus-debug (message "Matching rule \"%s\" created" rule1)) | ||
| 2038 | |||
| 2039 | ;; Create a hash table entry. | ||
| 2040 | (setq key (list :monitor bus-private) | ||
| 2041 | key1 (list nil nil nil handler) | ||
| 2042 | value (gethash key dbus-registered-objects-table)) | ||
| 2043 | (unless (member key1 value) | ||
| 2044 | (puthash key (cons key1 value) dbus-registered-objects-table)) | ||
| 2045 | |||
| 2046 | (when dbus-debug (message "%s" dbus-registered-objects-table)) | ||
| 2047 | |||
| 2048 | ;; Return the object. | ||
| 2049 | (list key (list service path handler)))) | ||
| 2050 | |||
| 2051 | (defun dbus-monitor-handler (&rest _args) | ||
| 2052 | "Default handler for the \"org.freedesktop.DBus.Monitoring.BecomeMonitor\" interface. | ||
| 2053 | It will be applied all objects created by `dbus-register-monitor'." | ||
| 2054 | (with-current-buffer (get-buffer-create "*D-Bus Monitor*") | ||
| 2055 | (special-mode) | ||
| 2056 | (let* ((inhibit-read-only t) | ||
| 2057 | (eobp (eobp)) | ||
| 2058 | (event last-input-event) | ||
| 2059 | (type (dbus-event-message-type event)) | ||
| 2060 | (sender (dbus-event-service-name event)) | ||
| 2061 | (destination (dbus-event-destination-name event)) | ||
| 2062 | (serial (dbus-event-serial-number event)) | ||
| 2063 | (path (dbus-event-path-name event)) | ||
| 2064 | (interface (dbus-event-interface-name event)) | ||
| 2065 | (member (dbus-event-member-name event)) | ||
| 2066 | (arguments (dbus-event-arguments event))) | ||
| 2067 | (save-excursion | ||
| 2068 | (goto-char (point-max)) | ||
| 2069 | (insert | ||
| 2070 | (format | ||
| 2071 | (concat | ||
| 2072 | "%s sender=%s -> destination=%s serial=%s " | ||
| 2073 | "path=%s interface=%s member=%s\n") | ||
| 2074 | (cond | ||
| 2075 | ((= type dbus-message-type-method-call) "method-call") | ||
| 2076 | ((= type dbus-message-type-method-return) "method-return") | ||
| 2077 | ((= type dbus-message-type-error) "error") | ||
| 2078 | ((= type dbus-message-type-signal) "signal")) | ||
| 2079 | sender destination serial path interface member)) | ||
| 2080 | (dolist (arg arguments) | ||
| 2081 | (pp (dbus-flatten-types arg) (current-buffer))) | ||
| 2082 | (insert "\n")) | ||
| 2083 | (when eobp | ||
| 2084 | (goto-char (point-max)))))) | ||
| 2085 | |||
| 1910 | (defun dbus-handle-bus-disconnect () | 2086 | (defun dbus-handle-bus-disconnect () |
| 1911 | "React to a bus disconnection. | 2087 | "React to a bus disconnection. |
| 1912 | BUS is the bus that disconnected. This routine unregisters all | 2088 | BUS is the bus that disconnected. This routine unregisters all |
| 1913 | handlers on the given bus and causes all synchronous calls | 2089 | handlers on the given bus and causes all synchronous calls |
| 1914 | pending at the time of disconnect to fail." | 2090 | pending at the time of disconnect to fail." |
| 1915 | (let ((bus (dbus-event-bus-name last-input-event)) | 2091 | (let ((bus (dbus-event-bus-name last-input-event)) |
| 1916 | (keys-to-remove)) | 2092 | keys-to-remove) |
| 1917 | (maphash | 2093 | (maphash |
| 1918 | (lambda (key value) | 2094 | (lambda (key value) |
| 1919 | (when (and (eq (nth 0 key) :serial) | 2095 | (when (and (eq (nth 0 key) :serial) |
| @@ -1923,13 +2099,14 @@ pending at the time of disconnect to fail." | |||
| 1923 | (list 'dbus-event | 2099 | (list 'dbus-event |
| 1924 | bus | 2100 | bus |
| 1925 | dbus-message-type-error | 2101 | dbus-message-type-error |
| 1926 | (nth 2 key) | 2102 | (nth 2 key) ; serial |
| 1927 | nil | 2103 | nil ; service |
| 1928 | nil | 2104 | nil ; destination |
| 1929 | nil | 2105 | nil ; path |
| 1930 | nil | 2106 | nil ; interface |
| 1931 | value) | 2107 | nil ; member |
| 1932 | (list 'dbus-error "Bus disconnected" bus)) | 2108 | value) ; handler |
| 2109 | (list 'dbus-error dbus-error-disconnected "Bus disconnected" bus)) | ||
| 1933 | (push key keys-to-remove))) | 2110 | (push key keys-to-remove))) |
| 1934 | dbus-registered-objects-table) | 2111 | dbus-registered-objects-table) |
| 1935 | (dolist (key keys-to-remove) | 2112 | (dolist (key keys-to-remove) |
| @@ -1980,13 +2157,9 @@ this connection to those buses." | |||
| 1980 | 2157 | ||
| 1981 | ;;; TODO: | 2158 | ;;; TODO: |
| 1982 | 2159 | ||
| 1983 | ;; * Check property type in org.freedesktop.DBus.Properties.Set. | ||
| 1984 | ;; | ||
| 1985 | ;; * Implement org.freedesktop.DBus.ObjectManager.InterfacesAdded and | 2160 | ;; * Implement org.freedesktop.DBus.ObjectManager.InterfacesAdded and |
| 1986 | ;; org.freedesktop.DBus.ObjectManager.InterfacesRemoved. | 2161 | ;; org.freedesktop.DBus.ObjectManager.InterfacesRemoved. |
| 1987 | ;; | 2162 | ;; |
| 1988 | ;; * Implement org.freedesktop.DBus.Monitoring.BecomeMonitor. | ||
| 1989 | ;; | ||
| 1990 | ;; * Cache introspection data. | 2163 | ;; * Cache introspection data. |
| 1991 | ;; | 2164 | ;; |
| 1992 | ;; * Run handlers in own threads. | 2165 | ;; * Run handlers in own threads. |
diff --git a/src/dbusbind.c b/src/dbusbind.c index 4c5ab485803..09f0317be91 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c | |||
| @@ -44,7 +44,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 44 | 44 | ||
| 45 | /* Alist of D-Bus buses we are polling for messages. | 45 | /* Alist of D-Bus buses we are polling for messages. |
| 46 | The key is the symbol or string of the bus, and the value is the | 46 | The key is the symbol or string of the bus, and the value is the |
| 47 | connection address. */ | 47 | connection address. For every bus, just one connection is counted. |
| 48 | If there shall be a second connection to the same bus, a different | ||
| 49 | symbol or string for the bus must be chosen. On Lisp level, a bus | ||
| 50 | stands for the associated connection. */ | ||
| 48 | static Lisp_Object xd_registered_buses; | 51 | static Lisp_Object xd_registered_buses; |
| 49 | 52 | ||
| 50 | /* Whether we are reading a D-Bus event. */ | 53 | /* Whether we are reading a D-Bus event. */ |
| @@ -279,10 +282,13 @@ XD_OBJECT_TO_STRING (Lisp_Object object) | |||
| 279 | else \ | 282 | else \ |
| 280 | { \ | 283 | { \ |
| 281 | CHECK_SYMBOL (bus); \ | 284 | CHECK_SYMBOL (bus); \ |
| 282 | if (!(EQ (bus, QCsystem) || EQ (bus, QCsession))) \ | 285 | if (!(EQ (bus, QCsystem) || EQ (bus, QCsession) \ |
| 286 | || EQ (bus, QCsystem_private) \ | ||
| 287 | || EQ (bus, QCsession_private))) \ | ||
| 283 | XD_SIGNAL2 (build_string ("Wrong bus name"), bus); \ | 288 | XD_SIGNAL2 (build_string ("Wrong bus name"), bus); \ |
| 284 | /* We do not want to have an autolaunch for the session bus. */ \ | 289 | /* We do not want to have an autolaunch for the session bus. */ \ |
| 285 | if (EQ (bus, QCsession) && session_bus_address == NULL) \ | 290 | if ((EQ (bus, QCsession) || EQ (bus, QCsession_private)) \ |
| 291 | && session_bus_address == NULL) \ | ||
| 286 | XD_SIGNAL2 (build_string ("No connection to bus"), bus); \ | 292 | XD_SIGNAL2 (build_string ("No connection to bus"), bus); \ |
| 287 | } \ | 293 | } \ |
| 288 | } while (0) | 294 | } while (0) |
| @@ -968,8 +974,9 @@ xd_lisp_dbus_to_dbus (Lisp_Object bus) | |||
| 968 | return xmint_pointer (bus); | 974 | return xmint_pointer (bus); |
| 969 | } | 975 | } |
| 970 | 976 | ||
| 971 | /* Return D-Bus connection address. BUS is either a Lisp symbol, | 977 | /* Return D-Bus connection address. |
| 972 | :system or :session, or a string denoting the bus address. */ | 978 | BUS is either a Lisp symbol, :system, :session, :system-private or |
| 979 | :session-private, or a string denoting the bus address. */ | ||
| 973 | static DBusConnection * | 980 | static DBusConnection * |
| 974 | xd_get_connection_address (Lisp_Object bus) | 981 | xd_get_connection_address (Lisp_Object bus) |
| 975 | { | 982 | { |
| @@ -1031,7 +1038,8 @@ xd_add_watch (DBusWatch *watch, void *data) | |||
| 1031 | } | 1038 | } |
| 1032 | 1039 | ||
| 1033 | /* Stop monitoring WATCH for possible I/O. | 1040 | /* Stop monitoring WATCH for possible I/O. |
| 1034 | DATA is the used bus, either a string or QCsystem or QCsession. */ | 1041 | DATA is the used bus, either a string or QCsystem, QCsession, |
| 1042 | QCsystem_private or QCsession_private. */ | ||
| 1035 | static void | 1043 | static void |
| 1036 | xd_remove_watch (DBusWatch *watch, void *data) | 1044 | xd_remove_watch (DBusWatch *watch, void *data) |
| 1037 | { | 1045 | { |
| @@ -1046,7 +1054,7 @@ xd_remove_watch (DBusWatch *watch, void *data) | |||
| 1046 | /* Unset session environment. */ | 1054 | /* Unset session environment. */ |
| 1047 | #if 0 | 1055 | #if 0 |
| 1048 | /* This is buggy, since unsetenv is not thread-safe. */ | 1056 | /* This is buggy, since unsetenv is not thread-safe. */ |
| 1049 | if (XSYMBOL (QCsession) == data) | 1057 | if (XSYMBOL (QCsession) == data) || (XSYMBOL (QCsession_private) == data) |
| 1050 | { | 1058 | { |
| 1051 | XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); | 1059 | XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS"); |
| 1052 | unsetenv ("DBUS_SESSION_BUS_ADDRESS"); | 1060 | unsetenv ("DBUS_SESSION_BUS_ADDRESS"); |
| @@ -1120,6 +1128,11 @@ can be a string denoting the address of the corresponding bus. For | |||
| 1120 | the system and session buses, this function is called when loading | 1128 | the system and session buses, this function is called when loading |
| 1121 | `dbus.el', there is no need to call it again. | 1129 | `dbus.el', there is no need to call it again. |
| 1122 | 1130 | ||
| 1131 | A special case is BUS being the symbol `:system-private' or | ||
| 1132 | `:session-private'. These symbols still denote the system or session | ||
| 1133 | bus, but using a private connection. They should not be used outside | ||
| 1134 | dbus.el. | ||
| 1135 | |||
| 1123 | The function returns a number, which counts the connections this Emacs | 1136 | The function returns a number, which counts the connections this Emacs |
| 1124 | session has established to the BUS under the same unique name (see | 1137 | session has established to the BUS under the same unique name (see |
| 1125 | `dbus-get-unique-name'). It depends on the libraries Emacs is linked | 1138 | `dbus-get-unique-name'). It depends on the libraries Emacs is linked |
| @@ -1142,6 +1155,10 @@ this connection to those buses. */) | |||
| 1142 | ptrdiff_t refcount; | 1155 | ptrdiff_t refcount; |
| 1143 | 1156 | ||
| 1144 | /* Check parameter. */ | 1157 | /* Check parameter. */ |
| 1158 | if (!NILP (private)) | ||
| 1159 | bus = EQ (bus, QCsystem) | ||
| 1160 | ? QCsystem_private | ||
| 1161 | : EQ (bus, QCsession) ? QCsession_private : bus; | ||
| 1145 | XD_DBUS_VALIDATE_BUS_ADDRESS (bus); | 1162 | XD_DBUS_VALIDATE_BUS_ADDRESS (bus); |
| 1146 | 1163 | ||
| 1147 | /* Close bus if it is already open. */ | 1164 | /* Close bus if it is already open. */ |
| @@ -1169,8 +1186,9 @@ this connection to those buses. */) | |||
| 1169 | 1186 | ||
| 1170 | else | 1187 | else |
| 1171 | { | 1188 | { |
| 1172 | DBusBusType bustype = (EQ (bus, QCsystem) | 1189 | DBusBusType bustype |
| 1173 | ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION); | 1190 | = EQ (bus, QCsystem) || EQ (bus, QCsystem_private) |
| 1191 | ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION; | ||
| 1174 | if (NILP (private)) | 1192 | if (NILP (private)) |
| 1175 | connection = dbus_bus_get (bustype, &derror); | 1193 | connection = dbus_bus_get (bustype, &derror); |
| 1176 | else | 1194 | else |
| @@ -1184,9 +1202,9 @@ this connection to those buses. */) | |||
| 1184 | XD_SIGNAL2 (build_string ("No connection to bus"), bus); | 1202 | XD_SIGNAL2 (build_string ("No connection to bus"), bus); |
| 1185 | 1203 | ||
| 1186 | /* If it is not the system or session bus, we must register | 1204 | /* If it is not the system or session bus, we must register |
| 1187 | ourselves. Otherwise, we have called dbus_bus_get, which has | 1205 | ourselves. Otherwise, we have called dbus_bus_get{_private}, |
| 1188 | configured us to exit if the connection closes - we undo this | 1206 | which has configured us to exit if the connection closes - we |
| 1189 | setting. */ | 1207 | undo this setting. */ |
| 1190 | if (STRINGP (bus)) | 1208 | if (STRINGP (bus)) |
| 1191 | dbus_bus_register (connection, &derror); | 1209 | dbus_bus_register (connection, &derror); |
| 1192 | else | 1210 | else |
| @@ -1215,6 +1233,9 @@ this connection to those buses. */) | |||
| 1215 | dbus_error_free (&derror); | 1233 | dbus_error_free (&derror); |
| 1216 | } | 1234 | } |
| 1217 | 1235 | ||
| 1236 | XD_DEBUG_MESSAGE ("Registered buses: %s", | ||
| 1237 | XD_OBJECT_TO_STRING (xd_registered_buses)); | ||
| 1238 | |||
| 1218 | /* Return reference counter. */ | 1239 | /* Return reference counter. */ |
| 1219 | refcount = xd_get_connection_references (connection); | 1240 | refcount = xd_get_connection_references (connection); |
| 1220 | XD_DEBUG_MESSAGE ("Bus %s, Reference counter %"pD"d", | 1241 | XD_DEBUG_MESSAGE ("Bus %s, Reference counter %"pD"d", |
| @@ -1533,8 +1554,8 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1533 | } | 1554 | } |
| 1534 | 1555 | ||
| 1535 | /* Read one queued incoming message of the D-Bus BUS. | 1556 | /* Read one queued incoming message of the D-Bus BUS. |
| 1536 | BUS is either a Lisp symbol, :system or :session, or a string denoting | 1557 | BUS is either a Lisp symbol, :system, :session, :system-private or |
| 1537 | the bus address. */ | 1558 | :session-private, or a string denoting the bus address. */ |
| 1538 | static void | 1559 | static void |
| 1539 | xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | 1560 | xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) |
| 1540 | { | 1561 | { |
| @@ -1546,7 +1567,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1546 | int mtype; | 1567 | int mtype; |
| 1547 | dbus_uint32_t serial; | 1568 | dbus_uint32_t serial; |
| 1548 | unsigned int ui_serial; | 1569 | unsigned int ui_serial; |
| 1549 | const char *uname, *path, *interface, *member, *error_name; | 1570 | const char *uname, *destination, *path, *interface, *member, *error_name; |
| 1550 | 1571 | ||
| 1551 | dmessage = dbus_connection_pop_message (connection); | 1572 | dmessage = dbus_connection_pop_message (connection); |
| 1552 | 1573 | ||
| @@ -1579,6 +1600,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1579 | ? dbus_message_get_reply_serial (dmessage) | 1600 | ? dbus_message_get_reply_serial (dmessage) |
| 1580 | : dbus_message_get_serial (dmessage); | 1601 | : dbus_message_get_serial (dmessage); |
| 1581 | uname = dbus_message_get_sender (dmessage); | 1602 | uname = dbus_message_get_sender (dmessage); |
| 1603 | destination = dbus_message_get_destination (dmessage); | ||
| 1582 | path = dbus_message_get_path (dmessage); | 1604 | path = dbus_message_get_path (dmessage); |
| 1583 | interface = dbus_message_get_interface (dmessage); | 1605 | interface = dbus_message_get_interface (dmessage); |
| 1584 | member = dbus_message_get_member (dmessage); | 1606 | member = dbus_message_get_member (dmessage); |
| @@ -1586,7 +1608,8 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1586 | 1608 | ||
| 1587 | XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s %s", | 1609 | XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s %s", |
| 1588 | XD_MESSAGE_TYPE_TO_STRING (mtype), | 1610 | XD_MESSAGE_TYPE_TO_STRING (mtype), |
| 1589 | ui_serial, uname, path, interface, member, error_name, | 1611 | ui_serial, uname, destination, path, interface, |
| 1612 | mtype == DBUS_MESSAGE_TYPE_ERROR ? error_name : member, | ||
| 1590 | XD_OBJECT_TO_STRING (args)); | 1613 | XD_OBJECT_TO_STRING (args)); |
| 1591 | 1614 | ||
| 1592 | if (mtype == DBUS_MESSAGE_TYPE_INVALID) | 1615 | if (mtype == DBUS_MESSAGE_TYPE_INVALID) |
| @@ -1601,7 +1624,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1601 | 1624 | ||
| 1602 | /* There shall be exactly one entry. Construct an event. */ | 1625 | /* There shall be exactly one entry. Construct an event. */ |
| 1603 | if (NILP (value)) | 1626 | if (NILP (value)) |
| 1604 | goto cleanup; | 1627 | goto monitor; |
| 1605 | 1628 | ||
| 1606 | /* Remove the entry. */ | 1629 | /* Remove the entry. */ |
| 1607 | Fremhash (key, Vdbus_registered_objects_table); | 1630 | Fremhash (key, Vdbus_registered_objects_table); |
| @@ -1610,11 +1633,8 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1610 | EVENT_INIT (event); | 1633 | EVENT_INIT (event); |
| 1611 | event.kind = DBUS_EVENT; | 1634 | event.kind = DBUS_EVENT; |
| 1612 | event.frame_or_window = Qnil; | 1635 | event.frame_or_window = Qnil; |
| 1613 | event.arg = | 1636 | /* Handler. */ |
| 1614 | Fcons (value, | 1637 | event.arg = Fcons (value, args); |
| 1615 | (mtype == DBUS_MESSAGE_TYPE_ERROR) | ||
| 1616 | ? Fcons (list2 (QCstring, build_string (error_name)), args) | ||
| 1617 | : args); | ||
| 1618 | } | 1638 | } |
| 1619 | 1639 | ||
| 1620 | else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ | 1640 | else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ |
| @@ -1622,7 +1642,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1622 | /* Vdbus_registered_objects_table requires non-nil interface and | 1642 | /* Vdbus_registered_objects_table requires non-nil interface and |
| 1623 | member. */ | 1643 | member. */ |
| 1624 | if ((interface == NULL) || (member == NULL)) | 1644 | if ((interface == NULL) || (member == NULL)) |
| 1625 | goto cleanup; | 1645 | goto monitor; |
| 1626 | 1646 | ||
| 1627 | /* Search for a registered function of the message. */ | 1647 | /* Search for a registered function of the message. */ |
| 1628 | key = list4 (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL ? QCmethod : QCsignal, | 1648 | key = list4 (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL ? QCmethod : QCsignal, |
| @@ -1647,6 +1667,7 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1647 | EVENT_INIT (event); | 1667 | EVENT_INIT (event); |
| 1648 | event.kind = DBUS_EVENT; | 1668 | event.kind = DBUS_EVENT; |
| 1649 | event.frame_or_window = Qnil; | 1669 | event.frame_or_window = Qnil; |
| 1670 | /* Handler. */ | ||
| 1650 | event.arg | 1671 | event.arg |
| 1651 | = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args); | 1672 | = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args); |
| 1652 | break; | 1673 | break; |
| @@ -1655,16 +1676,22 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1655 | } | 1676 | } |
| 1656 | 1677 | ||
| 1657 | if (NILP (value)) | 1678 | if (NILP (value)) |
| 1658 | goto cleanup; | 1679 | goto monitor; |
| 1659 | } | 1680 | } |
| 1660 | 1681 | ||
| 1661 | /* Add type, serial, uname, path, interface and member to the event. */ | 1682 | /* Add type, serial, uname, destination, path, interface and member |
| 1662 | event.arg = Fcons ((member == NULL ? Qnil : build_string (member)), | 1683 | or error_name to the event. */ |
| 1663 | event.arg); | 1684 | event.arg |
| 1685 | = Fcons (mtype == DBUS_MESSAGE_TYPE_ERROR | ||
| 1686 | ? error_name == NULL ? Qnil : build_string (error_name) | ||
| 1687 | : member == NULL ? Qnil : build_string (member), | ||
| 1688 | event.arg); | ||
| 1664 | event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)), | 1689 | event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)), |
| 1665 | event.arg); | 1690 | event.arg); |
| 1666 | event.arg = Fcons ((path == NULL ? Qnil : build_string (path)), | 1691 | event.arg = Fcons ((path == NULL ? Qnil : build_string (path)), |
| 1667 | event.arg); | 1692 | event.arg); |
| 1693 | event.arg = Fcons ((destination == NULL ? Qnil : build_string (destination)), | ||
| 1694 | event.arg); | ||
| 1668 | event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)), | 1695 | event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)), |
| 1669 | event.arg); | 1696 | event.arg); |
| 1670 | event.arg = Fcons (INT_TO_INTEGER (serial), event.arg); | 1697 | event.arg = Fcons (INT_TO_INTEGER (serial), event.arg); |
| @@ -1678,14 +1705,58 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1678 | 1705 | ||
| 1679 | XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg)); | 1706 | XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg)); |
| 1680 | 1707 | ||
| 1708 | /* Monitor. */ | ||
| 1709 | monitor: | ||
| 1710 | /* Search for a registered function of the message. */ | ||
| 1711 | key = list2 (QCmonitor, bus); | ||
| 1712 | value = Fgethash (key, Vdbus_registered_objects_table, Qnil); | ||
| 1713 | |||
| 1714 | /* There shall be exactly one entry. Construct an event. */ | ||
| 1715 | if (NILP (value)) | ||
| 1716 | goto cleanup; | ||
| 1717 | |||
| 1718 | /* Construct an event. */ | ||
| 1719 | EVENT_INIT (event); | ||
| 1720 | event.kind = DBUS_EVENT; | ||
| 1721 | event.frame_or_window = Qnil; | ||
| 1722 | |||
| 1723 | /* Add type, serial, uname, destination, path, interface, member | ||
| 1724 | or error_name and handler to the event. */ | ||
| 1725 | event.arg | ||
| 1726 | = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (CAR_SAFE (value))))), | ||
| 1727 | args); | ||
| 1728 | event.arg | ||
| 1729 | = Fcons (mtype == DBUS_MESSAGE_TYPE_ERROR | ||
| 1730 | ? error_name == NULL ? Qnil : build_string (error_name) | ||
| 1731 | : member == NULL ? Qnil : build_string (member), | ||
| 1732 | event.arg); | ||
| 1733 | event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)), | ||
| 1734 | event.arg); | ||
| 1735 | event.arg = Fcons ((path == NULL ? Qnil : build_string (path)), | ||
| 1736 | event.arg); | ||
| 1737 | event.arg = Fcons ((destination == NULL ? Qnil : build_string (destination)), | ||
| 1738 | event.arg); | ||
| 1739 | event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)), | ||
| 1740 | event.arg); | ||
| 1741 | event.arg = Fcons (INT_TO_INTEGER (serial), event.arg); | ||
| 1742 | event.arg = Fcons (make_fixnum (mtype), event.arg); | ||
| 1743 | |||
| 1744 | /* Add the bus symbol to the event. */ | ||
| 1745 | event.arg = Fcons (bus, event.arg); | ||
| 1746 | |||
| 1747 | /* Store it into the input event queue. */ | ||
| 1748 | kbd_buffer_store_event (&event); | ||
| 1749 | |||
| 1750 | XD_DEBUG_MESSAGE ("Monitor event stored: %s", XD_OBJECT_TO_STRING (event.arg)); | ||
| 1751 | |||
| 1681 | /* Cleanup. */ | 1752 | /* Cleanup. */ |
| 1682 | cleanup: | 1753 | cleanup: |
| 1683 | dbus_message_unref (dmessage); | 1754 | dbus_message_unref (dmessage); |
| 1684 | } | 1755 | } |
| 1685 | 1756 | ||
| 1686 | /* Read queued incoming messages of the D-Bus BUS. | 1757 | /* Read queued incoming messages of the D-Bus BUS. |
| 1687 | BUS is either a Lisp symbol, :system or :session, or a string denoting | 1758 | BUS is either a Lisp symbol, :system, :session, :system-private or |
| 1688 | the bus address. */ | 1759 | :session-private, or a string denoting the bus address. */ |
| 1689 | static Lisp_Object | 1760 | static Lisp_Object |
| 1690 | xd_read_message (Lisp_Object bus) | 1761 | xd_read_message (Lisp_Object bus) |
| 1691 | { | 1762 | { |
| @@ -1762,6 +1833,8 @@ syms_of_dbusbind (void) | |||
| 1762 | /* Lisp symbols of the system and session buses. */ | 1833 | /* Lisp symbols of the system and session buses. */ |
| 1763 | DEFSYM (QCsystem, ":system"); | 1834 | DEFSYM (QCsystem, ":system"); |
| 1764 | DEFSYM (QCsession, ":session"); | 1835 | DEFSYM (QCsession, ":session"); |
| 1836 | DEFSYM (QCsystem_private, ":system-private"); | ||
| 1837 | DEFSYM (QCsession_private, ":session-private"); | ||
| 1765 | 1838 | ||
| 1766 | /* Lisp symbol for method call timeout. */ | 1839 | /* Lisp symbol for method call timeout. */ |
| 1767 | DEFSYM (QCtimeout, ":timeout"); | 1840 | DEFSYM (QCtimeout, ":timeout"); |
| @@ -1788,10 +1861,11 @@ syms_of_dbusbind (void) | |||
| 1788 | DEFSYM (QCdict_entry, ":dict-entry"); | 1861 | DEFSYM (QCdict_entry, ":dict-entry"); |
| 1789 | 1862 | ||
| 1790 | /* Lisp symbols of objects in `dbus-registered-objects-table'. | 1863 | /* Lisp symbols of objects in `dbus-registered-objects-table'. |
| 1791 | `:property', which does exist there as well, is not used here. */ | 1864 | `:property', which does exist there as well, is not declared here. */ |
| 1792 | DEFSYM (QCserial, ":serial"); | 1865 | DEFSYM (QCserial, ":serial"); |
| 1793 | DEFSYM (QCmethod, ":method"); | 1866 | DEFSYM (QCmethod, ":method"); |
| 1794 | DEFSYM (QCsignal, ":signal"); | 1867 | DEFSYM (QCsignal, ":signal"); |
| 1868 | DEFSYM (QCmonitor, ":monitor"); | ||
| 1795 | 1869 | ||
| 1796 | DEFVAR_LISP ("dbus-compiled-version", | 1870 | DEFVAR_LISP ("dbus-compiled-version", |
| 1797 | Vdbus_compiled_version, | 1871 | Vdbus_compiled_version, |
| @@ -1867,8 +1941,9 @@ path of the sending object. All of them can be nil, which means a | |||
| 1867 | wildcard then. | 1941 | wildcard then. |
| 1868 | 1942 | ||
| 1869 | OBJECT is either the handler to be called when a D-Bus message, which | 1943 | OBJECT is either the handler to be called when a D-Bus message, which |
| 1870 | matches the key criteria, arrives (TYPE `:method' and `:signal'), or a | 1944 | matches the key criteria, arrives (TYPE `:method', `:signal' and |
| 1871 | list (ACCESS EMITS-SIGNAL VALUE) for TYPE `:property'. | 1945 | `:monitor'), or a list (ACCESS EMITS-SIGNAL VALUE) for TYPE |
| 1946 | `:property'. | ||
| 1872 | 1947 | ||
| 1873 | For entries of type `:signal', there is also a fifth element RULE, | 1948 | For entries of type `:signal', there is also a fifth element RULE, |
| 1874 | which keeps the match string the signal is registered with. | 1949 | which keeps the match string the signal is registered with. |