New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Creating a transparent, click-through window? #200
Labels
Comments
|
@void4 here's an example that draws a red rectangle on an arbitrary part of the screen using python-xlib and ewmh to keep the window always on top: #!/usr/bin/python
from Xlib import X, Xutil
from Xlib.ext import shape
from ewmh import EWMH
class OutlineWindow:
def __init__(self, display, x, y, w, h, lw=3):
self.d = display
self.screen = self.d.screen()
self.WM_DELETE_WINDOW = self.d.intern_atom('WM_DELETE_WINDOW')
self.WM_PROTOCOLS = self.d.intern_atom('WM_PROTOCOLS')
# Creates a pixel map that will be used to draw the areas that aren't masked
bgpm = self.screen.root.create_pixmap(1, 1, self.screen.root_depth)
# In my case I chose the color of the rectangle to be red.
bggc = self.screen.root.create_gc(
foreground=0xff0000,
background=self.screen.black_pixel
)
# we fill the pixel map with red
bgpm.fill_rectangle(bggc, 0, 0, 1, 1)
geometry = self.screen.root.get_geometry()
# We then create a window with the background pixel map from above (a red window)
self.window = self.screen.root.create_window(
0, 0, geometry.width, geometry.height, 0,
self.screen.root_depth,
X.InputOutput,
X.CopyFromParent,
background_pixmap=bgpm,
event_mask=X.StructureNotifyMask,
colormap=X.CopyFromParent,
)
# We want to make sure we're notified of window destruction so we need to enable this protocol
self.window.set_wm_protocols([self.WM_DELETE_WINDOW])
self.window.set_wm_hints(flags=Xutil.StateHint, initial_state=Xutil.NormalState)
# Create an outer rectangle that will be the outer edge of the visible rectangle
outer_rect = self.window.create_pixmap(w, h, 1)
gc = outer_rect.create_gc(foreground=1, background=0)
# coordinates within the graphical context are always relative to itself - not the screen!
outer_rect.fill_rectangle(gc, 0, 0, w, h)
gc.free()
# Create an inner rectangle that is slightly smaller to represent the inner edge of the rectangle
inner_rect = self.window.create_pixmap(w - (lw * 2), h - (lw * 2), 1)
gc = inner_rect.create_gc(foreground=1, background=0)
inner_rect.fill_rectangle(gc, 0, 0, w - (lw * 2), h - (lw * 2))
gc.free()
# First add the outer rectangle within the window at x y coordinates
self.window.shape_mask(shape.SO.Set, shape.SK.Bounding, x, y, outer_rect)
# Now subtract the inner rectangle at the same coordinates + line width from the outer rect
# This creates a red rectangular outline that can be clicked through
self.window.shape_mask(shape.SO.Subtract, shape.SK.Bounding, x + lw, y + lw, inner_rect)
self.window.shape_select_input(0)
self.window.map()
# use the python-ewmh lib to set extended attributes on the window. Make sure to do this after
# calling window.map() otherwise your attributes will not be received by the window.
self.ewmh = EWMH(display, self.screen.root)
# Always on top
self.ewmh.setWmState(self.window, 1, '_NET_WM_STATE_ABOVE')
# Draw even over the task bar
self.ewmh.setWmState(self.window, 1, '_NET_WM_STATE_FULLSCREEN')
# Don't show the icon in the task bar
self.ewmh.setWmState(self.window, 1, '_NET_WM_STATE_SKIP_TASKBAR')
# Apply changes
display.flush()
# Main loop, handling events
def loop(self):
while True:
e = self.d.next_event()
# Window has been destroyed, quit
if e.type == X.DestroyNotify:
break
# Somebody wants to tell us something
elif e.type == X.ClientMessage:
if e.client_type == self.WM_PROTOCOLS:
fmt, data = e.data
if fmt == 32 and data[0] == self.WM_DELETE_WINDOW:
break
if __name__ == '__main__':
OutlineWindow(display.Display(), 0, 0, 200, 200).loop() |
|
On i3wm I also had to add this attribute to make it transparent and click-through: override_redirect=True# create_window(x, y, width, height, border_width, depth, window_class=0, visual=0, onerror=None, **keys) method of Xlib.display.Window instance
self.window = self.screen.root.create_window(
0, # x
0, # y
geometry.width, # width
geometry.height, # height
0, # border_width
self.screen.root_depth, # depth
X.InputOutput, # window_class
X.CopyFromParent, # visual
background_pixmap=bgpm, # attr
event_mask=X.StructureNotifyMask, # attr
colormap=X.CopyFromParent, # attr
override_redirect=True # attr
)Not sure about other GUIs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment


I've seen examples for C https://stackoverflow.com/a/3646456/9779026, but is this possible with this python library as well?
I can successfully change the opacity of the entire window with
self.window.change_property(display.get_atom('_NET_WM_WINDOW_OPACITY'), Xatom.CARDINAL,32,[0x20202020])But that isn't what I need, I need a completely transparent background on which I can draw fully opaque shapes.
Could someone please help?
Edit: Regarding the transparency, https://raw.githubusercontent.com/python-xlib/python-xlib/master/examples/shapewin.py seems to be a working example, although I do not understand it yet.
So remains my question on how to make the window completely transparent to user input (perhaps except closing the window)
The text was updated successfully, but these errors were encountered: