def init_window(self): log("Win32Clipboard.init_window() creating clipboard window class and instance" ) self.wndclass = WNDCLASSEX() self.wndclass.cbSize = sizeof(WNDCLASSEX) self.wndclass.lpfnWndProc = WNDPROC(self.wnd_proc) self.wndclass.style = win32con.CS_GLOBALCLASS self.wndclass.hInstance = GetModuleHandleA(0) self.wndclass.lpszClassName = clipboard_window_class_name self.wndclass_handle = RegisterClassExW(byref(self.wndclass)) log("RegisterClassExA(%s)=%#x", self.wndclass.lpszClassName, self.wndclass_handle) if self.wndclass_handle == 0: raise WinError() style = win32con.WS_CAPTION #win32con.WS_OVERLAPPED self.window = CreateWindowExW(0, self.wndclass_handle, u"Clipboard", style, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, win32con.HWND_MESSAGE, 0, self.wndclass.hInstance, None) log("clipboard window=%s", self.window) if not self.window: raise WinError() if not AddClipboardFormatListener(self.window): log.warn("Warning: failed to setup clipboard format listener") log.warn(" %s", get_last_error())
def check_support(self, force_enable=False): #create a temporary window to query opengl attributes: hInst = GetModuleHandleA(0) log("check_support() GetModuleHandleW()=%#x", hInst or 0) classname = "Xpra Temporary Window for OpenGL" wndc = WNDCLASSEX() wndc.cbSize = sizeof(WNDCLASSEX) wndc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW wndc.hInstance = hInst wndc.hBrush = COLOR_WINDOW wndc.lpszClassName = classname wndc.lpfnWndProc = WNDPROC(DefWndProc) reg_atom = RegisterClassExA(byref(wndc)) log("check_support() RegisterClassExW()=%#x", reg_atom or 0) if not reg_atom: return { "info": "disabled: failed to register window class, %s" % FormatError() } style = WS_OVERLAPPED | WS_SYSMENU window_name = "Xpra OpenGL Test" self.hwnd = CreateWindowExA(0, reg_atom, window_name, style, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, 0, 0, hInst, None) log("check_support() CreateWindowExW()=%#x", self.hwnd or 0) if not self.hwnd: return { "info": "disabled: failed to create temporary window, %s" % FormatError() } try: self.context = self.create_wgl_context(self.hwnd) with WGLWindowContext(self.hwnd, self.hdc, self.context): props = check_PyOpenGL_support(force_enable) props["display_mode"] = [ ["SINGLE", "DOUBLE"][int(DOUBLE_BUFFERED)], ] #, "ALPHA"] return props finally: hwnd = self.hwnd self.destroy() if hwnd and not DestroyWindow(hwnd): log.warn( "Warning: failed to destroy temporary OpenGL test window") latom = c_void_p(reg_atom) if not UnregisterClassW(cast(latom, LPCWSTR), hInst): log.warn( "Warning: failed to unregister class for OpenGL test window" ) log.warn(" for class %r and module handle %#x:", classname, hInst or 0) log.warn(" '%s'", FormatError())
def cleanup_window(self): w = self.window if w: self.window = None RemoveClipboardFormatListener(w) DestroyWindow(w) wch = self.wndclass_handle if wch: self.wndclass = None self.wndclass_handle = None UnregisterClassW(clipboard_window_class_name, GetModuleHandleA(0))
def cleanup_window(self): w = self.window if w: self.window = None RemoveClipboardFormatListener(w) DestroyWindow(w) wch = self.wndclass_handle if wch: self.wndclass = None self.wndclass_handle = None UnregisterClassW(CLIPBOARD_WINDOW_CLASS_NAME, GetModuleHandleA(0))
def __init__(self): assert singleton is None self.hwnd = None self.event_callbacks = {} self.ignore_events = IGNORE_EVENTS self.log_events = LOG_EVENTS if not WINDOW_EVENTS: return self.wc = WNDCLASSEX() self.wc.cbSize = ctypes.sizeof(WNDCLASSEX) self.wc.style = win32con.CS_GLOBALCLASS | win32con.CS_VREDRAW | win32con.CS_HREDRAW self.wc.lpfnWndProc = WNDPROC(self.WndProc) self.wc.cbClsExtra = 0 self.wc.cbWndExtra = 0 self.wc.hInstance = GetModuleHandleA(0) self.wc.hIcon = 0 self.wc.hCursor = 0 self.wc.hBrush = GetStockObject(win32con.WHITE_BRUSH) self.wc.lpszMenuName = 0 self.wc.lpszClassName = u'Xpra-Event-Window' self.wc.hIconSm = 0 self.wc.hbrBackground = win32con.COLOR_WINDOW self.wc_atom = RegisterClassExW(ctypes.byref(self.wc)) if self.wc_atom == 0: raise ctypes.WinError(ctypes.get_last_error()) self.hwnd = CreateWindowExA(0, self.wc_atom, u"For xpra event listener only", win32con.WS_CAPTION, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, self.wc.hInstance, None) if self.hwnd == 0: raise ctypes.WinError(ctypes.get_last_error()) if wtsapi32: #register our interest in session events: #http://timgolden.me.uk/python/win32_how_do_i/track-session-events.html#isenslogon #http://stackoverflow.com/questions/365058/detect-windows-logout-in-python #http://msdn.microsoft.com/en-us/library/aa383841.aspx #http://msdn.microsoft.com/en-us/library/aa383828.aspx wtsapi32.WTSRegisterSessionNotification(self.hwnd, NOTIFY_FOR_THIS_SESSION) log("Win32EventListener created with hwnd=%s", self.hwnd)
def init_keyboard_listener(self): class KBDLLHOOKSTRUCT(Structure): _fields_ = [ ("vk_code", DWORD), ("scan_code", DWORD), ("flags", DWORD), ("time", c_int), ] DOWN = [win32con.WM_KEYDOWN, win32con.WM_SYSKEYDOWN] #UP = [win32con.WM_KEYUP, win32con.WM_SYSKEYUP] ALL_KEY_EVENTS = { win32con.WM_KEYDOWN: "KEYDOWN", win32con.WM_SYSKEYDOWN: "SYSKEYDOWN", win32con.WM_KEYUP: "KEYUP", win32con.WM_SYSKEYUP: "SYSKEYUP", } def low_level_keyboard_handler(nCode, wParam, lParam): log("WH_KEYBOARD_LL: %s", (nCode, wParam, lParam)) try: scan_code = lParam.contents.scan_code vk_code = lParam.contents.vk_code focused = self.client._focused #the keys we intercept before the OS: keyname = { win32con.VK_LWIN: "Super_L", win32con.VK_RWIN: "Super_R", win32con.VK_TAB: "Tab", }.get(vk_code) modifiers = [] kh = self.client.keyboard_helper key_event_type = ALL_KEY_EVENTS.get(wParam) #log("low_level_keyboard_handler(%s, %s, %s) vk_code=%i, scan_code=%i, keyname=%s, key_event_type=%s, focused=%s, keyboard_grabbed=%s", nCode, wParam, lParam, vk_code, scan_code, keyname, key_event_type, focused, self.client.keyboard_grabbed) if self.client.keyboard_grabbed and focused and keyname and kh and kh.keyboard and key_event_type: modifier_keycodes = kh.keyboard.modifier_keycodes modifier_keys = kh.keyboard.modifier_keys if keyname.startswith("Super"): keycode = 0 #find the modifier keycode: (try the exact key we hit first) for x in (keyname, "Super_L", "Super_R"): keycodes = modifier_keycodes.get(x, []) for k in keycodes: #only interested in numeric keycodes: try: keycode = int(k) break except ValueError: pass if keycode > 0: break else: keycode = vk_code #true for non-modifier keys only! for vk, modkeynames in { win32con.VK_NUMLOCK: ["Num_Lock"], win32con.VK_CAPITAL: ["Caps_Lock"], win32con.VK_CONTROL: ["Control_L", "Control_R"], win32con.VK_SHIFT: ["Shift_L", "Shift_R"], }.items(): if GetKeyState(vk): for modkeyname in modkeynames: mod = modifier_keys.get(modkeyname) if mod: modifiers.append(mod) break #keylog.info("keyboard helper=%s, modifier keycodes=%s", kh, modifier_keycodes) grablog( "vk_code=%s, scan_code=%s, event=%s, keyname=%s, keycode=%s, modifiers=%s, focused=%s", vk_code, scan_code, ALL_KEY_EVENTS.get(wParam), keyname, keycode, modifiers, focused) if keycode > 0: key_event = KeyEvent() key_event.keyname = keyname key_event.pressed = wParam in DOWN key_event.modifiers = modifiers key_event.keyval = scan_code key_event.keycode = keycode key_event.string = "" key_event.group = 0 grablog("detected '%s' key, sending %s", keyname, key_event) self.client.keyboard_helper.send_key_action( focused, key_event) #swallow this event: return 1 except Exception as e: keylog.error("Error: low level keyboard hook failed") keylog.error(" %s", e) return CallNextHookEx(0, nCode, wParam, lParam) # Our low level handler signature. CMPFUNC = CFUNCTYPE(c_int, WPARAM, LPARAM, POINTER(KBDLLHOOKSTRUCT)) # Convert the Python handler into C pointer. pointer = CMPFUNC(low_level_keyboard_handler) # Hook both key up and key down events for common keys (non-system). keyboard_hook_id = SetWindowsHookExA(win32con.WH_KEYBOARD_LL, pointer, GetModuleHandleA(None), 0) # Register to remove the hook when the interpreter exits: keylog("init_keyboard_listener() hook_id=%#x", keyboard_hook_id) msg = MSG() lpmsg = byref(msg) while not self._exit: ret = GetMessageA(lpmsg, 0, 0, 0) keylog("keyboard listener: GetMessage()=%s", ret) if ret == -1: raise ctypes.WinError(ctypes.get_last_error()) if ret == 0: keylog("GetMessage()=0, exiting loop") return r = TranslateMessage(lpmsg) keylog("TranslateMessage(%#x)=%s", lpmsg, r) r = DispatchMessageA(lpmsg) keylog("DispatchMessageA(%#x)=%s", lpmsg, r)
def NotifyIconWndProc(hwnd, msg, wParam, lParam): instance = win32NotifyIcon.instances.get(hwnd) fn = message_map.get(msg) log("NotifyIconWndProc%s instance=%s, message(%i)=%s", (hwnd, msg, wParam, lParam), instance, msg, fn) #log("potential matching win32 constants for message: %s", [x for x in dir(win32con) if getattr(win32con, x)==msg]) if instance and fn: return fn(instance, hwnd, msg, wParam, lParam) or 0 return DefWindowProcA(hwnd, msg, wParam, lParam) NIwc = WNDCLASSEX() NIwc.cbSize = sizeof(WNDCLASSEX) NIwc.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW NIwc.lpfnWndProc = WNDPROC(NotifyIconWndProc) NIwc.hInstance = GetModuleHandleA(0) NIwc.hBrush = GetStockObject(win32con.WHITE_BRUSH) NIwc.lpszClassName = u"win32NotifyIcon" NIclassAtom = RegisterClassExA(byref(NIwc)) if NIclassAtom == 0: raise ctypes.WinError(ctypes.get_last_error()) log("RegisterClassExA(%s)=%i", NIwc.lpszClassName, NIclassAtom) def main(): import os from xpra.platform.win32.common import user32 def click_callback(button, pressed): menu = CreatePopupMenu()