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:
retoor 2025-12-28 04:30:10 +01:00
parent 7a4f7a82ad
commit 9182d9931e
42 changed files with 262 additions and 76 deletions

BIN
bin/dwn

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* AI Integration (OpenRouter API)
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Application launcher with .desktop file support
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* X11 Atoms management (EWMH/ICCCM compliance)
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Client (window) management
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Configuration system
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Window decorations (title bars, borders, buttons)
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* 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,

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Keyboard shortcut handling
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Layout algorithms (tiling, floating, monocle)
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* 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 */

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* D-Bus Notification daemon
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Panel system (top and bottom panels with widgets)
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* System tray widgets (WiFi, Audio, etc.)
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Utility functions
*/
@ -9,6 +10,11 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdarg.h>
#include <assert.h>
/* 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 {

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Workspace (tag/virtual desktop) management
*/

View File

@ -28,7 +28,7 @@
<a href="architecture.html">Architecture</a>
</div>
</li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
<div class="nav-toggle" onclick="toggleNav()">
<span></span>
@ -434,21 +434,21 @@ model = google/gemini-2.0-flash-exp:free</code></pre>
<li><a href="features.html">Features</a></li>
<li><a href="installation.html">Installation</a></li>
<li><a href="ai-features.html">AI Integration</a></li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/dwn/dwn/issues">Issue Tracker</a></li>
<li><a href="https://github.com/dwn/dwn/discussions">Discussions</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/LICENSE">License (MIT)</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>DWN Window Manager - Open Source under the MIT License</p>
<p>DWN Window Manager by retoor &lt;retoor@molodetz.nl&gt; - MIT License</p>
</div>
</div>
</footer>

View File

@ -28,7 +28,7 @@
<a href="architecture.html">Architecture</a>
</div>
</li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
<div class="nav-toggle" onclick="toggleNav()">
<span></span>
@ -541,21 +541,21 @@ extern DWNState *dwn; // Global singleton</code></pre>
<li><a href="features.html">Features</a></li>
<li><a href="installation.html">Installation</a></li>
<li><a href="ai-features.html">AI Integration</a></li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/dwn/dwn/issues">Issue Tracker</a></li>
<li><a href="https://github.com/dwn/dwn/discussions">Discussions</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/LICENSE">License (MIT)</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>DWN Window Manager - Open Source under the MIT License</p>
<p>DWN Window Manager by retoor &lt;retoor@molodetz.nl&gt; - MIT License</p>
</div>
</div>
</footer>

View File

@ -28,7 +28,7 @@
<a href="architecture.html">Architecture</a>
</div>
</li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
<div class="nav-toggle" onclick="toggleNav()">
<span></span>
@ -496,21 +496,21 @@ model = google/gemini-2.0-flash-exp:free
<li><a href="features.html">Features</a></li>
<li><a href="installation.html">Installation</a></li>
<li><a href="ai-features.html">AI Integration</a></li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/dwn/dwn/issues">Issue Tracker</a></li>
<li><a href="https://github.com/dwn/dwn/discussions">Discussions</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/LICENSE">License (MIT)</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>DWN Window Manager - Open Source under the MIT License</p>
<p>DWN Window Manager by retoor &lt;retoor@molodetz.nl&gt; - MIT License</p>
</div>
</div>
</footer>

View File

@ -28,7 +28,7 @@
<a href="architecture.html">Architecture</a>
</div>
</li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
<div class="nav-toggle" onclick="toggleNav()">
<span></span>
@ -360,8 +360,10 @@
<h3>Bottom Panel</h3>
<p>
The bottom panel shows the current time and date. Both panels can be hidden
in the configuration if you prefer a minimal setup.
The bottom panel shows the current time and a scrolling news ticker. Navigate
news articles with <kbd>Super</kbd> + <kbd>Up</kbd>/<kbd>Down</kbd> and open
the current article with <kbd>Super</kbd> + <kbd>Return</kbd>. Both panels can
be hidden in the configuration if you prefer a minimal setup.
</p>
<h2>Next Steps</h2>
@ -399,21 +401,21 @@
<li><a href="features.html">Features</a></li>
<li><a href="installation.html">Installation</a></li>
<li><a href="ai-features.html">AI Integration</a></li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/dwn/dwn/issues">Issue Tracker</a></li>
<li><a href="https://github.com/dwn/dwn/discussions">Discussions</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/LICENSE">License (MIT)</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>DWN Window Manager - Open Source under the MIT License</p>
<p>DWN Window Manager by retoor &lt;retoor@molodetz.nl&gt; - MIT License</p>
</div>
</div>
</footer>

View File

@ -28,7 +28,7 @@
<a href="architecture.html">Architecture</a>
</div>
</li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
<div class="nav-toggle" onclick="toggleNav()">
<span></span>
@ -160,12 +160,27 @@
<p>Optional bottom panel for additional information:</p>
<ul style="margin-top: 1rem; padding-left: 1.25rem; color: var(--text-muted);">
<li><strong>Clock Display</strong> - Time and date</li>
<li><strong>Status Messages</strong> - System notifications</li>
<li><strong>News Ticker</strong> - Scrolling news feed with navigation</li>
<li><strong>Customizable</strong> - Can be hidden in config</li>
</ul>
</div>
</div>
<h3 style="margin-top: 3rem; margin-bottom: 1.5rem;">News Ticker</h3>
<div class="card">
<p>The bottom panel includes a scrolling news ticker that displays headlines from a news feed.
Navigate through articles using keyboard shortcuts:</p>
<ul style="margin-top: 1rem; padding-left: 1.25rem; color: var(--text-muted);">
<li><kbd>Super</kbd> + <kbd>Down</kbd> - Next article</li>
<li><kbd>Super</kbd> + <kbd>Up</kbd> - Previous article</li>
<li><kbd>Super</kbd> + <kbd>Return</kbd> - Open in browser</li>
</ul>
<p style="margin-top: 1rem; color: var(--text-muted);">
The ticker updates automatically and caches up to 50 articles. Smooth scrolling animation
at 80 pixels per second keeps you informed without distraction.
</p>
</div>
<h3 style="margin-top: 3rem; margin-bottom: 1.5rem;">System Tray Features</h3>
<div class="features-grid">
<div class="card">
@ -387,21 +402,21 @@
<li><a href="features.html">Features</a></li>
<li><a href="installation.html">Installation</a></li>
<li><a href="ai-features.html">AI Integration</a></li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/dwn/dwn/issues">Issue Tracker</a></li>
<li><a href="https://github.com/dwn/dwn/discussions">Discussions</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/LICENSE">License (MIT)</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>DWN Window Manager - Open Source under the MIT License</p>
<p>DWN Window Manager by retoor &lt;retoor@molodetz.nl&gt; - MIT License</p>
</div>
</div>
</footer>

View File

@ -29,7 +29,7 @@
<a href="architecture.html">Architecture</a>
</div>
</li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
<div class="nav-toggle" onclick="toggleNav()">
<span></span>
@ -109,7 +109,7 @@
<div class="container">
<div class="stats">
<div class="stat-item">
<h3>~10K</h3>
<h3>~15K</h3>
<p>Lines of Pure C</p>
</div>
<div class="stat-item">
@ -121,7 +121,7 @@
<p>Memory Footprint</p>
</div>
<div class="stat-item">
<h3>64+</h3>
<h3>43+</h3>
<p>Keyboard Shortcuts</p>
</div>
</div>
@ -143,7 +143,7 @@
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
</div>
<pre><code># Clone the repository
git clone https://github.com/dwn/dwn.git
git clone https://retoor.molodetz.nl/retoor/dwn.git
cd dwn
# Install dependencies (auto-detects your distro)
@ -328,21 +328,21 @@ echo "exec dwn" >> ~/.xinitrc</code></pre>
<li><a href="features.html">Features</a></li>
<li><a href="installation.html">Installation</a></li>
<li><a href="ai-features.html">AI Integration</a></li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/dwn/dwn/issues">Issue Tracker</a></li>
<li><a href="https://github.com/dwn/dwn/discussions">Discussions</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/LICENSE">License (MIT)</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>DWN Window Manager - Open Source under the MIT License</p>
<p>DWN Window Manager by retoor &lt;retoor@molodetz.nl&gt; - MIT License</p>
</div>
</div>
</footer>

View File

