Ejemplo n.º 1
0
def test_default_float_hints(xmanager):
    xmanager.c.next_layout()
    w = None
    conn = xcbq.Connection(xmanager.display)

    def size_hints():
        nonlocal w
        w = conn.create_window(5, 5, 10, 10)

        # set the size hints
        hints = [0] * 18
        hints[0] = xcbq.NormalHintsFlags["PMinSize"] | xcbq.NormalHintsFlags["PMaxSize"]
        hints[5] = hints[6] = hints[7] = hints[8] = 10
        w.set_property("WM_NORMAL_HINTS", hints, type="WM_SIZE_HINTS", format=32)
        w.map()
        conn.conn.flush()

    try:
        xmanager.create_window(size_hints)
        assert xmanager.c.window.info()['floating'] is True
    finally:
        w.kill_client()
        conn.finalize()

    w = None
    conn = xcbq.Connection(xmanager.display)

    def size_hints():
        nonlocal w
        w = conn.create_window(5, 5, 10, 10)

        # set the aspect hints
        hints = [0] * 18
        hints[0] = xcbq.NormalHintsFlags["PAspect"]
        hints[11] = hints[12] = hints[13] = hints[14] = 1
        w.set_property("WM_NORMAL_HINTS", hints, type="WM_SIZE_HINTS", format=32)
        w.map()
        conn.conn.flush()

    try:
        xmanager.create_window(size_hints)
        assert xmanager.c.window.info()['floating'] is True
        info = xmanager.c.window.info()
        assert info['width'] == 10
        assert info['height'] == 10
        xmanager.c.window.toggle_floating()
        assert xmanager.c.window.info()['floating'] is False
        info = xmanager.c.window.info()
        assert info['width'] == 398
        assert info['height'] == 578
        xmanager.c.window.toggle_fullscreen()
        info = xmanager.c.window.info()
        assert info['width'] == 800
        assert info['height'] == 600
    finally:
        w.kill_client()
        conn.finalize()
Ejemplo n.º 2
0
def test_user_position(xmanager):
    w = None
    conn = xcbq.Connection(xmanager.display)

    def user_position_window():
        nonlocal w
        w = conn.create_window(5, 5, 10, 10)
        # xmanager config automatically floats "float"
        w.set_property("WM_CLASS", "float", type="STRING", format=8)
        # set the user specified position flag
        hints = [0] * 18
        hints[0] = xcbq.NormalHintsFlags["USPosition"]
        w.set_property("WM_NORMAL_HINTS",
                       hints,
                       type="WM_SIZE_HINTS",
                       format=32)
        w.map()
        conn.conn.flush()

    try:
        xmanager.create_window(user_position_window)
        assert xmanager.c.window.info()['floating'] is True
        assert xmanager.c.window.info()['x'] == 5
        assert xmanager.c.window.info()['y'] == 5
        assert xmanager.c.window.info()['width'] == 10
        assert xmanager.c.window.info()['height'] == 10
    finally:
        w.kill_client()
        conn.finalize()
Ejemplo n.º 3
0
def test_only_input_hint_focus(manager):
    w = None
    conn = xcbq.Connection(manager.display)

    def only_input_hint():
        nonlocal w
        w = conn.create_window(5, 5, 10, 10)
        w.set_attribute(eventmask=xcffib.xproto.EventMask.FocusChange)
        # manager config automatically floats xclock
        w.set_property("WM_CLASS", "xclock", type="STRING", format=8)

        # set the input hint
        hints = [0] * 14
        hints[0] = xcbq.HintsFlags["InputHint"]
        hints[1] = 1  # set hints to 1, i.e. we want them
        w.set_property("WM_HINTS", hints, type="WM_HINTS", format=32)

        w.map()
        conn.conn.flush()
    try:
        manager.create_window(only_input_hint)
        assert manager.c.window.info()['floating'] is True
        got_take_focus, got_focus_in = wait_for_focus_events(conn)
        assert not got_take_focus
        assert got_focus_in
    finally:
        w.kill_client()
        conn.finalize()
