DBus wrapper function that helps invoke the portal for the SaveFile() API. This function returns NFD_OKAY iff outMsg gets set (to the returned message). Caller is responsible for freeing the outMsg using dbus_message_unref() (or use DBusMessage_Guard).
| 1180 | // Caller is responsible for freeing the outMsg using dbus_message_unref() (or use |
| 1181 | // DBusMessage_Guard). |
| 1182 | nfdresult_t NFD_DBus_SaveFile(DBusMessage*& outMsg, |
| 1183 | const nfdnfilteritem_t* filterList, |
| 1184 | nfdfiltersize_t filterCount, |
| 1185 | const nfdnchar_t* defaultPath, |
| 1186 | const nfdnchar_t* defaultName) { |
| 1187 | const char* handle_token_ptr; |
| 1188 | char* handle_obj_path = MakeUniqueObjectPath(&handle_token_ptr); |
| 1189 | Free_Guard<char> handle_obj_path_guard(handle_obj_path); |
| 1190 | |
| 1191 | DBusError err; // need a separate error object because we don't want to mess with the old one |
| 1192 | // if it's stil set |
| 1193 | dbus_error_init(&err); |
| 1194 | |
| 1195 | // Subscribe to the signal using the handle_obj_path |
| 1196 | DBusSignalSubscriptionHandler signal_sub; |
| 1197 | nfdresult_t res = signal_sub.Subscribe(handle_obj_path); |
| 1198 | if (res != NFD_OKAY) return res; |
| 1199 | |
| 1200 | // TODO: use XOpenDisplay()/XGetInputFocus() to find xid of window... but what should one do on |
| 1201 | // Wayland? |
| 1202 | |
| 1203 | DBusMessage* query = dbus_message_new_method_call("org.freedesktop.portal.Desktop", |
| 1204 | "/org/freedesktop/portal/desktop", |
| 1205 | "org.freedesktop.portal.FileChooser", |
| 1206 | "SaveFile"); |
| 1207 | DBusMessage_Guard query_guard(query); |
| 1208 | AppendSaveFileQueryParams( |
| 1209 | query, handle_token_ptr, filterList, filterCount, defaultPath, defaultName); |
| 1210 | |
| 1211 | DBusMessage* reply = |
| 1212 | dbus_connection_send_with_reply_and_block(dbus_conn, query, DBUS_TIMEOUT_INFINITE, &err); |
| 1213 | if (!reply) { |
| 1214 | dbus_error_free(&dbus_err); |
| 1215 | dbus_move_error(&err, &dbus_err); |
| 1216 | NFDi_SetError(dbus_err.message); |
| 1217 | return NFD_ERROR; |
| 1218 | } |
| 1219 | DBusMessage_Guard reply_guard(reply); |
| 1220 | |
| 1221 | // Check the reply and update our signal subscription if necessary |
| 1222 | { |
| 1223 | DBusMessageIter iter; |
| 1224 | if (!dbus_message_iter_init(reply, &iter)) { |
| 1225 | NFDi_SetError("D-Bus reply is missing an argument."); |
| 1226 | return NFD_ERROR; |
| 1227 | } |
| 1228 | if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH) { |
| 1229 | NFDi_SetError("D-Bus reply is not an object path."); |
| 1230 | return NFD_ERROR; |
| 1231 | } |
| 1232 | |
| 1233 | const char* path; |
| 1234 | dbus_message_iter_get_basic(&iter, &path); |
| 1235 | if (strcmp(path, handle_obj_path) != 0) { |
| 1236 | // needs to change our signal subscription |
| 1237 | signal_sub.Subscribe(path); |
| 1238 | } |
| 1239 | } |
no test coverage detected