fix: player bar CSS + Windows media keys HWND (v1.17.2)

- layout: overflow:hidden on .app-shell + min-height:0 on sidebar/main/queue
  prevents player bar from being pushed off-screen when window is resized
  below OS minHeight constraint (ignored by some Linux WMs)
- lib.rs: pass main window HWND to souvlaki PlatformConfig on Windows so
  SMTC hooks into the existing Win32 message loop instead of creating its
  own — fixes media keys on Windows without crashing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-03-26 18:15:25 +01:00
parent 65a828e3fa
commit b67c198227
6 changed files with 84 additions and 51 deletions
+63 -48
View File
@@ -252,61 +252,76 @@ pub fn run() {
.build(app)?;
// ── MPRIS2 / OS media controls via souvlaki ──────────────────
// Windows: souvlaki SMTC init requires a valid HWND and a running
// COM message loop, neither of which is available this early in
// setup(). Disabled on Windows until we can defer init post-window.
// mpris_set_metadata / mpris_set_playback no-op via the None branch.
#[cfg(target_os = "windows")]
app.manage(MprisControls::new(None));
#[cfg(not(target_os = "windows"))]
{
use souvlaki::{MediaControlEvent, MediaControls, PlatformConfig};
// On Linux, souvlaki requires a live D-Bus session.
#[cfg(target_os = "linux")]
let dbus_ok = std::env::var("DBUS_SESSION_BUS_ADDRESS")
.map(|v| !v.is_empty())
.unwrap_or(false);
#[cfg(not(target_os = "linux"))]
let dbus_ok = true;
if !dbus_ok {
eprintln!("[Psysonic] No D-Bus session — MPRIS media controls disabled");
app.manage(MprisControls::new(None));
} else {
let config = PlatformConfig {
dbus_name: "psysonic",
display_name: "Psysonic",
hwnd: None,
};
let maybe_controls = match MediaControls::new(config) {
Ok(mut controls) => {
let app_handle = app.handle().clone();
if let Err(e) = controls.attach(move |event: MediaControlEvent| {
let event_name = match event {
MediaControlEvent::Toggle => "media:play-pause",
MediaControlEvent::Play => "media:play-pause",
MediaControlEvent::Pause => "media:play-pause",
MediaControlEvent::Next => "media:next",
MediaControlEvent::Previous => "media:prev",
_ => return,
};
let _ = app_handle.emit(event_name, ());
}) {
eprintln!("[Psysonic] Failed to attach media controls: {e:?}");
// Collect pre-conditions and the platform-specific HWND.
// Returns None early (with a log) on any unrecoverable condition
// so app.manage() always executes exactly once at the bottom.
let maybe_controls: Option<MediaControls> = (|| {
// Linux: requires a live D-Bus session.
#[cfg(target_os = "linux")]
{
let dbus_ok = std::env::var("DBUS_SESSION_BUS_ADDRESS")
.map(|v| !v.is_empty())
.unwrap_or(false);
if !dbus_ok {
eprintln!("[Psysonic] No D-Bus session — MPRIS media controls disabled");
return None;
}
Some(controls)
}
Err(e) => {
eprintln!("[Psysonic] Could not create media controls: {e:?}");
None
// Windows: souvlaki SMTC must hook into the existing Win32
// message loop rather than spinning up its own. Pass the
// main window's HWND so it can do so. If we can't get one,
// skip init (no crash, just no media overlay).
#[cfg(target_os = "windows")]
let hwnd = {
use tauri::Manager;
let h = app.get_webview_window("main")
.and_then(|w| w.hwnd().ok())
.map(|h| h.0 as *mut std::ffi::c_void);
if h.is_none() {
eprintln!("[Psysonic] Could not get HWND — Windows media controls disabled");
return None;
}
h
};
#[cfg(not(target_os = "windows"))]
let hwnd: Option<*mut std::ffi::c_void> = None;
let config = PlatformConfig {
dbus_name: "psysonic",
display_name: "Psysonic",
hwnd,
};
match MediaControls::new(config) {
Ok(mut controls) => {
let app_handle = app.handle().clone();
if let Err(e) = controls.attach(move |event: MediaControlEvent| {
let event_name = match event {
MediaControlEvent::Toggle => "media:play-pause",
MediaControlEvent::Play => "media:play-pause",
MediaControlEvent::Pause => "media:play-pause",
MediaControlEvent::Next => "media:next",
MediaControlEvent::Previous => "media:prev",
_ => return,
};
let _ = app_handle.emit(event_name, ());
}) {
eprintln!("[Psysonic] Failed to attach media controls: {e:?}");
}
Some(controls)
}
Err(e) => {
eprintln!("[Psysonic] Could not create media controls: {e:?}");
None
}
}
};
})();
app.manage(MprisControls::new(maybe_controls));
} // end dbus_ok
}
Ok(())
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Psysonic",
"version": "1.17.1",
"version": "1.17.2",
"identifier": "dev.psysonic.player",
"build": {
"beforeDevCommand": "npm run dev",