Ejemplo n.º 4
0
def test_no_focus(xmanager):
    w = None
    conn = xcbq.Connection(xmanager.display)

    def no_focus():
        nonlocal w
        w = conn.create_window(5, 5, 10, 10)
        w.set_attribute(eventmask=xcffib.xproto.EventMask.FocusChange)
        # xmanager config automatically floats "float"
        w.set_property("WM_CLASS", "float", type="STRING", format=8)

        hints = [0] * 14
        hints[0] = xcbq.HintsFlags["InputHint"]
        w.set_property("WM_HINTS", hints, type="WM_HINTS", format=32)
        w.map()
        conn.conn.flush()

    try:
        xmanager.create_window(no_focus)
        assert xmanager.c.window.info()['floating'] is True
        got_take_focus, got_focus_in = wait_for_focus_events(conn)
        assert not got_take_focus
        assert not got_focus_in
    finally:
        w.kill_client()
        conn.finalize()
Ejemplo n.º 5
0
def test_net_client_list(xmanager):
    conn = xcbq.Connection(xmanager.display)

    def assert_clients(number):
        clients = conn.default_screen.root.get_property("_NET_CLIENT_LIST",
                                                        unpack=int)
        assert len(clients) == number

    # ManagerConfig has a Bar, which should not appear in _NET_CLIENT_LIST
    assert_clients(0)
    one = xmanager.test_window("one")
    assert_clients(1)
    two = xmanager.test_window("two")
    xmanager.c.window.toggle_minimize()
    three = xmanager.test_window("three")
    xmanager.c.screen.next_group()
    assert_clients(
        3)  # Minimized windows and windows on other groups are included
    xmanager.kill_window(one)
    xmanager.c.screen.next_group()
    assert_clients(2)
    xmanager.kill_window(three)
    assert_clients(1)
    xmanager.c.screen.next_group()
    one = xmanager.test_window("one")
    assert_clients(2)
    xmanager.c.window.static()  # Static windows are not included
    assert_clients(1)
    xmanager.kill_window(two)
    assert_clients(0)
Ejemplo n.º 6
0
def test_net_client_list(xmanager):
    conn = xcbq.Connection(xmanager.display)

    def assert_clients(number):
        clients = conn.default_screen.root.get_property('_NET_CLIENT_LIST', unpack=int)
        assert len(clients) == number

    assert_clients(0)
    one = xmanager.test_window("one")
    assert_clients(1)
    two = xmanager.test_window("two")
    wins = xmanager.c.windows()
    xmanager.c.window.toggle_minimize()
    three = xmanager.test_window("three")
    xmanager.c.screen.next_group()
    assert_clients(3)
    xmanager.kill_window(one)
    xmanager.c.screen.next_group()
    assert_clients(2)
    xmanager.kill_window(three)
    assert_clients(1)
    xmanager.c.screen.next_group()
    one = xmanager.test_window("one")
    assert_clients(2)
    xmanager.kill_window(one)
    xmanager.kill_window(two)
    assert_clients(0)
Ejemplo n.º 7
0
def test_cursor_warp(xmanager):
    conn = xcbq.Connection(xmanager.display)
    root = conn.default_screen.root.wid

    assert xmanager.c.screen.info()["index"] == 0

    xmanager.test_window("one")
    xmanager.c.window.set_position_floating(50, 50)
    xmanager.c.window.set_size_floating(50, 50)

    xmanager.c.to_screen(1)
    assert xmanager.c.screen.info()["index"] == 1

    p = conn.conn.core.QueryPointer(root).reply()
    # Here pointer should warp to the second screen as there are no windows
    # there.
    assert p.root_x == WIDTH + SECOND_WIDTH // 2
    # Reduce the bar height from the screen height.
    assert p.root_y == (SECOND_HEIGHT - 20) // 2

    xmanager.c.to_screen(0)
    assert xmanager.c.window.info()["name"] == "one"

    p = conn.conn.core.QueryPointer(xmanager.c.window.info()["id"]).reply()

    # Here pointer should warp to the window.
    assert p.win_x == 25
    assert p.win_y == 25
    assert p.same_screen
Ejemplo n.º 8
0
def test_max_size_hint(xmanager):
    w = None
    conn = xcbq.Connection(xmanager.display)

    def size_hints():
        nonlocal w
        w = conn.create_window(0, 0, 100, 100)

        # set the size hints
        hints = [0] * 18
        hints[0] = xcbq.NormalHintsFlags["PMaxSize"]
        hints[7] = hints[8] = 100
        w.set_property("WM_NORMAL_HINTS",
                       hints,
                       type="WM_SIZE_HINTS",
                       format=32)
        w.map()
        conn.conn.flush()

    try:
        xmanager.create_window(size_hints)
        xmanager.c.window.enable_floating()
        assert xmanager.c.window.info()['width'] == 100
        assert xmanager.c.window.info()['height'] == 100

        xmanager.c.window.set_size_floating(50, 50)
        assert xmanager.c.window.info()['width'] == 50
        assert xmanager.c.window.info()['height'] == 50

        xmanager.c.window.set_size_floating(200, 200)
        assert xmanager.c.window.info()['width'] == 100
        assert xmanager.c.window.info()['height'] == 100
    finally:
        w.kill_client()
        conn.finalize()
