1#!/usr/bin/env ruby 2# 3# ixset -- 4# A nice interface to "xset" to change X server settings 5# 6 7require 'tk' 8 9class Xsettings 10 # 11 # Button actions 12 # 13 def quit 14 @root.destroy 15 end 16 17 def ok 18 writesettings 19 quit 20 end 21 22 def cancel 23 readsettings 24 dispsettings 25 @btn_APPLY.state(:disabled) 26 @btn_CANCEL.state(:disabled) 27 end 28 29 # apply is just "writesettings" 30 def apply 31 writesettings 32 @btn_APPLY.state(:disabled) 33 @btn_CANCEL.state(:disabled) 34 end 35 36 # 37 # Read current settings 38 # 39 def readsettings 40 xfd = open("|xset q", 'r') 41 xfd.readlines.each{|line| 42 fields = line.chomp.strip.split(/\s+/) 43 case fields[0] 44 when "auto" 45 if fields[1] == 'repeat:' 46 @kbdrep = fields[2] 47 @w_kbdrep.set(@kbdrep) 48 @kbdcli = fields[6] 49 end 50 51 when "bell" 52 @bellvol = fields[2] 53 @bellpit = fields[5] 54 @belldur = fields[8] 55 56 when "acceleration:" 57 @mouseacc = fields[1] 58 @mousethr = fields[3] 59 60 when "prefer" 61 if fields[2] == 'yes' 62 @screenbla = 'blank' 63 else 64 @screenbla = 'noblank' 65 end 66 @w_screenbla.set(@screenbla) 67 68 when "timeout:" 69 @screentim = fields[1] 70 @screencyc = fields[3] 71 72 end 73 } 74 75 xfd.close 76 end 77 78 # 79 # Write settings into the X server 80 # 81 def writesettings 82 @bellvol = @w_bellvol.get 83 @bellpit = @w_bellpit.get 84 @belldur = @w_belldur.get 85 86 @kbdrep = @w_kbdrep.get 87 if @kbdrep == 'on' 88 @kbdcli = @w_kbdcli.get 89 else 90 @kbdcli = 'off' 91 end 92 93 @mouseacc = @w_mouseacc.get 94 @mousethr = @w_mousethr.get 95 96 @screentim = @w_screentim.get 97 @screencyc = @w_screencyc.get 98 @screenbla = @w_screenbla.get 99 100 system("xset \ 101 b #{@bellvol} #{@bellpit} #{@belldur} \ 102 c #{@kbdcli} \ 103 r #{@kbdrep} \ 104 m #{@mouseacc} #{@mousethr} \ 105 s #{@screentim} #{@screencyc} \ 106 s #{@screenbla}") 107 end 108 109 # 110 # Sends all settings to the window 111 # 112 def dispsettings 113 @w_bellvol.set(@bellvol) 114 @w_bellpit.set(@bellpit) 115 @w_belldur.set(@belldur) 116 117 @w_kbdonoff.set(@w_kbdrep.get) 118 @w_kbdcli.set(@kbdcli) 119 120 @w_mouseacc.set(@mouseacc) 121 @w_mousethr.set(@mousethr) 122 123 @w_screenblank.set(@w_screenbla.get) 124 @w_screenpat.set(@w_screenbla.get) 125 126 @w_screentim.set(@screentim) 127 @w_screencyc.set(@screencyc) 128 end 129 130 # 131 # Create all windows, and pack them 132 # 133 class LabelEntry 134 def initialize(parent, text, length, range=[]) 135 @frame = TkFrame.new(parent) 136 TkLabel.new(@frame, 'text'=>text).pack('side'=>'left') 137 if range.size > 0 138 @entry = TkSpinbox.new(@frame, 'width'=>length, 'relief'=>'sunken', 139 'from'=>range[0], 'to'=>range[1]) 140 else 141 @entry = TkEntry.new(@frame, 'width'=>length, 'relief'=>'sunken') 142 end 143 @entry.pack('side'=>'right','expand'=>'y', 'fill'=>'x') 144 end 145 def epath 146 @frame 147 end 148 def pack(keys) 149 @frame.pack(keys) 150 end 151 def get 152 @entry.value 153 end 154 def set(value) 155 @entry.delete(0,'end') 156 @entry.insert(0, value) 157 end 158 end 159 160 def createwindows 161 win = self 162 163 # 164 # Buttons 165 # 166 btn_frame = TkFrame.new(@root) 167 buttons = [ 168 @btn_OK = TkButton.new(btn_frame, 'command'=>proc{win.ok}, 169 'default'=>'active', 'text'=>'Ok'), 170 @btn_APPLY = TkButton.new(btn_frame, 'command'=>proc{win.writesettings}, 171 'default'=>'normal', 'text'=>'Apply', 172 'state'=>'disabled'), 173 @btn_CANCEL = TkButton.new(btn_frame, 'command'=>proc{win.cancel}, 174 'default'=>'normal', 'text'=>'Cancel', 175 'state'=>'disabled'), 176 @btn_QUIT = TkButton.new(btn_frame, 'command'=>proc{win.quit}, 177 'default'=>'normal', 'text'=>'Quit') 178 ] 179 buttons.each{|b| b.pack('side'=>'left', 'expand'=>'yes', 'pady'=>5) } 180 181 @root.bind('Return', proc{@btn_OK.flash; @btn_OK.invoke}) 182 @root.bind('Escape', proc{@btn_QUIT.flash; @btn_QUIT.invoke}) 183 @root.bind('1', proc{|w| 184 unless buttons.index(w) 185 @btn_APPLY.state(:normal) 186 @btn_CANCEL.state(:normal) 187 end 188 }, '%W') 189 @root.bind('Key', proc{|w, k| 190 unless buttons.index(w) 191 case k 192 when 'Return', 'Escape', 'Tab', /.*Shift.*/ 193 # do nothing 194 else 195 @btn_APPLY.state(:normal) 196 @btn_CANCEL.state(:normal) 197 end 198 end 199 }, '%W %K') 200 201 # 202 # Bell settings 203 # 204 bell = TkLabelframe.new(@root, 'text'=>'Bell Settings', 205 'padx'=>'1.5m', 'pady'=>'1.5m') 206 @w_bellvol = TkScale.new(bell, 'from'=>0, 'to'=>100, 'length'=>200, 207 'tickinterval'=>20, 'orient'=>'horizontal', 208 'label'=>"Volume (%)") 209 210 f = TkFrame.new(bell) 211 @w_bellpit = LabelEntry.new(f, "Pitch (Hz)", 6, [25, 20000]) 212 @w_bellpit.pack('side'=>'left', 'padx'=>5) 213 @w_belldur = LabelEntry.new(f, "Duration (ms)", 6, [1, 10000]) 214 @w_belldur.pack('side'=>'right', 'padx'=>5) 215 216 @w_bellvol.pack('side'=>'top', 'expand'=>'yes') 217 f.pack('side'=>'top', 'expand'=>'yes') 218 219 # 220 # Keyboard settings 221 # 222 kbdonoff = nil 223 kbdcli = nil 224 kbd = TkLabelframe.new(@root, 'text'=>'Keyboard Repeat Settings', 225 'padx'=>'1.5m', 'pady'=>'1.5m') 226 f = TkFrame.new(kbd) 227 @w_kbdonoff = TkCheckButton.new(f, 'text'=>'On', 'relief'=>'flat', 228 'onvalue'=>'on', 'offvalue'=>'off', 229 'variable'=>@w_kbdrep ) { 230 def self.set(value) 231 if value == 'on' 232 self.select 233 else 234 self.deselect 235 end 236 end 237 pack('side'=>'left', 'expand'=>'yes', 'fill'=>'x', 'padx'=>[0, '1m']) 238 } 239 @w_kbdcli = TkScale.new(f, 'from'=>0, 'to'=>100, 'length'=>200, 240 'tickinterval'=>20, 'orient'=>'horizontal', 241 'label'=>'Click Volume (%)') 242 @w_kbdcli.pack('side'=>'left', 'expand'=>'yes', 243 'fill'=>'x', 'padx'=>['1m', 0]) 244 f.pack('side'=>'top', 'expand'=>'yes', 'pady'=>2, 'fill'=>'x') 245 246 # 247 # Mouse settings 248 # 249 mouse = TkLabelframe.new(@root, 'text'=>'Mouse Settings', 250 'padx'=>'1.5m', 'pady'=>'1.5m') 251 f = TkFrame.new(mouse) 252 @w_mouseacc = LabelEntry.new(f, 'Acceleration', 5) 253 @w_mouseacc.pack('side'=>'left', 'padx'=>[0, '1m']) 254 @w_mousethr = LabelEntry.new(f, 'Threshold (pixels)', 3, [1, 2000]) 255 @w_mousethr.pack('side'=>'right', 'padx'=>['1m', 0]) 256 f.pack('side'=>'top', 'expand'=>'yes') 257 258 # 259 # Screen Saver settings 260 # 261 screen = TkLabelframe.new(@root, 'text'=>'Screen-saver Settings', 262 'padx'=>'1.5m', 'pady'=>'1.5m') 263 @w_screenblank = TkRadioButton.new(screen, 'text'=>'Blank', 264 'relief'=>'flat', 'anchor'=>'w', 265 'variable'=>@w_screenbla, 266 'value'=>'blank') { 267 def self.set(value) 268 if value == 'blank' 269 self.select 270 else 271 self.deselect 272 end 273 end 274 } 275 276 @w_screenpat = TkRadioButton.new(screen, 'text'=>'Pattern', 277 'relief'=>'flat', 'anchor'=>'w', 278 'variable'=>@w_screenbla, 279 'value'=>'noblank') { 280 def self.set(value) 281 if value != 'blank' 282 self.select 283 else 284 self.deselect 285 end 286 end 287 } 288 289 @w_screentim = LabelEntry.new(screen, 'Timeout (s)', 5, [1, 100000]) 290 @w_screencyc = LabelEntry.new(screen, 'Cycle (s)', 5, [1, 100000]) 291 292 Tk.grid(@w_screenblank, @w_screentim, 'sticky'=>'e') 293 Tk.grid(@w_screenpat, @w_screencyc, 'sticky'=>'e') 294 TkGrid.configure(@w_screenblank, @w_screenpat, 'sticky'=>'ew') 295 296 # 297 # Main window 298 # 299 param = { 300 'side'=>'top', 'fill'=>'both', 'expand'=>'yes', 301 'padx'=>'1m', 'pady'=>'1m' 302 } 303 btn_frame.pack('side'=>'top', 'fill'=>'both') 304 bell.pack(param) 305 kbd.pack(param) 306 mouse.pack(param) 307 screen.pack(param) 308 309 # 310 # Let the user resize our window 311 # 312 @root.minsize(10,10) 313 end 314 315 def initialize(title) 316 @root = TkRoot.new('title'=>title) 317 318 @kbdrep = 'on' 319 @w_kbdrep = TkVariable.new(@kbdrep) 320 def @w_kbdrep.get 321 self.value 322 end 323 def @w_kbdrep.set(val) 324 self.value=val 325 end 326 327 @kbdcli = 0 328 329 @bellvol = 100 330 @bellpit = 440 331 @belldur = 100 332 333 @mouseacc = "3/1" 334 @mousethr = 4 335 336 @screenbla = "blank" 337 @w_screenbla = TkVariable.new(@screenbla) 338 def @w_screenbla.get 339 self.value 340 end 341 def @w_screenbla.set(val) 342 self.value=val 343 end 344 345 @screentim = 600 346 @screencyc = 600 347 348 # 349 # Listen what "xset" tells us... 350 # 351 readsettings 352 353 # 354 # Create all windows 355 # 356 createwindows 357 358 # 359 # Write xset parameters 360 # 361 dispsettings 362 end 363end 364 365Xsettings.new(File.basename($0,'.rb')) 366 367Tk.mainloop 368