@ -28,7 +28,7 @@
<a href="architecture.html">Architecture</a>
</div>
</li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
<div class="nav-toggle" onclick="toggleNav()">
<span></span>
@ -133,7 +133,7 @@
<span>Terminal</span>
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
</div>
<pre><code>git clone https://github.com/dwn/dwn.git
<pre><code>git clone https://retoor.molodetz.nl/retoor/dwn.git
cd dwn</code></pre>
</div>
</div>
@ -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</code></pre>
@ -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</code></pre>
@ -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</code></pre>
@ -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</code></pre>
@ -586,21 +586,21 @@ sudo dnf install dejavu-fonts-all liberation-fonts # Fedora</code></pre>
<li><a href="features.html">Features</a></li>
<li><a href="installation.html">Installation</a></li>
<li><a href="ai-features.html">AI Integration</a></li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/dwn/dwn/issues">Issue Tracker</a></li>
<li><a href="https://github.com/dwn/dwn/discussions">Discussions</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/LICENSE">License (MIT)</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>DWN Window Manager - Open Source under the MIT License</p>
<p>DWN Window Manager by retoor &lt;retoor@molodetz.nl&gt; - MIT License</p>
</div>
</div>
</footer>

View File

@ -28,7 +28,7 @@
<a href="architecture.html">Architecture</a>
</div>
</li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
<div class="nav-toggle" onclick="toggleNav()">
<span></span>
@ -71,7 +71,7 @@
<td>Open terminal (configurable)</td>
</tr>
<tr>
<td><kbd>Alt</kbd> + <kbd>F2</kbd></td>
<td><kbd>Super</kbd> / <kbd>Alt</kbd> + <kbd>F2</kbd></td>
<td>Open application launcher (dmenu/rofi)</td>
</tr>
<tr>
@ -82,6 +82,10 @@
<td><kbd>Super</kbd> + <kbd>B</kbd></td>
<td>Open web browser</td>
</tr>
<tr>
<td><kbd>Print</kbd></td>
<td>Take screenshot (xfce4-screenshooter)</td>
</tr>
</tbody>
</table>
</div>
@ -285,6 +289,36 @@
</table>
</div>
<!-- News Ticker -->
<h2 id="news">News Ticker</h2>
<p style="color: var(--text-muted); margin-bottom: 1rem;">
Navigate the scrolling news ticker displayed in the bottom panel.
</p>
<div class="table-wrapper">
<table class="shortcuts-table">
<thead>
<tr>
<th style="width: 40%;">Shortcut</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td><kbd>Super</kbd> + <kbd>Down</kbd></td>
<td>Next news article</td>
</tr>
<tr>
<td><kbd>Super</kbd> + <kbd>Up</kbd></td>
<td>Previous news article</td>
</tr>
<tr>
<td><kbd>Super</kbd> + <kbd>Return</kbd></td>
<td>Open current article in browser</td>
</tr>
</tbody>
</table>
</div>
<!-- Help & System -->
<h2 id="system">Help & System</h2>
<div class="table-wrapper">
@ -389,21 +423,21 @@
<li><a href="features.html">Features</a></li>
<li><a href="installation.html">Installation</a></li>
<li><a href="ai-features.html">AI Integration</a></li>
<li><a href="https://github.com/dwn/dwn">GitHub</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/dwn/dwn/issues">Issue Tracker</a></li>
<li><a href="https://github.com/dwn/dwn/discussions">Discussions</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://github.com/dwn/dwn/blob/main/LICENSE">License (MIT)</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>DWN Window Manager - Open Source under the MIT License</p>
<p>DWN Window Manager by retoor &lt;retoor@molodetz.nl&gt; - MIT License</p>
</div>
</div>
</footer>

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* AI Integration implementation
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Application launcher with .desktop file support
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* X11 Atoms management implementation
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Client (window) management implementation
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Configuration system implementation
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Window decorations implementation
*/

View File

@ -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"

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Layout algorithms implementation
*/

View File

@ -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);

View File

@ -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];

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* D-Bus Notification daemon implementation
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Panel system implementation
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* System tray widgets implementation with UTF-8 support
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Utility functions implementation
*/

View File

@ -1,5 +1,6 @@
/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Workspace management implementation
*/