Last active
April 21, 2016 03:35
-
-
Save wfpaisa/b6b4398bd147ce6b93d7d04f34379c6d to your computer and use it in GitHub Desktop.
screenkey linux personalizando, permitiendo solo comando y agregando el texto espacio en blanco: /lib/python2.7/site-packages/Screenkey
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) 2010 Pablo Seminario <[email protected]> | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# for arabic characters | |
# -*- coding: utf-8 -*- | |
import threading | |
import time | |
import sys | |
import subprocess | |
import modmap | |
import gtk | |
from Xlib import X, XK, display | |
from Xlib.ext import record | |
from Xlib.protocol import rq | |
MODE_RAW = 0 | |
MODE_NORMAL = 1 | |
MODE_SOLOCOMANDO = 2 | |
REPLACE_KEYS = { | |
'XK_Escape':_('Esc '), | |
'XK_Tab':u'\u21B9 ', | |
'XK_Return':u'\u23CE ', | |
'XK_Space':u' ', | |
'XK_Caps_Lock':_('Caps '), | |
'XK_F1':u'F1 ', | |
'XK_F2':u'F2 ', | |
'XK_F3':u'F3 ', | |
'XK_F4':u'F4 ', | |
'XK_F5':u'F5 ', | |
'XK_F6':u'F6 ', | |
'XK_F7':u'F7 ', | |
'XK_F8':u'F8 ', | |
'XK_F9':u'F9 ', | |
'XK_F10':u'F10 ', | |
'XK_F11':u'F11 ', | |
'XK_F12':u'F12 ', | |
'XK_Home':_('Home '), | |
'XK_Up':u'\u2191', | |
'XK_Page_Up':_('PgUp '), | |
'XK_Left':u'\u2190', | |
'XK_Right':u'\u2192', | |
'XK_End':_('End '), | |
'XK_Down':u'\u2193', | |
'XK_Next':_('PgDn '), | |
'XK_Insert':_('Ins '), | |
'XK_Delete':_('Del '), | |
'XK_KP_Home':u'(7)', | |
'XK_KP_Up':u'(8)', | |
'XK_KP_Prior':u'(9)', | |
'XK_KP_Left':u'(4)', | |
'XK_KP_Right':u'(6)', | |
'XK_KP_End':u'(1)', | |
'XK_KP_Down':u'(2)', | |
'XK_KP_Page_Down':u'(3)', | |
'XK_KP_Begin':u'(5)', | |
'XK_KP_Insert':u'(0)', | |
'XK_KP_Delete':u'(.)', | |
'XK_KP_Add':u'(+)', | |
'XK_KP_Subtract':u'(-)', | |
'XK_KP_Multiply':u'(*)', | |
'XK_KP_Divide':u'(/)', | |
'XK_Num_Lock':u'NumLock ', | |
'XK_KP_Enter':u'\u23CE ', | |
} | |
class ListenKbd(threading.Thread): | |
def __init__(self, label, logger, mode): | |
threading.Thread.__init__(self) | |
self.mode = mode | |
self.logger = logger | |
self.label = label | |
self.text = "" | |
self.command = None | |
self.shift = None | |
self.cmd_keys = { | |
'shift': False, | |
'ctrl': False, | |
'alt': False, | |
'capslock': False, | |
'meta': False, | |
'super':False | |
} | |
self.logger.debug("Thread created") | |
self.keymap = modmap.get_keymap_table() | |
self.modifiers = modmap.get_modifier_map() | |
self.local_dpy = display.Display() | |
self.record_dpy = display.Display() | |
if not self.record_dpy.has_extension("RECORD"): | |
self.logger.error("RECORD extension not found.") | |
print "RECORD extension not found" | |
sys.exit(1) | |
self.ctx = self.record_dpy.record_create_context( | |
0, | |
[record.AllClients], | |
[{ | |
'core_requests': (0, 0), | |
'core_replies': (0, 0), | |
'ext_requests': (0, 0, 0, 0), | |
'ext_replies': (0, 0, 0, 0), | |
'delivered_events': (0, 0), | |
'device_events': (X.KeyPress, X.KeyRelease), | |
'errors': (0, 0), | |
'client_started': False, | |
'client_died': False, | |
}]) | |
def run(self): | |
self.logger.debug("Thread started.") | |
self.record_dpy.record_enable_context(self.ctx, self.key_press) | |
def lookup_keysym(self, keysym): | |
for name in dir(XK): | |
if name[:3] == "XK_" and getattr(XK, name) == keysym: | |
return name[3:] | |
return "" | |
def replace_key(self, key, keysym): | |
for name in dir(XK): | |
if name[:3] == "XK_" and getattr(XK, name) == keysym: | |
if name in REPLACE_KEYS: | |
return REPLACE_KEYS[name] | |
def update_text(self, string=None): | |
gtk.gdk.threads_enter() | |
if not string is None: | |
self.text = "%s%s" % (self.label.get_text(), string) | |
self.label.set_text(self.text) | |
else: | |
self.label.set_text("") | |
gtk.gdk.threads_leave() | |
self.label.emit("text-changed") | |
def key_press(self, reply): | |
# FIXME: | |
# This is not the most efficient way to detect the | |
# use of sudo/gksudo but it works. | |
sudo_is_running = subprocess.call(['ps', '-C', 'sudo'], | |
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | |
if not sudo_is_running: | |
return | |
if reply.category != record.FromServer: | |
return | |
if reply.client_swapped: | |
self.logger.warning( | |
"* received swapped protocol data, cowardly ignored" | |
) | |
return | |
if not len(reply.data) or ord(reply.data[0]) < 2: | |
# not an event | |
return | |
data = reply.data | |
key = None | |
while len(data): | |
event, data = rq.EventField(None).parse_binary_value(data, | |
self.record_dpy.display, None, None) | |
if event.type in [X.KeyPress, X.KeyRelease]: | |
if self.mode == MODE_NORMAL or self.mode == MODE_SOLOCOMANDO: | |
key = self.key_normal_mode(event) | |
if self.mode == MODE_RAW: | |
key = self.key_raw_mode(event) | |
if not key: | |
return | |
self.update_text(key) | |
def key_normal_mode(self, event): | |
key = '' | |
mod = '' | |
keysym = self.local_dpy.keycode_to_keysym(event.detail, 0) | |
if event.detail in self.keymap: | |
key_normal, key_shift, key_dead, key_deadshift = \ | |
self.keymap[event.detail] | |
self.logger.debug("Key %s(keycode) %s. Symbols %s" % | |
(event.detail, | |
event.type == X.KeyPress and "pressed" or "released", | |
self.keymap[event.detail]) | |
) | |
else: | |
self.logger.debug('No mapping for scan_code %d' % event.detail) | |
return | |
# Alt key | |
if event.detail in self.modifiers['mod1']: | |
if event.type == X.KeyPress: | |
self.cmd_keys['alt'] = True | |
else: | |
self.cmd_keys['alt'] = False | |
return | |
# Meta key | |
# Fixme: it must use self.modifiers['mod5'] | |
# but doesn't work | |
if event.detail == 108: | |
if event.type == X.KeyPress: | |
self.cmd_keys['meta'] = True | |
else: | |
self.cmd_keys['meta'] = False | |
return | |
# Super key | |
if event.detail in self.modifiers['mod4']: | |
if event.type == X.KeyPress: | |
self.cmd_keys['super'] = True | |
else: | |
self.cmd_keys['super'] = False | |
return | |
# Ctrl keys | |
elif event.detail in self.modifiers['control']: | |
if event.type == X.KeyPress: | |
self.cmd_keys['ctrl'] = True | |
else: | |
self.cmd_keys['ctrl'] = False | |
return | |
# Shift keys | |
elif event.detail in self.modifiers['shift']: | |
if event.type == X.KeyPress: | |
self.cmd_keys['shift'] = True | |
else: | |
self.cmd_keys['shift'] = False | |
return | |
# Capslock key | |
elif event.detail in self.modifiers['lock']: | |
if event.type == X.KeyPress: | |
if self.cmd_keys['capslock']: | |
self.cmd_keys['capslock'] = False | |
else: | |
self.cmd_keys['capslock'] = True | |
return | |
# Backspace key | |
elif event.detail == 22 and event.type == X.KeyPress: | |
gtk.gdk.threads_enter() | |
if len(self.label.get_text()) > 0: | |
self.label.set_text( | |
unicode(self.label.get_text(), 'utf-8')[:-1] | |
) | |
key = "" | |
gtk.gdk.threads_leave() | |
else: | |
gtk.gdk.threads_leave() | |
return | |
else: | |
if event.type == X.KeyPress: | |
key = key_normal | |
if self.cmd_keys['ctrl']: | |
mod = mod + _("Ctrl+") | |
if self.cmd_keys['alt']: | |
mod = mod + _("Alt+") | |
if self.cmd_keys['super']: | |
mod = mod + _("Super+") | |
if self.cmd_keys['shift']: | |
mod = mod + _("Shift+") | |
key = key_shift | |
if self.cmd_keys['capslock'] \ | |
and ord(key_normal) in range(97,123): | |
key = key_shift | |
if self.cmd_keys['meta']: | |
key = key_dead | |
if self.cmd_keys['shift'] and self.cmd_keys['meta']: | |
key = key_deadshift | |
# En los espacios blancos muestra el texto: space | |
if key == ' ': | |
key = 'Space ' | |
# print 'mod:'+str(event.detail) + ' - key:' + key | |
# los keys que evita mostrar solos | |
if self.mode == MODE_SOLOCOMANDO and mod == '': | |
EVITAMOSTRAR = ['65','111','113','114','116','24','25','26','27','28','29','30','31','32','33','38','39','40','41','42','43','44','45','46','52','53','54','55','56','57','58','10','11','12','13','14','15','16','17','18','19'] | |
for nxn in EVITAMOSTRAR: | |
if nxn == str(event.detail): | |
return | |
string = self.replace_key(key, keysym) | |
if string: | |
key = string | |
if mod != '': | |
key = "%s%s " % (mod, key) | |
else: | |
key = "%s%s" % (mod, key) | |
else: | |
return | |
return key | |
def key_raw_mode(self, event): | |
key = '' | |
if event.type == X.KeyPress: | |
keysym = self.local_dpy.keycode_to_keysym(event.detail, 0) | |
key = self.lookup_keysym(keysym) | |
else: | |
return | |
return key | |
def stop(self): | |
self.local_dpy.record_disable_context(self.ctx) | |
self.local_dpy.flush() | |
self.record_dpy.record_free_context(self.ctx) | |
self.logger.debug("Thread stopped.") | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) 2010 Pablo Seminario <[email protected]> | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# for arabic characters | |
# -*- coding: utf-8 -*- | |
import os | |
import pygtk | |
pygtk.require('2.0') | |
import gtk | |
import gobject | |
import glib | |
import pango | |
import pickle | |
from threading import Timer | |
from Screenkey import APP_NAME, APP_DESC, APP_URL, VERSION, AUTHOR | |
from listenkbd import ListenKbd | |
POS_TOP = 0 | |
POS_CENTER = 1 | |
POS_BOTTOM = 2 | |
SIZE_LARGE = 0 | |
SIZE_MEDIUM = 1 | |
SIZE_SMALL = 2 | |
MODE_RAW = 0 | |
MODE_NORMAL = 1 | |
MODE_SOLOCOMANDO = 2 | |
class Screenkey(gtk.Window): | |
POSITIONS = { | |
POS_TOP:_('Top'), | |
POS_CENTER:_('Center'), | |
POS_BOTTOM:_('Bottom'), | |
} | |
SIZES = { | |
SIZE_LARGE:_('Large'), | |
SIZE_MEDIUM:_('Medium'), | |
SIZE_SMALL:_('Small'), | |
} | |
MODES = { | |
MODE_RAW:_('Raw'), | |
MODE_NORMAL:_('Normal'), | |
MODE_SOLOCOMANDO:_('Solo comando'), | |
} | |
STATE_FILE = os.path.join(glib.get_user_cache_dir(), | |
'screenkey.dat') | |
def __init__(self, logger, nodetach): | |
gtk.Window.__init__(self) | |
self.timer = None | |
self.logger = logger | |
self.options = self.load_state() | |
if not self.options: | |
self.options = { | |
'timeout': 2.5, | |
'position': POS_BOTTOM, | |
'size': SIZE_MEDIUM, | |
'mode': MODE_NORMAL, | |
} | |
if not nodetach: | |
self.logger.debug("Detach from the parent.") | |
self.drop_tty() | |
self.set_skip_taskbar_hint(True) | |
self.set_skip_pager_hint(True) | |
self.set_keep_above(True) | |
self.set_decorated(False) | |
self.stick() | |
self.set_property('accept-focus', False) | |
self.set_property('focus-on-map', False) | |
self.set_position(gtk.WIN_POS_CENTER) | |
bgcolor = gtk.gdk.color_parse("black") | |
self.modify_bg(gtk.STATE_NORMAL, bgcolor) | |
self.set_opacity(0.7) | |
gobject.signal_new("text-changed", gtk.Label, | |
gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()) | |
self.label = gtk.Label() | |
self.label.set_justify(gtk.JUSTIFY_RIGHT) | |
self.label.set_ellipsize(pango.ELLIPSIZE_START) | |
self.label.connect("text-changed", self.on_label_change) | |
self.label.show() | |
self.add(self.label) | |
self.screen_width = gtk.gdk.screen_width() | |
self.screen_height = gtk.gdk.screen_height() | |
self.set_window_size(self.options['size']) | |
self.set_gravity(gtk.gdk.GRAVITY_CENTER) | |
self.set_xy_position(self.options['position']) | |
self.listenkbd = ListenKbd(self.label, logger=self.logger, | |
mode=self.options['mode']) | |
self.listenkbd.start() | |
menu = gtk.Menu() | |
show_item = gtk.CheckMenuItem(_("Show keys")) | |
show_item.set_active(True) | |
show_item.connect("toggled", self.on_show_keys) | |
show_item.show() | |
menu.append(show_item) | |
preferences_item = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES) | |
preferences_item.connect("activate", self.on_preferences_dialog) | |
preferences_item.show() | |
menu.append(preferences_item) | |
about_item = gtk.ImageMenuItem(gtk.STOCK_ABOUT) | |
about_item.connect("activate", self.on_about_dialog) | |
about_item.show() | |
menu.append(about_item) | |
separator_item = gtk.SeparatorMenuItem() | |
separator_item.show() | |
menu.append(separator_item) | |
image = gtk.ImageMenuItem(gtk.STOCK_QUIT) | |
image.connect("activate", self.quit) | |
image.show() | |
menu.append(image) | |
menu.show() | |
try: | |
import appindicator | |
self.systray = appindicator.Indicator(APP_NAME, | |
'indicator-messages', | |
appindicator.CATEGORY_APPLICATION_STATUS) | |
self.systray.set_status(appindicator.STATUS_ACTIVE) | |
self.systray.set_attention_icon("indicator-messages-new") | |
self.systray.set_icon( | |
"preferences-desktop-keyboard-shortcuts") | |
self.systray.set_menu(menu) | |
self.logger.debug("Using AppIndicator.") | |
except(ImportError): | |
self.systray = gtk.StatusIcon() | |
self.systray.set_from_icon_name( | |
"preferences-desktop-keyboard-shortcuts") | |
self.systray.connect("popup-menu", | |
self.on_statusicon_popup, menu) | |
self.logger.debug("Using StatusIcon.") | |
self.connect("delete-event", self.quit) | |
def quit(self, widget, data=None): | |
self.listenkbd.stop() | |
gtk.main_quit() | |
def load_state(self): | |
"""Load stored options""" | |
options = None | |
try: | |
f = open(self.STATE_FILE, 'r') | |
try: | |
options = pickle.load(f) | |
self.logger.debug("Options loaded.") | |
except: | |
f.close() | |
except IOError: | |
self.logger.debug("file %s does not exists." % | |
self.STATE_FILE) | |
return options | |
def store_state(self, options): | |
"""Store options""" | |
try: | |
f = open(self.STATE_FILE, 'w') | |
try: | |
pickle.dump(options, f) | |
self.logger.debug("Options saved.") | |
except: | |
f.close() | |
except IOError: | |
self.logger.debug("Cannot open %s." % self.STATE_FILE) | |
def set_window_size(self, setting): | |
"""Set window and label size.""" | |
window_width = self.screen_width / 4 | |
window_height = -1 | |
if setting == SIZE_LARGE: | |
window_height = 24 * self.screen_height / 100 | |
if setting == SIZE_MEDIUM: | |
window_height = 12 * self.screen_height / 100 | |
if setting == SIZE_SMALL: | |
window_height = 6 * self.screen_height / 100 | |
attr = pango.AttrList() | |
attr.change(pango.AttrSize(( | |
30 * window_height / 100) * 1000, 0, -1)) | |
attr.change(pango.AttrFamily("Sans", 0, -1)) | |
attr.change(pango.AttrWeight(pango.WEIGHT_BOLD, 0, -1)) | |
attr.change(pango.AttrForeground(65535, 65535, 65535, 0, -1)) | |
self.label.set_attributes(attr) | |
self.resize(window_width, window_height) | |
def set_xy_position(self, setting): | |
"""Set window position.""" | |
window_width, window_height = self.get_size() | |
if setting == POS_TOP: | |
self.move(0, window_height * 2) | |
if setting == POS_CENTER: | |
self.move(0, self.screen_height / 2) | |
if setting == POS_BOTTOM: | |
self.move(0, self.screen_height - window_height * 2) | |
def on_statusicon_popup(self, widget, button, timestamp, data=None): | |
if button == 3: | |
if data: | |
data.show() | |
data.popup(None, None, gtk.status_icon_position_menu, | |
3, timestamp, widget) | |
def on_label_change(self, widget, data=None): | |
if not self.get_property('visible'): | |
gtk.gdk.threads_enter() | |
self.set_xy_position(self.options['position']) | |
self.stick() | |
self.show() | |
gtk.gdk.threads_leave() | |
if self.timer: | |
self.timer.cancel() | |
self.timer = Timer(self.options['timeout'], self.on_timeout) | |
self.timer.start() | |
def on_timeout(self): | |
gtk.gdk.threads_enter() | |
self.hide() | |
self.label.set_text("") | |
gtk.gdk.threads_leave() | |
def on_change_mode(self, mode): | |
self.listenkbd.stop() | |
self.listenkbd = ListenKbd(self.label, logger=self.logger, | |
mode=mode) | |
self.listenkbd.start() | |
def on_show_keys(self, widget, data=None): | |
if widget.get_active(): | |
self.logger.debug("Screenkey enabled.") | |
self.listenkbd = ListenKbd(self.label, logger=self.logger, | |
mode=self.options['mode']) | |
self.listenkbd.start() | |
else: | |
self.logger.debug("Screenkey disabled.") | |
self.listenkbd.stop() | |
def on_preferences_dialog(self, widget, data=None): | |
prefs = gtk.Dialog(APP_NAME, None, | |
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, | |
(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) | |
def on_sb_time_changed(widget, data=None): | |
self.options['timeout'] = widget.get_value() | |
self.logger.debug("Timeout value changed.") | |
def on_cbox_sizes_changed(widget, data=None): | |
index = widget.get_active() | |
if index >= 0: | |
self.options['size'] = index | |
self.set_window_size(self.options['size']) | |
self.logger.debug("Window size changed.") | |
def on_cbox_modes_changed(widget, data=None): | |
index = widget.get_active() | |
if index >= 0: | |
self.options['mode'] = index | |
self.on_change_mode(self.options['mode']) | |
self.logger.debug("Key mode changed.") | |
def on_cbox_changed(widget, data=None): | |
index = widget.get_active() | |
name = widget.get_name() | |
if index >= 0: | |
self.options[name] = index | |
self.logger.debug("Window position changed.") | |
frm_main = gtk.Frame(_("Preferences")) | |
frm_main.set_border_width(6) | |
vbox_main = gtk.VBox() | |
frm_time = gtk.Frame(_("<b>Time</b>")) | |
frm_time.set_border_width(4) | |
frm_time.get_label_widget().set_use_markup(True) | |
frm_time.set_shadow_type(gtk.SHADOW_NONE) | |
hbox_time = gtk.HBox() | |
lbl_time1 = gtk.Label(_("Display for")) | |
lbl_time2 = gtk.Label(_("seconds")) | |
sb_time = gtk.SpinButton(digits=1) | |
sb_time.set_increments(0.5, 1.0) | |
sb_time.set_range(0.5, 10.0) | |
sb_time.set_numeric(True) | |
sb_time.set_update_policy(gtk.UPDATE_IF_VALID) | |
sb_time.set_value(self.options['timeout']) | |
sb_time.connect("value-changed", on_sb_time_changed) | |
hbox_time.pack_start(lbl_time1, expand=False, | |
fill=False, padding=6) | |
hbox_time.pack_start(sb_time, expand=False, | |
fill=False, padding=4) | |
hbox_time.pack_start(lbl_time2, expand=False, | |
fill=False, padding=4) | |
frm_time.add(hbox_time) | |
frm_time.show_all() | |
frm_aspect = gtk.Frame(_("<b>Aspect</b>")) | |
frm_aspect.set_border_width(4) | |
frm_aspect.get_label_widget().set_use_markup(True) | |
frm_aspect.set_shadow_type(gtk.SHADOW_NONE) | |
vbox_aspect = gtk.VBox(spacing=6) | |
hbox1_aspect = gtk.HBox() | |
lbl_positions = gtk.Label(_("Position")) | |
cbox_positions = gtk.combo_box_new_text() | |
cbox_positions.set_name('position') | |
for key, value in self.POSITIONS.items(): | |
cbox_positions.insert_text(key, value) | |
cbox_positions.set_active(self.options['position']) | |
cbox_positions.connect("changed", on_cbox_changed) | |
hbox1_aspect.pack_start(lbl_positions, expand=False, | |
fill=False, padding=6) | |
hbox1_aspect.pack_start(cbox_positions, expand=False, | |
fill=False, padding=4) | |
hbox2_aspect = gtk.HBox() | |
lbl_sizes = gtk.Label(_("Size")) | |
cbox_sizes = gtk.combo_box_new_text() | |
cbox_sizes.set_name('size') | |
for key, value in self.SIZES.items(): | |
cbox_sizes.insert_text(key, value) | |
cbox_sizes.set_active(self.options['size']) | |
cbox_sizes.connect("changed", on_cbox_sizes_changed) | |
hbox2_aspect.pack_start(lbl_sizes, expand=False, | |
fill=False, padding=6) | |
hbox2_aspect.pack_start(cbox_sizes, expand=False, | |
fill=False, padding=4) | |
vbox_aspect.pack_start(hbox1_aspect) | |
vbox_aspect.pack_start(hbox2_aspect) | |
frm_aspect.add(vbox_aspect) | |
frm_kbd = gtk.Frame(_("<b>Keys</b>")) | |
frm_kbd.set_border_width(4) | |
frm_kbd.get_label_widget().set_use_markup(True) | |
frm_kbd.set_shadow_type(gtk.SHADOW_NONE) | |
hbox_kbd = gtk.HBox() | |
lbl_kbd = gtk.Label(_("Mode")) | |
cbox_modes = gtk.combo_box_new_text() | |
cbox_modes.set_name('mode') | |
for key, value in self.MODES.items(): | |
cbox_modes.insert_text(key, value) | |
cbox_modes.set_active(self.options['mode']) | |
cbox_modes.connect("changed", on_cbox_modes_changed) | |
hbox_kbd.pack_start(lbl_kbd, expand=False, | |
fill=False, padding=6) | |
hbox_kbd.pack_start(cbox_modes, expand=False, | |
fill=False, padding=4) | |
frm_kbd.add(hbox_kbd) | |
vbox_main.pack_start(frm_time, False, False, 6) | |
vbox_main.pack_start(frm_aspect, False, False, 6) | |
vbox_main.pack_start(frm_kbd, False, False, 6) | |
frm_main.add(vbox_main) | |
prefs.vbox.pack_start(frm_main) | |
prefs.set_destroy_with_parent(True) | |
prefs.set_resizable(False) | |
prefs.set_has_separator(False) | |
prefs.set_default_response(gtk.RESPONSE_CLOSE) | |
prefs.vbox.show_all() | |
response = prefs.run() | |
if response: | |
self.store_state(self.options) | |
prefs.destroy() | |
def on_about_dialog(self, widget, data=None): | |
about = gtk.AboutDialog() | |
about.set_program_name(APP_NAME) | |
about.set_version(VERSION) | |
about.set_copyright(u"2010 \u00a9 %s" % AUTHOR) | |
about.set_comments(APP_DESC) | |
about.set_documenters( | |
[u"Jos\xe9 Mar\xeda Quiroga <[email protected]>"] | |
) | |
about.set_website(APP_URL) | |
about.set_icon_name('preferences-desktop-keyboard-shortcuts') | |
about.set_logo_icon_name( | |
'preferences-desktop-keyboard-shortcuts' | |
) | |
about.run() | |
about.destroy() | |
def drop_tty(self): | |
# We fork and setsid so that we drop the controlling | |
# tty. | |
if os.fork() != 0: | |
os._exit(0) | |
os.setsid() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment