summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/misc.c16
-rw-r--r--src/misc.h4
-rw-r--r--src/render.c4
-rw-r--r--src/wlclock.c299
-rw-r--r--src/wlclock.h10
5 files changed, 285 insertions, 48 deletions
diff --git a/src/misc.c b/src/misc.c
index dd4500d..289e00d 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1,3 +1,4 @@
+#include<stdbool.h>
#include<stdarg.h>
#include<stdio.h>
#include<stdlib.h>
@@ -28,3 +29,18 @@ void clocklog (struct Wlclock *clock, int level, const char *fmt, ...)
vfprintf(stderr, fmt, args);
va_end(args);
}
+
+bool is_boolean_true (const char *in)
+{
+ if ( ! strcmp(in, "true") || ! strcmp(in, "yes") || ! strcmp(in, "on") || ! strcmp(in, "1") )
+ return true;
+ return false;
+}
+
+bool is_boolean_false (const char *in)
+{
+ if ( ! strcmp(in, "false") || ! strcmp(in, "no") || ! strcmp(in, "off") || ! strcmp(in, "0") )
+ return true;
+ return false;
+}
+
diff --git a/src/misc.h b/src/misc.h
index f262771..477841f 100644
--- a/src/misc.h
+++ b/src/misc.h
@@ -1,10 +1,14 @@
#ifndef WLCLOCK_MISC_H
#define WLCLOCK_MISC_H
+#include<stdbool.h>
+
struct Wlclock;
void free_if_set (void *ptr);
void set_string (char **ptr, char *arg);
void clocklog (struct Wlclock *clock, int level, const char *fmt, ...);
+bool is_boolean_true (const char *in);
+bool is_boolean_false (const char *in);
#endif
diff --git a/src/render.c b/src/render.c
index bd3d91e..2b3d626 100644
--- a/src/render.c
+++ b/src/render.c
@@ -62,7 +62,6 @@ static void draw_background (cairo_t *cairo,
}
else
{
- fputs("here\n", stderr);
/* Calculate dimensions of center. */
uint32_t cx = x + border_left,
cy = y + border_top,
@@ -146,7 +145,8 @@ void render_surface_frame (struct Wlclock_surface *surface)
clock->radius_bottom_left, clock->radius_bottom_right,
scale, &clock->background_colour, &clock->border_colour);
- // TODO draw clock stuff
+ // TODO draw clock face
+ // TODO draw clock hands to subsurface
wl_surface_set_buffer_scale(surface->surface, scale);
wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0);
diff --git a/src/wlclock.c b/src/wlclock.c
index 1fad08f..9269e31 100644
--- a/src/wlclock.c
+++ b/src/wlclock.c
@@ -6,11 +6,8 @@
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
-
-#if HANDLE_SIGNALS
#include<sys/signalfd.h>
#include<signal.h>
-#endif
#include<wayland-server.h>
#include<wayland-client.h>
@@ -135,6 +132,9 @@ static bool init_wayland (struct Wlclock *clock)
/* Finish him! */
static void finish_wayland (struct Wlclock *clock)
{
+ if ( clock->display == NULL )
+ return;
+
clocklog(clock, 1, "[main] Finish Wayland.\n");
destroy_all_outputs(clock);
@@ -149,11 +149,22 @@ static void finish_wayland (struct Wlclock *clock)
if ( clock->registry != NULL )
wl_registry_destroy(clock->registry);
- if ( clock->display != NULL )
+ clocklog(clock, 2, "[main] Diconnecting from server.\n");
+ wl_display_disconnect(clock->display);
+}
+
+static int count_args (int index, int argc, char *argv[])
+{
+ index--;
+ int args = 0;
+ while ( index < argc )
{
- clocklog(clock, 2, "[main] Diconnecting from server.\n");
- wl_display_disconnect(clock->display);
+ if ( *argv[index] == '-' )
+ break;
+ args++;
+ index++;
}
+ return args;
}
static bool handle_command_flags (struct Wlclock *clock, int argc, char *argv[])
@@ -199,7 +210,7 @@ static bool handle_command_flags (struct Wlclock *clock, int argc, char *argv[])
" --size Size of the clock.\n"
"\n";
- int opt;
+ int opt, args;
extern int optind;
extern char *optarg;
while ( (opt = getopt_long(argc, argv, "hvV", opts, &optind)) != -1 ) switch (opt)
@@ -218,31 +229,127 @@ static bool handle_command_flags (struct Wlclock *clock, int argc, char *argv[])
clock->ret = EXIT_SUCCESS;
return false;
- case 1100: // TODO anchor
+ case 1100: /* Anchor */
+ args = count_args(optind, argc, argv);
+ if ( args != 4 )
+ {
+ clocklog(NULL, 0, "ERROR: Anchor configuration requires four arguments.\n");
+ return false;
+ }
+ if (is_boolean_true(argv[optind-1]))
+ clock->anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
+ if (is_boolean_true(argv[optind]))
+ clock->anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
+ if (is_boolean_true(argv[optind+1]))
+ clock->anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
+ if (is_boolean_true(argv[optind+2]))
+ clock->anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
+ optind += 3; /* Tell getopt() to skip three argv fields. */
break;
case 1101: /* Background colour */
- colour_from_string(&clock->background_colour, optarg);
+ if (! colour_from_string(&clock->background_colour, optarg))
+ return false;
break;
case 1102: /* Border colour */
- colour_from_string(&clock->border_colour, optarg);
+ if (! colour_from_string(&clock->border_colour, optarg))
+ return false;
break;
- case 1103: // TODO border size
+ case 1103: /* Border size */
+ args = count_args(optind, argc, argv);
+ if ( args == 1 )
+ clock->border_top = clock->border_right =
+ clock->border_bottom = clock->border_left =
+ atoi(optarg);
+ else if ( args == 4 )
+ {
+ clock->border_top = atoi(argv[optind-1]);
+ clock->border_right = atoi(argv[optind]);
+ clock->border_bottom = atoi(argv[optind+1]);
+ clock->border_left = atoi(argv[optind+2]);
+ optind += 3; /* Tell getopt() to skip three argv fields. */
+ }
+ else
+ {
+ clocklog(NULL, 0, "ERROR: Border configuration "
+ "requires one or four arguments.\n");
+ return false;
+ }
+ if ( clock->border_top < 0 || clock->border_right < 0
+ || clock->border_bottom < 0 || clock->border_left < 0 )
+ {
+ clocklog(NULL, 0, "ERROR: Borders may not be smaller than zero.\n");
+ return false;
+ }
break;
case 1104: /* Clock colour */
- colour_from_string(&clock->clock_colour, optarg);
+ if (! colour_from_string(&clock->clock_colour, optarg))
+ return false;
break;
- case 1105: // TODO exclusive zone
+ case 1105: /* Exclusive zone */
+ if (is_boolean_true(optarg))
+ clock->exclusive_zone = 1;
+ else if (is_boolean_false(optarg))
+ clock->exclusive_zone = 0;
+ else if (! strcmp(optarg, "stationary"))
+ clock->exclusive_zone = -1;
+ else
+ {
+ clocklog(NULL, 0, "ERROR: Unrecognized exclusive zone option \"%s\".\n"
+ "INFO: Possible options are 'true', "
+ "'false' and 'stationary'.\n", optarg);
+ return false;
+ }
break;
- case 1106: // TODO layer
+ case 1106: /* Layer */
+ if (! strcmp(optarg, "overlay"))
+ clock->layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
+ else if (! strcmp(optarg, "top"))
+ clock->layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
+ else if (! strcmp(optarg, "bottom"))
+ clock->layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
+ else if (! strcmp(optarg, "background"))
+ clock->layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND;
+ else
+ {
+ clocklog(NULL, 0, "ERROR: Unrecognized layer \"%s\".\n"
+ "INFO: Possible layers are 'overlay', "
+ "'top', 'bottom', and 'background'.\n", optarg);
+ return false;
+ }
break;
- case 1107: // TODO margins
+ case 1107: /* Margins */
+ args = count_args(optind, argc, argv);
+ if ( args == 1 )
+ clock->margin_top = clock->margin_right =
+ clock->margin_bottom = clock->margin_left =
+ atoi(optarg);
+ else if ( args == 4 )
+ {
+ clock->margin_top = atoi(argv[optind-1]);
+ clock->margin_right = atoi(argv[optind]);
+ clock->margin_bottom = atoi(argv[optind+1]);
+ clock->margin_left = atoi(argv[optind+2]);
+ optind += 3; /* Tell getopt() to skip three argv fields. */
+ }
+ else
+ {
+ clocklog(NULL, 0, "ERROR: Margin configuration "
+ "requires one or four arguments.\n");
+ return false;
+ }
+ if ( clock->margin_top < 0 || clock->margin_right < 0
+ || clock->margin_bottom < 0 || clock->margin_left < 0 )
+ {
+ clocklog(NULL, 0, "ERROR: Margins may not be smaller than zero.\n");
+ return false;
+ }
break;
case 1108: /* Namespace */
@@ -257,10 +364,42 @@ static bool handle_command_flags (struct Wlclock *clock, int argc, char *argv[])
set_string(&clock->output, optarg);
break;
- case 1111: // TODO corner radii
+ case 1111: /* Corner radii */
+ args = count_args(optind, argc, argv);
+ if ( args == 1 )
+ clock->radius_top_left = clock->radius_top_right =
+ clock->radius_bottom_right = clock->radius_bottom_left =
+ atoi(optarg);
+ else if ( args == 4 )
+ {
+ clock->radius_top_left = atoi(argv[optind-1]);
+ clock->radius_top_right = atoi(argv[optind]);
+ clock->radius_bottom_right = atoi(argv[optind+1]);
+ clock->radius_bottom_left = atoi(argv[optind+2]);
+ optind += 3; /* Tell getopt() to skip three argv fields. */
+ }
+ else
+ {
+ clocklog(NULL, 0, "ERROR: Radius configuration "
+ "requires one or four arguments.\n");
+ return false;
+ }
+ if ( clock->radius_top_left < 0 || clock->radius_top_right < 0
+ || clock->radius_bottom_right < 0 || clock->radius_bottom_left < 0 )
+ {
+ clocklog(NULL, 0, "ERROR: Radii may not be smaller than zero.\n");
+ return false;
+ }
break;
- case 1112: // TODO size
+ case 1112: /* Size */
+ clock->size = atoi(optarg);
+ if ( clock->size <= 10 )
+ {
+ clocklog(NULL, 0, "ERROR: Unreasonably small size \"%d\".\n",
+ clock->size);
+ return false;
+ }
break;
default:
@@ -272,18 +411,46 @@ static bool handle_command_flags (struct Wlclock *clock, int argc, char *argv[])
static time_t get_timeout (time_t now)
{
+ /* Timeout until the next minute. */
return ((now / 60 * 60 ) + 60 - now) * 1000;
}
static void clock_run (struct Wlclock *clock)
{
clocklog(clock, 1, "[main] Starting loop.\n");
-
clock->ret = EXIT_SUCCESS;
- struct pollfd fds[] = {
- { .fd = wl_display_get_fd(clock->display), .events = POLLIN }
- };
+ struct pollfd fds[2] = { 0 };
+ size_t wayland_fd = 0;
+ size_t signal_fd = 1;
+
+ fds[wayland_fd].events = POLLIN;
+ if ( -1 == (fds[wayland_fd].fd = wl_display_get_fd(clock->display)) )
+ {
+ clocklog(NULL, 0, "ERROR: Unable to open Wayland display fd.\n");
+ goto error;
+ }
+
+ sigset_t mask;
+ struct signalfd_siginfo fdsi;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGUSR1);
+ sigaddset(&mask, SIGUSR2);
+ if ( sigprocmask(SIG_BLOCK, &mask, NULL) == -1 )
+ {
+ clocklog(NULL, 0, "ERROR: sigprocmask() failed.\n");
+ goto error;
+ }
+ fds[signal_fd].events = POLLIN;
+ if ( -1 == (fds[signal_fd].fd = signalfd(-1, &mask, 0)) )
+ {
+ clocklog(NULL, 0, "ERROR: Unable to open signal fd.\n"
+ "ERROR: signalfd: %s\n", strerror(errno));
+ goto error;
+ }
while (clock->loop)
{
@@ -299,59 +466,107 @@ static void clock_run (struct Wlclock *clock)
} while ( errno == EAGAIN );
clock->now = time(NULL);
- errno = 0;
- int ret = poll(fds, 1, get_timeout(clock->now));
+ int ret = poll(fds, 2, get_timeout(clock->now));
if ( ret == 0 )
+ {
update_all_surfaces(clock);
- else if ( ret > 0 )
+ continue;
+ }
+ else if ( ret < 0 )
{
- if ( fds[0].revents & POLLIN && wl_display_dispatch(clock->display) == -1 )
+ clocklog(NULL, 0, "ERROR: poll: %s\n", strerror(errno));
+ continue;
+ }
+
+ /* Wayland events */
+ if ( fds[wayland_fd].revents & POLLIN && wl_display_dispatch(clock->display) == -1 )
+ {
+ clocklog(NULL, 0, "ERROR: wl_display_flush: %s\n", strerror(errno));
+ goto error;
+ }
+ if ( fds[wayland_fd].revents & POLLOUT && wl_display_flush(clock->display) == -1 )
+ {
+ clocklog(NULL, 0, "ERROR: wl_display_flush: %s\n", strerror(errno));
+ goto error;
+ }
+
+ /* Signal events. */
+ if ( fds[signal_fd].revents & POLLIN )
+ {
+ if ( read(fds[signal_fd].fd, &fdsi, sizeof(struct signalfd_siginfo))
+ != sizeof(struct signalfd_siginfo) )
{
- clocklog(NULL, 0, "ERROR: wl_display_flush: %s\n", strerror(errno));
+ clocklog(NULL, 0, "ERROR: Can not read signal info.\n");
goto error;
}
- if ( fds[0].revents & POLLOUT && wl_display_flush(clock->display) == -1 )
+
+ if ( fdsi.ssi_signo == SIGINT || fdsi.ssi_signo == SIGQUIT || fdsi.ssi_signo == SIGTERM )
{
- clocklog(NULL, 0, "ERROR: wl_display_flush: %s\n", strerror(errno));
- goto error;
+ clocklog(clock, 1, "[main] Received SIGINT, SIGQUIT or SIGTERM; Exiting.\n");
+ goto exit;
}
+ else if ( fdsi.ssi_signo == SIGUSR1 || fdsi.ssi_signo == SIGUSR2 )
+ clocklog(clock, 1, "[main] Received SIGUSR; Ignoring.\n");
}
- else
- clocklog(NULL, 0, "ERROR: poll: %s\n", strerror(errno));
}
return;
error:
clock->ret = EXIT_FAILURE;
+exit:
+ if ( fds[wayland_fd].fd != -1 )
+ close(fds[wayland_fd].fd);
+ if ( fds[signal_fd].fd != -1 )
+ close(fds[signal_fd].fd);
return;
}
int main (int argc, char *argv[])
{
struct Wlclock clock = { 0 };
+ wl_list_init(&clock.outputs);
clock.ret = EXIT_FAILURE;
clock.loop = true;
clock.verbosity = 0;
- clock.size = 100;
- clock.exclusive_zone = 1;
+
+ clock.size = 165; /* About the size of xclock, at least on my machine. */
+ clock.exclusive_zone = -1;
clock.input = true;
- clock.layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
- clock.anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
+ clock.layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
+ clock.anchor = 0; /* Center */
set_string(&clock.namespace, "wlclock");
- wl_list_init(&clock.outputs);
clock.border_bottom = clock.border_top
= clock.border_left = clock.border_right = 1;
clock.radius_bottom_left = clock.radius_bottom_right
- = clock.radius_top_left = clock.radius_top_right = 5;
+ = clock.radius_top_left = clock.radius_top_right = 0;
clock.margin_bottom = clock.margin_top
= clock.margin_left = clock.margin_right = 0;
- colour_from_string(&clock.background_colour, "#000000");
- colour_from_string(&clock.border_colour, "#FFFFFF");
- colour_from_string(&clock.clock_colour, "#FFFFFF");
+ colour_from_string(&clock.background_colour, "#FFFFFF");
+ colour_from_string(&clock.border_colour, "#000000");
+ colour_from_string(&clock.clock_colour, "#000000");
if (! handle_command_flags(&clock, argc, argv))
- return clock.ret;
+ goto exit;
+
+ if ( clock.border_bottom > clock.size / 3
+ || clock.border_top > clock.size / 3
+ || clock.border_left > clock.size / 3
+ || clock.border_right > clock.size / 3 )
+ {
+ clocklog(NULL, 0, "ERROR: Corner radii may not be larger than "
+ "half the clock size.\n");
+ goto exit;
+ }
+ if ( clock.radius_bottom_left > clock.size / 2
+ || clock.radius_bottom_right > clock.size / 2
+ || clock.radius_top_left > clock.size / 2
+ || clock.radius_top_right > clock.size / 2 )
+ {
+ clocklog(NULL, 0, "ERROR: Corner radii may not be larger than "
+ "half the clock size.\n");
+ goto exit;
+ }
clocklog(&clock, 1, "[main] wlclock: version=%s\n", VERSION);
@@ -362,6 +577,8 @@ int main (int argc, char *argv[])
exit:
finish_wayland(&clock);
+ free_if_set(clock.output);
+ free_if_set(clock.namespace);
return clock.ret;
}
diff --git a/src/wlclock.h b/src/wlclock.h
index 78b5c41..d051b7c 100644
--- a/src/wlclock.h
+++ b/src/wlclock.h
@@ -29,13 +29,13 @@ struct Wlclock
int ret;
enum zwlr_layer_shell_v1_layer layer;
- uint32_t size;
+ int32_t size;
char *namespace;
int32_t exclusive_zone;
- uint32_t border_top, border_right, border_bottom, border_left;
- uint32_t margin_top, margin_right, margin_bottom, margin_left;
- uint32_t radius_top_left, radius_top_right, radius_bottom_left, radius_bottom_right;
- uint32_t anchor;
+ int32_t border_top, border_right, border_bottom, border_left;
+ int32_t margin_top, margin_right, margin_bottom, margin_left;
+ int32_t radius_top_left, radius_top_right, radius_bottom_left, radius_bottom_right;
+ int32_t anchor;
bool input;
struct Wlclock_colour background_colour;