Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 83 additions & 7 deletions src/autorotate-iio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extern "C"
{
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_seat.h>
#include <wayland-server-core.h>
}

using namespace Gio;
Expand Down Expand Up @@ -105,6 +106,12 @@ class WayfireAutorotateIIO : public wf::per_output_plugin_instance_t
/* Transform coming from the iio-sensors, -1 means not set */
int32_t sensor_transform = -1;

/* Debounce: pending transform waiting to be confirmed stable */
int32_t pending_transform = -1;
guint debounce_timer_id = 0;
static constexpr guint DEBOUNCE_ROTATE_MS = 500;
static constexpr guint DEBOUNCE_NORMAL_MS = 1200;

bool on_rotate_binding(int32_t target_rotation)
{
if (!output->can_activate_plugin(&grab_interface))
Expand Down Expand Up @@ -154,10 +161,18 @@ class WayfireAutorotateIIO : public wf::per_output_plugin_instance_t
return true;
}

wf::effect_hook_t on_frame = [=] ()
/* Wayland event loop timer — fires every 50ms to pump the GLib main context
* even when the display is idle and on_frame would not run. */
wl_event_source *glib_timer = nullptr;

static int glib_timer_cb(void *data)
{
auto *self = static_cast<WayfireAutorotateIIO*>(data);
Glib::MainContext::get_default()->iteration(false);
};
wl_event_source_timer_update(self->glib_timer, 50);
return 0;
}

Glib::RefPtr<Glib::MainLoop> loop;

public:
Expand Down Expand Up @@ -185,7 +200,10 @@ class WayfireAutorotateIIO : public wf::per_output_plugin_instance_t
Gio::init();

loop = Glib::MainLoop::create(true);
output->render->add_effect(&on_frame, wf::OUTPUT_EFFECT_PRE);

auto *evloop = wl_display_get_event_loop(wf::get_core().display);
glib_timer = wl_event_loop_add_timer(evloop, glib_timer_cb, this);
wl_event_source_timer_update(glib_timer, 50);

watch_id = DBus::watch_name(DBus::BUS_TYPE_SYSTEM, "net.hadess.SensorProxy",
sigc::mem_fun(this, &WayfireAutorotateIIO::on_iio_appeared),
Expand All @@ -210,6 +228,7 @@ class WayfireAutorotateIIO : public wf::per_output_plugin_instance_t
iio_proxy->signal_properties_changed().connect_notify(
sigc::mem_fun(this, &WayfireAutorotateIIO::on_properties_changed));
iio_proxy->call_sync("ClaimAccelerometer");
update_orientation();
}

void on_properties_changed(
Expand All @@ -228,6 +247,11 @@ class WayfireAutorotateIIO : public wf::per_output_plugin_instance_t

Glib::Variant<Glib::ustring> orientation;
iio_proxy->get_cached_property(orientation, "AccelerometerOrientation");
if (!orientation)
{
return;
}

LOGI("IIO Accelerometer orientation: %s", orientation.get().c_str());

static const std::map<std::string, wl_output_transform> transform_by_name =
Expand All @@ -238,10 +262,55 @@ class WayfireAutorotateIIO : public wf::per_output_plugin_instance_t
{"bottom-up", WL_OUTPUT_TRANSFORM_180},
};

if (transform_by_name.count(orientation.get()))
if (!transform_by_name.count(orientation.get()))
{
sensor_transform = transform_by_name.find(orientation.get())->second;
update_transform();
return;
}

int32_t new_transform = transform_by_name.find(orientation.get())->second;

bool timer_running = (debounce_timer_id != 0);
bool new_is_normal = (new_transform == WL_OUTPUT_TRANSFORM_NORMAL);
bool pend_is_normal = (pending_transform == WL_OUTPUT_TRANSFORM_NORMAL);

if (!timer_running)
{
if (new_transform == sensor_transform)
{
return;
}

pending_transform = new_transform;
guint delay = new_is_normal ? DEBOUNCE_NORMAL_MS : DEBOUNCE_ROTATE_MS;
debounce_timer_id = g_timeout_add(delay, [] (gpointer data) -> gboolean
{
auto *self = static_cast<WayfireAutorotateIIO*>(data);
self->debounce_timer_id = 0;
self->sensor_transform = self->pending_transform;
self->update_transform();
return G_SOURCE_REMOVE;
}, this);
} else if (!pend_is_normal)
{
if (!new_is_normal)
{
pending_transform = new_transform;
}
} else
{
if (!new_is_normal)
{
g_source_remove(debounce_timer_id);
pending_transform = new_transform;
debounce_timer_id = g_timeout_add(DEBOUNCE_ROTATE_MS, [] (gpointer data) -> gboolean
{
auto *self = static_cast<WayfireAutorotateIIO*>(data);
self->debounce_timer_id = 0;
self->sensor_transform = self->pending_transform;
self->update_transform();
return G_SOURCE_REMOVE;
}, this);
}
}
}

Expand All @@ -259,13 +328,20 @@ class WayfireAutorotateIIO : public wf::per_output_plugin_instance_t
output->rem_binding(&on_rotate_up);
output->rem_binding(&on_rotate_down);

if (debounce_timer_id)
{
g_source_remove(debounce_timer_id);
debounce_timer_id = 0;
}

/* If loop is NULL, autorotate was disabled for the current output */
if (loop)
{
iio_proxy.reset();
DBus::unwatch_name(watch_id);
loop->quit();
output->render->rem_effect(&on_frame);
wl_event_source_remove(glib_timer);
glib_timer = nullptr;
}
}
};
Expand Down
Loading