1#!/usr/local/bin/python3.8 2 3import gi 4gi.require_version("Gtk", "3.0") 5 6from gi.repository import Gtk 7from SettingsWidgets import SidePage, GSettingsDependencySwitch, DependencyCheckInstallButton, GSettingsSoundFileChooser 8from xapp.GSettingsWidgets import * 9 10DPI_FACTOR_LARGE = 1.25 11DPI_FACTOR_NORMAL = 1.0 12 13HIGH_CONTRAST_THEME = "HighContrast" 14KEY_TEXT_SCALING_FACTOR = "text-scaling-factor" 15KEY_GTK_THEME = "gtk-theme" 16KEY_GTK_THEME_BACKUP = "gtk-theme-backup" 17KEY_ICON_THEME = "icon-theme" 18KEY_ICON_THEME_BACKUP = "icon-theme-backup" 19KEY_WM_THEME = "theme" 20KEY_WM_THEME_BACKUP = "theme-backup" 21 22 23class Module: 24 name = "universal-access" 25 comment = _("Configure accessibility features") 26 category = "prefs" 27 28 def __init__(self, content_box): 29 keywords = _("magnifier, talk, access, zoom, keys, contrast"); 30 sidePage = SidePage(_("Accessibility"), "cs-universal-access", keywords, content_box, module=self) 31 self.sidePage = sidePage 32 33 def on_module_selected(self): 34 if not self.loaded: 35 print("Loading Accessibility module") 36 37 self.iface_settings = Gio.Settings(schema_id="org.cinnamon.desktop.interface") 38 self.wm_settings = Gio.Settings(schema_id="org.cinnamon.desktop.wm.preferences"); 39 self.mag_settings = Gio.Settings(schema_id="org.cinnamon.desktop.a11y.magnifier"); 40 41 self.sidePage.stack = SettingsStack() 42 self.sidePage.add_widget(self.sidePage.stack) 43 44#### Visual 45 46 page = SettingsPage() 47 self.sidePage.stack.add_titled(page, "visual", _("Visual")) 48 49# Visual Aids 50 51 settings = page.add_section(_("Visual Aids")) 52 53 switch = Switch(_("High contrast")) 54 self.iface_settings.bind_with_mapping(KEY_GTK_THEME, 55 switch.content_widget, "active", 56 Gio.SettingsBindFlags.DEFAULT, 57 self.hi_con_get_mapping, 58 self.hi_con_set_mapping) 59 settings.add_row(switch) 60 61 switch = Switch(_("Large text")) 62 self.iface_settings.bind_with_mapping(KEY_TEXT_SCALING_FACTOR, 63 switch.content_widget, "active", 64 Gio.SettingsBindFlags.DEFAULT, 65 self.lg_text_get_mapping, 66 self.lg_text_set_mapping) 67 settings.add_row(switch) 68 69 switch = GSettingsDependencySwitch(_("Screen reader"), 70 "org.cinnamon.desktop.a11y.applications", 71 "screen-reader-enabled", 72 None, 73 ["orca"], 74 ["gnome-orca"]) 75 settings.add_row(switch) 76 77# Desktop Zoom 78 79 settings = page.add_section(_("Desktop Zoom")) 80 81 switch = GSettingsSwitch(_("Enable zoom"), "org.cinnamon.desktop.a11y.applications", "screen-magnifier-enabled") 82 settings.add_row(switch) 83 84 spin = GSettingsSpinButton(_("Magnification"), "org.cinnamon.desktop.a11y.magnifier", "mag-factor", None, 1.0, 15.0, step=0.5) 85 settings.add_reveal_row(spin, "org.cinnamon.desktop.a11y.applications", "screen-magnifier-enabled") 86 87 zoom_key_options = [["", _("Disabled")], ["<Alt>", "<Alt>"],["<Super>", "<Super>"],["<Control>", "<Control>"], ["<Shift>", "<Shift>"]] 88 widget = GSettingsComboBox(_("Mouse wheel modifier"), "org.cinnamon.desktop.wm.preferences", "mouse-button-zoom-modifier", zoom_key_options) 89 widget.set_tooltip_text(_("While this modifier is pressed, mouse scrolling will increase or decrease zoom.")) 90 settings.add_reveal_row(widget, "org.cinnamon.desktop.a11y.applications", "screen-magnifier-enabled") 91 92 switch = GSettingsSwitch(_("Scroll at screen edges"), "org.cinnamon.desktop.a11y.magnifier", "scroll-at-edges") 93 settings.add_reveal_row(switch, "org.cinnamon.desktop.a11y.applications", "screen-magnifier-enabled") 94 95 mouse_track_options = [["centered", _("Keep cursor centered")], 96 ["proportional", _("Cursor moves with contents")], 97 ["push", _("Cursor pushes contents around")]] 98 99 widget = GSettingsComboBox(_("Mouse tracking mode"), "org.cinnamon.desktop.a11y.magnifier", "mouse-tracking", mouse_track_options) 100 settings.add_reveal_row(widget, "org.cinnamon.desktop.a11y.applications", "screen-magnifier-enabled") 101 102 switch = GSettingsSwitch(_("Lens mode"), "org.cinnamon.desktop.a11y.magnifier", "lens-mode") 103 settings.add_reveal_row(switch, "org.cinnamon.desktop.a11y.applications", "screen-magnifier-enabled") 104 105 self.zoom_stack = SettingsStack() 106 self.zoom_stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE) 107 108 lens_shape_options = [["square", _("Square")], 109 ["horizontal", _("Horizontal strip")], 110 ["vertical", _("Vertical strip")]] 111 112 widget = GSettingsComboBox(_("Lens shape"), "org.cinnamon.desktop.a11y.magnifier", "lens-shape", lens_shape_options) 113 self.zoom_stack.add_named(widget, "shape") 114 115 screen_pos_options = [["full-screen", _("Full screen")], 116 ["top-half", _("Top half")], 117 ["bottom-half", _("Bottom half")], 118 ["left-half", _("Left half")], 119 ["right-half", _("Right half")]] 120 121 widget = GSettingsComboBox(_("Screen position"), "org.cinnamon.desktop.a11y.magnifier", "screen-position", screen_pos_options) 122 self.zoom_stack.add_named(widget, "screen") 123 124 settings.add_reveal_row(self.zoom_stack, "org.cinnamon.desktop.a11y.applications", "screen-magnifier-enabled") 125 126 self.mag_settings.bind_with_mapping("lens-mode", 127 self.zoom_stack, "visible-child-name", 128 Gio.SettingsBindFlags.GET, 129 self.zoom_stack_get, 130 None) 131 132 if (self.mag_settings.get_boolean("lens-mode")): 133 self.zoom_stack.set_visible_child_name("shape") 134 else: 135 self.zoom_stack.set_visible_child_name("screen") 136 137#### Keyboard 138 139 page = SettingsPage() 140 self.sidePage.stack.add_titled(page, "keyboard", _("Keyboard")) 141 142# Virtual keyboard 143 144 settings = page.add_section(_("Virtual keyboard")) 145 146 switch = GSettingsSwitch(_("Enable the on-screen keyboard"), 147 "org.cinnamon.desktop.a11y.applications", 148 "screen-keyboard-enabled", 149 None) 150 151 settings.add_row(switch) 152 153 keyboard_type_options = [["tablet", _("Tablet")], 154 ["touch", _("Touch")], 155 ["fullscale", _("Full scale")], 156 ["scan", _("Scanning")]] 157 158 widget = GSettingsComboBox(_("Keyboard layout"), "org.cinnamon.keyboard", "keyboard-type", keyboard_type_options) 159 settings.add_reveal_row(widget, "org.cinnamon.desktop.a11y.applications", "screen-keyboard-enabled") 160 161 keyboard_position_options = [["bottom", _("At the bottom of the screen")], 162 ["top", _("At the top of the screen")]] 163 widget = GSettingsComboBox(_("Keyboard position"), "org.cinnamon.keyboard", "keyboard-position", keyboard_position_options) 164 settings.add_reveal_row(widget, "org.cinnamon.desktop.a11y.applications", "screen-keyboard-enabled") 165 166 keyboard_size_options = [[4, _("A quarter of the screen")], 167 [3, _("A third of the screen")], 168 [2, _("Half of the screen")]] 169 170 widget = GSettingsComboBox(_("Keyboard size"), "org.cinnamon.keyboard", "keyboard-size", keyboard_size_options) 171 settings.add_reveal_row(widget, "org.cinnamon.desktop.a11y.applications", "screen-keyboard-enabled") 172 173 activation_mode_options = [["accessible", _("Show the keyboard any time something expects input")], 174 ["on-demand", _("Show keyboard only when the user activates it")]]; 175 176 widget = GSettingsComboBox(_("Activation mode"), "org.cinnamon.keyboard", "activation-mode", activation_mode_options) 177 settings.add_reveal_row(widget, "org.cinnamon.desktop.a11y.applications", "screen-keyboard-enabled") 178 179# Keyboard indicators 180 181 settings = page.add_section(_("Keyboard indicators")) 182 183 switch = GSettingsSwitch(_("Use visual indicator on Caps and Num Lock"), 184 "org.cinnamon.desktop.a11y.keyboard", 185 "togglekeys-enable-osd") 186 187 settings.add_row(switch) 188 189 switch = GSettingsSwitch(_("Use audio indicator on Caps and Num Lock"), 190 "org.cinnamon.desktop.a11y.keyboard", 191 "togglekeys-enable-beep") 192 193 settings.add_row(switch) 194 195 sound_picker = GSettingsSoundFileChooser(_("Sound to use Caps or Num Lock on"), 196 "org.cinnamon.desktop.a11y.keyboard", 197 "togglekeys-sound-on") 198 settings.add_reveal_row(sound_picker, "org.cinnamon.desktop.a11y.keyboard", "togglekeys-enable-beep") 199 200 sound_picker = GSettingsSoundFileChooser(_("Sound to use Caps or Num Lock off"), 201 "org.cinnamon.desktop.a11y.keyboard", 202 "togglekeys-sound-off") 203 settings.add_reveal_row(sound_picker, "org.cinnamon.desktop.a11y.keyboard", "togglekeys-enable-beep") 204 205 settings = page.add_section(_("Event feedback (required for typing assistance alerts)")) 206 207 switch = GSettingsSwitch(_("Enable visual alerts"), 208 "org.cinnamon.desktop.wm.preferences", 209 "visual-bell") 210 settings.add_row(switch) 211 212 visual_bell_options = [["fullscreen-flash", _("Flash the entire monitor")], 213 ["frame-flash", _("Flash the active window")]] 214 215 widget = GSettingsComboBox(_("Visual style"), "org.cinnamon.desktop.wm.preferences", "visual-bell-type", visual_bell_options) 216 settings.add_reveal_row(widget, "org.cinnamon.desktop.wm.preferences", "visual-bell") 217 218 switch = GSettingsSwitch(_("Enable audio alerts"), 219 "org.cinnamon.desktop.wm.preferences", 220 "audible-bell") 221 settings.add_row(switch) 222 223 sound_picker = GSettingsSoundFileChooser(_("Sound to use for window alerts"), 224 "org.cinnamon.desktop.wm.preferences", 225 "bell-sound") 226 settings.add_reveal_row(sound_picker, "org.cinnamon.desktop.wm.preferences", "audible-bell") 227 228#### Typing Assistance 229 230 page = SettingsPage() 231 self.sidePage.stack.add_titled(page, "typing", _("Typing assistance")) 232 233# Stickykeys 234 235 settings = page.add_section(_("Sticky keys")) 236 237 switch = GSettingsSwitch(_("Treat a sequence of modifier keys as a combination"), 238 "org.cinnamon.desktop.a11y.keyboard", 239 "stickykeys-enable", 240 None) 241 242 settings.add_row(switch) 243 244 switch = GSettingsSwitch(_("Disable if two modifiers are pressed together"), 245 "org.cinnamon.desktop.a11y.keyboard", 246 "stickykeys-two-key-off", 247 None) 248 249 settings.add_reveal_row(switch, "org.cinnamon.desktop.a11y.keyboard", "stickykeys-enable") 250 251 switch = GSettingsSwitch(_("Alert when a modifier key is pressed"), 252 "org.cinnamon.desktop.a11y.keyboard", 253 "stickykeys-modifier-beep", 254 "org.cinnamon.desktop.sound/event-sounds") 255 256 settings.add_reveal_row(switch, "org.cinnamon.desktop.a11y.keyboard", "stickykeys-enable") 257 258# Slowkeys 259 260 settings = page.add_section(_("Slow keys")) 261 262 switch = GSettingsSwitch(_("Put a delay between when a key is pressed and when it is accepted"), 263 "org.cinnamon.desktop.a11y.keyboard", 264 "slowkeys-enable", 265 None) 266 267 settings.add_row(switch) 268 269 switch = GSettingsSwitch(_("Alert when a key is pressed"), 270 "org.cinnamon.desktop.a11y.keyboard", 271 "slowkeys-beep-press", 272 "org.cinnamon.desktop.sound/event-sounds") 273 274 settings.add_reveal_row(switch, "org.cinnamon.desktop.a11y.keyboard", "slowkeys-enable") 275 276 switch = GSettingsSwitch(_("Alert when a key is accepted"), 277 "org.cinnamon.desktop.a11y.keyboard", 278 "slowkeys-beep-accept", 279 "org.cinnamon.desktop.sound/event-sounds") 280 281 settings.add_reveal_row(switch, "org.cinnamon.desktop.a11y.keyboard", "slowkeys-enable") 282 283 switch = GSettingsSwitch(_("Alert when a key is rejected"), 284 "org.cinnamon.desktop.a11y.keyboard", 285 "slowkeys-beep-reject", 286 "org.cinnamon.desktop.sound/event-sounds") 287 288 settings.add_reveal_row(switch, "org.cinnamon.desktop.a11y.keyboard", "slowkeys-enable") 289 290 slider = GSettingsRange(_("Acceptance delay"), 291 "org.cinnamon.desktop.a11y.keyboard", 292 "slowkeys-delay", 293 _("Short"), _("Long"), 294 0, 500, 10, show_value=False) 295 296 settings.add_reveal_row(slider, "org.cinnamon.desktop.a11y.keyboard", "slowkeys-enable") 297 298# Bouncekeys 299 300 settings = page.add_section(_("Bounce keys")) 301 302 switch = GSettingsSwitch(_("Ignore fast duplicate keypresses"), 303 "org.cinnamon.desktop.a11y.keyboard", 304 "bouncekeys-enable", 305 None) 306 307 settings.add_row(switch) 308 309 switch = GSettingsSwitch(_("Alert when a key is rejected"), 310 "org.cinnamon.desktop.a11y.keyboard", 311 "bouncekeys-beep-reject", 312 "org.cinnamon.desktop.sound/event-sounds") 313 314 settings.add_reveal_row(switch, "org.cinnamon.desktop.a11y.keyboard", "bouncekeys-enable") 315 316 slider = GSettingsRange(_("Acceptance delay"), 317 "org.cinnamon.desktop.a11y.keyboard", 318 "bouncekeys-delay", 319 _("Short"), _("Long"), 320 0, 900, 10, show_value=False) 321 322 settings.add_reveal_row(slider, "org.cinnamon.desktop.a11y.keyboard", "bouncekeys-enable") 323 324#### Pointing and Clicking 325 326 page = SettingsPage() 327 self.sidePage.stack.add_titled(page, "mouse", _("Mouse")) 328 329# Mousekeys 330 331 settings = page.add_section(_("Mouse keys")) 332 333 switch = GSettingsSwitch(_("Control the pointer using the keypad"), 334 "org.cinnamon.desktop.a11y.keyboard", 335 "mousekeys-enable", 336 None) 337 338 settings.add_row(switch) 339 340 slider = GSettingsRange(_("Initial delay"), 341 "org.cinnamon.desktop.a11y.keyboard", 342 "mousekeys-init-delay", 343 _("Shorter"), _("Longer"), 344 10, 2000, 10, show_value=False) 345 346 settings.add_reveal_row(slider, "org.cinnamon.desktop.a11y.keyboard", "mousekeys-enable") 347 348 slider = GSettingsRange(_("Acceleration time"), 349 "org.cinnamon.desktop.a11y.keyboard", 350 "mousekeys-accel-time", 351 _("Shorter"), _("Longer"), 352 10, 2000, 10, show_value=False) 353 354 settings.add_reveal_row(slider, "org.cinnamon.desktop.a11y.keyboard", "mousekeys-enable") 355 356 slider = GSettingsRange(_("Maximum speed"), 357 "org.cinnamon.desktop.a11y.keyboard", 358 "mousekeys-max-speed", 359 _("Slower"), _("Faster"), 360 1, 500, 1, show_value=False) 361 362 settings.add_reveal_row(slider, "org.cinnamon.desktop.a11y.keyboard", "mousekeys-enable") 363 364# Dependency Checker 365 366 settings = page.add_reveal_section(_("Simulated secondary click and hover click")) 367 self.dc_section = settings 368 369 install_widget = SettingsWidget() 370 371 self.dep_button = DependencyCheckInstallButton(_("Checking dependencies"), 372 _("Please install: %s") % ("mousetweaks"), 373 ["mousetweaks"], 374 Gtk.Alignment(), 375 self.on_dep_satisfied) 376 377 install_widget.pack_start(self.dep_button, True, False, 0) 378 379 settings.add_row(install_widget) 380 381 self.dc_section._revealer.set_reveal_child(True) 382 383# Secondary click 384 385 settings = page.add_reveal_section(_("Simulated secondary click")) 386 self.ssc_section = settings 387 388 switch = GSettingsSwitch(_("Trigger a secondary click by holding down the primary button"), 389 "org.cinnamon.desktop.a11y.mouse", 390 "secondary-click-enabled", 391 None) 392 393 settings.add_row(switch) 394 395 slider = GSettingsRange(_("Acceptance delay"), 396 "org.cinnamon.desktop.a11y.mouse", 397 "secondary-click-time", 398 _("Shorter"), _("Longer"), 399 0.5, 3.0, 0.1, show_value=False) 400 401 settings.add_reveal_row(slider, "org.cinnamon.desktop.a11y.mouse", "secondary-click-enabled") 402 403# Hover Click 404 405 settings = page.add_reveal_section(_("Hover click")) 406 self.hc_section = settings 407 408 switch = GSettingsSwitch(_("Trigger a click when the pointer hovers"), 409 "org.cinnamon.desktop.a11y.mouse", 410 "dwell-click-enabled", 411 None) 412 413 settings.add_row(switch) 414 415 slider = GSettingsRange(_("Delay"), 416 "org.cinnamon.desktop.a11y.mouse", 417 "dwell-time", 418 _("Short"), _("Long"), 419 0.2, 3.0, 0.1, show_value=False) 420 421 settings.add_reveal_row(slider, "org.cinnamon.desktop.a11y.mouse", "dwell-click-enabled") 422 423 slider = GSettingsRange(_("Motion threshold"), 424 "org.cinnamon.desktop.a11y.mouse", 425 "dwell-threshold", 426 _("Small"), _("Large"), 427 1, 30, 1, show_value=False) 428 429 settings.add_reveal_row(slider, "org.cinnamon.desktop.a11y.mouse", "dwell-click-enabled") 430 431 def on_dep_satisfied(self): 432 self.ssc_section._revealer.set_reveal_child(True) 433 self.hc_section._revealer.set_reveal_child(True) 434 self.dc_section._revealer.destroy() 435 436 def zoom_stack_get(self, lens_mode): 437 ret = "screen" 438 439 if lens_mode: 440 ret = "shape" 441 else: 442 ret = "screen" 443 444 return ret 445 446 def hi_con_get_mapping(self, string): 447 return string == HIGH_CONTRAST_THEME 448 449 def hi_con_set_mapping(self, active): 450 ret = None 451 452 if active: 453 ret = HIGH_CONTRAST_THEME 454 455 theme = self.iface_settings.get_string(KEY_GTK_THEME) 456 self.iface_settings.set_string(KEY_GTK_THEME_BACKUP, theme) 457 458 theme = self.iface_settings.get_string(KEY_ICON_THEME) 459 self.iface_settings.set_string(KEY_ICON_THEME_BACKUP, theme) 460 self.iface_settings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME) 461 462 theme = self.wm_settings.get_string(KEY_WM_THEME) 463 self.wm_settings.set_string(KEY_WM_THEME_BACKUP, theme) 464 self.wm_settings.set_string(KEY_WM_THEME, HIGH_CONTRAST_THEME) 465 else: 466 ret = self.iface_settings.get_string(KEY_GTK_THEME_BACKUP) 467 468 theme = self.iface_settings.get_string(KEY_ICON_THEME_BACKUP) 469 self.iface_settings.set_string(KEY_ICON_THEME, theme) 470 471 theme = self.wm_settings.get_string(KEY_WM_THEME_BACKUP) 472 self.wm_settings.set_string(KEY_WM_THEME, theme) 473 474 return ret 475 476 def lg_text_get_mapping(self, factor): 477 return factor > DPI_FACTOR_NORMAL 478 479 def lg_text_set_mapping(self, active): 480 ret = None 481 482 if active: 483 ret = DPI_FACTOR_LARGE 484 else: 485 ret = self.iface_settings.get_default_value(KEY_TEXT_SCALING_FACTOR).get_double() 486 487 return ret 488