diff --git a/bin/dwn b/bin/dwn index 02852c2..08a379b 100755 Binary files a/bin/dwn and b/bin/dwn differ diff --git a/build/keys.o b/build/keys.o index d1c4f08..59b81d4 100644 Binary files a/build/keys.o and b/build/keys.o differ diff --git a/build/main.o b/build/main.o index 939e7bc..dff840f 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/build/news.o b/build/news.o index 55a3472..5993552 100644 Binary files a/build/news.o and b/build/news.o differ diff --git a/include/ai.h b/include/ai.h index a41ac02..109c5c9 100644 --- a/include/ai.h +++ b/include/ai.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * AI Integration (OpenRouter API) */ diff --git a/include/applauncher.h b/include/applauncher.h index 1ef5f2a..1431845 100644 --- a/include/applauncher.h +++ b/include/applauncher.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Application launcher with .desktop file support */ diff --git a/include/atoms.h b/include/atoms.h index 4bd88fd..eae169b 100644 --- a/include/atoms.h +++ b/include/atoms.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * X11 Atoms management (EWMH/ICCCM compliance) */ diff --git a/include/client.h b/include/client.h index bb095f2..3954db5 100644 --- a/include/client.h +++ b/include/client.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Client (window) management */ diff --git a/include/config.h b/include/config.h index 507644f..3207293 100644 --- a/include/config.h +++ b/include/config.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Configuration system */ diff --git a/include/decorations.h b/include/decorations.h index 916ebe4..904ab68 100644 --- a/include/decorations.h +++ b/include/decorations.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Window decorations (title bars, borders, buttons) */ diff --git a/include/dwn.h b/include/dwn.h index ba4e466..9305eee 100644 --- a/include/dwn.h +++ b/include/dwn.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Main header with shared types and global state */ @@ -32,6 +33,17 @@ #define DEFAULT_PANEL_HEIGHT 28 #define DEFAULT_GAP 4 +/* Common error/status codes */ +typedef enum { + DWN_OK = 0, + DWN_ERROR = -1, + DWN_ERROR_INVALID_ARG = -2, + DWN_ERROR_NO_MEMORY = -3, + DWN_ERROR_NOT_FOUND = -4, + DWN_ERROR_DISPLAY = -5, + DWN_ERROR_IO = -6 +} DwnStatus; + /* Layout types */ typedef enum { LAYOUT_TILING, diff --git a/include/keys.h b/include/keys.h index c09a23e..da05a54 100644 --- a/include/keys.h +++ b/include/keys.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Keyboard shortcut handling */ diff --git a/include/layout.h b/include/layout.h index 883746b..579de8f 100644 --- a/include/layout.h +++ b/include/layout.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Layout algorithms (tiling, floating, monocle) */ diff --git a/include/news.h b/include/news.h index 6eefc6e..96e2bea 100644 --- a/include/news.h +++ b/include/news.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * News ticker for bottom panel */ @@ -13,12 +14,21 @@ #define MAX_NEWS_ARTICLES 50 #define NEWS_API_URL "https://news.app.molodetz.nl/api" +/* Sentiment classification */ +typedef enum { + SENTIMENT_NEUTRAL = 0, + SENTIMENT_POSITIVE, + SENTIMENT_NEGATIVE +} NewsSentiment; + /* News article */ typedef struct { char title[256]; char content[1024]; char link[512]; char author[128]; + NewsSentiment sentiment; + float sentiment_score; } NewsArticle; /* News ticker state */ diff --git a/include/notifications.h b/include/notifications.h index d44f8b0..22f669c 100644 --- a/include/notifications.h +++ b/include/notifications.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * D-Bus Notification daemon */ diff --git a/include/panel.h b/include/panel.h index 0392cd3..174a8f6 100644 --- a/include/panel.h +++ b/include/panel.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Panel system (top and bottom panels with widgets) */ diff --git a/include/systray.h b/include/systray.h index 546508a..9420c1d 100644 --- a/include/systray.h +++ b/include/systray.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * System tray widgets (WiFi, Audio, etc.) */ diff --git a/include/util.h b/include/util.h index 8e833c7..0bbb5f0 100644 --- a/include/util.h +++ b/include/util.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Utility functions */ @@ -9,6 +10,11 @@ #include #include #include +#include + +/* Contract assertion macro - use for programmer errors */ +#define DWN_ASSERT(cond) assert(cond) +#define DWN_ASSERT_MSG(cond, msg) assert((cond) && (msg)) /* Logging levels */ typedef enum { diff --git a/include/workspace.h b/include/workspace.h index ace5354..8e0837a 100644 --- a/include/workspace.h +++ b/include/workspace.h @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Workspace (tag/virtual desktop) management */ diff --git a/site/ai-features.html b/site/ai-features.html index e227235..64b7c64 100644 --- a/site/ai-features.html +++ b/site/ai-features.html @@ -28,7 +28,7 @@ Architecture -
  • GitHub
  • +
  • Git
  • diff --git a/site/architecture.html b/site/architecture.html index e4ce219..561937c 100644 --- a/site/architecture.html +++ b/site/architecture.html @@ -28,7 +28,7 @@ Architecture -
  • GitHub
  • +
  • Git
  • diff --git a/site/configuration.html b/site/configuration.html index 5e26383..a340781 100644 --- a/site/configuration.html +++ b/site/configuration.html @@ -28,7 +28,7 @@ Architecture -
  • GitHub
  • +
  • Git
  • diff --git a/site/documentation.html b/site/documentation.html index 15d24f8..1e9fc46 100644 --- a/site/documentation.html +++ b/site/documentation.html @@ -28,7 +28,7 @@ Architecture -
  • GitHub
  • +
  • Git
  • diff --git a/site/features.html b/site/features.html index b72b795..605678c 100644 --- a/site/features.html +++ b/site/features.html @@ -28,7 +28,7 @@ Architecture -
  • GitHub
  • +
  • Git
  • +

    News Ticker

    +
    +

    The bottom panel includes a scrolling news ticker that displays headlines from a news feed. + Navigate through articles using keyboard shortcuts:

    +
      +
    • Super + Down - Next article
    • +
    • Super + Up - Previous article
    • +
    • Super + Return - Open in browser
    • +
    +

    + The ticker updates automatically and caches up to 50 articles. Smooth scrolling animation + at 80 pixels per second keeps you informed without distraction. +

    +
    +

    System Tray Features

    diff --git a/site/index.html b/site/index.html index b555703..48e4cdc 100644 --- a/site/index.html +++ b/site/index.html @@ -29,7 +29,7 @@ Architecture -
  • GitHub
  • +
  • Git
  • diff --git a/site/installation.html b/site/installation.html index e85c15a..9b621bc 100644 --- a/site/installation.html +++ b/site/installation.html @@ -28,7 +28,7 @@ Architecture -
  • GitHub
  • +
  • Git
  • -
    git clone https://github.com/dwn/dwn.git
    +                            
    git clone https://retoor.molodetz.nl/retoor/dwn.git
     cd dwn
    @@ -232,7 +232,7 @@ sudo apt install -y \ pkg-config # Build and install -git clone https://github.com/dwn/dwn.git +git clone https://retoor.molodetz.nl/retoor/dwn.git cd dwn make sudo make install
    @@ -259,7 +259,7 @@ sudo dnf install -y \ pkg-config # Build and install -git clone https://github.com/dwn/dwn.git +git clone https://retoor.molodetz.nl/retoor/dwn.git cd dwn make sudo make install @@ -285,7 +285,7 @@ sudo pacman -S --needed \ pkg-config # Build and install -git clone https://github.com/dwn/dwn.git +git clone https://retoor.molodetz.nl/retoor/dwn.git cd dwn make sudo make install @@ -316,7 +316,7 @@ sudo xbps-install -S \ pkg-config # Build and install -git clone https://github.com/dwn/dwn.git +git clone https://retoor.molodetz.nl/retoor/dwn.git cd dwn make sudo make install @@ -586,21 +586,21 @@ sudo dnf install dejavu-fonts-all liberation-fonts # Fedora
  • Features
  • Installation
  • AI Integration
  • -
  • GitHub
  • +
  • Git
  • diff --git a/site/shortcuts.html b/site/shortcuts.html index 53a6777..513d4e2 100644 --- a/site/shortcuts.html +++ b/site/shortcuts.html @@ -28,7 +28,7 @@ Architecture -
  • GitHub
  • +
  • Git
  • @@ -285,6 +289,36 @@ + +

    News Ticker

    +

    + Navigate the scrolling news ticker displayed in the bottom panel. +

    +
    + + + + + + + + + + + + + + + + + + + + + +
    ShortcutAction
    Super + DownNext news article
    Super + UpPrevious news article
    Super + ReturnOpen current article in browser
    +
    +

    Help & System

    @@ -389,21 +423,21 @@
  • Features
  • Installation
  • AI Integration
  • -
  • GitHub
  • +
  • Git
  • diff --git a/src/ai.c b/src/ai.c index 81ab432..3111c5a 100644 --- a/src/ai.c +++ b/src/ai.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * AI Integration implementation */ diff --git a/src/applauncher.c b/src/applauncher.c index 6ad02f3..4c91df5 100644 --- a/src/applauncher.c +++ b/src/applauncher.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Application launcher with .desktop file support */ diff --git a/src/atoms.c b/src/atoms.c index e024882..b83d625 100644 --- a/src/atoms.c +++ b/src/atoms.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * X11 Atoms management implementation */ diff --git a/src/client.c b/src/client.c index 14c582b..d0771f8 100644 --- a/src/client.c +++ b/src/client.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Client (window) management implementation */ diff --git a/src/config.c b/src/config.c index 3efb77e..4f341a7 100644 --- a/src/config.c +++ b/src/config.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Configuration system implementation */ diff --git a/src/decorations.c b/src/decorations.c index c769912..3ba91b1 100644 --- a/src/decorations.c +++ b/src/decorations.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Window decorations implementation */ diff --git a/src/keys.c b/src/keys.c index 3167aee..a8b4ba0 100644 --- a/src/keys.c +++ b/src/keys.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Keyboard shortcut handling implementation */ @@ -15,6 +16,11 @@ #include #include +#include +#include + +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" diff --git a/src/layout.c b/src/layout.c index 22631a9..f7bbbfd 100644 --- a/src/layout.c +++ b/src/layout.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Layout algorithms implementation */ diff --git a/src/main.c b/src/main.c index 97a96fb..178aa7b 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * 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); diff --git a/src/news.c b/src/news.c index cd1d35e..e6b0a86 100644 --- a/src/news.c +++ b/src/news.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * News ticker implementation */ @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -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]; diff --git a/src/notifications.c b/src/notifications.c index 221a37a..e3edf19 100644 --- a/src/notifications.c +++ b/src/notifications.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * D-Bus Notification daemon implementation */ diff --git a/src/panel.c b/src/panel.c index b7ac118..3257de9 100644 --- a/src/panel.c +++ b/src/panel.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Panel system implementation */ diff --git a/src/systray.c b/src/systray.c index 9f39b61..07e6867 100644 --- a/src/systray.c +++ b/src/systray.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * System tray widgets implementation with UTF-8 support */ diff --git a/src/util.c b/src/util.c index 06cb92a..b44ed76 100644 --- a/src/util.c +++ b/src/util.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Utility functions implementation */ diff --git a/src/workspace.c b/src/workspace.c index 1db163f..eed8ec4 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -1,5 +1,6 @@ /* * DWN - Desktop Window Manager + * retoor * Workspace management implementation */