Python: how to switch between workspaces using Xlib? - python

How do I switch between my window manager's workspaces using Python with Xlib module?
This is my most promising attempt:
#!/usr/bin/python
from Xlib import X, display, error, Xatom, Xutil
import Xlib.protocol.event
screen = Xlib.display.Display().screen()
root = screen.root
def sendEvent(win, ctype, data, mask=None):
""" Send a ClientMessage event to the root """
data = (data+[0]*(5-len(data)))[:5]
ev = Xlib.protocol.event.ClientMessage(window=win, client_type=ctype, data=(32,(data)))
if not mask:
mask = (X.SubstructureRedirectMask|X.SubstructureNotifyMask)
root.send_event(ev, event_mask=mask)
# switch to desktop 2
sendEvent(root, Xlib.display.Display().intern_atom("_NET_CURRENT_DESKTOP"), [2])
The above code is shamelessly stolen from various places in the PyPanel source; unfortunately, it doesn't do anything, not even generate a warning / exception. Am I missing something here?
I'm using Python and PyGTK. Xlib seems to be the right choice for switching desktops. I don't intend to use wnck (buggy Python module) or similar, but I'd appreciate any pointers anyway.
I might add that this is my first attempt at writing a Python application using Xlib (or PyGTK).

Apparently you need to work on the same Display object and then flush it at the end. Something like:
display = Xlib.display.Display()
screen = display.screen()
root = screen.root
# ...
sendEvent(root, display.intern_atom("_NET_CURRENT_DESKTOP"), [1, X.CurrentTime])
display.flush()
Credit: Idea from a very similar thread (which almost works).
P.S. By the way, the desktop number starts from 0.

Related

How I can get DrawingArea window handle in Gtk3?

I get this code on CEF Python 3 (link)
...
self.container = gtk.DrawingArea()
self.container.set_property('can-focus', True)
self.container.connect('size-allocate', self.OnSize)
self.container.show()
...
windowID = self.container.get_window().handle
windowInfo = cefpython.WindowInfo()
windowInfo.SetAsChild(windowID)
self.browser = cefpython.CreateBrowserSync(windowInfo,
browserSettings={},
navigateUrl=GetApplicationPath('example.html'))
...
This code [self.container.get_window().handle] don't work with PyGI and GTK3.
I trying port the code from GTK2 to GTK3, how I can do this?
Edited:
After some search, I found a tip to make get_window work: I call: self.container.realize() before self.container.get_window(). But I cant't get Window Handle yet.
I need put CEF3 window inside a DrawingArea or any element. How I can do this with PyGI?
Edited:
My environment is:
Windows 7
Python 2.7 and Python 3.2
Sadly there seems to be no progress on the python gobject introspection to fix this and make gdk_win32_window_get_handle available (reported a bug in the gnome bugtracker quite a while ago) - it is also quite needed for Python GStreamer and Windows ...
So I followed the suggestion of totaam and used ctypes to access gdk_win32_window_get_handle. Took me forever since I had no experience with this - and well it is somehow quite an ugly hack - but well when needed...
Here is the code:
Gdk.threads_enter()
#get the gdk window and the corresponding c gpointer
drawingareawnd = drawingarea.get_property("window")
#make sure to call ensure_native before e.g. on realize
if not drawingareawnd.has_native():
print("Your window is gonna freeze as soon as you move or resize it...")
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object]
drawingarea_gpointer = ctypes.pythonapi.PyCapsule_GetPointer(drawingareawnd.__gpointer__, None)
#get the win32 handle
gdkdll = ctypes.CDLL ("libgdk-3-0.dll")
hnd = gdkdll.gdk_win32_window_get_handle(drawingarea_gpointer)
#do what you want with it ... I pass it to a gstreamer videosink
Gdk.threads_leave()
You must first import GdkX11 for get_xid() to be available on the returned GdkX11Window.
from gi.repository import GdkX11
...
-windowID = self.container.get_window().handle
+windowID = self.container.get_window().get_xid()
The answer advising you to use .handle or .get_xid() works on GTK2, but not with GTK3 or on MS Windows, which are part of your question.
I've done a lot of digging and found that there is a function in GTK3 which does what you want: gdk_win32_window_get_handle, but sadly it is not available in the gi bindings.
You may be able to get to it using ctypes or Cython (which is what I am going to do).

