gardesk/gartk / 1a7afd5

Browse files

Add documentation for gartk toolkit

docs/README.md - Overview, quick start, crate summary
docs/core.md - Color, Rect, Theme, InputEvent types
docs/x11.md - Connection, Window, Monitor, EventLoop, Cursor
docs/render.md - Surface, Renderer, TextStyle, shape functions
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
1a7afd55384c4c4f12493e757f1b5e9ac308fbaf
Parents
65eb650
Tree
596653c

4 changed files

StatusFile+-
A docs/README.md 70 0
A docs/core.md 184 0
A docs/render.md 236 0
A docs/x11.md 196 0
docs/README.mdadded
@@ -0,0 +1,70 @@
1
+# gartk Documentation
2
+
3
+gartk is a shared X11/Cairo toolkit for the gardesk suite. It provides common functionality used by garlaunch, garbar, gardm-greeter, and other gar components.
4
+
5
+## Crates
6
+
7
+| Crate | Purpose |
8
+|-------|---------|
9
+| `gartk-core` | Fundamental types: Color, Rect, Theme, InputEvent |
10
+| `gartk-x11` | X11 connection, window management, monitors, event loop |
11
+| `gartk-render` | Cairo/Pango rendering: surfaces, shapes, text |
12
+
13
+## Quick Start
14
+
15
+```toml
16
+[dependencies]
17
+gartk-core = { path = "../gartk/gartk-core" }
18
+gartk-x11 = { path = "../gartk/gartk-x11" }
19
+gartk-render = { path = "../gartk/gartk-render" }
20
+```
21
+
22
+### Minimal Window
23
+
24
+```rust
25
+use gartk_core::Theme;
26
+use gartk_x11::{Connection, Window, WindowConfig, EventLoop};
27
+use gartk_render::Renderer;
28
+
29
+fn main() -> anyhow::Result<()> {
30
+    let conn = Connection::connect(None)?;
31
+    let window = Window::create(
32
+        conn.clone(),
33
+        WindowConfig::default()
34
+            .title("Example")
35
+            .size(400, 300),
36
+    )?;
37
+
38
+    window.show()?;
39
+    window.focus()?;
40
+
41
+    let theme = Theme::dark();
42
+    let renderer = Renderer::with_theme(400, 300, theme)?;
43
+    renderer.clear()?;
44
+    renderer.flush();
45
+
46
+    let event_loop = EventLoop::new(conn, Default::default());
47
+    event_loop.run(|event| {
48
+        // Handle events
49
+        Ok(true) // Return false to exit
50
+    })?;
51
+
52
+    Ok(())
53
+}
54
+```
55
+
56
+## Documentation
57
+
58
+- [gartk-core](core.md) - Types and theming
59
+- [gartk-x11](x11.md) - X11 integration
60
+- [gartk-render](render.md) - Cairo/Pango rendering
61
+
62
+## Usage in gardesk
63
+
64
+gartk is used by:
65
+
66
+- **garlaunch**: Popup window, text rendering, keyboard input
67
+- **garbar**: Status bar rendering (shares patterns, not yet migrated)
68
+- **gardm-greeter**: Login UI (shares patterns, not yet migrated)
69
+
70
+The toolkit extracts common patterns from these components. Future gar components can use gartk directly.
docs/core.mdadded
@@ -0,0 +1,184 @@
1
+# gartk-core
2
+
3
+Fundamental types used throughout gartk.
4
+
5
+## Color
6
+
7
+RGBA color representation with parsing utilities.
8
+
9
+```rust
10
+use gartk_core::Color;
11
+
12
+// Constructors
13
+let c = Color::new(255, 128, 64, 255);
14
+let c = Color::from_rgb(255, 128, 64);
15
+let c = Color::from_hex("#ff8040").unwrap();
16
+let c = Color::from_hex("#ff804080").unwrap(); // with alpha
17
+
18
+// Named colors
19
+let c = Color::WHITE;
20
+let c = Color::BLACK;
21
+let c = Color::TRANSPARENT;
22
+let c = Color::RED;
23
+let c = Color::GRAY;
24
+
25
+// Methods
26
+let (r, g, b, a) = c.to_rgba();
27
+let (r, g, b, a) = c.to_rgba_f64(); // 0.0-1.0 range
28
+let hex = c.to_hex();
29
+let lighter = c.lighten(0.1);
30
+let darker = c.darken(0.1);
31
+let faded = c.with_alpha(128);
32
+```
33
+
34
+## Geometry
35
+
36
+### Point
37
+
38
+```rust
39
+use gartk_core::Point;
40
+
41
+let p = Point::new(10, 20);
42
+let p = Point::origin(); // (0, 0)
43
+```
44
+
45
+### Size
46
+
47
+```rust
48
+use gartk_core::Size;
49
+
50
+let s = Size::new(800, 600);
51
+let area = s.area();
52
+let is_empty = s.is_empty();
53
+```
54
+
55
+### Rect
56
+
57
+```rust
58
+use gartk_core::Rect;
59
+
60
+let r = Rect::new(10, 20, 100, 50); // x, y, width, height
61
+let r = Rect::from_points(Point::new(10, 20), Point::new(110, 70));
62
+
63
+// Properties
64
+r.x; r.y; r.width; r.height;
65
+r.left(); r.right(); r.top(); r.bottom();
66
+r.center();
67
+r.size();
68
+r.origin();
69
+
70
+// Operations
71
+r.contains(Point::new(50, 40));
72
+r.intersects(&other);
73
+r.intersection(&other);
74
+r.union(&other);
75
+r.inset(5); // shrink by 5 on all sides
76
+r.offset(10, 20); // move
77
+```
78
+
79
+### Edges
80
+
81
+Padding/margin representation.
82
+
83
+```rust
84
+use gartk_core::Edges;
85
+
86
+let e = Edges::all(10);
87
+let e = Edges::symmetric(10, 5); // horizontal, vertical
88
+let e = Edges::new(5, 10, 5, 10); // top, right, bottom, left
89
+```
90
+
91
+## InputEvent
92
+
93
+Abstraction over X11 input events.
94
+
95
+```rust
96
+use gartk_core::{InputEvent, Key, Modifiers};
97
+
98
+match event {
99
+    InputEvent::Key(key_event) => {
100
+        if key_event.pressed {
101
+            match key_event.key {
102
+                Key::Return => { /* enter pressed */ }
103
+                Key::Escape => { /* escape pressed */ }
104
+                Key::Char(c) => { /* character input */ }
105
+                _ => {}
106
+            }
107
+        }
108
+        // Check modifiers
109
+        if key_event.modifiers.ctrl { /* ctrl held */ }
110
+        if key_event.modifiers.shift { /* shift held */ }
111
+    }
112
+    InputEvent::Mouse(mouse_event) => {
113
+        // mouse_event.x, mouse_event.y, mouse_event.button
114
+    }
115
+    InputEvent::Scroll(scroll_event) => {
116
+        // scroll_event.delta_x, scroll_event.delta_y
117
+    }
118
+    InputEvent::FocusIn | InputEvent::FocusOut => {}
119
+    InputEvent::Close => { /* window close requested */ }
120
+}
121
+```
122
+
123
+### Key Enum
124
+
125
+Common keys: `Escape`, `Return`, `Tab`, `Backspace`, `Delete`, `Left`, `Right`, `Up`, `Down`, `Home`, `End`, `PageUp`, `PageDown`, `Space`, `Char(char)`, `F1`-`F12`, `Unknown(u8)`.
126
+
127
+## Theme
128
+
129
+UI theming with presets.
130
+
131
+```rust
132
+use gartk_core::Theme;
133
+
134
+// Presets
135
+let theme = Theme::dark();
136
+let theme = Theme::light();
137
+let theme = Theme::high_contrast();
138
+
139
+// Access properties
140
+theme.background;
141
+theme.foreground;
142
+theme.border;
143
+theme.border_width;
144
+theme.border_radius;
145
+theme.font_family;
146
+theme.font_size;
147
+theme.padding;
148
+theme.item_padding;
149
+theme.item_spacing;
150
+
151
+// Input field colors
152
+theme.input_background;
153
+theme.input_foreground;
154
+theme.input_border;
155
+theme.input_placeholder;
156
+theme.input_cursor;
157
+
158
+// Item/list colors
159
+theme.item_background;
160
+theme.item_foreground;
161
+theme.item_selected_background;
162
+theme.item_selected_foreground;
163
+theme.item_hover_background;
164
+theme.item_hover_foreground;
165
+theme.item_description;
166
+```
167
+
168
+### ThemeBuilder
169
+
170
+```rust
171
+use gartk_core::{Theme, ThemeBuilder, Color};
172
+
173
+let theme = Theme::builder()
174
+    .background(Color::from_hex("#1a1a1a").unwrap())
175
+    .foreground(Color::WHITE)
176
+    .font_size(16.0)
177
+    .padding(16)
178
+    .build();
179
+
180
+// Or modify existing
181
+let theme = ThemeBuilder::from(Theme::dark())
182
+    .font_family("JetBrains Mono")
183
+    .build();
184
+```
docs/render.mdadded
@@ -0,0 +1,236 @@
1
+# gartk-render
2
+
3
+Cairo/Pango rendering with surface management.
4
+
5
+## Surface
6
+
7
+Cairo ImageSurface wrapper.
8
+
9
+```rust
10
+use gartk_render::Surface;
11
+use gartk_core::Color;
12
+
13
+let mut surface = Surface::new(800, 600)?;
14
+
15
+// Clear
16
+surface.clear(Color::BLACK)?;
17
+
18
+// Access Cairo context
19
+let ctx = surface.context()?;
20
+// ... custom Cairo drawing ...
21
+
22
+// Resize
23
+surface.resize(1024, 768)?;
24
+
25
+// Get raw pixel data (ARGB32 format)
26
+let data: &[u8] = surface.data()?;
27
+
28
+// Dimensions
29
+surface.size(); // Size
30
+surface.width();
31
+surface.height();
32
+
33
+// Flush pending operations
34
+surface.flush();
35
+
36
+// Access underlying Cairo surface
37
+surface.cairo_surface();
38
+```
39
+
40
+### DoubleBufferedSurface
41
+
42
+For flicker-free rendering (swap buffers pattern).
43
+
44
+```rust
45
+use gartk_render::DoubleBufferedSurface;
46
+
47
+let mut db = DoubleBufferedSurface::new(800, 600)?;
48
+
49
+// Draw to back buffer
50
+let ctx = db.back_context()?;
51
+// ... draw ...
52
+
53
+// Swap buffers
54
+db.swap();
55
+
56
+// Access front buffer data
57
+let data = db.front_data()?;
58
+```
59
+
60
+## Renderer
61
+
62
+High-level rendering API combining shapes and text.
63
+
64
+```rust
65
+use gartk_render::Renderer;
66
+use gartk_core::{Theme, Color, Rect, Point};
67
+
68
+// Create with theme
69
+let theme = Theme::dark();
70
+let renderer = Renderer::with_theme(800, 600, theme)?;
71
+
72
+// Or without theme
73
+let renderer = Renderer::new(800, 600)?;
74
+
75
+// Clear
76
+renderer.clear()?;  // Uses theme background
77
+renderer.clear_color(Color::RED)?;
78
+
79
+// Resize
80
+renderer.resize(1024, 768)?;
81
+
82
+// After drawing, flush
83
+renderer.flush();
84
+
85
+// Access internals
86
+renderer.surface();
87
+renderer.theme();
88
+renderer.size();
89
+renderer.context()?;  // Cairo context for custom drawing
90
+```
91
+
92
+### Shapes
93
+
94
+```rust
95
+use gartk_core::{Rect, Color};
96
+
97
+let rect = Rect::new(10, 10, 100, 50);
98
+
99
+// Rectangles
100
+renderer.fill_rect(rect, Color::BLUE)?;
101
+renderer.stroke_rect(rect, Color::WHITE, 2.0)?;
102
+
103
+// Rounded rectangles
104
+renderer.fill_rounded_rect(rect, 8.0, Color::BLUE)?;
105
+renderer.stroke_rounded_rect(rect, 8.0, Color::WHITE, 2.0)?;
106
+
107
+// Circles
108
+renderer.fill_circle(50.0, 50.0, 20.0, Color::RED)?;
109
+
110
+// Lines
111
+renderer.line(0.0, 0.0, 100.0, 100.0, Color::WHITE, 1.0)?;
112
+```
113
+
114
+### Text
115
+
116
+```rust
117
+use gartk_render::TextStyle;
118
+use gartk_core::Color;
119
+
120
+let style = TextStyle::new()
121
+    .font_family("sans-serif")
122
+    .font_size(14.0)
123
+    .color(Color::WHITE);
124
+
125
+// Draw text at position
126
+renderer.text("Hello", 10.0, 20.0, &style)?;
127
+
128
+// Draw with theme defaults
129
+renderer.text_default("Hello", 10.0, 20.0, Color::WHITE)?;
130
+
131
+// Draw in rectangle (auto-centers vertically)
132
+renderer.text_in_rect("Hello", rect, &style)?;
133
+
134
+// Draw centered at point
135
+renderer.text_centered("Hello", Point::new(100, 100), &style)?;
136
+
137
+// Measure text
138
+let size = renderer.measure_text("Hello", &style)?;
139
+```
140
+
141
+## TextStyle
142
+
143
+Text rendering configuration.
144
+
145
+```rust
146
+use gartk_render::{TextStyle, TextAlign};
147
+use gartk_core::Color;
148
+
149
+let style = TextStyle::new()
150
+    .font_family("JetBrains Mono")
151
+    .font_size(12.0)
152
+    .color(Color::WHITE)
153
+    .align(TextAlign::Left)    // Left, Center, Right
154
+    .ellipsize(true)           // Add "..." when truncated
155
+    .wrap(true)                // Word wrap
156
+    .max_width(200);           // Width constraint (required for ellipsize/wrap)
157
+```
158
+
159
+## TextRenderer
160
+
161
+Lower-level Pango text rendering (used internally by Renderer).
162
+
163
+```rust
164
+use gartk_render::TextRenderer;
165
+
166
+let text_renderer = TextRenderer::new();
167
+
168
+// Or with default style
169
+let text_renderer = TextRenderer::with_style(style);
170
+
171
+// Measure
172
+let size = text_renderer.measure(&ctx, "Hello", &style);
173
+
174
+// Draw
175
+text_renderer.draw(&ctx, "Hello", 10.0, 20.0, &style);
176
+text_renderer.draw_in_rect(&ctx, "Hello", rect, &style);
177
+text_renderer.draw_centered(&ctx, "Hello", center_point, &style);
178
+```
179
+
180
+## Low-Level Shape Functions
181
+
182
+Direct Cairo drawing (requires Cairo context).
183
+
184
+```rust
185
+use gartk_render::{fill_rect, stroke_rect, fill_rounded_rect, rounded_rect_path};
186
+use gartk_render::{fill_circle, stroke_circle, circle_path};
187
+use gartk_render::{line, hline, vline, set_color};
188
+
189
+let ctx = surface.context()?;
190
+
191
+// Color
192
+set_color(&ctx, Color::RED);
193
+
194
+// Paths (for custom operations)
195
+rect_path(&ctx, rect);
196
+rounded_rect_path(&ctx, rect, radius);
197
+circle_path(&ctx, cx, cy, radius);
198
+
199
+// Fill/stroke
200
+fill_rect(&ctx, rect, color);
201
+stroke_rect(&ctx, rect, color, line_width);
202
+fill_rounded_rect(&ctx, rect, radius, color);
203
+stroke_rounded_rect(&ctx, rect, radius, color, line_width);
204
+fill_circle(&ctx, cx, cy, radius, color);
205
+stroke_circle(&ctx, cx, cy, radius, color, line_width);
206
+
207
+// Lines
208
+line(&ctx, x1, y1, x2, y2, color, line_width);
209
+hline(&ctx, x1, x2, y, color, line_width);
210
+vline(&ctx, x, y1, y2, color, line_width);
211
+```
212
+
213
+## Font Parsing
214
+
215
+Parse font specification strings.
216
+
217
+```rust
218
+use gartk_render::parse_font_spec;
219
+
220
+// Pango-style
221
+let (family, size) = parse_font_spec("Sans 12")?;
222
+let (family, size) = parse_font_spec("JetBrains Mono 11")?;
223
+
224
+// Polybar-style
225
+let (family, size) = parse_font_spec("Monospace:size=14")?;
226
+```
227
+
228
+## Re-exports
229
+
230
+For direct access to underlying libraries:
231
+
232
+```rust
233
+use gartk_render::cairo;
234
+use gartk_render::pango;
235
+use gartk_render::pangocairo;
236
+```
docs/x11.mdadded
@@ -0,0 +1,196 @@
1
+# gartk-x11
2
+
3
+X11 integration using x11rb with RustConnection.
4
+
5
+## Connection
6
+
7
+Wrapper around x11rb connection with atom caching.
8
+
9
+```rust
10
+use gartk_x11::Connection;
11
+
12
+let conn = Connection::connect(None)?; // Use $DISPLAY
13
+let conn = Connection::connect(Some(":1"))?; // Specific display
14
+
15
+// Access underlying connection
16
+conn.inner(); // &RustConnection
17
+conn.screen_num();
18
+conn.default_screen(); // &Screen
19
+
20
+// Utilities
21
+conn.generate_id()?;
22
+conn.flush()?;
23
+conn.sync()?;
24
+
25
+// Atoms (cached)
26
+conn.atoms(); // &Atoms
27
+```
28
+
29
+### Atoms
30
+
31
+Pre-interned X11 atoms for EWMH, ICCCM, and common properties.
32
+
33
+```rust
34
+let atoms = conn.atoms();
35
+
36
+// Window types
37
+atoms.NET_WM_WINDOW_TYPE;
38
+atoms.NET_WM_WINDOW_TYPE_NORMAL;
39
+atoms.NET_WM_WINDOW_TYPE_DIALOG;
40
+atoms.NET_WM_WINDOW_TYPE_DOCK;
41
+atoms.NET_WM_WINDOW_TYPE_POPUP_MENU;
42
+
43
+// State
44
+atoms.NET_WM_STATE;
45
+atoms.NET_WM_STATE_ABOVE;
46
+atoms.NET_WM_STATE_FULLSCREEN;
47
+atoms.NET_WM_STATE_STICKY;
48
+
49
+// Properties
50
+atoms.NET_WM_NAME;
51
+atoms.NET_WM_PID;
52
+atoms.WM_NAME;
53
+atoms.WM_CLASS;
54
+atoms.WM_PROTOCOLS;
55
+atoms.WM_DELETE_WINDOW;
56
+
57
+// Selections
58
+atoms.CLIPBOARD;
59
+atoms.PRIMARY;
60
+atoms.UTF8_STRING;
61
+```
62
+
63
+## Window
64
+
65
+X11 window creation and management.
66
+
67
+```rust
68
+use gartk_x11::{Window, WindowConfig, WindowType};
69
+
70
+let window = Window::create(
71
+    conn.clone(),
72
+    WindowConfig::default()
73
+        .title("My Window")
74
+        .class("myapp")
75
+        .position(100, 100)
76
+        .size(800, 600)
77
+        .window_type(WindowType::Normal)
78
+        .transparent(false)
79
+        .override_redirect(false),
80
+)?;
81
+
82
+// Presets
83
+WindowConfig::popup();    // override_redirect, above, skip taskbar
84
+WindowConfig::dock();     // dock type, struts
85
+WindowConfig::fullscreen();
86
+```
87
+
88
+### Window Methods
89
+
90
+```rust
91
+// Visibility
92
+window.show()?;
93
+window.hide()?;
94
+
95
+// Focus and input
96
+window.focus()?;
97
+window.grab_keyboard()?;
98
+window.ungrab_keyboard()?;
99
+
100
+// Properties
101
+window.set_title("New Title")?;
102
+window.id(); // XWindow
103
+window.size(); // Size
104
+window.depth(); // u8
105
+
106
+// Connection access
107
+window.connection(); // &Connection
108
+```
109
+
110
+### WindowType
111
+
112
+`Normal`, `Dialog`, `Utility`, `Toolbar`, `Dock`, `Desktop`, `Splash`, `Popup`, `Dropdown`, `Tooltip`, `Notification`, `Combo`, `Dnd`.
113
+
114
+## Monitor
115
+
116
+RandR multi-monitor detection.
117
+
118
+```rust
119
+use gartk_x11::{detect_monitors, primary_monitor, monitor_at_point};
120
+use gartk_core::Point;
121
+
122
+// Get all monitors
123
+let monitors = detect_monitors(&conn)?;
124
+
125
+// Primary monitor
126
+let primary = primary_monitor(&conn)?;
127
+
128
+// Monitor at specific point
129
+let monitor = monitor_at_point(&conn, Point::new(100, 100))?;
130
+
131
+// Monitor properties
132
+monitor.name;       // String ("eDP-1", "HDMI-1", etc.)
133
+monitor.rect;       // Rect (position and size)
134
+monitor.is_primary; // bool
135
+```
136
+
137
+## EventLoop
138
+
139
+Blocking event loop with frame limiting.
140
+
141
+```rust
142
+use gartk_x11::{EventLoop, EventLoopConfig};
143
+use gartk_core::InputEvent;
144
+
145
+let config = EventLoopConfig {
146
+    target_fps: 60,
147
+};
148
+
149
+let event_loop = EventLoop::new(conn, config);
150
+
151
+event_loop.run(|event: InputEvent| {
152
+    match event {
153
+        InputEvent::Key(key_event) => { /* ... */ }
154
+        InputEvent::Close => return Ok(false), // Exit loop
155
+        _ => {}
156
+    }
157
+    Ok(true) // Continue running
158
+})?;
159
+```
160
+
161
+## Keyboard
162
+
163
+Keycode translation (evdev-based).
164
+
165
+```rust
166
+use gartk_x11::{key_from_keycode, key_event_from_x11, modifiers_from_x11};
167
+use gartk_core::Key;
168
+
169
+// Low-level
170
+let key = key_from_keycode(keycode);
171
+
172
+// From X11 event
173
+let key_event = key_event_from_x11(&x11_key_event, pressed);
174
+let modifiers = modifiers_from_x11(state);
175
+```
176
+
177
+## Cursor
178
+
179
+Cursor shape management.
180
+
181
+```rust
182
+use gartk_x11::{CursorManager, CursorShape};
183
+
184
+let mut cursor_mgr = CursorManager::new(conn.clone())?;
185
+
186
+// Set cursor for window
187
+cursor_mgr.set_cursor(window.id(), CursorShape::Default)?;
188
+cursor_mgr.set_cursor(window.id(), CursorShape::Pointer)?;
189
+cursor_mgr.set_cursor(window.id(), CursorShape::Text)?;
190
+cursor_mgr.set_cursor(window.id(), CursorShape::Wait)?;
191
+cursor_mgr.set_cursor(window.id(), CursorShape::Move)?;
192
+```
193
+
194
+### CursorShape
195
+
196
+`Default`, `Pointer`, `Text`, `Wait`, `Crosshair`, `Move`, `NotAllowed`, `ResizeNS`, `ResizeEW`, `ResizeNESW`, `ResizeNWSE`, `Grab`, `Grabbing`.