summaryrefslogtreecommitdiff
path: root/src/main.cc
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@yahoo.com>2017-09-26 23:44:35 +0200
committerJoel Klinghed <the_jk@yahoo.com>2017-09-26 23:44:35 +0200
commiteff2e4cc49bfadd9716f3ad65854b3b0ca309b74 (patch)
treebafa49f7efcf39e9057b8f006c14d7f3a2a53e2d /src/main.cc
parent811e04305457108bc32d8895fd9bd274715d02fc (diff)
Animate job count changes
Diffstat (limited to 'src/main.cc')
-rw-r--r--src/main.cc104
1 files changed, 95 insertions, 9 deletions
diff --git a/src/main.cc b/src/main.cc
index c5d47fd..d3017d9 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -12,6 +12,8 @@
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_keysyms.h>
+#include "animation.hh"
+#include "animator.hh"
#include "args.hh"
#include "fake_monitor.hh"
#include "io.hh"
@@ -65,10 +67,11 @@ struct MwmHints {
uint32_t status;
};
-class MonMon : virtual Monitor::Observer {
+class MonMon : virtual Monitor::Observer, virtual Animator::Observer {
public:
explicit MonMon(std::shared_ptr<PollLooper> const& looper)
- : looper_(looper), connected_(false), depth_(0), black_pixel_(0),
+ : looper_(looper), animator_(Animator::create(looper)),
+ connected_(false), depth_(0), black_pixel_(0),
screen_(nullptr), max_jobs_(0), jobs_(0), requests_(0),
x_(0), y_(0), w_(0), h_(0),
rootpmap_(XCB_ATOM_NONE), desktop_window_(XCB_NONE),
@@ -77,9 +80,11 @@ public:
looper_->add(pipe_.read(), Looper::EV_READ,
std::bind(&MonMon::pipe, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3));
+ animator_->add_observer(this);
}
~MonMon() {
+ stop_all_animations();
unset_desktop_window();
close_pipe();
wnd_.reset();
@@ -179,6 +184,7 @@ public:
depth_ = format.depth;
black_pixel_ = screen->black_pixel;
update_desktop_window();
+
internal_draw();
xcb_map_window(wnd_.conn(), wnd_.get());
xcb_flush(wnd_.conn());
@@ -339,14 +345,22 @@ public:
}
private:
- struct Machine {
+ class MachineAnimation;
+
+ struct Machine : virtual Animator::AnimationObserver {
uint32_t id;
Monitor::Machine data;
unsigned jobs;
unsigned requests;
+ double x;
+ std::shared_ptr<MachineAnimation> animation;
explicit Machine(uint32_t id)
- : id(id), jobs(0), requests(0) {
+ : id(id), jobs(0), requests(0), x(0.0) {
+ }
+
+ ~Machine() override {
+ assert(!animation);
}
bool operator<(Machine const& machine) const {
@@ -354,6 +368,48 @@ private:
if (data.name > machine.data.name) return false;
return id < machine.id;
}
+
+ void ticked(Animator*, Animation*, double value) override {
+ x = value;
+ }
+
+ void stopped(Animator*, Animation*) override {
+ x = static_cast<double>(jobs) / data.max_jobs;
+ animation.reset();
+ }
+ };
+
+ class MachineAnimation : public Animation {
+ public:
+ explicit MachineAnimation(Machine* machine)
+ : machine_(machine), last_(0.0) {
+ }
+
+ bool tick(double duration, double* value) override {
+ auto target = static_cast<double>(machine_->jobs)
+ / machine_->data.max_jobs;
+ if (duration == 0.0) {
+ last_ = duration;
+ *value = machine_->x;
+ return machine_->x != target;
+ } else {
+ double diff = target - machine_->x;
+ double max = (duration - last_) * .5;
+ last_ = duration;
+ if (fabs(diff) > max) {
+ diff = diff < 0.0 ? -max : max;
+ *value = machine_->x + diff;
+ return true;
+ } else {
+ *value = target;
+ return false;
+ }
+ }
+ }
+
+ private:
+ Machine* machine_;
+ double last_;
};
void unset_desktop_window() {
@@ -453,6 +509,8 @@ private:
}
}
+ stop_all_animations();
+ animator_.reset();
monitor_->disconnect();
looper_->exit_when_empty();
close_pipe();
@@ -462,6 +520,7 @@ private:
switch (state) {
case Monitor::SEARCHING:
connected_ = false;
+ stop_all_animations();
machines_.clear();
max_jobs_ = 0;
jobs_ = 0;
@@ -476,19 +535,29 @@ private:
}
}
+ void stop_all_animations() {
+ if (!animator_) return;
+ for (auto& machine : machines_) {
+ if (machine.animation) animator_->stop(machine.animation.get());
+ }
+ }
+
void update(Machine& machine) {
auto old = machine.data.max_jobs;
machine.data = monitor_->machine(machine.id);
if (old < machine.data.max_jobs) {
max_jobs_ += machine.data.max_jobs - old;
+ if (machine.jobs) animate(machine);
} else if (old > machine.data.max_jobs) {
max_jobs_ -= old - machine.data.max_jobs;
+ if (machine.jobs) animate(machine);
}
}
void draw() {
- internal_draw();
- xcb_flush(wnd_.conn());
+ // Animator will draw soon anyway, so let it
+ if (animator_ && animator_->active()) return;
+ tick(nullptr);
}
static void rounded_path(cairo_t* cr, double x, double y,
@@ -543,14 +612,13 @@ private:
rounded_path(cairo_.get(), pad_x, y, box_width, box_height);
cairo_set_source_rgba(cairo_.get(), 0.1, 0.1, 0.1, 0.7);
- if (machine.jobs > 0) {
+ if (machine.x > 0.0) {
cairo_fill_preserve(cairo_.get());
auto old = std::unique_ptr<cairo_path_t, CairoPathDelete>(
cairo_copy_path(cairo_.get()));
cairo_new_path(cairo_.get());
cairo_rectangle(cairo_.get(), pad_x, y,
- (machine.jobs * box_width) / machine.data.max_jobs,
- box_height);
+ machine.x * box_width, box_height);
cairo_clip(cairo_.get());
cairo_append_path(cairo_.get(), old.get());
cairo_set_source(cairo_.get(), job_pattern_.get());
@@ -619,6 +687,7 @@ private:
max_jobs_ -= it->data.max_jobs;
requests_ -= it->requests;
jobs_ -= it->jobs;
+ if (animator_) animator_->stop(it->animation.get());
machines_.erase(it);
draw();
return;
@@ -632,6 +701,7 @@ private:
for (auto& machine : machines_) {
if (machine.id == source) {
++machine.jobs;
+ animate(machine);
}
}
} else {
@@ -641,6 +711,7 @@ private:
}
if (machine.id == target) {
++machine.jobs;
+ animate(machine);
}
}
++requests_;
@@ -654,6 +725,7 @@ private:
for (auto& machine : machines_) {
if (machine.id == source) {
--machine.jobs;
+ animate(machine);
}
}
} else {
@@ -663,6 +735,7 @@ private:
}
if (machine.id == target) {
--machine.jobs;
+ animate(machine);
}
}
--requests_;
@@ -671,8 +744,21 @@ private:
draw();
}
+ void tick(Animator*) override {
+ internal_draw();
+ xcb_flush(wnd_.conn());
+ }
+
+ void animate(Machine& machine) {
+ if (!animator_) return;
+ if (machine.animation) return;
+ machine.animation.reset(new MachineAnimation(&machine));
+ animator_->start(machine.animation, &machine);
+ }
+
std::shared_ptr<PollLooper> looper_;
std::unique_ptr<Monitor> monitor_;
+ std::unique_ptr<Animator> animator_;
bool connected_;
io::pipe pipe_;
std::shared_ptr<x::Atoms> atoms_;