I want to reserve some space on the screen for my Gtk application written in Python. I've wrote this function:
import xcb, xcb.xproto
import struct
def reserve_space(xid, data):
connection = xcb.connect()
atom_cookie = connection.core.InternAtom(True, len("_NET_WM_STRUT_PARTIAL"),
"_NET_WM_STRUT_PARTIAL")
type_cookie = connection.core.InternAtom(True, len("CARDINAL"), "CARDINAL")
atom = atom_cookie.reply().atom
atom_type = type_cookie.reply().atom
data_p = struct.pack("I I I I I I I I I I I I", *data)
strat_cookie = connection.core.ChangeProperty(xcb.xproto.PropMode.Replace, xid,
atom, xcb.xproto.Atom.CARDINAL, 32, len(data_p), data_p)
connection.flush()
It's call looks like this:
utils.reserve_space(xid, [0, 60, 0, 0, 0, 0, 24, 767, 0, 0, 0, 0])
Unfortunately, it doesn't work. Where is an error in my code?
UPD: Here is my xprop output. My WM is Compiz.
I have uploaded a gist that demonstrates how to specify a strut across the top of the current monitor for what might be a task-bar. It may help explain some of this.
The gist of my gist is below:
window = gtk.Window()
window.show_all()
topw = window.get_toplevel().window
topw.property_change("_NET_WM_STRUT","CARDINAL",32,gtk.gdk.PROP_MODE_REPLACE,
[0, 0, bar_size, 0])
topw.property_change("_NET_WM_STRUT_PARTIAL","CARDINAL",32,gtk.gdk.PROP_MODE_REPLACE,
[0, 0, bar_size, 0, 0, 0, 0, 0, x, x+width, 0, 0])
I found the strut arguments confusing at first, so here is an explanation that I hope is clearer:
we set _NET_WM_STRUT
, the older mechanism as well as _NET_WM_STRUT_PARTIAL
but window managers ignore the former if they support the latter. The numbers in the array are as follows:
0, 0, bar_size, 0
are the number of pixels to reserve along each edge of the screen given in the order left , right , top , bottom . Here the size of the bar is reserved at the top of the screen and the other edges are left alone. _NET_WM_STRUT_PARTIAL
also supplies a further four pairs, each being a start and end position for the strut (they don't need to occupy the entire edge). In the example, we set the top start to the current monitor's x co-ordinate and the top-end to the same value plus that monitor's width. The net result is that space is reserved only on the current monitor.
Note that co-ordinates are specified relative to the screen (ie all monitors together).
(see the referenced gist for the full context)
Changing to using ChangePropertyChecked(), and then checking the result gives a BadLength exception.
I think the bug here is that the ChangeProperty()
parameter data_len
is the number of elements of the size given by format
, not the number of bytes, in the property data data
.
Slightly modified code which works for me:
def reserve_space(xid, data):
connection = xcb.connect()
atom_cookie = connection.core.InternAtom(False, len("_NET_WM_STRUT_PARTIAL"),
"_NET_WM_STRUT_PARTIAL")
atom = atom_cookie.reply().atom
data_p = struct.pack("12I", *data)
strat_cookie = connection.core.ChangePropertyChecked(xcb.xproto.PropMode.Replace, xid,
atom, xcb.xproto.Atom.CARDINAL, 32, len(data_p)/4, data_p)
strat_cookie.check()
connection.flush()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.