feat: add news ticker with sentiment analysis and error codes
docs: update site links to retoor repository and documentation chore: add author lines to header files build: rebuild binary and object files
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* AI Integration implementation
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Application launcher with .desktop file support
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* X11 Atoms management implementation
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Client (window) management implementation
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Configuration system implementation
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Window decorations implementation
|
||||
*/
|
||||
|
||||
|
||||
+41
-3
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Keyboard shortcut handling implementation
|
||||
*/
|
||||
|
||||
@@ -15,6 +16,11 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
static bool super_pressed = false;
|
||||
static bool super_used_in_combo = false;
|
||||
|
||||
/* Forward declarations for key callbacks */
|
||||
void key_spawn_terminal(void);
|
||||
@@ -354,6 +360,17 @@ void keys_grab_all(void)
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
}
|
||||
|
||||
KeyCode super_l = XKeysymToKeycode(dpy, XK_Super_L);
|
||||
KeyCode super_r = XKeysymToKeycode(dpy, XK_Super_R);
|
||||
unsigned int lock_mods[] = { 0, Mod2Mask, LockMask, Mod2Mask | LockMask };
|
||||
|
||||
for (size_t i = 0; i < sizeof(lock_mods) / sizeof(lock_mods[0]); i++) {
|
||||
if (super_l) XGrabKey(dpy, super_l, lock_mods[i], root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
if (super_r) XGrabKey(dpy, super_r, lock_mods[i], root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
}
|
||||
|
||||
void keys_ungrab_all(void)
|
||||
@@ -412,6 +429,16 @@ void keys_handle_press(XKeyEvent *ev)
|
||||
|
||||
KeySym keysym = XLookupKeysym(ev, 0);
|
||||
|
||||
if (keysym == XK_Super_L || keysym == XK_Super_R) {
|
||||
super_pressed = true;
|
||||
super_used_in_combo = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (super_pressed && (ev->state & Mod4Mask)) {
|
||||
super_used_in_combo = true;
|
||||
}
|
||||
|
||||
/* Clean modifiers (remove NumLock, CapsLock) */
|
||||
unsigned int clean_mask = ev->state & ~(Mod2Mask | LockMask);
|
||||
|
||||
@@ -434,8 +461,19 @@ void keys_handle_press(XKeyEvent *ev)
|
||||
|
||||
void keys_handle_release(XKeyEvent *ev)
|
||||
{
|
||||
/* Currently no release handling needed */
|
||||
(void)ev;
|
||||
if (ev == NULL || dwn == NULL || dwn->display == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
KeySym keysym = XLookupKeysym(ev, 0);
|
||||
|
||||
if (keysym == XK_Super_L || keysym == XK_Super_R) {
|
||||
if (super_pressed && !super_used_in_combo) {
|
||||
key_spawn_launcher();
|
||||
}
|
||||
super_pressed = false;
|
||||
super_used_in_combo = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== Default key bindings (XFCE-style) ========== */
|
||||
@@ -770,7 +808,7 @@ void key_show_shortcuts(void)
|
||||
const char *shortcuts =
|
||||
"=== Applications ===\n"
|
||||
"Ctrl+Alt+T Terminal\n"
|
||||
"Alt+F2 App launcher\n"
|
||||
"Super / Alt+F2 App launcher\n"
|
||||
"Super+E File manager\n"
|
||||
"Super+B Web browser\n"
|
||||
"Print Screenshot\n"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Layout algorithms implementation
|
||||
*/
|
||||
|
||||
|
||||
+9
-4
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Main entry point and event loop
|
||||
*/
|
||||
|
||||
@@ -456,15 +457,19 @@ static void handle_button_press(XButtonEvent *ev)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Focus on click */
|
||||
client_focus(c);
|
||||
|
||||
/* If click was on client window content, replay the event to the application */
|
||||
/* If click was on client window content, replay the event to the application FIRST
|
||||
* before any other X operations. The synchronous grab freezes pointer events until
|
||||
* XAllowEvents is called. Calling XAllowEvents before client_focus ensures the
|
||||
* click reaches the application (tabs, buttons, etc.) without timing issues. */
|
||||
if (is_client_window) {
|
||||
XAllowEvents(dwn->display, ReplayPointer, ev->time);
|
||||
client_focus(c);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Focus on click */
|
||||
client_focus(c);
|
||||
|
||||
/* Check for button clicks in decorations */
|
||||
if (c->frame != None && ev->window == c->frame) {
|
||||
ButtonType btn = decorations_hit_test_button(c, ev->x, ev->y);
|
||||
|
||||
+41
-1
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* News ticker implementation
|
||||
*/
|
||||
|
||||
@@ -12,6 +13,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <pthread.h>
|
||||
@@ -24,6 +26,20 @@
|
||||
/* Fetch interval in milliseconds (5 minutes) */
|
||||
#define FETCH_INTERVAL 300000
|
||||
|
||||
/* Sentiment colors (RGB hex values) */
|
||||
#define SENTIMENT_COLOR_POSITIVE 0x81C784
|
||||
#define SENTIMENT_COLOR_NEUTRAL 0xB0BEC5
|
||||
#define SENTIMENT_COLOR_NEGATIVE 0xE57373
|
||||
|
||||
static unsigned long news_sentiment_color(NewsSentiment sentiment)
|
||||
{
|
||||
switch (sentiment) {
|
||||
case SENTIMENT_POSITIVE: return SENTIMENT_COLOR_POSITIVE;
|
||||
case SENTIMENT_NEGATIVE: return SENTIMENT_COLOR_NEGATIVE;
|
||||
default: return SENTIMENT_COLOR_NEUTRAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Global state */
|
||||
NewsState news_state = {0};
|
||||
|
||||
@@ -225,6 +241,27 @@ static int parse_news_json(const char *json_str)
|
||||
strncpy(art->author, author->valuestring, sizeof(art->author) - 1);
|
||||
}
|
||||
|
||||
cJSON *sentiment_obj = cJSON_GetObjectItemCaseSensitive(article, "sentiment");
|
||||
if (cJSON_IsObject(sentiment_obj)) {
|
||||
cJSON *sentiment_type = cJSON_GetObjectItemCaseSensitive(sentiment_obj, "sentiment");
|
||||
cJSON *sentiment_score = cJSON_GetObjectItemCaseSensitive(sentiment_obj, "score");
|
||||
|
||||
if (cJSON_IsString(sentiment_type) && sentiment_type->valuestring) {
|
||||
if (strcasecmp(sentiment_type->valuestring, "Positive") == 0) {
|
||||
art->sentiment = SENTIMENT_POSITIVE;
|
||||
} else if (strcasecmp(sentiment_type->valuestring, "Negative") == 0) {
|
||||
art->sentiment = SENTIMENT_NEGATIVE;
|
||||
} else {
|
||||
art->sentiment = SENTIMENT_NEUTRAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cJSON_IsNumber(sentiment_score)) {
|
||||
art->sentiment_score = (float)sentiment_score->valuedouble;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -630,9 +667,12 @@ void news_render(Panel *panel, int x, int max_width, int *used_width)
|
||||
char display_text[2048];
|
||||
get_article_display_text(current_article, display_text, sizeof(display_text));
|
||||
|
||||
unsigned long article_color = news_sentiment_color(
|
||||
news_state.articles[current_article].sentiment);
|
||||
|
||||
if (draw_x + news_state.display_widths[current_article] > x) {
|
||||
news_draw_text_clipped(panel->buffer, draw_x, text_y, display_text,
|
||||
colors->panel_fg, &clip_rect);
|
||||
article_color, &clip_rect);
|
||||
}
|
||||
draw_x += news_state.display_widths[current_article];
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* D-Bus Notification daemon implementation
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Panel system implementation
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* System tray widgets implementation with UTF-8 support
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Utility functions implementation
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Workspace management implementation
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user