Commit 872583f
3
files
+42
added
-6
deleted
@@ -363,7 +363,13 @@ fn main() -> Result<(), Box<dyn Error>> {
363
363
.wrapping_add(state.workspaces as u64 ^ ((state.current_ws as u64) << 8));
364
364
let sig = (open, power_open, state.clock.clone(), th);
365
365
let animating = osd.visible() || notes.visible();
366
- if !frame.events.is_empty() || animating || open || sig != last_sig {
366
+ // Ruch myszy nad panelem NIE wymusza przerysowania (brak hoverów) — to było
367
+ // głównym źródłem „5 FPS”: każde zdarzenie ruchu odświeżało bufor 1920×680.
368
+ let interactive = frame
369
+ .events
370
+ .iter()
371
+ .any(|e| !matches!(e, Event::PointerMotion { .. }));
372
+ if interactive || animating || open || sig != last_sig {
367
373
frame.request_frame();
368
374
}
369
375
last_sig = sig;
@@ -167,8 +167,9 @@ pub fn spawn_drm(
167
167
let (cursor_rgba, cw, ch) = cursor_image();
168
168
let mut hw_cursor = true;
169
169
for i in 0..sizes.len() {
170
- // Próba ustawienia obrazu (potem chowamy); gdy sterownik nie umie — kursor programowy.
171
- if !backend.set_cursor_image(i, &cursor_rgba, cw, ch, 0, 0) || !backend.hide_cursor(i) {
170
+ // Obraz startowy poza ekranem (nie mruga, nie chowamy osobno ioctlem);
171
+ // gdy sterownik nie umie kursora sprzętowego — zostaje programowy.
172
+ if !backend.set_cursor_image(i, &cursor_rgba, cw, ch, -1000, -1000) {
172
173
hw_cursor = false;
173
174
}
174
175
}
@@ -178,7 +179,8 @@ pub fn spawn_drm(
178
179
libluna_i18n::tr("DRM hardware cursor unavailable; using software cursor")
179
180
);
180
181
}
181
- let mut cursor_shown = vec![false; sizes.len()];
182
+ // Obraz ustawiony → ruchy realizujemy samym `MOVE`.
183
+ let mut cursor_shown = vec![hw_cursor; sizes.len()];
182
184
183
185
// Diagnostyka (SELENE_STATS=1): fps i rozbicie czasu na render/present/wait_flip.
184
186
let stats = std::env::var("SELENE_STATS").is_ok();
@@ -284,8 +284,14 @@ fn window_geometry(state: &State, slot: usize) -> Option<(f64, f64, f64, f64)> {
284
284
}
285
285
286
286
fn content_local(state: &State, slot: usize, pos: Point) -> (f64, f64) {
287
- match window_geometry(state, slot) {
288
- Some((x, y, _, _)) => (pos.x - x, pos.y - (y + TITLEBAR)),
287
+ // Używamy `content()` — dla paneli/popupów pasek tytułu ma wysokość 0, więc
288
+ // współrzędne nie są przesunięte (wcześniej odejmowano `TITLEBAR` zawsze).
289
+ let windows = state.windows.lock_or_recover();
290
+ match windows.get(slot) {
291
+ Some(w) => {
292
+ let c = w.content();
293
+ (pos.x - c.x(), pos.y - c.y())
294
+ }
289
295
None => (pos.x, pos.y),
290
296
}
291
297
}
@@ -1242,6 +1248,28 @@ mod tests {
1242
1248
}
1243
1249
}
1244
1250
1251
+ #[test]
1252
+ fn content_local_does_not_offset_layer_surfaces() {
1253
+ // Panel (powierzchnia warstwowa) nie ma paska tytułu — współrzędne bez przesunięcia.
1254
+ let mut s = State::default();
1255
+ let mut w = sample_window();
1256
+ w.layer = true;
1257
+ w.x = 0.0;
1258
+ w.y = 0.0;
1259
+ s.windows.lock_or_recover().push(w);
1260
+ assert_eq!(content_local(&s, 0, Point::new(50.0, 20.0)), (50.0, 20.0));
1261
+ }
1262
+
1263
+ #[test]
1264
+ fn content_local_offsets_titlebar_for_windows() {
1265
+ let mut s = State::default();
1266
+ s.windows.lock_or_recover().push(sample_window()); // x=100, y=50
1267
+ assert_eq!(
1268
+ content_local(&s, 0, Point::new(120.0, 80.0)),
1269
+ (20.0, 80.0 - (50.0 + TITLEBAR))
1270
+ );
1271
+ }
1272
+
1245
1273
#[test]
1246
1274
fn workspace_predicate_switch_and_move() {
1247
1275
let mut s = State::default();