1#!/usr/local/bin/python3.8 2 3from SettingsWidgets import SidePage 4from xapp.GSettingsWidgets import * 5from ChooserButtonWidgets import TweenChooserButton, EffectChooserButton 6 7EFFECT_SETS = { 8 "cinnamon": ("traditional", "traditional", "traditional", "none", "none", "none"), 9 "scale": ("scale", "scale", "scale", "scale", "scale", "scale"), 10 "fade": ("fade", "fade", "fade", "scale", "scale", "scale"), 11 "blend": ("blend", "blend", "blend", "scale", "scale", "scale"), 12 "move": ("move", "move", "move", "scale", "scale", "scale"), 13 "flyUp": ("flyUp", "flyDown", "flyDown", "scale", "scale", "scale"), 14 "flyDown": ("flyDown", "flyUp", "flyUp", "scale", "scale", "scale"), 15 "default": ("scale", "scale", "none", "none", "none", "none") 16} 17 18TRANSITIONS_SETS = { 19 "cinnamon": ("easeOutQuad", "easeOutQuad", "easeInQuad", "easeInExpo", "easeNone", "easeInQuad"), 20 "normal": ("easeOutSine", "easeInBack", "easeInSine", "easeInBack", "easeOutBounce", "easeInBack"), 21 "extra": ("easeOutElastic", "easeOutBounce", "easeOutExpo", "easeInExpo", "easeOutElastic", "easeInExpo"), 22 "fade": ("easeOutQuart", "easeInQuart", "easeInQuart", "easeInBack", "easeOutBounce", "easeInBack") 23} 24 25TIME_SETS = { 26 "cinnamon": (100, 120, 160, 100, 100, 100), 27 "slow": (400, 400, 400, 100, 100, 100), 28 "normal": (250, 250, 250, 100, 100, 100), 29 "fast": (100, 100, 100, 100, 100, 100), 30 "default": (250, 250, 150, 400, 400, 400) 31} 32 33COMBINATIONS = { 34 # name effect transition time 35 "cinnamon": ("cinnamon", "cinnamon", "cinnamon"), 36 "scale": ("scale", "normal", "normal"), 37 "fancyScale": ("scale", "extra", "slow"), 38 "fade": ("fade", "fade", "normal"), 39 "blend": ("blend", "fade", "normal"), 40 "move": ("move", "normal", "fast"), 41 "flyUp": ("flyUp", "normal", "fast"), 42 "flyDown": ("flyDown", "normal", "fast"), 43 #for previous versions 44 "default": ("default", "normal", "default") 45} 46 47OPTIONS = ( 48 ("cinnamon", _("Cinnamon")), 49 ("scale", _("Scale")), 50 ("fancyScale", _("Fancy Scale")), 51 ("fade", _("Fade")), 52 ("blend", _("Blend")), 53 ("move", _("Move")), 54 ("flyUp", _("Fly up, down")), 55 ("flyDown", _("Fly down, up")), 56 #for previous versions 57 ("default", _("Default")) 58) 59TYPES = ("map", "close", "minimize", "maximize", "unmaximize", "tile") 60SCHEMA = "org.cinnamon" 61DEP_PATH = "org.cinnamon/desktop-effects" 62KEY_TEMPLATE = "desktop-effects-%s-%s" 63 64class GSettingsTweenChooserButton(TweenChooserButton, PXGSettingsBackend): 65 def __init__(self, schema, key, dep_key): 66 self.key = key 67 self.bind_prop = "tween" 68 self.bind_dir = Gio.SettingsBindFlags.DEFAULT 69 self.bind_object = self 70 71 if schema not in settings_objects: 72 settings_objects[schema] = Gio.Settings.new(schema) 73 self.settings = settings_objects[schema] 74 75 super(GSettingsTweenChooserButton, self).__init__() 76 self.bind_settings() 77 78class GSettingsEffectChooserButton(EffectChooserButton, PXGSettingsBackend): 79 def __init__(self, schema, key, dep_key, options): 80 self.key = key 81 self.bind_prop = "effect" 82 self.bind_dir = Gio.SettingsBindFlags.DEFAULT 83 self.bind_object = self 84 85 if schema not in settings_objects: 86 settings_objects[schema] = Gio.Settings.new(schema) 87 self.settings = settings_objects[schema] 88 89 super(GSettingsEffectChooserButton, self).__init__(options) 90 self.bind_settings() 91 92class Module: 93 name = "effects" 94 category = "appear" 95 comment = _("Control Cinnamon visual effects.") 96 97 def __init__(self, content_box): 98 keywords = _("effects, fancy, window") 99 sidePage = SidePage(_("Effects"), "cs-desktop-effects", keywords, content_box, module=self) 100 self.sidePage = sidePage 101 102 def on_module_selected(self): 103 if not self.loaded: 104 print("Loading Effects module") 105 106 self.sidePage.stack = SettingsStack() 107 self.sidePage.add_widget(self.sidePage.stack) 108 109 self.schema = Gio.Settings(SCHEMA) 110 self.effect_sets = {} 111 for name, sets in COMBINATIONS.items(): 112 self.effect_sets[name] = (EFFECT_SETS[sets[0]], TRANSITIONS_SETS[sets[1]], TIME_SETS[sets[2]]) 113 114 # Enable effects 115 116 page = SettingsPage() 117 self.sidePage.stack.add_titled(page, "effects", _("Enable effects")) 118 119 settings = page.add_section(_("Enable Effects")) 120 121 widget = GSettingsSwitch(_("Window effects"), "org.cinnamon.muffin", "desktop-effects") 122 settings.add_row(widget) 123 124 widget = GSettingsSwitch(_("Effects on dialog boxes"), "org.cinnamon", "desktop-effects-on-dialogs") 125 settings.add_reveal_row(widget, "org.cinnamon", "desktop-effects") 126 127 widget = GSettingsSwitch(_("Effects on menus"), "org.cinnamon", "desktop-effects-on-menus") 128 settings.add_reveal_row(widget, "org.cinnamon", "desktop-effects") 129 130 self.chooser = GSettingsComboBox(_("Effects style"), "org.cinnamon", "desktop-effects-style", OPTIONS) 131 self.chooser.content_widget.connect("changed", self.on_value_changed) 132 settings.add_reveal_row(self.chooser, "org.cinnamon", "desktop-effects") 133 134 widget = GSettingsSwitch(_("Fade effect on Cinnamon scrollboxes (like the Menu application list)"), "org.cinnamon", "enable-vfade") 135 settings.add_row(widget) 136 137 widget = GSettingsSwitch(_("Session startup animation"), "org.cinnamon", "startup-animation") 138 settings.add_row(widget) 139 140 self.schema.connect("changed::desktop-effects", self.on_desktop_effects_enabled_changed) 141 142 # Customize 143 144 page = SettingsPage() 145 self.sidePage.stack.add_titled(page, "customize", _("Customize")) 146 147 box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) 148 label = Gtk.Label() 149 label.set_markup("<b>%s</b>" % _("Customize settings")) 150 box.pack_start(label, False, False, 0) 151 self.custom_switch = Gtk.Switch(active = self.is_custom()) 152 box.pack_end(self.custom_switch, False, False, 0) 153 self.custom_switch.connect("notify::active", self.update_effects) 154 page.add(box) 155 156 self.revealer = Gtk.Revealer() 157 self.revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_DOWN) 158 self.revealer.set_transition_duration(150) 159 page.add(self.revealer) 160 settings = SettingsSection(_("Effect")) 161 self.revealer.add(settings) 162 163 self.size_group = Gtk.SizeGroup.new(Gtk.SizeGroupMode.HORIZONTAL) 164 165 effects = ["none", "scale", "fade", "blend", "move", "flyUp", "flyDown", "traditional"] 166 167 # MAPPING WINDOWS 168 widget = self.make_effect_group(_("Mapping windows"), "map", effects) 169 settings.add_row(widget) 170 171 # CLOSING WINDOWS 172 widget = self.make_effect_group(_("Closing windows"), "close", effects) 173 settings.add_row(widget) 174 175 # MINIMIZING WINDOWS 176 widget = self.make_effect_group(_("Minimizing windows"), "minimize", effects) 177 settings.add_row(widget) 178 179 # MAXIMIZING WINDOWS 180 # effects = ["none", _("None")], ["scale", _("Scale")]] 181 widget = self.make_effect_group(_("Maximizing windows"), "maximize") 182 settings.add_row(widget) 183 184 # UNMAXIMIZING WINDOWS 185 widget = self.make_effect_group(_("Unmaximizing windows"), "unmaximize") 186 settings.add_row(widget) 187 188 # TILING WINDOWS 189 widget = self.make_effect_group(_("Tiling and snapping windows"), "tile") 190 settings.add_row(widget) 191 192 self.update_effects(self.custom_switch, None) 193 194 def make_effect_group(self, group_label, key, effects=None): 195 tmin, tmax, tstep, tdefault = (0, 2000, 50, 200) 196 197 row = SettingsWidget() 198 row.set_spacing(5) 199 200 label = SettingsLabel() 201 label.set_margin_right(5) 202 label.set_markup(group_label) 203 label.props.xalign = 0.0 204 row.pack_start(label, False, False, 0) 205 206 label = Gtk.Label(_("ms")) 207 row.pack_end(label, False, False, 0) 208 209 effect = GSettingsEffectChooserButton(SCHEMA, KEY_TEMPLATE % (key, "effect"), DEP_PATH, effects) 210 self.size_group.add_widget(effect) 211 tween = GSettingsTweenChooserButton(SCHEMA, KEY_TEMPLATE % (key, "transition"), DEP_PATH) 212 self.size_group.add_widget(tween) 213 time = GSettingsSpinButton("", SCHEMA, KEY_TEMPLATE % (key, "time"), dep_key=DEP_PATH, mini=tmin, maxi=tmax, step=tstep, page=tdefault) 214 time.set_border_width(0) 215 time.set_margin_right(0) 216 time.set_margin_left(0) 217 time.set_spacing(0) 218 row.pack_end(time, False, False, 0) 219 row.pack_end(tween, False, False, 0) 220 row.pack_end(effect, False, False, 0) 221 222 return row 223 224 def is_custom(self): 225 effects = [] 226 transitions = [] 227 times = [] 228 229 for i in TYPES: 230 effects.append(self.schema.get_string(KEY_TEMPLATE % (i, "effect"))) 231 transitions.append(self.schema.get_string(KEY_TEMPLATE % (i, "transition"))) 232 times.append(self.schema.get_int(KEY_TEMPLATE % (i, "time"))) 233 234 value = (tuple(effects), tuple(transitions), tuple(times)) 235 return value != self.effect_sets[self.chooser.value] 236 237 def on_value_changed(self, widget): 238 value = self.effect_sets[self.schema.get_string("desktop-effects-style")] 239 j = 0 240 for i in TYPES: 241 self.schema.set_string(KEY_TEMPLATE % (i, "effect"), value[0][j]) 242 self.schema.set_string(KEY_TEMPLATE % (i, "transition"), value[1][j]) 243 self.schema.set_int(KEY_TEMPLATE % (i, "time"), value[2][j]) 244 j += 1 245 246 def update_effects(self, switch, gparam): 247 active = switch.get_active() 248 249 self.revealer.set_reveal_child(active) 250 #when unchecking the checkbutton, reset the values 251 if not active: 252 self.on_value_changed(self.chooser) 253 254 def on_desktop_effects_enabled_changed(self, schema, key): 255 active = schema.get_boolean(key) 256 257 if not active and schema.get_boolean("desktop-effects-on-dialogs"): 258 schema.set_boolean("desktop-effects-on-dialogs", False) 259 260 if not active and schema.get_boolean("desktop-effects-on-menus"): 261 schema.set_boolean("desktop-effects-on-menus", False) 262 263 self.update_effects(self.custom_switch, None) 264