Toast notification daemon
This commit is contained in:
parent
c31bedd69e
commit
1b3dcea6a1
BIN
hdd/usr/share/ttk/toast/default.png
Normal file
BIN
hdd/usr/share/ttk/toast/default.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
39
userspace/extra/toast.c
Normal file
39
userspace/extra/toast.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/pex.h"
|
||||
#include "lib/toastd.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "%s: \"title\" \"message\"\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char * server = getenv("TOASTD");
|
||||
|
||||
if (!server) {
|
||||
server = "toastd"; /* Appropriate fallback */
|
||||
}
|
||||
|
||||
FILE * c = pex_connect(server);
|
||||
|
||||
if (!c) {
|
||||
fprintf(stderr, "%s: Could not connect to toast daemon.\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int size = strlen(argv[1]) + strlen(argv[2]) + 2 + sizeof(notification_t);
|
||||
|
||||
notification_t * note = malloc(size);
|
||||
|
||||
note->ttl = 5; /* seconds */
|
||||
|
||||
memcpy(note->strings, argv[1], strlen(argv[1])+1);
|
||||
memcpy(note->strings + strlen(argv[1])+1, argv[2], strlen(argv[2])+1);
|
||||
|
||||
pex_reply(c, size, (void*)note);
|
||||
|
||||
return 0;
|
||||
}
|
@ -64,6 +64,11 @@ int main(int argc, char * argv[]) {
|
||||
char * args[] = {"/bin/panel", NULL};
|
||||
execvp(args[0], args);
|
||||
}
|
||||
int _toastd_pid = fork();
|
||||
if (!_toastd_pid) {
|
||||
char * args[] = {"/bin/toastd", NULL};
|
||||
execvp(args[0], args);
|
||||
}
|
||||
|
||||
syscall_wait(_panel_pid);
|
||||
|
||||
|
194
userspace/gui/core/toastd.c
Normal file
194
userspace/gui/core/toastd.c
Normal file
@ -0,0 +1,194 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*
|
||||
* Toast (Notification) Daemon
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "lib/yutani.h"
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/shmemfonts.h"
|
||||
#include "lib/pex.h"
|
||||
#include "lib/pthread.h"
|
||||
#include "lib/spinlock.h"
|
||||
|
||||
#include "lib/toastd.h"
|
||||
|
||||
static yutani_t * yctx;
|
||||
static list_t * notifications;
|
||||
static FILE * toastd_server;
|
||||
static int notification_lock = 0;
|
||||
static int exit_app = 0;
|
||||
static sprite_t * toast_bg;
|
||||
|
||||
#define TOASTD_NAME "toastd"
|
||||
|
||||
#define TOAST_WIDTH 310
|
||||
#define TOAST_HEIGHT 110
|
||||
#define TOAST_PAD 20
|
||||
|
||||
typedef struct {
|
||||
int ttl;
|
||||
char * title;
|
||||
char * content;
|
||||
yutani_window_t * window;
|
||||
int stack;
|
||||
} notification_int_t;
|
||||
|
||||
static void add_toast(notification_t * incoming) {
|
||||
notification_int_t * toast = malloc(sizeof(notification_int_t));
|
||||
|
||||
toast->ttl = incoming->ttl + time(NULL);
|
||||
toast->title = strdup(incoming->strings);
|
||||
toast->content = strdup(incoming->strings + 1 + strlen(incoming->strings));
|
||||
|
||||
fprintf(stderr, "ttl=%d, title=\"%s\" content=\"%s\"\n", toast->ttl, toast->title, toast->content);
|
||||
|
||||
spin_lock(¬ification_lock);
|
||||
|
||||
toast->window = yutani_window_create(yctx, TOAST_WIDTH, TOAST_HEIGHT);
|
||||
|
||||
/* Find best location */
|
||||
int i = 0, hit_something = 1;
|
||||
while (hit_something) {
|
||||
hit_something = 0;
|
||||
foreach(node, notifications) {
|
||||
notification_int_t * toast = node->value;
|
||||
if (toast->stack == i) {
|
||||
i++;
|
||||
hit_something = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toast->stack = i;
|
||||
|
||||
yutani_window_move(yctx, toast->window, yctx->display_width - TOAST_WIDTH - 20, 30 + (TOAST_HEIGHT + TOAST_PAD) * i);
|
||||
|
||||
gfx_context_t * ctx = init_graphics_yutani(toast->window);
|
||||
draw_sprite(ctx, toast_bg, 0, 0);
|
||||
|
||||
set_font_face(FONT_SANS_SERIF_BOLD);
|
||||
set_font_size(14);
|
||||
draw_string(ctx, 20, 22, rgb(255,255,255), toast->title);
|
||||
|
||||
char * str = toast->content;
|
||||
char * end = toast->content + strlen(toast->content);
|
||||
unsigned int line = 0;
|
||||
while (str) {
|
||||
|
||||
char * next = strstr(str, "\n");
|
||||
if (next) {
|
||||
next[0] = '\0';
|
||||
next++;
|
||||
}
|
||||
|
||||
set_font_face(FONT_SANS_SERIF);
|
||||
set_font_size(12);
|
||||
draw_string(ctx, 20, 40 + line * 14, rgb(255,255,255), str);
|
||||
|
||||
str = next;
|
||||
line++;
|
||||
}
|
||||
|
||||
free(ctx);
|
||||
yutani_flip(yctx, toast->window);
|
||||
|
||||
list_insert(notifications, toast);
|
||||
|
||||
spin_unlock(¬ification_lock);
|
||||
}
|
||||
|
||||
static void * toastd_handler(void * garbage) {
|
||||
(void)garbage;
|
||||
|
||||
setenv("TOASTD", TOASTD_NAME, 1);
|
||||
toastd_server = pex_bind(TOASTD_NAME);
|
||||
|
||||
while (!exit_app) {
|
||||
pex_packet_t * p = calloc(PACKET_SIZE, 1);
|
||||
pex_listen(toastd_server, p);
|
||||
|
||||
notification_t * toast = (void *)p->data;
|
||||
add_toast(toast);
|
||||
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
static void * closer_handler(void * garbage) {
|
||||
while (!exit_app) {
|
||||
time_t now = time(NULL);
|
||||
|
||||
spin_lock(¬ification_lock);
|
||||
|
||||
list_t * tmp = list_create();
|
||||
|
||||
foreach(node, notifications) {
|
||||
notification_int_t * toast = node->value;
|
||||
if (toast->window && toast->ttl <= now) {
|
||||
yutani_close(yctx, toast->window);
|
||||
free(toast->title);
|
||||
free(toast->content);
|
||||
list_insert(tmp, node);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(node, tmp) {
|
||||
list_delete(notifications, node->value);
|
||||
}
|
||||
list_free(tmp);
|
||||
free(tmp);
|
||||
spin_unlock(¬ification_lock);
|
||||
|
||||
usleep(500000);
|
||||
}
|
||||
|
||||
foreach(node, notifications) {
|
||||
notification_int_t * toast = node->value;
|
||||
|
||||
if (toast->window) {
|
||||
yutani_close(yctx, toast->window);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char ** argv) {
|
||||
yctx = yutani_init();
|
||||
|
||||
notifications = list_create();
|
||||
|
||||
toast_bg = malloc(sizeof(sprite_t));
|
||||
load_sprite_png(toast_bg, "/usr/share/ttk/toast/default.png");
|
||||
|
||||
init_shmemfonts();
|
||||
|
||||
pthread_t toastd_thread;
|
||||
pthread_create(&toastd_thread, NULL, toastd_handler, NULL);
|
||||
|
||||
pthread_t closer_thread;
|
||||
pthread_create(&closer_thread, NULL, closer_handler, NULL);
|
||||
|
||||
while (!exit_app) {
|
||||
yutani_msg_t * m = yutani_poll(yctx);
|
||||
if (m) {
|
||||
switch (m->type) {
|
||||
case YUTANI_MSG_SESSION_END:
|
||||
exit_app = 1;
|
||||
break;
|
||||
}
|
||||
free(m);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_kill(toastd_thread, SIGWINCH);
|
||||
pthread_kill(closer_thread, SIGWINCH);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <syscall.h>
|
||||
#include <signal.h>
|
||||
#include "pthread.h"
|
||||
|
||||
#define PTHREAD_STACK_SIZE 0x100000
|
||||
@ -20,6 +21,10 @@ int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_rout
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_kill(pthread_t thread, int sig) {
|
||||
return kill(thread.id, sig);
|
||||
}
|
||||
|
||||
void pthread_exit(void * value) {
|
||||
/* Perform nice cleanup */
|
||||
#if 0
|
||||
|
@ -13,6 +13,7 @@ typedef unsigned int pthread_attr_t;
|
||||
|
||||
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
|
||||
void pthread_exit(void * value);
|
||||
int pthread_kill(pthread_t thread, int sig);
|
||||
|
||||
int clone(uintptr_t,uintptr_t,void*);
|
||||
int gettid();
|
||||
|
16
userspace/lib/spinlock.h
Normal file
16
userspace/lib/spinlock.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef _SPINLOCK_H_
|
||||
#define _SPINLOCK_H_
|
||||
|
||||
#ifndef spin_lock
|
||||
static void spin_lock(int volatile * lock) {
|
||||
while(__sync_lock_test_and_set(lock, 0x01)) {
|
||||
syscall_yield();
|
||||
}
|
||||
}
|
||||
|
||||
static void spin_unlock(int volatile * lock) {
|
||||
__sync_lock_release(lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SPINLOCK_H */
|
9
userspace/lib/toastd.h
Normal file
9
userspace/lib/toastd.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef _TOASTD_H_
|
||||
#define _TOASTD_H_
|
||||
|
||||
typedef struct {
|
||||
unsigned int ttl;
|
||||
char strings[];
|
||||
} notification_t;
|
||||
|
||||
#endif /* _TOASTD_H_ */
|
Loading…
Reference in New Issue
Block a user