Ejemplo n.º 9
0
    def get_valid_timestamp(self):
        """Get a valid timestamp, i.e. not CurrentTime, for X server.

        It may be used in cases where CurrentTime is unacceptable for X server."""
        # do a zero length append to get the time offset as suggested by ICCCM
        # https://tronche.com/gui/x/icccm/sec-2.html#s-2.1
        # we do this on a separate connection since we can't receive events
        # without returning control to the event loop, which we can't do
        # because the event loop (via some window event) wants to know the
        # current time.
        conn = None
        try:
            conn = xcbq.Connection(self._display_name)
            conn.default_screen.root.set_attribute(
                eventmask=EventMask.PropertyChange)
            conn.conn.core.ChangePropertyChecked(
                xcffib.xproto.PropMode.Append,
                self._root.wid,
                self.conn.atoms["WM_CLASS"],
                self.conn.atoms["STRING"],
                8,
                0,
                "",
            ).check()
            while True:
                event = conn.conn.wait_for_event()
                if event.__class__ != xcffib.xproto.PropertyNotifyEvent:
                    continue
                return event.time
        finally:
            if conn is not None:
                conn.finalize()
Ejemplo n.º 10
0
def test_min_size_hint_no_flag(manager):
    w = None
    conn = xcbq.Connection(manager.display)

    def size_hints():
        nonlocal w
        w = conn.create_window(0, 0, 100, 100)

        # set the size hints
        hints = [0] * 18
        hints[5] = hints[6] = 100
        w.set_property("WM_NORMAL_HINTS", hints, type="WM_SIZE_HINTS", format=32)
        w.map()
        conn.conn.flush()

    try:
        manager.create_window(size_hints)
        manager.c.window.enable_floating()
        print(w.get_wm_normal_hints())
        assert manager.c.window.info()['width'] == 100
        assert manager.c.window.info()['height'] == 100

        manager.c.window.set_size_floating(50, 50)
        assert manager.c.window.info()['width'] == 50
        assert manager.c.window.info()['height'] == 50

        manager.c.window.set_size_floating(200, 200)
        assert manager.c.window.info()['width'] == 200
        assert manager.c.window.info()['height'] == 200
    finally:
        w.kill_client()
        conn.finalize()
Ejemplo n.º 11
0
def test_widgetbox_widget(manager):
    manager.conn = xcbq.Connection(manager.display)

    # We need to trick the widgets into thinking this is libqtile.qtile so
    # we add some methods that are called when the widgets are configured
    manager.call_soon = no_op
    manager.register_widget = no_op

    tb_one = TextBox(name="tb_one", text="TB ONE")
    tb_two = TextBox(name="tb_two", text="TB TWO")

    # Give widgetbox invalid value for button location
    widget_box = WidgetBox([tb_one, tb_two],
                           close_button_location="middle",
                           fontsize=10)

    # Create a bar and set attributes needed to run widget
    fakebar = Bar([widget_box], 24)
    fakebar.window = FakeWindow()
    fakebar.width = 10
    fakebar.height = 10
    fakebar.draw = no_op

    # Configure the widget box
    widget_box._configure(manager, fakebar)

    # Invalid value should be corrected to default
    assert widget_box.close_button_location == "left"

    # Check only widget in bar is widgetbox
    assert fakebar.widgets == [widget_box]

    # Open box
    widget_box.cmd_toggle()

    # Check it's open
    assert widget_box.box_is_open

    # Default text position is left
    assert fakebar.widgets == [widget_box, tb_one, tb_two]

    # Close box
    widget_box.cmd_toggle()

    # Check it's closed
    assert not widget_box.box_is_open

    # Check widgets have been removed
    assert fakebar.widgets == [widget_box]

    # Move button to right-hand side
    widget_box.close_button_location = "right"

    # Re-open box with new layout
    widget_box.cmd_toggle()

    # Now widgetbox is on the right
    assert fakebar.widgets == [tb_one, tb_two, widget_box]
