return NULL;
}
+const char *sysview_device_get_name(sysview_device *device) {
+ assert_return(device, NULL);
+
+ return device->name;
+}
+
unsigned int sysview_device_get_type(sysview_device *device) {
assert_return(device, (unsigned)-1);
return NULL;
}
+void sysview_session_set_userdata(sysview_session *session, void *userdata) {
+ assert(session);
+
+ session->userdata = userdata;
+}
+
+void *sysview_session_get_userdata(sysview_session *session) {
+ assert_return(session, NULL);
+
+ return session->userdata;
+}
+
const char *sysview_session_get_name(sysview_session *session) {
assert_return(session, NULL);
return session->name;
}
+sysview_seat *sysview_session_get_seat(sysview_session *session) {
+ assert_return(session, NULL);
+
+ return session->seat;
+}
+
static int session_take_control_fn(sd_bus *bus,
sd_bus_message *reply,
void *userdata,
sd_bus_error *ret_error) {
sysview_session *session = userdata;
- int error;
+ int r, error;
session->slot_take_control = sd_bus_slot_unref(session->slot_take_control);
log_debug("sysview: %s: TakeControl failed: %s: %s",
session->name, e->name, e->message);
- error = sd_bus_error_get_errno(e);
+ error = -sd_bus_error_get_errno(e);
} else {
session->has_control = true;
error = 0;
}
- return context_raise_session_control(session->seat->context, session, error);
+ r = context_raise_session_control(session->seat->context, session, error);
+ if (r < 0)
+ log_debug("sysview: callback failed while signalling session control '%d' on session '%s': %s",
+ error, session->name, strerror(-r));
+
+ return 0;
}
int sysview_session_take_control(sysview_session *session) {
if (!seat->name)
return -ENOMEM;
- seat->session_map = hashmap_new(string_hash_func, string_compare_func);
+ r = sd_bus_path_encode("/org/freedesktop/login1/seat", seat->name, &seat->path);
+ if (r < 0)
+ return r;
+
+ seat->session_map = hashmap_new(&string_hash_ops);
if (!seat->session_map)
return -ENOMEM;
- seat->device_map = hashmap_new(string_hash_func, string_compare_func);
+ seat->device_map = hashmap_new(&string_hash_ops);
if (!seat->device_map)
return -ENOMEM;
hashmap_free(seat->device_map);
hashmap_free(seat->session_map);
+ free(seat->path);
free(seat->name);
free(seat);
return seat->name;
}
+int sysview_seat_switch_to(sysview_seat *seat, uint32_t nr) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ int r;
+
+ assert_return(seat, -EINVAL);
+ assert_return(seat->context->sysbus, -EINVAL);
+
+ r = sd_bus_message_new_method_call(seat->context->sysbus,
+ &m,
+ "org.freedesktop.login1",
+ seat->path,
+ "org.freedesktop.login1.Seat",
+ "SwitchTo");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(m, "u", nr);
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(seat->context->sysbus, m, NULL);
+}
+
/*
* Contexts
*/
return context_raise(c, &event, 0);
}
-static int context_add_device(sysview_context *c, sysview_device *device) {
+static int context_raise_session_refresh(sysview_context *c, sysview_session *session, sysview_device *device, struct udev_device *ud) {
+ sysview_event event = {
+ .type = SYSVIEW_EVENT_SESSION_REFRESH,
+ .session_refresh = {
+ .session = session,
+ .device = device,
+ .ud = ud,
+ }
+ };
+
+ return context_raise(c, &event, 0);
+}
+
+static void context_add_device(sysview_context *c, sysview_device *device) {
sysview_session *session;
- int r, error = 0;
Iterator i;
+ int r;
assert(c);
assert(device);
continue;
r = context_raise_session_attach(c, session, device);
- if (r != 0)
- error = r;
+ if (r < 0)
+ log_debug("sysview: callback failed while attaching device '%s' to session '%s': %s",
+ device->name, session->name, strerror(-r));
}
-
- if (error < 0)
- log_debug("sysview: error while adding device '%s': %s",
- device->name, strerror(-r));
- return error;
}
-static int context_remove_device(sysview_context *c, sysview_device *device) {
+static void context_remove_device(sysview_context *c, sysview_device *device) {
sysview_session *session;
- int r, error = 0;
Iterator i;
+ int r;
assert(c);
assert(device);
continue;
r = context_raise_session_detach(c, session, device);
- if (r != 0)
- error = r;
+ if (r < 0)
+ log_debug("sysview: callback failed while detaching device '%s' from session '%s': %s",
+ device->name, session->name, strerror(-r));
}
- if (error < 0)
- log_debug("sysview: error while removing device '%s': %s",
- device->name, strerror(-r));
sysview_device_free(device);
- return error;
}
-static int context_add_session(sysview_context *c, sysview_seat *seat, const char *id) {
+static void context_change_device(sysview_context *c, sysview_device *device, struct udev_device *ud) {
+ sysview_session *session;
+ Iterator i;
+ int r;
+
+ assert(c);
+ assert(device);
+
+ log_debug("sysview: change device '%s'", device->name);
+
+ HASHMAP_FOREACH(session, device->seat->session_map, i) {
+ if (!session->public)
+ continue;
+
+ r = context_raise_session_refresh(c, session, device, ud);
+ if (r < 0)
+ log_debug("sysview: callback failed while changing device '%s' on session '%s': %s",
+ device->name, session->name, strerror(-r));
+ }
+}
+
+static void context_add_session(sysview_context *c, sysview_seat *seat, const char *id) {
sysview_session *session;
sysview_device *device;
- int r, error = 0;
Iterator i;
+ int r;
assert(c);
assert(seat);
session = sysview_find_session(c, id);
if (session)
- return 0;
+ return;
log_debug("sysview: add session '%s' on seat '%s'", id, seat->name);
if (seat->public) {
session->public = true;
r = context_raise_session_add(c, session);
- if (r != 0) {
+ if (r < 0) {
+ log_debug("sysview: callback failed while adding session '%s': %s",
+ session->name, strerror(-r));
session->public = false;
goto error;
}
HASHMAP_FOREACH(device, seat->device_map, i) {
r = context_raise_session_attach(c, session, device);
- if (r != 0)
- error = r;
+ if (r < 0)
+ log_debug("sysview: callback failed while attaching device '%s' to new session '%s': %s",
+ device->name, session->name, strerror(-r));
}
-
- r = error;
- if (r != 0)
- goto error;
}
- return 0;
+ return;
error:
if (r < 0)
log_debug("sysview: error while adding session '%s': %s",
id, strerror(-r));
- return r;
}
-static int context_remove_session(sysview_context *c, sysview_session *session) {
+static void context_remove_session(sysview_context *c, sysview_session *session) {
sysview_device *device;
- int r, error = 0;
Iterator i;
+ int r;
assert(c);
assert(session);
if (session->public) {
HASHMAP_FOREACH(device, session->seat->device_map, i) {
r = context_raise_session_detach(c, session, device);
- if (r != 0)
- error = r;
+ if (r < 0)
+ log_debug("sysview: callback failed while detaching device '%s' from old session '%s': %s",
+ device->name, session->name, strerror(-r));
}
session->public = false;
r = context_raise_session_remove(c, session);
- if (r != 0)
- error = r;
+ if (r < 0)
+ log_debug("sysview: callback failed while removing session '%s': %s",
+ session->name, strerror(-r));
}
if (!session->custom)
sysview_session_release_control(session);
- if (error < 0)
- log_debug("sysview: error while removing session '%s': %s",
- session->name, strerror(-error));
sysview_session_free(session);
- return error;
}
-static int context_add_seat(sysview_context *c, const char *id) {
+static void context_add_seat(sysview_context *c, const char *id) {
sysview_seat *seat;
int r;
seat = sysview_find_seat(c, id);
if (seat)
- return 0;
+ return;
log_debug("sysview: add seat '%s'", id);
seat->public = true;
r = context_raise_seat_add(c, seat);
- if (r != 0) {
+ if (r < 0) {
+ log_debug("sysview: callback failed while adding seat '%s': %s",
+ seat->name, strerror(-r));
seat->public = false;
- goto error;
}
- return 0;
+ return;
error:
if (r < 0)
log_debug("sysview: error while adding seat '%s': %s",
id, strerror(-r));
- return r;
}
-static int context_remove_seat(sysview_context *c, sysview_seat *seat) {
+static void context_remove_seat(sysview_context *c, sysview_seat *seat) {
sysview_session *session;
sysview_device *device;
- int r, error = 0;
+ int r;
assert(c);
assert(seat);
log_debug("sysview: remove seat '%s'", seat->name);
- while ((device = hashmap_first(seat->device_map))) {
- r = context_remove_device(c, device);
- if (r != 0)
- error = r;
- }
+ while ((device = hashmap_first(seat->device_map)))
+ context_remove_device(c, device);
- while ((session = hashmap_first(seat->session_map))) {
- r = context_remove_session(c, session);
- if (r != 0)
- error = r;
- }
+ while ((session = hashmap_first(seat->session_map)))
+ context_remove_session(c, session);
if (seat->public) {
seat->public = false;
r = context_raise_seat_remove(c, seat);
- if (r != 0)
- error = r;
+ if (r < 0)
+ log_debug("sysview: callback failed while removing seat '%s': %s",
+ seat->name, strerror(-r));
}
- if (error < 0)
- log_debug("sysview: error while removing seat '%s': %s",
- seat->name, strerror(-error));
sysview_seat_free(seat);
- return error;
}
int sysview_context_new(sysview_context **out,
return errno > 0 ? -errno : -EFAULT;
}
- c->seat_map = hashmap_new(string_hash_func, string_compare_func);
+ c->seat_map = hashmap_new(&string_hash_ops);
if (!c->seat_map)
return -ENOMEM;
- c->session_map = hashmap_new(string_hash_func, string_compare_func);
+ c->session_map = hashmap_new(&string_hash_ops);
if (!c->session_map)
return -ENOMEM;
- c->device_map = hashmap_new(string_hash_func, string_compare_func);
+ c->device_map = hashmap_new(&string_hash_ops);
if (!c->device_map)
return -ENOMEM;
if (!device)
return 0;
- return context_remove_device(c, device);
+ context_remove_device(c, device);
} else if (streq_ptr(action, "change")) {
if (!device)
return 0;
- /* TODO: send REFRESH event */
+ context_change_device(c, device, d);
} else if (!action || streq_ptr(action, "add")) {
struct udev_device *p;
unsigned int type, t;
if (streq(subsystem, "input") && startswith(sysname, "event") && safe_atou(sysname + 5, &t) >= 0)
type = SYSVIEW_DEVICE_EVDEV;
- else if (streq(subsystem, "drm") && startswith(sysname, "card") && safe_atou(sysname + 4, &t) >= 0)
+ else if (streq(subsystem, "drm") && startswith(sysname, "card"))
type = SYSVIEW_DEVICE_DRM;
else
type = (unsigned)-1;
p = d;
seatname = NULL;
- while ((p = udev_device_get_parent(p))) {
+ do {
seatname = udev_device_get_property_value(p, "ID_SEAT");
if (seatname)
break;
- }
+ } while ((p = udev_device_get_parent(p)));
seat = sysview_find_seat(c, seatname ? : "seat0");
if (!seat)
return r;
}
- return context_add_device(c, device);
+ context_add_device(c, device);
}
return 0;
return r;
}
- return context_add_seat(c, id);
+ context_add_seat(c, id);
+ return 0;
}
static int context_ld_seat_removed(sysview_context *c, sd_bus_message *signal) {
if (!seat)
return 0;
- return context_remove_seat(c, seat);
+ context_remove_seat(c, seat);
+ return 0;
}
static int context_ld_session_new(sysview_context *c, sd_bus_message *signal) {
}
r = context_raise_session_filter(c, id, seatid, username, uid);
- if (r <= 0) {
- if (r < 0)
- log_debug("sysview: cannot filter new session '%s' on seat '%s': %s",
- id, seatid, strerror(-r));
- return r;
- }
+ if (r < 0)
+ log_debug("sysview: callback failed while filtering session '%s': %s",
+ id, strerror(-r));
+ else if (r > 0)
+ context_add_session(c, seat, id);
- return context_add_session(c, seat, id);
+ return 0;
error:
log_debug("sysview: failed retrieving information for new session '%s': %s",
if (!session)
return 0;
- return context_remove_session(c, session);
+ context_remove_session(c, session);
+ return 0;
}
static int context_ld_manager_signal_fn(sd_bus *bus,
log_debug("sysview: ListSeats on logind failed: %s: %s",
error->name, error->message);
- return sd_bus_error_get_errno(error);
+ return -sd_bus_error_get_errno(error);
}
r = sd_bus_message_enter_container(reply, 'a', "(so)");
if (r < 0)
goto error;
- r = context_add_seat(c, id);
- if (r != 0)
- return r;
+ context_add_seat(c, id);
r = sd_bus_message_exit_container(reply);
if (r < 0)
log_debug("sysview: ListSessions on logind failed: %s: %s",
error->name, error->message);
- return sd_bus_error_get_errno(error);
+ return -sd_bus_error_get_errno(error);
}
r = sd_bus_message_enter_container(reply, 'a', "(susso)");
seat = sysview_find_seat(c, seatid);
if (seat) {
r = context_raise_session_filter(c, id, seatid, username, uid);
- if (r < 0) {
- log_debug("sysview: cannot filter listed session '%s' on seat '%s': %s",
- id, seatid, strerror(-r));
- return r;
- } else if (r > 0) {
- r = context_add_session(c, seat, id);
- if (r != 0)
- return r;
- }
+ if (r < 0)
+ log_debug("sysview: callback failed while filtering session '%s': %s",
+ id, strerror(-r));
+ else if (r > 0)
+ context_add_session(c, seat, id);
}
r = sd_bus_message_exit_container(reply);
log_debug("sysview: stop");
- c->running = false;
- c->scanned = false;
- c->event_fn = NULL;
- c->userdata = NULL;
- c->scan_src = sd_event_source_unref(c->scan_src);
- context_ud_stop(c);
- context_ld_stop(c);
-
- /*
- * Event-callbacks are already cleared, hence we can safely ignore
- * return codes of the context_remove_*() helpers. They cannot be
- * originated from user-callbacks, so we already handled them.
- */
-
while ((device = hashmap_first(c->device_map)))
context_remove_device(c, device);
while ((seat = hashmap_first(c->seat_map)))
context_remove_seat(c, seat);
+
+ c->running = false;
+ c->scanned = false;
+ c->event_fn = NULL;
+ c->userdata = NULL;
+ c->scan_src = sd_event_source_unref(c->scan_src);
+ context_ud_stop(c);
+ context_ld_stop(c);
}
static int context_scan_fn(sd_event_source *s, void *userdata) {