How can I use Python 3.3 to continuously update my MouseSpeed in Windows?

I am developing a python script to drive a prototype I'm developing, and my current stumbling block is attempting to continuously write to the MouseSensitivity register in Windows. I'm using Windows 7, for specificity.
Unfortunately, I've hit some dead ends.
I've attempted to use pywin32 to write to the registry, but have not succeeded. After some searching, I've come across the SystemParametersInfo Function, but have not had any success with that either.
Essentially, for the purpose of solving this crisis, I've installed pyserial, pywin32, and ctypes (it appears that pywin32 may not be required). Assume I have an integer variable that will be between (and including) 1 to 20.
What I have for code right now is listed below. Much of it has been modified from here, as it appears that the author was using python, ctypes, user32.dll, and the SystemParametersInfo Function. However, when I run the code below, the shell enters a loop where the next line gets two tabs of space, and the cursor sits blinking until I keyboard interrupt. Any ideas?
import sys
import ctypes
import ctypes.wintypes
num = 12 # Between 1 and 20
SystemParametersInfo = ctypes.windll.user32.SystemParametersInfoW
SystemParametersInfo.argtypes = (
ctypes.wintypes.UINT,
ctypes.wintypes.UINT,
ctypes.c_void_p,
ctypes.wintypes.UINT,
)
SPI_SETMOUSESPEED = 0x0071
SystemParametersInfo(SPI_SETMOUSESPEED, 0, ctypes.cast(num, ctypes.c_void_p, 0)

system wide shortcut for Mac OS X

So I was asked to port some internal helper applications to Mac OS X 10.7.
Works all quite welll as the platform dependent code is minimal anyhow, but one application needs a system wide shortcut to function (i.e. RegisterHotkey functionality) and I can't find any documentation on how I'd do this on a Mac.
The program is using a PyQt gui with Python 3.2. and the corresponding code for windows is basically:
def register_hotkey(self):
hwnd = int(self.winId())
modifiers, key = self._get_hotkey()
user32.RegisterHotKey(hwnd, self._MESSAGE_ID, modifiers, key)
and then to receive the hotkey events:
def winEvent(self, msg):
if msg.message == w32.WM_HOTKEY:
self.handle_hotkey()
return True, id(msg)
return False, id(msg)
Note that I don't need a python variant, I can easily write a simple c extension - so C/objective-c solutions are welcome as well.
I recently coded up an extension to quodlibet capturing multimedia keys (since absorbed into quodlibet itself); for your setup the same process applies.
I used the Quartz CGEventTapCreate hook and event loop, and the Cocoa AppKit framework to decipher key codes to achieve this.
The following code registers a python callback which is passed global key presses, and starts the event loop:
import Quartz
from AppKit import NSKeyUp, NSSystemDefined, NSEvent
# Set up a tap, with type of tap, location, options and event mask
tap = Quartz.CGEventTapCreate(
Quartz.kCGSessionEventTap, # Session level is enough for our needs
Quartz.kCGHeadInsertEventTap, # Insert wherever, we do not filter
Quartz.kCGEventTapOptionListenOnly, # Listening is enough
Quartz.CGEventMaskBit(NSSystemDefined), # NSSystemDefined for media keys
keyboardTapCallback,
None
)
runLoopSource = Quartz.CFMachPortCreateRunLoopSource(None, tap, 0)
Quartz.CFRunLoopAddSource(
Quartz.CFRunLoopGetCurrent(),
runLoopSource,
Quartz.kCFRunLoopDefaultMode
)
# Enable the tap
Quartz.CGEventTapEnable(tap, True)
# and run! This won't return until we exit or are terminated.
Quartz.CFRunLoopRun()
I defined a tap for system defined keys only (media keys); you'll have to specify a different event mask (CGEventMaskBit with one or more Event Types); e.g. Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp) for key up events.
The callback should have the following signature (it implements the CGEventTapCallBack method from the Quartz API:
def keyboardTapCallback(proxy, type_, event, refcon):
# Convert the Quartz CGEvent into something more useful
keyEvent = NSEvent.eventWithCGEvent_(event)
I converted the Quartz event into a NSEvent, because all the information I could find on Mac multimedia keys was referring to that class.
In principle you can achieve the same thing with the AppKit APIs too, but then your Python application is treated as a Mac Application (visible in the Dock with an icon and everything), while I wanted this to be kept in the background altogether.
Using the power of google, I found this snippet of code, which allows the registration of global hotkeys for Mac OS X
You'll need to add the Carbon framework, and probably a bridged cast for ARC when passing the Objective-C self pointer to the C function.
At a minimum, you'll also need to:
#import <Carbon/Carbon.h>
The keycodes can be seen on this page explaining the virtual key codes.
Why has nobody ever mentioned the hammerspoon, which supports custom global system shortcuts, which can invoke shell command or launch UI application like Safari, PHOTOSHOP.
The following is an example written by me demonstrating how to invoke shell function with global hotkeys.
https://gist.github.com/BigSully/0e59ab97f148bc167ea19dbd42ebef4b
Use hs.execute to execute shell command, either non-interactive or interactive.
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "P", function()
local output = hs.execute("toggleProxy", true)
hs.alert.show(output)
end)
or
Use hs.application.launchOrFocus to launch application
hs.application.launchOrFocus("Safari")

Programmatically detect system-proxy settings on Windows XP with Python

I develop a critical application used by a multi-national company. Users in offices all around the globe need to be able to install this application.
The application is actually a plugin to Excel and we have an automatic installer based on Setuptools' easy_install that ensures that all a project's dependancies are automatically installed or updated any time a user switches on their Excel. It all works very elegantly as users are seldom aware of all the installation which occurs entirely in the background.
Unfortunately we are expanding and opening new offices which all have different proxy settings. These settings seem to change from day to day so we cannot keep up with the outsourced security guys who change stuff without telling us. It sucks but we just have to work around it.
I want to programatically detect the system-wide proxy settings on the Windows workstations our users run:
Everybody in the organisazation runs Windows XP and Internet Explorer. I've verified that everybody can download our stuff from IE without problems regardless of where they are int the world.
So all I need to do is detect what proxy settings IE is using and make Setuptools use those settings. Theoretically all of this information should be in the Registry.. but is there a better way to find it that is guaranteed not to change with people upgrade IE? For example is there a Windows API call I can use to discover the proxy settings?
In summary:
We use Python 2.4.4 on Windows XP
We need to detect the Internet Explorer proxy settings (e.g. host, port and Proxy type)
I'm going to use this information to dynamically re-configure easy_install so that it can download the egg files via the proxy.
UPDATE0:
I forgot one important detail: Each site has an auto-config "pac" file.
There's a key in Windows\CurrentVersion\InternetSettings\AutoConfigURL which points to a HTTP document on a local server which contains what looks like a javascript file.
The pac script is basically a series of nested if-statements which compare URLs against a regexp and then eventually return the hostname of the chosen proxy-server. The script is a single javascript function called FindProxyForURL(url, host)
The challenge is therefore to find out for any given server which proxy to use. The only 100% guaranteed way to do this is to look up the pac file and call the Javascript function from Python.
Any suggestions? Is there a more elegant way to do this?
Here's a sample that should create a bullet green (proxy enable) or red (proxy disable) in your systray
It shows how to read and write in windows registry
it uses gtk
#!/usr/bin/env python
import gobject
import gtk
from _winreg import *
class ProxyNotifier:
def __init__(self):
self.trayIcon = gtk.StatusIcon()
self.updateIcon()
#set callback on right click to on_right_click
self.trayIcon.connect('popup-menu', self.on_right_click)
gobject.timeout_add(1000, self.checkStatus)
def isProxyEnabled(self):
aReg = ConnectRegistry(None,HKEY_CURRENT_USER)
aKey = OpenKey(aReg, r"Software\Microsoft\Windows\CurrentVersion\Internet Settings")
subCount, valueCount, lastModified = QueryInfoKey(aKey)
for i in range(valueCount):
try:
n,v,t = EnumValue(aKey,i)
if n == 'ProxyEnable':
return v and True or False
except EnvironmentError:
break
CloseKey(aKey)
def invertProxyEnableState(self):
aReg = ConnectRegistry(None,HKEY_CURRENT_USER)
aKey = OpenKey(aReg, r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", 0, KEY_WRITE)
if self.isProxyEnabled() :
val = 0
else:
val = 1
try:
SetValueEx(aKey,"ProxyEnable",0, REG_DWORD, val)
except EnvironmentError:
print "Encountered problems writing into the Registry..."
CloseKey(aKey)
def updateIcon(self):
if self.isProxyEnabled():
icon=gtk.STOCK_YES
else:
icon=gtk.STOCK_NO
self.trayIcon.set_from_stock(icon)
def checkStatus(self):
self.updateIcon()
return True
def on_right_click(self, data, event_button, event_time):
self.invertProxyEnableState()
self.updateIcon()
if __name__ == '__main__':
proxyNotifier = ProxyNotifier()
gtk.main()
As far as I know, In a Windows environment, if no proxy environment variables are set, proxy settings are obtained from the registry's Internet Settings section. .
Isn't it enough?
Or u can get something useful info from registry:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer
Edit:
sorry for don't know how to format comment's source code, I repost it here.
>>> import win32com.client
>>> js = win32com.client.Dispatch('MSScriptControl.ScriptControl')
>>> js.Language = 'JavaScript'
>>> js.AddCode('function add(a, b) {return a+b;}')
>>> js.Run('add', 1, 2)
3

How do I deal with multiple common user interfaces?

I'm working on a python application that runs on 2 different platforms, namely regular desktop linux and Maemo 4. We use PyGTK on both platforms but on Maemo there are a bunch of little tweaks to make it look nice which are implemented as follows:
if util.platform.MAEMO:
# do something fancy for maemo
else:
# regular pygtk
There are roughly 15 of these if statements needed to get the UI looking and working nice on Maemo 4.
This has been very manageable for all this time. The problem is that a while ago there was a new version of Maemo released (5, aka fremantle) and it has some big differences compared to Maemo 4. I don't want to add a bunch of checks throughout the GUI code in order to get all 3 platforms working nicely with the same codebase because that would get messy. I also don't want to create a copy of the original GUI code for each platform and simply modify it for the specific platform (I'd like to re-use as much code as possible).
So, what are ways to have slightly different UIs for different platforms which are based on the same core UI code? I don't think this is a python or Maemo-specific question, I'd just like to know how this is done.
You could wind up much of this in a factory:
def createSpec():
if util.platform.MAEMO: return Maemo4Spec()
elif util.platform.MAEMO5: return Maemo5Spec()
return StandardPyGTKSpec()
Then, somewhere early in your code, you just call that factory:
spec = createSpec()
Now, everywhere else you had conditions, you just call the necessary function:
spec.drawComboBox()
As long as drawComboBox(), handles anything specific to the platform, you should be in good shape.
You could isolate the platform specific stuff you need to do into small consistently named functions inside a platform module, create the right function name using the platform you're running on and then getattr the right one and call it. The if/else boilerplate would disappear then.
I've made a separate module to handle all of my specializing between normal Linux, Maemo 4.1, and Maemo 5. It detects what features are available and allows the program to gracefully degrade.
For example
def _fremantle_hildonize_window(app, window):
oldWindow = window
newWindow = hildon.StackableWindow()
oldWindow.get_child().reparent(newWindow)
app.add_window(newWindow)
return newWindow
def _hildon_hildonize_window(app, window):
oldWindow = window
newWindow = hildon.Window()
oldWindow.get_child().reparent(newWindow)
app.add_window(newWindow)
return newWindow
def _null_hildonize_window(app, window):
return window
try:
hildon.StackableWindow
hildonize_window = _fremantle_hildonize_window
except AttributeError:
try:
hildon.Window
hildonize_window = _hildon_hildonize_window
except AttributeError:
hildonize_window = _null_hildonize_window
For more, see
Dialcentral, Gonert, ejpi, or Quicknote's source code for a file called hildonize.py
https://garage.maemo.org/plugins/ggit/browse.php/?p=gc-dialer;a=blob;f=src/hildonize.py;
Another example from The One Ring's GObject Utils (go_utils.py)
def _old_timeout_add_seconds(timeout, callback):
return gobject.timeout_add(timeout * 1000, callback)
def _timeout_add_seconds(timeout, callback):
return gobject.timeout_add_seconds(timeout, callback)
try:
gobject.timeout_add_seconds
timeout_add_seconds = _timeout_add_seconds
except AttributeError:
timeout_add_seconds = _old_timeout_add_seconds

Categories