Ejemplo n.º 12
0
def test_bring_front_click(manager, bring_front_click):
    def get_all_windows(conn):
        root = conn.default_screen.root.wid
        q = conn.conn.core.QueryTree(root).reply()
        return list(q.children)

    def fake_click(conn, xtest, x, y):
        root = conn.default_screen.root.wid
        xtest.FakeInput(6, 0, xcffib.xproto.Time.CurrentTime, root, x, y, 0)
        xtest.FakeInput(4, 1, xcffib.xproto.Time.CurrentTime, root, 0, 0, 0)
        xtest.FakeInput(5, 1, xcffib.xproto.Time.CurrentTime, root, 0, 0, 0)
        conn.conn.flush()

    conn = xcbq.Connection(manager.display)
    xtest = conn.conn(xcffib.xtest.key)

    # this is a tiled window.
    manager.test_window("one")
    manager.c.sync()

    manager.test_window("two")
    manager.c.window.set_position_floating(50, 50)
    manager.c.window.set_size_floating(50, 50)
    manager.c.sync()

    manager.test_window("three")
    manager.c.window.set_position_floating(150, 50)
    manager.c.window.set_size_floating(50, 50)
    manager.c.sync()

    wids = [x["id"] for x in manager.c.windows()]
    names = [x["name"] for x in manager.c.windows()]

    assert names == ["one", "two", "three"]
    wins = get_all_windows(conn)
    assert wins.index(wids[0]) < wins.index(wids[1]) < wins.index(wids[2])

    # Click on window two
    fake_click(conn, xtest, 55, 55)
    manager.c.sync()
    wins = get_all_windows(conn)
    if bring_front_click:
        assert wins.index(wids[0]) < wins.index(wids[2]) < wins.index(wids[1])
    else:
        assert wins.index(wids[0]) < wins.index(wids[1]) < wins.index(wids[2])

    # Click on window one
    fake_click(conn, xtest, 10, 10)
    manager.c.sync()
    wins = get_all_windows(conn)
    if bring_front_click == "floating_only":
        assert wins.index(wids[0]) < wins.index(wids[2]) < wins.index(wids[1])
    elif bring_front_click:
        assert wins.index(wids[2]) < wins.index(wids[1]) < wins.index(wids[0])
    else:
        assert wins.index(wids[0]) < wins.index(wids[1]) < wins.index(wids[2])
Ejemplo n.º 13
0
def test_kill_via_message(xmanager):
    xmanager.test_window("one")
    window_info = xmanager.c.window.info()
    conn = xcbq.Connection(xmanager.display)
    data = xcffib.xproto.ClientMessageData.synthetic([0, 0, 0, 0, 0], "IIIII")
    ev = xcffib.xproto.ClientMessageEvent.synthetic(
        32, window_info["id"], conn.atoms['_NET_CLOSE_WINDOW'], data)
    conn.default_screen.root.send_event(
        ev, mask=xcffib.xproto.EventMask.SubstructureRedirect)
    conn.xsync()
    conn.finalize()
    assert_window_died(xmanager.c, window_info)
Ejemplo n.º 14
0
def test_new_window(xdisplay):
    conn = xcbq.Connection(xdisplay)
    win = conn.create_window(1, 2, 640, 480)
    assert isinstance(win, xcbq.Window)
    geom = win.get_geometry()
    assert geom.x == 1
    assert geom.y == 2
    assert geom.width == 640
    assert geom.height == 480
    win.kill_client()
    with pytest.raises(xcffib.ConnectionException):
        win.get_geometry()
Ejemplo n.º 15
0
def test_focus(qtile):
    qtile.conn = xcbq.Connection(qtile.display)
    qtile.test_xeyes()

    popup = Popup(qtile)
    popup.width = qtile.c.screen.info()["width"]
    popup.height = qtile.c.screen.info()["height"]
    popup.place()
    popup.unhide()
    assert qtile.c.group.info()['focus'] == 'xeyes'
    assert qtile.c.group.info()['windows'] == ['xeyes']
    assert len(qtile.c.windows()) == 1
    popup.hide()
    popup.kill()
