简体   繁体   中英

Can't change _NET_WM_STRUT_PARTIAL property

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM