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};
|
char * args[] = {"/bin/panel", NULL};
|
||||||
execvp(args[0], args);
|
execvp(args[0], args);
|
||||||
}
|
}
|
||||||
|
int _toastd_pid = fork();
|
||||||
|
if (!_toastd_pid) {
|
||||||
|
char * args[] = {"/bin/toastd", NULL};
|
||||||
|
execvp(args[0], args);
|
||||||
|
}
|
||||||
|
|
||||||
syscall_wait(_panel_pid);
|
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 <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
|
#include <signal.h>
|
||||||
#include "pthread.h"
|
#include "pthread.h"
|
||||||
|
|
||||||
#define PTHREAD_STACK_SIZE 0x100000
|
#define PTHREAD_STACK_SIZE 0x100000
|
||||||
@ -20,6 +21,10 @@ int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_rout
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pthread_kill(pthread_t thread, int sig) {
|
||||||
|
return kill(thread.id, sig);
|
||||||
|
}
|
||||||
|
|
||||||
void pthread_exit(void * value) {
|
void pthread_exit(void * value) {
|
||||||
/* Perform nice cleanup */
|
/* Perform nice cleanup */
|
||||||
#if 0
|
#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);
|
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
|
||||||
void pthread_exit(void * value);
|
void pthread_exit(void * value);
|
||||||
|
int pthread_kill(pthread_t thread, int sig);
|
||||||
|
|
||||||
int clone(uintptr_t,uintptr_t,void*);
|
int clone(uintptr_t,uintptr_t,void*);
|
||||||
int gettid();
|
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