Ejemplo n.º 16
0
def test_net_frame_extents(xmanager):
    conn = xcbq.Connection(xmanager.display)

    def assert_frame(wid, frame):
        r = conn.conn.core.GetProperty(
            False, wid, conn.atoms["_NET_FRAME_EXTENTS"], conn.atoms["CARDINAL"], 0, (2**32) - 1
        ).reply()
        assert r.value.to_atoms() == frame

    pid = xmanager.test_window("one")
    wid = xmanager.c.window.info()["id"]
    assert_frame(wid, (2, 2, 2, 2))
    xmanager.c.next_layout()
    assert_frame(wid, (4, 4, 4, 4))
    xmanager.c.window.enable_floating()
    assert_frame(wid, (6, 6, 6, 6))
    xmanager.kill_window(pid)
Ejemplo n.º 17
0
def test_hints_setting_unsetting(xmanager):
    w = None
    conn = xcbq.Connection(xmanager.display)

    def no_input_hint():
        nonlocal w
        w = conn.create_window(5, 5, 10, 10)
        w.map()
        conn.conn.flush()

    try:
        xmanager.create_window(no_input_hint)
        # We default the input hint to true since some non-trivial number of
        # windows don't set it, and most of them want focus. The spec allows
        # WMs to assume "convenient" values.
        assert xmanager.c.window.hints()['input']

        # now try to "update" it, but don't really set an update (i.e. the
        # InputHint bit is 0, so the WM should not derive a new hint from the
        # content of the message at the input hint's offset)
        hints = [0] * 14
        w.set_property("WM_HINTS", hints, type="WM_HINTS", format=32)
        conn.flush()

        # should still have the hint
        assert xmanager.c.window.hints()['input']

        # now do an update: turn it off
        hints[0] = xcbq.HintsFlags["InputHint"]
        hints[1] = 0
        w.set_property("WM_HINTS", hints, type="WM_HINTS", format=32)
        conn.flush()
        assert not xmanager.c.window.hints()['input']

        # turn it back on
        hints[0] = xcbq.HintsFlags["InputHint"]
        hints[1] = 1
        w.set_property("WM_HINTS", hints, type="WM_HINTS", format=32)
        conn.flush()
        assert xmanager.c.window.hints()['input']

    finally:
        w.kill_client()
        conn.finalize()
Ejemplo n.º 18
0
def test_popup_focus(manager):
    manager.test_xeyes()
    manager.windows_map = {}

    # we have to add .conn so that Popup thinks this is libqtile.qtile
    manager.conn = xcbq.Connection(manager.display)

    try:
        popup = Popup(manager)
        popup.width = manager.c.screen.info()["width"]
        popup.height = manager.c.screen.info()["height"]
        popup.place()
        popup.unhide()
        assert manager.c.group.info()['focus'] == 'xeyes'
        assert manager.c.group.info()['windows'] == ['xeyes']
        assert len(manager.c.windows()) == 1
        popup.hide()
    finally:
        popup.kill()
        manager.conn.finalize()
Ejemplo n.º 19
0
def test_strut_handling(manager):
    w = None
    conn = xcbq.Connection(manager.display)

    def has_struts():
        nonlocal w
        w = conn.create_window(0, 0, 10, 10)
        w.set_property("_NET_WM_STRUT", [0, 0, 0, 10])
        w.map()
        conn.conn.flush()

    def test_initial_state():
        assert manager.c.window.info()['width'] == 798
        assert manager.c.window.info()['height'] == 578
        assert manager.c.window.info()['x'] == 0
        assert manager.c.window.info()['y'] == 0
        bar_id = manager.c.bar["bottom"].info()["window"]
        bar = manager.c.window[bar_id].info()
        assert bar["height"] == 20
        assert bar["y"] == 580

    manager.test_xcalc()
    test_initial_state()

    try:
        manager.create_window(has_struts)
        manager.c.window.static(0, None, None, None, None)
        assert manager.c.window.info()['width'] == 798
        assert manager.c.window.info()['height'] == 568
        assert manager.c.window.info()['x'] == 0
        assert manager.c.window.info()['y'] == 0
        bar_id = manager.c.bar["bottom"].info()["window"]
        bar = manager.c.window[bar_id].info()
        assert bar["height"] == 20
        assert bar["y"] == 570

    finally:
        w.kill_client()
        conn.finalize()

    test_initial_state()
Ejemplo n.º 20
0
def test_only_one_focus(xmanager):
    w = None
    conn = xcbq.Connection(xmanager.display)

    def both_wm_take_focus_and_input_hint():
        nonlocal w
        w = conn.create_window(5, 5, 10, 10)
        w.set_attribute(eventmask=xcffib.xproto.EventMask.FocusChange)
        # xmanager config automatically floats "float"
        w.set_property("WM_CLASS", "float", type="STRING", format=8)

        # set both the input hit
        hints = [0] * 14
        hints[0] = xcbq.HintsFlags["InputHint"]
        hints[1] = 1  # set hints to 1, i.e. we want them
        w.set_property("WM_HINTS", hints, type="WM_HINTS", format=32)

        # and add the WM_PROTOCOLS protocol WM_TAKE_FOCUS
        conn.conn.core.ChangePropertyChecked(
            xcffib.xproto.PropMode.Append,
            w.wid,
            conn.atoms["WM_PROTOCOLS"],
            conn.atoms["ATOM"],
            32,
            1,
            [conn.atoms["WM_TAKE_FOCUS"]],
        ).check()

        w.map()
        conn.conn.flush()

    try:
        xmanager.create_window(both_wm_take_focus_and_input_hint)
        assert xmanager.c.window.info()['floating'] is True
        got_take_focus, got_focus_in = wait_for_focus_events(conn)
        assert not got_take_focus
        assert got_focus_in
    finally:
        w.kill_client()
        conn.finalize()
Ejemplo n.º 21
0
def test_change_state_via_message(manager):
    manager.test_window("one")
    window_info = manager.c.window.info()
    conn = xcbq.Connection(manager.display)

    data = xcffib.xproto.ClientMessageData.synthetic([libqtile.window.IconicState, 0, 0, 0, 0], "IIIII")
    ev = xcffib.xproto.ClientMessageEvent.synthetic(
        32, window_info["id"], conn.atoms['WM_CHANGE_STATE'], data
    )
    conn.default_screen.root.send_event(ev, mask=xcffib.xproto.EventMask.SubstructureRedirect)
    conn.xsync()
    assert manager.c.window.info()["minimized"]

    data = xcffib.xproto.ClientMessageData.synthetic([libqtile.window.NormalState, 0, 0, 0, 0], "IIIII")
    ev = xcffib.xproto.ClientMessageEvent.synthetic(
        32, window_info["id"], conn.atoms['WM_CHANGE_STATE'], data
    )
    conn.default_screen.root.send_event(ev, mask=xcffib.xproto.EventMask.SubstructureRedirect)
    conn.xsync()
    assert not manager.c.window.info()["minimized"]

    conn.finalize()
Ejemplo n.º 22
0
def test_net_wm_states(xdisplay):
    conn = xcbq.Connection(xdisplay)
    win = conn.create_window(1, 1, 640, 480)
    assert isinstance(win, xcbq.Window)

    def attr_name(x):
        return x.lstrip('_').lower()

    names = [attr_name(x) for x in xcbq.net_wm_states]

    for name in names:
        val = getattr(win, name)
        assert val is False
        setattr(win, name, True)
        val = getattr(win, name)
        assert val is True

    for name in names:
        assert getattr(win, name) is True

    for name in names:
        setattr(win, name, False)
        val = getattr(win, name)
        assert val is False
Ejemplo n.º 23
0
    def __init__(self, display_name: str = None) -> None:
        """Setup the X11 core backend

        :param display_name:
            The display name to setup the X11 connection to.  Uses the DISPLAY
            environment variable if not given.
        """
        if display_name is None:
            display_name = os.environ.get("DISPLAY")
            if not display_name:
                raise QtileError("No DISPLAY set")

        self.conn = xcbq.Connection(display_name)
        self._display_name = display_name
        self._fd = None  # type: Optional[int]

        # Because we only do Xinerama multi-screening,
        # we can assume that the first
        # screen's root is _the_ root.
        self._root = self.conn.default_screen.root
        self._root.set_attribute(
            eventmask=(xcffib.xproto.EventMask.StructureNotify
                       | xcffib.xproto.EventMask.SubstructureNotify
                       | xcffib.xproto.EventMask.SubstructureRedirect
                       | xcffib.xproto.EventMask.EnterWindow
                       | xcffib.xproto.EventMask.LeaveWindow))

        self._root.set_property(
            "_NET_SUPPORTED",
            [self.conn.atoms[x] for x in xcbq.SUPPORTED_ATOMS])

        self._last_event_timestamp = xcffib.CurrentTime

        self._wmname = "qtile"
        self._supporting_wm_check_window = self.conn.create_window(
            -1, -1, 1, 1)
        self._supporting_wm_check_window.set_property("_NET_WM_NAME",
                                                      self._wmname)
        self._supporting_wm_check_window.set_property(
            "_NET_SUPPORTING_WM_CHECK", self._supporting_wm_check_window.wid)
        self._root.set_property("_NET_SUPPORTING_WM_CHECK",
                                self._supporting_wm_check_window.wid)

        self._selection = {
            "PRIMARY": {
                "owner": None,
                "selection": ""
            },
            "CLIPBOARD": {
                "owner": None,
                "selection": ""
            },
        }
        self._selection_window = self.conn.create_window(-1, -1, 1, 1)
        self._selection_window.set_attribute(
            eventmask=xcffib.xproto.EventMask.PropertyChange)
        if hasattr(self.conn, "xfixes"):
            self.conn.xfixes.select_selection_input(self._selection_window,
                                                    "PRIMARY")  # type: ignore
            self.conn.xfixes.select_selection_input(
                self._selection_window, "CLIPBOARD")  # type: ignore

        primary_atom = self.conn.atoms["PRIMARY"]
        reply = self.conn.conn.core.GetSelectionOwner(primary_atom).reply()
        self._selection["PRIMARY"]["owner"] = reply.owner

        clipboard_atom = self.conn.atoms["CLIPBOARD"]
        reply = self.conn.conn.core.GetSelectionOwner(primary_atom).reply()
        self._selection["CLIPBOARD"]["owner"] = reply.owner

        # ask for selection on start-up
        self.convert_selection(primary_atom)
        self.convert_selection(clipboard_atom)

        # setup the default cursor
        self._root.set_cursor("left_ptr")

        self.qtile = None  # type: Optional[Qtile]
        self._painter = None

        numlock_code = self.conn.keysym_to_keycode(xcbq.keysyms["Num_Lock"])
        self._numlock_mask = xcbq.ModMasks.get(
            self.conn.get_modifier(numlock_code), 0)
        self._valid_mask = ~(self._numlock_mask | xcbq.ModMasks["lock"])
Ejemplo n.º 24
0
def test_strut_handling(xmanager):
    w = []
    conn = xcbq.Connection(xmanager.display)

    def has_struts():
        nonlocal w
        w.append(conn.create_window(0, 0, 10, 10))
        w[-1].set_property("_NET_WM_STRUT_PARTIAL",
                           [0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 800])
        w[-1].map()
        conn.conn.flush()

    def with_gaps_left():
        nonlocal w
        w.append(conn.create_window(800, 0, 10, 10))
        w[-1].set_property("_NET_WM_STRUT_PARTIAL",
                           [820, 0, 0, 0, 0, 480, 0, 0, 0, 0, 0, 0])
        w[-1].map()
        conn.conn.flush()

    def with_gaps_bottom():
        nonlocal w
        w.append(conn.create_window(800, 0, 10, 10))
        w[-1].set_property("_NET_WM_STRUT_PARTIAL",
                           [0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 800, 1440])
        w[-1].map()
        conn.conn.flush()

    def test_initial_state():
        while xmanager.c.screen.info()["index"] != 0:
            xmanager.c.next_screen()
        assert xmanager.c.window.info()['width'] == 798
        assert xmanager.c.window.info()['height'] == 578
        assert xmanager.c.window.info()['x'] == 0
        assert xmanager.c.window.info()['y'] == 0
        bar_id = xmanager.c.bar["bottom"].info()["window"]
        bar = xmanager.c.window[bar_id].info()
        assert bar["height"] == 20
        assert bar["y"] == 580
        xmanager.c.next_screen()
        assert xmanager.c.window.info()['width'] == 638
        assert xmanager.c.window.info()['height'] == 478
        assert xmanager.c.window.info()['x'] == 800
        assert xmanager.c.window.info()['y'] == 0

    xmanager.test_window('one')
    xmanager.c.next_screen()
    xmanager.test_window('two')
    test_initial_state()

    try:
        while xmanager.c.screen.info()["index"] != 0:
            xmanager.c.next_screen()
        xmanager.create_window(has_struts)
        xmanager.c.window.static(None, None, None, None, None)
        assert xmanager.c.window.info()['width'] == 798
        assert xmanager.c.window.info()['height'] == 568
        assert xmanager.c.window.info()['x'] == 0
        assert xmanager.c.window.info()['y'] == 0
        bar_id = xmanager.c.bar["bottom"].info()["window"]
        bar = xmanager.c.window[bar_id].info()
        assert bar["height"] == 20
        assert bar["y"] == 570

        xmanager.c.next_screen()
        xmanager.create_window(with_gaps_bottom)
        xmanager.c.window.static(None, None, None, None, None)
        xmanager.create_window(with_gaps_left)
        xmanager.c.window.static(None, None, None, None, None)
        assert xmanager.c.window.info()['width'] == 618
        assert xmanager.c.window.info()['height'] == 468
        assert xmanager.c.window.info()['x'] == 820
        assert xmanager.c.window.info()['y'] == 0
    finally:
        for win in w:
            win.kill_client()
        conn.finalize()

    test_initial_state()
