fix(settings): add Close button to settings dialog for WM compatibility (fixes #323) (#356)

Some window managers (on both X11 and Wayland) hide the title-bar close
button for Gtk.Dialog windows that have no action buttons. The previous
fix (PR #333) added set_decorated(True) which was not sufficient.

This adds an explicit Close action button to the dialog so users always
have a visible way to dismiss it, regardless of WM behavior. The
instant-apply pattern is preserved — settings still apply immediately
on change.
This commit is contained in:
Jatin K Malik
2026-03-27 11:29:18 -07:00
committed by GitHub
parent 5b53e850dd
commit fd33a9a4ae
2 changed files with 19 additions and 7 deletions
+7 -2
View File
@@ -8,7 +8,7 @@ UX Design Notes:
- Follows GNOME Human Interface Guidelines (HIG) for modern desktop look
- Uses preference-page style layout with clearly grouped sections
- Settings apply immediately when changed (instant-apply pattern)
- No action buttons needed - use title bar close button
- Close button provided for WM compatibility (some WMs hide title bar close)
- Provides real-time progress feedback for recognition state
- Multi-modal feedback (text + icon + audio level) for accessibility
- Modal dialog for model downloads (explicit confirmation for large downloads)
@@ -727,6 +727,11 @@ class SettingsDialog(Gtk.Dialog):
):
super().__init__(title="Vocalinux Settings", transient_for=parent, flags=0)
self.set_decorated(True) # Force window decorations (close button) on all WMs
# Add a Close action button so the dialog always has a visible way to
# dismiss it, even on window managers that hide the title-bar close
# button for Gtk.Dialog windows without action buttons (fixes #323).
self.add_button("Close", Gtk.ResponseType.CLOSE)
self.config_manager = config_manager
self.speech_engine = speech_engine
self.shortcut_update_callback = shortcut_update_callback
@@ -742,7 +747,7 @@ class SettingsDialog(Gtk.Dialog):
# Setup CSS styling
_setup_css()
# Dialog configuration - no action buttons needed (use title bar close)
# Dialog configuration - Close button added above for WM compatibility
# Calculate dialog size
display = Gdk.Display.get_default()
if display:
+12 -5
View File
@@ -262,8 +262,14 @@ class TestSettingsDialogInstantApply(unittest.TestCase):
self.assertIn("def _auto_apply_settings(self", source_code)
def test_settings_dialog_no_action_buttons(self):
"""Test that SettingsDialog uses no action buttons (title bar close only)."""
def test_settings_dialog_has_close_button_only(self):
"""Test that SettingsDialog has a Close button but no Apply button.
A Close button is required for window managers that hide the title bar
close button on Gtk.Dialog windows (fixes #323). The instant-apply
pattern means settings are applied immediately, so no Apply button is
needed.
"""
import os
source_path = os.path.join(
@@ -277,11 +283,12 @@ class TestSettingsDialogInstantApply(unittest.TestCase):
with open(source_path, "r") as f:
source_code = f.read()
# Should NOT have action buttons - uses title bar close (instant-apply pattern)
self.assertNotIn("_Close", source_code)
# Should have a Close button for WM compatibility
self.assertIn("ResponseType.CLOSE", source_code)
# Should NOT have Apply button - uses instant-apply pattern
self.assertNotIn("_Apply", source_code)
self.assertNotIn("ResponseType.APPLY", source_code)
self.assertNotIn("ResponseType.CLOSE", source_code)
def test_settings_dialog_no_revert_settings(self):
"""Test that SettingsDialog does NOT have _revert_settings (removed)."""