console: Rework keygrab/accelerator preferences

Reduce the keygrab options to a single question: whether to enable the
console window menu modifiers while the VNC console is active. This makes
the VNC widget focus act like a regular app (rather than default to stealing
keyboard focus on mouse over), and is the most intuitive I think we can
get. Inspired by vinagre.
This commit is contained in:
Cole Robinson 2010-12-02 13:41:22 -05:00
parent b673fee41c
commit 9e312c7a67
5 changed files with 93 additions and 78 deletions

View File

@ -118,15 +118,15 @@
</schema>
<schema>
<key>/schemas/apps/::PACKAGE::/console/keygrab</key>
<applyto>/apps/::PACKAGE::/console/keygrab</applyto>
<key>/schemas/apps/::PACKAGE::/console/enable-accels</key>
<applyto>/apps/::PACKAGE::/console/enable-accels</applyto>
<owner>::PACKAGE::</owner>
<type>int</type>
<default>2</default>
<type>bool</type>
<default>false</default>
<locale name="C">
<short>When to grab keyboard input for the console</short>
<long>Whether to grab keyboard input for a guest console. 0 = never, 1 = only when in full screen mode, 2 = when mouse is over console</long>
<short>Enable menu accelerators in console window</short>
<long>Whether to enable menu accelerators while connected to the guest graphical console.</long>
</locale>
</schema>

View File

@ -425,15 +425,16 @@ class vmmConfig:
def set_console_popup(self, pref):
self.conf.set_int(self.conf_dir + "/console/popup", pref)
def on_console_keygrab_changed(self, callback):
self.conf.notify_add(self.conf_dir + "/console/keygrab", callback)
def get_console_keygrab(self):
console_pref = self.conf.get_int(self.conf_dir + "/console/keygrab")
def on_console_accels_changed(self, callback):
self.conf.notify_add(self.conf_dir + "/console/enable-accels", callback)
def get_console_accels(self):
console_pref = self.conf.get_bool(self.conf_dir +
"/console/enable-accels")
if console_pref == None:
console_pref = 0
console_pref = False
return console_pref
def set_console_keygrab(self, pref):
self.conf.set_int(self.conf_dir + "/console/keygrab", pref)
def set_console_accels(self, pref):
self.conf.set_bool(self.conf_dir + "/console/enable-accels", pref)
def on_console_scaling_changed(self, callback):
self.conf.notify_add(self.conf_dir + "/console/scaling", callback)

View File

@ -75,6 +75,7 @@ class vmmConsolePages(gobject.GObject):
self.vncViewerRetriesScheduled = 0
self.vncViewerRetryDelay = 125
self.vnc_connected = False
self.modifiers_enabled = True
self.vncViewer = gtkvnc.Display()
self.window.get_widget("console-vnc-viewport").add(self.vncViewer)
@ -129,10 +130,12 @@ class vmmConsolePages(gobject.GObject):
self.vm.on_console_scaling_changed(self.refresh_scaling)
self.refresh_scaling()
self.set_keyboard_grab()
self.config.on_console_keygrab_changed(self.set_keyboard_grab)
self.vncViewer.set_keyboard_grab(False)
self.vncViewer.set_pointer_grab(True)
self.set_enable_accel()
self.config.on_console_accels_changed(self.set_enable_accel)
scroll = self.window.get_widget("console-vnc-scroll")
scroll.connect("size-allocate", self.scroll_size_allocate)
@ -141,19 +144,25 @@ class vmmConsolePages(gobject.GObject):
self.vncViewer.connect("vnc-auth-credential", self._vnc_auth_credential)
self.vncViewer.connect("vnc-initialized", self._vnc_initialized)
self.vncViewer.connect("vnc-disconnected", self._vnc_disconnected)
self.vncViewer.connect("vnc-keyboard-grab", self.keyboard_grabbed)
self.vncViewer.connect("vnc-keyboard-ungrab", self.keyboard_ungrabbed)
self.vncViewer.connect("vnc-desktop-resize", self.desktop_resize)
self.vncViewer.connect("focus-in-event", self._vnc_focus_changed)
self.vncViewer.connect("focus-out-event", self._vnc_focus_changed)
self.vncViewer.show()
#############
# Listeners #
#############
def keyboard_grabbed(self, src):
self._disable_modifiers()
def keyboard_ungrabbed(self, src=None):
self._enable_modifiers()
def _vnc_focus_changed(self, ignore1=None, ignore2=None):
has_focus = self.vncViewer.get_property("has-focus")
force_accel = self.config.get_console_accels()
if force_accel:
self._enable_modifiers()
elif has_focus and self.vnc_connected:
self._disable_modifiers()
else:
self._enable_modifiers()
def pointer_grabbed(self, src):
keystr = None
@ -191,10 +200,10 @@ class vmmConsolePages(gobject.GObject):
settings.set_property('gtk-menu-bar-accel', None)
if has_property(settings, "gtk-enable-mnemonics"):
self.gtk_settings_mnemonic = settings.get_property("gtk-enable-mnemonics")
self.gtk_settings_mnemonic = settings.get_property(
"gtk-enable-mnemonics")
settings.set_property("gtk-enable-mnemonics", False)
def _enable_modifiers(self):
if self.gtk_settings_accel is None:
return
@ -210,10 +219,10 @@ class vmmConsolePages(gobject.GObject):
for g in self.accel_groups:
self.topwin.add_accel_group(g)
def set_keyboard_grab(self, ignore=None, ignore1=None,
ignore2=None, ignore3=None):
grab = self.config.get_console_keygrab() == 2
self.vncViewer.set_keyboard_grab(grab)
def set_enable_accel(self, ignore=None, ignore1=None,
ignore2=None, ignore3=None):
# Make sure modifiers are up to date
self._vnc_focus_changed()
def refresh_scaling(self, ignore1=None, ignore2=None, ignore3=None,
ignore4=None):
@ -270,17 +279,8 @@ class vmmConsolePages(gobject.GObject):
if do_fullscreen:
self.topwin.fullscreen()
if self.config.get_console_keygrab() == 1:
gtk.gdk.keyboard_grab(self.vncViewer.window, False, 0L)
self._disable_modifiers()
self.window.get_widget("toolbar-box").hide()
else:
if self.config.get_console_keygrab() == 1:
self._enable_modifiers()
gtk.gdk.keyboard_ungrab(0L)
self.topwin.unfullscreen()
if self.window.get_widget("details-menu-view-toolbar").get_active():
@ -433,7 +433,9 @@ class vmmConsolePages(gobject.GObject):
self.vnc_connected = False
logging.debug("VNC disconnected")
self.keyboard_ungrabbed()
# Make sure modifiers are set correctly
self._vnc_focus_changed()
if (self.skip_connect_attempt() or
self.guest_not_avail()):
@ -458,6 +460,9 @@ class vmmConsolePages(gobject.GObject):
self.vncViewerRetriesScheduled = 0
self.vncViewerRetryDelay = 125
# Make sure modifiers are set correctly
self._vnc_focus_changed()
def schedule_retry(self):
if self.vncViewerRetriesScheduled >= 10:
logging.error("Too many connection failures, not retrying again")

View File

@ -33,14 +33,16 @@ class vmmPreferences(gobject.GObject):
}
def __init__(self, config):
gobject.GObject.__init__(self)
self.window = gtk.glade.XML(config.get_glade_dir() + "/vmm-preferences.glade", "vmm-preferences", domain="virt-manager")
self.window = gtk.glade.XML(
config.get_glade_dir() + "/vmm-preferences.glade",
"vmm-preferences", domain="virt-manager")
self.config = config
self.topwin = self.window.get_widget("vmm-preferences")
self.config.on_view_system_tray_changed(self.refresh_view_system_tray)
self.config.on_console_popup_changed(self.refresh_console_popup)
self.config.on_console_keygrab_changed(self.refresh_console_keygrab)
self.config.on_console_accels_changed(self.refresh_console_accels)
self.config.on_console_scaling_changed(self.refresh_console_scaling)
self.config.on_stats_update_interval_changed(self.refresh_update_interval)
self.config.on_stats_history_length_changed(self.refresh_history_length)
@ -59,7 +61,7 @@ class vmmPreferences(gobject.GObject):
self.refresh_update_interval()
self.refresh_history_length()
self.refresh_console_popup()
self.refresh_console_keygrab()
self.refresh_console_accels()
self.refresh_console_scaling()
self.refresh_sound_local()
self.refresh_sound_remote()
@ -77,7 +79,7 @@ class vmmPreferences(gobject.GObject):
"on_prefs_stats_update_interval_changed": self.change_update_interval,
"on_prefs_stats_history_length_changed": self.change_history_length,
"on_prefs_console_popup_changed": self.change_console_popup,
"on_prefs_console_keygrab_changed": self.change_console_keygrab,
"on_prefs_console_accels_toggled": self.change_console_accels,
"on_prefs_console_scaling_changed": self.change_console_scaling,
"on_prefs_close_clicked": self.close,
"on_vmm_preferences_delete_event": self.close,
@ -127,10 +129,10 @@ class vmmPreferences(gobject.GObject):
ignore3=None, ignore4=None):
self.window.get_widget("prefs-console-popup").set_active(
self.config.get_console_popup())
def refresh_console_keygrab(self, ignore1=None, ignore2=None,
def refresh_console_accels(self, ignore1=None, ignore2=None,
ignore3=None, ignore4=None):
self.window.get_widget("prefs-console-keygrab").set_active(
self.config.get_console_keygrab())
self.window.get_widget("prefs-console-accels").set_active(
self.config.get_console_accels())
def refresh_console_scaling(self, ignore1=None, ignore2=None,
ignore3=None, ignore4=None):
val = self.config.get_console_scaling()
@ -249,8 +251,8 @@ class vmmPreferences(gobject.GObject):
def change_console_popup(self, box):
self.config.set_console_popup(box.get_active())
def change_console_keygrab(self, box):
self.config.set_console_keygrab(box.get_active())
def change_console_accels(self, src):
self.config.set_console_accels(src.get_active())
def change_console_scaling(self, box):
self.config.set_console_scaling(box.get_active())

View File

@ -322,7 +322,7 @@
<child>
<widget class="GtkTable" id="table3">
<property name="visible">True</property>
<property name="n_rows">7</property>
<property name="n_rows">6</property>
<property name="row_spacing">3</property>
<child>
<widget class="GtkComboBox" id="prefs-console-scaling">
@ -333,8 +333,8 @@ Always</property>
<signal name="changed" handler="on_prefs_console_scaling_changed"/>
</widget>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_padding">5</property>
</packing>
</child>
@ -346,33 +346,6 @@ Always</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">prefs-console-scaling</property>
</widget>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="prefs-console-keygrab">
<property name="visible">True</property>
<property name="items" translatable="yes">Never
When fullscreen
On mouse over</property>
<signal name="changed" handler="on_prefs_console_keygrab_changed"/>
</widget>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_padding">5</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label15">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Grab _keyboard accelerators:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">prefs-console-keygrab</property>
</widget>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
@ -441,8 +414,42 @@ For all domains</property>
</child>
</widget>
<packing>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<widget class="GtkLabel" id="label15">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Force console menu accelerators while the console is active. Enabling this may overwrite keyboard interaction with the guest.</property>
<property name="label" translatable="yes">Force console keyboard shortcuts:</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="prefs-console-accels">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_prefs_console_accels_toggled"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
</widget>