Ejemplo n.º 25
0
    def __init__(self, display_name: str = None) -> None:
        """Setup the X11 core backend

        :param display_name:
            The display name to setup the X11 connection to.  Uses the DISPLAY
            environment variable if not given.
        """
        if display_name is None:
            display_name = os.environ.get("DISPLAY")
            if not display_name:
                raise QtileError("No DISPLAY set")

        self.conn = xcbq.Connection(display_name)
        self._display_name = display_name

        # Because we only do Xinerama multi-screening,
        # we can assume that the first
        # screen's root is _the_ root.
        self._root = self.conn.default_screen.root

        supporting_wm_wid = self._root.get_property("_NET_SUPPORTING_WM_CHECK",
                                                    "WINDOW",
                                                    unpack=int)
        if len(supporting_wm_wid) > 0:
            supporting_wm_wid = supporting_wm_wid[0]

            supporting_wm = window.XWindow(self.conn, supporting_wm_wid)
            existing_wmname = supporting_wm.get_property("_NET_WM_NAME",
                                                         "UTF8_STRING",
                                                         unpack=str)
            if existing_wmname:
                logger.error("not starting; existing window manager {}".format(
                    existing_wmname))
                raise ExistingWMException(existing_wmname)

        self.eventmask = (EventMask.StructureNotify
                          | EventMask.SubstructureNotify
                          | EventMask.SubstructureRedirect
                          | EventMask.EnterWindow
                          | EventMask.LeaveWindow
                          | EventMask.ButtonPress)
        self._root.set_attribute(eventmask=self.eventmask)

        self._root.set_property(
            "_NET_SUPPORTED",
            [self.conn.atoms[x] for x in xcbq.SUPPORTED_ATOMS])

        self._wmname = "qtile"
        self._supporting_wm_check_window = self.conn.create_window(
            -1, -1, 1, 1)
        self._supporting_wm_check_window.set_property("_NET_WM_NAME",
                                                      self._wmname)
        self._supporting_wm_check_window.set_property(
            "_NET_SUPPORTING_WM_CHECK", self._supporting_wm_check_window.wid)
        self._root.set_property("_NET_SUPPORTING_WM_CHECK",
                                self._supporting_wm_check_window.wid)

        self._selection = {
            "PRIMARY": {
                "owner": None,
                "selection": ""
            },
            "CLIPBOARD": {
                "owner": None,
                "selection": ""
            },
        }
        self._selection_window = self.conn.create_window(-1, -1, 1, 1)
        self._selection_window.set_attribute(
            eventmask=EventMask.PropertyChange)
        if hasattr(self.conn, "xfixes"):
            self.conn.xfixes.select_selection_input(self._selection_window,
                                                    "PRIMARY")  # type: ignore
            self.conn.xfixes.select_selection_input(
                self._selection_window, "CLIPBOARD")  # type: ignore

        primary_atom = self.conn.atoms["PRIMARY"]
        reply = self.conn.conn.core.GetSelectionOwner(primary_atom).reply()
        self._selection["PRIMARY"]["owner"] = reply.owner

        clipboard_atom = self.conn.atoms["CLIPBOARD"]
        reply = self.conn.conn.core.GetSelectionOwner(primary_atom).reply()
        self._selection["CLIPBOARD"]["owner"] = reply.owner

        # ask for selection on start-up
        self.convert_selection(primary_atom)
        self.convert_selection(clipboard_atom)

        # setup the default cursor
        self._root.set_cursor("left_ptr")

        self.qtile = None  # type: Optional[Qtile]
        self._painter = None

        numlock_code = self.conn.keysym_to_keycode(xcbq.keysyms["Num_Lock"])[0]
        self._numlock_mask = xcbq.ModMasks.get(
            self.conn.get_modifier(numlock_code), 0)
        self._valid_mask = ~(self._numlock_mask | xcbq.ModMasks["lock"]
                             | xcbq.AllButtonsMask)