mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
Grab mouse when clicking
This commit is contained in:
parent
8118b4ac05
commit
29d8ae34c5
@ -23,6 +23,7 @@ import gtk.glade
|
|||||||
import libvirt
|
import libvirt
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
|
import dbus
|
||||||
|
|
||||||
from vncViewer.vnc import GRFBViewer
|
from vncViewer.vnc import GRFBViewer
|
||||||
|
|
||||||
@ -45,7 +46,8 @@ class vmmConsole(gobject.GObject):
|
|||||||
|
|
||||||
topwin = self.window.get_widget("vmm-console")
|
topwin = self.window.get_widget("vmm-console")
|
||||||
topwin.hide()
|
topwin.hide()
|
||||||
topwin.set_title(vm.get_name() + " " + topwin.get_title())
|
self.title = vm.get_name() + " " + topwin.get_title()
|
||||||
|
topwin.set_title(self.title)
|
||||||
self.window.get_widget("control-shutdown").set_icon_widget(gtk.Image())
|
self.window.get_widget("control-shutdown").set_icon_widget(gtk.Image())
|
||||||
self.window.get_widget("control-shutdown").get_icon_widget().set_from_file(config.get_icon_dir() + "/icon_shutdown.png")
|
self.window.get_widget("control-shutdown").get_icon_widget().set_from_file(config.get_icon_dir() + "/icon_shutdown.png")
|
||||||
|
|
||||||
@ -53,6 +55,9 @@ class vmmConsole(gobject.GObject):
|
|||||||
self.vncViewer = GRFBViewer(topwin, autograbkey=True)
|
self.vncViewer = GRFBViewer(topwin, autograbkey=True)
|
||||||
else:
|
else:
|
||||||
self.vncViewer = GRFBViewer(topwin, autograbkey=False)
|
self.vncViewer = GRFBViewer(topwin, autograbkey=False)
|
||||||
|
self.vncViewer.connect("pointer-grabbed", self.notify_grabbed)
|
||||||
|
self.vncViewer.connect("pointer-ungrabbed", self.notify_ungrabbed)
|
||||||
|
|
||||||
self.window.get_widget("console-vnc-align").add(self.vncViewer)
|
self.window.get_widget("console-vnc-align").add(self.vncViewer)
|
||||||
self.vncViewer.connect("size-request", self.autosize)
|
self.vncViewer.connect("size-request", self.autosize)
|
||||||
self.vncViewer.show()
|
self.vncViewer.show()
|
||||||
@ -109,6 +114,32 @@ class vmmConsole(gobject.GObject):
|
|||||||
|
|
||||||
self.window.get_widget("console-vnc-vp").set_size_request(vncWidth+2, vncHeight+2)
|
self.window.get_widget("console-vnc-vp").set_size_request(vncWidth+2, vncHeight+2)
|
||||||
|
|
||||||
|
def notify_grabbed(self, src):
|
||||||
|
topwin = self.window.get_widget("vmm-console")
|
||||||
|
try:
|
||||||
|
bus = dbus.SessionBus()
|
||||||
|
noteSvr = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
|
||||||
|
noteObj = dbus.Interface(noteSvr, "org.freedesktop.Notifications")
|
||||||
|
(x, y) = topwin.window.get_origin()
|
||||||
|
noteObj.Notify(topwin.get_title(),
|
||||||
|
0,
|
||||||
|
'',
|
||||||
|
"Pointer grabbed",
|
||||||
|
"The mouse pointer has been restricted to the virtual " +
|
||||||
|
"console window. To release the pointer press the key pair " +
|
||||||
|
"Ctrl+Alt",
|
||||||
|
[],
|
||||||
|
{"desktop-entry": "virt-manager",
|
||||||
|
"x": x+200, "y": y},
|
||||||
|
5 * 1000);
|
||||||
|
except Exception, e:
|
||||||
|
pass
|
||||||
|
topwin.set_title(_("Press Ctrl+Alt to release mouse.") + " " + self.title)
|
||||||
|
|
||||||
|
def notify_ungrabbed(self, src):
|
||||||
|
topwin = self.window.get_widget("vmm-console")
|
||||||
|
topwin.set_title(self.title)
|
||||||
|
|
||||||
def keygrab_changed(self, src, ignore1=None,ignore2=None,ignore3=None):
|
def keygrab_changed(self, src, ignore1=None,ignore2=None,ignore3=None):
|
||||||
if self.config.get_console_keygrab() == 2:
|
if self.config.get_console_keygrab() == 2:
|
||||||
self.vncViewer.set_autograb_keyboard(True)
|
self.vncViewer.set_autograb_keyboard(True)
|
||||||
|
@ -174,7 +174,11 @@ class GRFBViewer(gtk.DrawingArea):
|
|||||||
"connected": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [str, int]),
|
"connected": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [str, int]),
|
||||||
"authenticated": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
"authenticated": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
||||||
"activated": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
"activated": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
||||||
"disconnected": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [])
|
"disconnected": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
||||||
|
"pointer-grabbed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
||||||
|
"pointer-ungrabbed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
||||||
|
"keyboard-grabbed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
||||||
|
"keyboard-ungrabbed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, topwin, autograbkey=False):
|
def __init__(self, topwin, autograbkey=False):
|
||||||
@ -185,6 +189,7 @@ class GRFBViewer(gtk.DrawingArea):
|
|||||||
self.authenticated = False
|
self.authenticated = False
|
||||||
self.needpw = True
|
self.needpw = True
|
||||||
self.autograbkey = autograbkey
|
self.autograbkey = autograbkey
|
||||||
|
self.autograbptr = True
|
||||||
self.topwin = topwin
|
self.topwin = topwin
|
||||||
self.accel_groups = gtk.accel_groups_from_object(topwin)
|
self.accel_groups = gtk.accel_groups_from_object(topwin)
|
||||||
self.preferred_encoding = (rfb.ENCODING_RAW, rfb.ENCODING_DESKTOP_RESIZE)
|
self.preferred_encoding = (rfb.ENCODING_RAW, rfb.ENCODING_DESKTOP_RESIZE)
|
||||||
@ -197,9 +202,10 @@ class GRFBViewer(gtk.DrawingArea):
|
|||||||
|
|
||||||
self.connect("expose-event", self.expose_region)
|
self.connect("expose-event", self.expose_region)
|
||||||
|
|
||||||
self.connect("motion-notify-event", self.update_pointer)
|
self.connect("motion-notify-event", self.pointer_move)
|
||||||
self.connect("button-press-event", self.update_pointer)
|
self.connect("button-press-event", self.pointer_press)
|
||||||
self.connect("button-release-event", self.update_pointer)
|
self.connect("button-release-event", self.pointer_release)
|
||||||
|
self.connect("scroll-event", self.pointer_scroll)
|
||||||
self.connect("key-press-event", self.key_press)
|
self.connect("key-press-event", self.key_press)
|
||||||
self.connect("key-release-event", self.key_release)
|
self.connect("key-release-event", self.key_release)
|
||||||
self.connect("enter-notify-event", self.enter_notify)
|
self.connect("enter-notify-event", self.enter_notify)
|
||||||
@ -265,6 +271,10 @@ class GRFBViewer(gtk.DrawingArea):
|
|||||||
self.lastKeyVal = None
|
self.lastKeyVal = None
|
||||||
self.lastKeyRepeat = 0
|
self.lastKeyRepeat = 0
|
||||||
|
|
||||||
|
empty = gtk.gdk.Pixmap(None, 1, 1, 1)
|
||||||
|
clear = gtk.gdk.Color()
|
||||||
|
self.nullcursor = gtk.gdk.Cursor(empty, empty, clear, clear, 0, 0)
|
||||||
|
|
||||||
self.set_events(gtk.gdk.EXPOSURE_MASK |
|
self.set_events(gtk.gdk.EXPOSURE_MASK |
|
||||||
gtk.gdk.LEAVE_NOTIFY_MASK |
|
gtk.gdk.LEAVE_NOTIFY_MASK |
|
||||||
gtk.gdk.ENTER_NOTIFY_MASK |
|
gtk.gdk.ENTER_NOTIFY_MASK |
|
||||||
@ -364,18 +374,48 @@ class GRFBViewer(gtk.DrawingArea):
|
|||||||
mask = mask + 8
|
mask = mask + 8
|
||||||
if state & gtk.gdk.BUTTON5_MASK:
|
if state & gtk.gdk.BUTTON5_MASK:
|
||||||
mask = mask + 16
|
mask = mask + 16
|
||||||
|
|
||||||
return mask
|
return mask
|
||||||
|
|
||||||
def take_screenshot(self):
|
def take_screenshot(self):
|
||||||
return self.fb.clone_pixmap()
|
return self.fb.clone_pixmap()
|
||||||
|
|
||||||
|
def pointer_move(self, win, event):
|
||||||
|
self.update_pointer(win, event)
|
||||||
|
|
||||||
|
def pointer_press(self, win, event):
|
||||||
|
if not gtk.gdk.pointer_is_grabbed() and self.will_autograb_pointer():
|
||||||
|
self.grab_pointer()
|
||||||
|
self.update_pointer(win, event)
|
||||||
|
|
||||||
|
def pointer_release(self, win, event):
|
||||||
|
self.update_pointer(win, event)
|
||||||
|
|
||||||
|
def pointer_scroll(self, win, event):
|
||||||
|
if self.client != None:
|
||||||
|
x, y, state = event.window.get_pointer()
|
||||||
|
newstate = state
|
||||||
|
if event.direction == gtk.gdk.SCROLL_UP:
|
||||||
|
newstate = newstate | gtk.gdk.BUTTON4_MASK
|
||||||
|
else:
|
||||||
|
newstate = newstate | gtk.gdk.BUTTON5_MASK
|
||||||
|
self.client.update_pointer(self.state_to_mask(newstate), x, y)
|
||||||
|
self.client.update_pointer(self.state_to_mask(state), x, y)
|
||||||
|
|
||||||
def update_pointer(self, win, event):
|
def update_pointer(self, win, event):
|
||||||
if self.client != None:
|
if self.client != None:
|
||||||
x, y, state = event.window.get_pointer()
|
x, y, state = event.window.get_pointer()
|
||||||
self.client.update_pointer(self.state_to_mask(state), x, y)
|
self.client.update_pointer(self.state_to_mask(state), x, y)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def will_autograb_pointer(self):
|
||||||
|
return self.autograbptr
|
||||||
|
|
||||||
|
def set_autograb_pointer(self, grab):
|
||||||
|
self.autograbptr = grab
|
||||||
|
if grab == False and gtk.gdk.pointer_is_grabbed():
|
||||||
|
self.ungrab_pointer()
|
||||||
|
|
||||||
def has_grabbed_keyboard(self):
|
def has_grabbed_keyboard(self):
|
||||||
return self.grabbedKeyboard
|
return self.grabbedKeyboard
|
||||||
|
|
||||||
@ -384,18 +424,38 @@ class GRFBViewer(gtk.DrawingArea):
|
|||||||
|
|
||||||
def set_autograb_keyboard(self, grab):
|
def set_autograb_keyboard(self, grab):
|
||||||
self.autograbkey = grab
|
self.autograbkey = grab
|
||||||
|
if grab == False and grabbedKeyboard:
|
||||||
|
self.ungrab_keyboard()
|
||||||
|
|
||||||
|
|
||||||
|
def grab_pointer(self):
|
||||||
|
gtk.gdk.pointer_grab(self.window, False,
|
||||||
|
gtk.gdk.LEAVE_NOTIFY_MASK |
|
||||||
|
gtk.gdk.ENTER_NOTIFY_MASK |
|
||||||
|
gtk.gdk.BUTTON_RELEASE_MASK |
|
||||||
|
gtk.gdk.BUTTON_PRESS_MASK |
|
||||||
|
gtk.gdk.POINTER_MOTION_MASK |
|
||||||
|
gtk.gdk.POINTER_MOTION_HINT_MASK,
|
||||||
|
self.window, self.nullcursor)
|
||||||
|
self.emit("pointer-grabbed")
|
||||||
|
|
||||||
|
def ungrab_pointer(self):
|
||||||
|
gtk.gdk.pointer_ungrab()
|
||||||
|
self.emit("pointer-ungrabbed")
|
||||||
|
|
||||||
def grab_keyboard(self):
|
def grab_keyboard(self):
|
||||||
gtk.gdk.keyboard_grab(self.window, False, long(0))
|
gtk.gdk.keyboard_grab(self.window, False, long(0))
|
||||||
for g in self.accel_groups:
|
for g in self.accel_groups:
|
||||||
self.topwin.remove_accel_group(g)
|
self.topwin.remove_accel_group(g)
|
||||||
self.grabbedKeyboard = True
|
self.grabbedKeyboard = True
|
||||||
|
self.emit("keyboard-grabbed")
|
||||||
|
|
||||||
def ungrab_keyboard(self):
|
def ungrab_keyboard(self):
|
||||||
gtk.gdk.keyboard_ungrab()
|
gtk.gdk.keyboard_ungrab()
|
||||||
for g in self.accel_groups:
|
for g in self.accel_groups:
|
||||||
self.topwin.add_accel_group(g)
|
self.topwin.add_accel_group(g)
|
||||||
self.grabbedKeyboard = False
|
self.grabbedKeyboard = False
|
||||||
|
self.emit("keyboard-ungrabbed")
|
||||||
|
|
||||||
def enter_notify(self, win, event):
|
def enter_notify(self, win, event):
|
||||||
if self.autograbkey:
|
if self.autograbkey:
|
||||||
@ -417,6 +477,13 @@ class GRFBViewer(gtk.DrawingArea):
|
|||||||
|
|
||||||
|
|
||||||
def key_press(self, win, event):
|
def key_press(self, win, event):
|
||||||
|
# Allow Ctrl+Alt+Esc to break the pointer grab
|
||||||
|
if self.will_autograb_pointer():
|
||||||
|
if event.state & gtk.gdk.CONTROL_MASK and event.state & gtk.gdk.MOD1_MASK and gtk.gdk.pointer_is_grabbed():
|
||||||
|
self.ungrab_pointer()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.ungrab_pointer()
|
||||||
# Key handling in VNC is screwy. The event.keyval from GTK is
|
# Key handling in VNC is screwy. The event.keyval from GTK is
|
||||||
# interpreted relative to modifier state. This really messes
|
# interpreted relative to modifier state. This really messes
|
||||||
# up with VNC which has no concept of modifiers. If we interpret
|
# up with VNC which has no concept of modifiers. If we interpret
|
||||||
|
Loading…
Reference in New Issue
Block a user