Skip to content

Instantly share code, notes, and snippets.

@inean
Created May 29, 2012 18:00
Show Gist options
  • Save inean/2829771 to your computer and use it in GitHub Desktop.
Save inean/2829771 to your computer and use it in GitHub Desktop.
A class to interact with Harmattan compositor
from os import getpid
class HarmattanCompositor(object):
# Atoms
XA_ATOM = 4
XA_STRING = 31
XA_WINDOW = 33
# Contants
PropModeReplace, \
PropModePrepend, \
PropModeAppend = xrange(0, 3)
def __init__(self):
# C types
try:
import ctypes as c
except ImportError:
sys.exit(1)
# store ctypes modules
self.c = c
@property
@cached
def xlib(self):
"""Load Xlib library and setup required methods properly"""
# load library
xlib, c = self.c.cdll.LoadLibrary('/usr/lib/libX11.so.6'), self.c
# XInterAtom
xlib.XInternAtom.argtypes = [
c.c_void_p, c.c_char_p, c.c_int
]
# XChangeProperty
xlib.XChangeProperty.argtypes = [
c.c_void_p, c.c_long, c.c_int, c.c_int, c.c_int,
c.c_int, c.c_char_p, c.c_int
]
# XGetWindowProperty
xlib.XGetWindowProperty.argtypes = [
c.c_void_p, c.c_long, c.c_int, c.c_int, c.c_int, c.c_int,
c.c_int, c.c_void_p, c.c_void_p, c.c_void_p, c.c_void_p, c.POINTER(c.POINTER(c.c_ulong))]
#XSetTransientForHint
xlib.XSetTransientForHint.argtypes = [
c.c_void_p, c.c_long, c.c_long
]
# define a data Union class and store on xlib
class data(c.Union):
_fields_ = [("i", c.c_int, 32), ("s", c.c_char * 4)]
setattr(xlib, "data", data)
return xlib
@cached
def _get_display(self):
"""get display"""
return self.xlib.XOpenDisplay(None)
@cached
def _get_root(self):
return self.xlib.XDefaultRootWindow(self._get_display())
@cached
def _get_data(self, value):
"""Create a data object required as by XChangeProperty"""
data, c = self.xlib.data(), self.c
attr = 'i' if isinstance(value, (int, long,)) else 's'
setattr(data, attr, value)
return c.cast(c.pointer(data), c.c_char_p)
@cached
def _get_atom(self, atom):
"""Get atom specified by atom string"""
return self.xlib.XInternAtom(self._get_display(), atom, False)
def _change_property(self, child, atom, ptype, psize, mode, data, dlen):
"""Invoke XChangeProperty"""
self.xlib.XChangeProperty(
self._get_display(), child,
self._get_atom(atom), ptype,
psize, mode, data, dlen)
def _get_property(self, atom):
"""Call XGetWindowProperty"""
# init return vars
c = self.c
type_ret = c.c_int()
format_ret = c.c_int()
nitems_ret = c.c_ulong()
bytes_after_ret = c.c_ulong()
winp = c.pointer(c.c_ulong())
# invoke
retval = self.xlib.XGetWindowProperty(
self._get_display(),
self._get_root(),
self._get_atom(atom),
0, 0x7fffffff, False, self.XA_WINDOW,
c.byref(type_ret), c.byref(format_ret), c.byref(nitems_ret),
c.byref(bytes_after_ret), c.byref(winp))
# return requested values
return not retval, winp
def splash_window(self, wm_class, image):
retval, compositor = self._get_property("_NET_SUPPORTING_WM_CHECK")
if retval and compositor:
c = self.c
# create_string_buffer adds missing NUL
buff = "%d\0%s\0%s\0\0" %(getpid(), wm_class, image,)
buff = c.create_string_buffer(buff)
data = c.cast(buff, c.POINTER(c.c_char))
# invoke
self._change_property(
compositor.contents.value, "_MEEGO_SPLASH_SCREEN",
self.XA_STRING, 8, self.PropModeReplace, data, len(buff))
# flush
self.xlib.XFlush(self._get_display())
self.xlib.XFree(compositor)
def stack_window(self, parent_id, child_id):
"""Stack child_id to parent_id"""
# Notify that we want a stacked window
self._change_property(
child_id,
"_MEEGOTOUCH_WM_INVOKED_BY", self.XA_WINDOW,
self.PropModeReplace, 32, self._get_data(parent_id), 1
)
# for task switcher view stacking
self.xlib.XSetTransientForHint(
self._get_display(), child_id, parent_id)
def set_window_type(self, child_id, wtype):
"""Append wtype as window type"""
self._change_property(
child_id,
"_NET_WM_WINDOW_TYPE", self.XA_ATOM, 32,
self.PropModeAppend, self._get_data(self._get_atom(wtype)), 1
)
@inean
Copy link
Author

inean commented May 29, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment