5

I'm running a Debian 10 stable x64 system with the dwm window manager, and I'm using Python 3.7.3. From what I can tell from some example code and the draw_text method itself, I should be able to draw text on the root window with code like this:

#!/usr/bin/env python3

import Xlib
import Xlib.display

display = Xlib.display.Display()
screen = display.screen()
root = screen.root

gc = root.create_gc(foreground = screen.white_pixel, background = screen.black_pixel)
root.draw_text(gc, 1, 1, b"Hello, world!")

This code runs without error, but no text is displayed. I've also experimented with different coordinates without any luck. My root window background is just the default black, so I don't think the text is failing to show up, since I set the foreground pixel color to white.

Michael A
  • 4,391
  • 8
  • 34
  • 61

1 Answers1

3

You are right that your code should draw text on root window. You just need to:

  • Ensure that your background is indeed the root window (xwininfo is great)
  • Check the coordinates again: (i) if dwm, as by default, shows a topbar, it may hide the text. Or just [Alt]+b, to toggle the bar (ii) if you have other windows, for example your terminal, on top, you will not see the text.
  • Perform an XFlush in the end. Without it the request stays in the client.

The code that works here(Gentoo amd64/desktop/stable, dwm-6.2, python-3.6.9):

 #!/usr/bin/env python3

import Xlib
import Xlib.display

display = Xlib.display.Display()
screen = display.screen()
root = screen.root

gc = root.create_gc(foreground = screen.white_pixel, background = screen.black_pixel)
root.draw_text(gc, 100, 100, b"Hello, world!")  # changed the coords more towards the center

display.flush()  # To actually send the request to the server

Notice that the text will disappear, if other windows overlap or refresh that spot. The text remains until, for example, you move a window over (erases it), or you change to another dwm-Tab that has a window covering these coordinates.

If you want to prevent the text from disappearing, you need a loop:

  • either a while True loop on the code as is, which is going to redraw it no matter what
  • or, better, an event loop, which is going to redraw it only when it is necessary (see below)

The expose events (refer https://tronche.com/gui/x/xlib/events/exposure/expose.html and http://python-xlib.sourceforge.net/doc/html/python-xlib_13.html#SEC12)

are generated when regions of a window has to be redrawn

BUT, if we listen for the expose event for root window, we get none (reason: (see the setup function in the dwm's source code) no ExposureMask for root). What i tried and worked:

#!/usr/bin/env python3

import Xlib
from Xlib import display, X   # X is also needed

display = Xlib.display.Display()
screen = display.screen()
root = screen.root

#print(root.get_attributes())
root.change_attributes(event_mask=X.ExposureMask)  # "adds" this event mask
#print(root.get_attributes())  # see the difference

gc = root.create_gc(foreground = screen.white_pixel, background = screen.black_pixel)

def draw_it():
    root.draw_text(gc, 100, 100, b"Hello, world!")
    display.flush()

draw_it()
while 1:
    if display.pending_events() != 0:  # check to safely apply next_event
        event = display.next_event()
        if event.type == X.Expose and event.count == 0:
            draw_it()
adatzer
  • 556
  • 1
  • 4
  • 6
  • 1
    This works! Thank you. I was missing the flush. Another strategy for making sure the text "stays" on the root window is capturing a window change event, right? (I know that's a separate question) – Michael A Jan 08 '20 at 17:49
  • 1
    Exactly. I edited my answer according to your comment. (To me it looks as part of the same question) – adatzer Jan 09 '20 at 10:17
  • hm, neither of these two scripts do anything for me - it silently executes, but no text is drawn on the screen. – user920391 May 31 '20 at 20:10
  • cannot really imagine why without more info. the text is supposed to appear towards the upper left of the root window (maybe other window on top?). If you uncomment the 2 print lines in the second script, do you see any difference? – adatzer Jun 02 '20 at 05:13