diff --git a/README b/README index 92b2e69..e3f462f 100644 --- a/README +++ b/README @@ -17,4 +17,3 @@ The following features are missing from this fork for now: - Neko does not yet behave differently at night. - Idle detection is working but implemented sloppily. - Pointer following is currently removed. -- Waking up Neko with a signal is something that should be possible. diff --git a/wayneko.1 b/wayneko.1 index dce4503..b976cb8 100644 --- a/wayneko.1 +++ b/wayneko.1 @@ -111,6 +111,15 @@ close the surface for a different reason. .RE . . +.SH SIGNALS +.P +\fBSIGUSR1\fR +.RS +You can send `wayneko` this signal to wake Neko up spontaneously. Neko won't notice +anything it she is already awake. Example: `pkill -10 wayneko` +.RE +. +. .SH AUTHOR .P Original code by diff --git a/wayneko.c b/wayneko.c index b83fe09..72da222 100644 --- a/wayneko.c +++ b/wayneko.c @@ -99,6 +99,8 @@ uint32_t phase_sleep_max = 1800; uint32_t phase_awake_min = 120; uint32_t phase_awake_max = 600; +bool wakeup_shock = false; /* will force a shock, used when woken up */ + struct Seat { struct wl_list link; @@ -230,6 +232,8 @@ static void handle_term (int signum) loop = false; } +static void wakeup(int signum); + /** * Set up signal handlers. */ @@ -240,6 +244,8 @@ static void init_signals (void) signal(SIGINT, handle_term); signal(SIGTERM, handle_term); + + signal(SIGUSR1, wakeup); } /************ @@ -930,6 +936,14 @@ static bool animation_next_state_with_hotspot (uint32_t x) /** Returns true if new frame is needed. */ static bool animation_next_state_awake (void) { + /* neko was just suddenly woken up */ + if (wakeup_shock) { + animation_neko_do_shock(); + + wakeup_shock = false; + return true; + } + switch (current_neko) { case NEKO_STARE: switch (rand() % 24) @@ -1044,6 +1058,16 @@ static void check_phase(void) { } } +/** called as a signal handler to wake up neko */ +static void wakeup(int signum) { + // already awake + if (current_phase == PHASE_AWAKE) return; + + animation_ticks_until_next_frame = 0; + ticks_until_phase_change = 0; // will trigger a phase change to awake + wakeup_shock = true; +} + /** Returns true if new frame is needed. */ static bool animation_next_state (void) { @@ -1578,6 +1602,7 @@ int main (int argc, char *argv[]) } } + /* Flush pending Wayland events/requests. */ while ( wl_display_prepare_read(wl_display) != 0 ) { @@ -1588,6 +1613,7 @@ int main (int argc, char *argv[]) goto exit_main_loop; } } + while (true) { /* Returns the amount of bytes flushed. */ @@ -1606,11 +1632,12 @@ int main (int argc, char *argv[]) if ( poll(pollfds, 1, current_timeout) < 0 ) { - if ( errno == EINTR ) /* Interrupt: Signal received. */ - continue; - fprintf(stderr, "ERROR: poll(): %s.\n", strerror(errno)); - ret = EXIT_FAILURE; - break; + if ( errno != EINTR ) { + /* Interrupt is NOT a signal */ + fprintf(stderr, "ERROR: poll(): %s.\n", strerror(errno)); + ret = EXIT_FAILURE; + break; + } } if ( wl_display_read_events(wl_display) == -1 ) @@ -1618,6 +1645,7 @@ int main (int argc, char *argv[]) fprintf(stderr, "ERROR: wl_display_read_events(): %s.\n", strerror(errno)); break; } + if ( wl_display_dispatch_pending(wl_display) == -1 ) { fprintf(stderr, "ERROR: wl_display_dispatch_pending(): %s.\n", strerror(errno));