What does "The screen root window" mean in Xlib? - python-3.x

I was looking for a way to get the location of the active window on my screen when I stumbled upon a post in SO that had the code for me, but I got stuck trying to figure out what it did. The xlibs docs (for python) doesn't seem very helpful either. Going through https://tronche.com/gui/x/xlib-tutorial, it provides a link to https://tronche.com/gui/x/xlib-tutorial/screen-and-root-window.html which, based on the URL, looks like what I'm looking for but sadly it gives me a "Page Not Found".
So, what does "The screen root window" refer to? Also, is there a better place I can look for xlib resources?

X window system organizes its display into a hierarchy of windows.
By default, X creates one window the size of a physical screen. This is called the "root window" and its purpose is typically to provide a default background in cases when there is nothing else covering that part of the screen. When root window is empty, X will (at least in the older versions) display a white-black checkerboard pattern.
In most graphical environments the root window is typically used for desktop background or for screen savers. When rendering the output, the X first paints the root window into a framebuffer, followed by all the nested elements. The nested elements are the "normal" windows - they are painted over the parent by covering parts of it, which is what in the end gives you the impression of "windows on a background".

Related

Displaying a Classification Banner at the top of each computer monitor in Gnome Desktop

I work in an environment where we have to have a security classification banner displayed at the top of each monitor on our Gnome Desktops. Currently, I am using a Perl/Tk window to display the classification of the system. However, that window cannot be moved because of the way it is built (no decorations) and occasionally overlays open windows making it difficult for users to manage those windows.
I would like to be able to do something different, but I'm not sure where to start. Three ideas I have are this:
An icon or something in the Top Bar showing the classification
A banner, like the Top Bar, that sits above the Top Bar
A window, like I already have, but relocatable
I figure the first option would be easiest, but since the Top Bar isn't shown on every monitor, that may not be the best option. I don't even know if the second option is even possible. The third option would require me to use something other than Perl/Tk but that's the only language I'm fluent in at the moment.
So I'm looking for suggestions or examples or Gnome extensions I can use to solve this problem.
Thanks.
There is a classification-banner python utility at https://github.com/fcaviggia/classification-banner. It's no longer maintained, but we've been using it without change for a few years now. It's OK. One problem is that it doesn't "shrink" the desktop screen, so application windows can overlap it; it's set to Always On Top, but it would be nicer if it actually couldn't be overlaid at all.
A simple solution, of sorts, would be to change the desktop background image. This can have issues if you're displaying on multiple resolutions (I don't know if Gnome supports SVG for such purposes) and of course it can be obscured by windows covering it.
Older versions of Gnome let you create multiple bars that worked perfectly, but that disappeared - along with many other customizations - in Gnome 3.

set window icon tkinter macosx

This line works fine for my Windows program.
When i run this same file on the Mac OS X, I get a blank page instead of my icon.
Here is the windows line:
self.iconbitmap("Boss.ico")
I have searched relentlusly for an answer I want this icon to work on both platforms. self is the root Tk window if your wondering if it's root or not.
Note: I have tried using icns, .xbm , .gif by loading a photo image and setting thru window attributes all produce the same blank page on the mac.
After 5 days of searching, and this post having been viewed at least 15 times I went directly to the tk/tcl documentation. If I understand this correctly, apparently there is no way to properly set the icon for mac OS X without using special library or other sort of hacks. It would be nice if there were a mac specific documentation for the tkinter library but alas there isn't that I have found. here is the part of the documentation I found:
wm iconphoto window ?-default? image1 ?image2 ...? Sets the titlebar
icon for window based on the named photo images. If -default is
specified, this is applied to all future created toplevels as well.
The data in the images is taken as a snapshot at the time of
invocation. If the images are later changed, this is not reflected to
the titlebar icons. Multiple images are accepted to allow different
images sizes (e.g., 16x16 and 32x32) to be provided. The window
manager may scale provided icons to an appropriate size. On Windows,
the images are packed into a Windows icon structure. This will
override an ico specified to wm iconbitmap, and vice versa.
On X, the images are arranged into the _NET_WM_ICON X property, which
most modern window managers support. A wm iconbitmap may exist
simultaneously. It is recommended to use not more than 2 icons,
placing the larger icon first.
On Macintosh, this currently does nothing.
if anyone has a working solution please post this. I want to accomplish this so that any system can open a freshly installed python and run my application without installing any additional library.
#GarryHurst This is not a solution but I sort of get the idea now:
On Mac, TK decided that the icon will never appear on the window title bar.
Instead, it shows up as the app's Dock icon.
It's most probably a by-design or won't fix issue on their side.
It is showing the icon of the file you are putting in the directory so setting the file to be an app will set the window icon to be the icon of that app.
for example:
root.iconbitmap("/Users/homedir./Desktop/Test apps/Clicker.app")
tk window with icon
I have a coup. Why not change mind, like this.
The emoji library is enough to choose a good-looking icon.
We can do that.:-D
Code
Effect

Drawing Custom Context Menus Anywhere on Desktop

I'm trying to figure out a way to draw a context menu foo at the cursor's current position no matter where on screen it is (i.e. over a window that has nothing to do with my program), and I can't seem to find a clean way of doing this, as all the libraries I can find define context menus upon the current window.
The things that come to mind for me are:
A: Drawing a tiny window at the cursor and then immediately opening up a context window
B: Drawing borderless windows that act like context menus
C: Drawing directly to the root window
However, none of these seem like clean and portable solutions, so I figured I would ask before diving into code.
I know that this is not what context menus were designed for, but the look fits my application very well. I would prefer to use Qt to keep things portable across systems, but at the moment I really only care about X on Linux.
Edit: 1st paragraph expansion

How to make an overlay which capture no events

I would like to draw some sort of window on top of all the other windows. For example, to display some debugging infos (like conky) or things like a timer.
The main thing is that I would like to able to continue using the other windows while using it (the events go through transparently).
I've tried doing it with pygtk, pyqt and others but can't find a way to make it a real overlay with no event capture.
Is there some low-level x11 solution?
I think the Composite-extension-approach will not work when a compositing manager is running (and thus Composite's overlay window is already used).
Since you explicitly mention "no event capture":
The SHAPE extension allows to set some different shapes for a window. Version 1.1 of this extension added the "input" shape. Just setting this to an empty region should pretty much do what you want.
Some concrete example of exactly what I think you ask for can be found in Conky's source code: http://sources.debian.net/src/conky/1.10.3-1/src/x11.cc/?hl=769#L764-L781
Edit: Since you said that you didn't find anything in Gtk (well, PyGtk), here is the function that you need in Gtk: https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-input-shape-combine-region
You might need Composite extension + GetOverlayWindow request:
Version 0.3 of the protocol adds the Composite Overlay Window, which
provides compositing managers with a surface on which to draw without
interference. This window is always above normal windows and is always
below the screen saver window. It is an InputOutput window whose width
and height are the screen dimensions. Its visual is the root visual
and its border width is zero. Attempts to redirect it using the
composite extension are ignored. This window does not appear in the
reply of the QueryTree request. It is also an override redirect
window. These last two features make it invisible to window managers
and other X11 clients. The only way to access the XID of this window
is via the CompositeGetOverlayWindow request. Initially, the Composite
Overlay Window is unmapped.
CompositeGetOverlayWindow returns the XID of the Composite Overlay
Window. If the window has not yet been mapped, it is mapped by this
request. When all clients who have called this request have terminated
their X11 connections the window is unmapped.
Composite managers may render directly to the Composite Overlay
Window, or they may reparent other windows to be children of this
window and render to these. Multiple clients may render to the
Composite Overlay Window, create child windows of it, reshape it, and
redefine its input region, but the specific arbitration rules followed
by these clients is not defined by this specification; these policies
should be defined by the clients themselves.
C api : XCompositeGetOverlayWindow
PyGTK Solution:
I think the composite and shapes X extensions are sufficiently ubiquitous and shall assume here that they are active on your system. Here's PyGtk code for this:
# avoid title bar and standard window minimize, maximize, close buttons
win.set_decorated(False)
# make the window stick above all others (super button will still override it in the z-order, which is fine)
win.set_keep_above(True)
# make events pass through
region = cairo.Region(cairo.RectangleInt(0, 0, 0, 0))
my_window.input_shape_combine_region(region)
win.show_all()
# set the entire window to be semi-transparent, if we like
win.set_opacity(0.2)
Basically what this does is tell Gtk that other than pixel (0,0) the entire window my_window should not be considered part of itself in terms of event propagation. That in turn, according to my current understanding means that when the pointer moves and clicks, the events go to the underlying window under the pointer position, as if my_window was not there.
Caveat:
This does allow your overlay window being the focus window (due to user-solicited window switching or just because it pops up and gets the focus when your application starts). Which means that for example, keyboard events will still undesirably go to it up until the user has clicked through it to make it lose focus in favor of whatever window is under the cursor. I would likely use the approach described here to iron out this aspect.
If there's a different and proper approach for making a portion of the screen "display stuff but not receive events", without building an oddball window like above over it, I'm happy to learn about it.
I assume that one's particular desktop environment (gnome, unity, etc. on linux) may interfere with this solution depending on version and configuration, on some occasions.

Xlib center window

I am writing a Xlib app where I want the window to be centered. I have used XMoveWindow with (desktopWidth - width) / 2, (desktopHeight - height) / 2 and it is roughly in the right place.
However the problem is that width and height are the client area, not the total area. Is there any way for me to get the total area of the window?
I need to use Xlib because I am using Glx and OpenGL. I don't want to use SDL, nor have a bulky graphics library.
There are various ways to go about this, depending on why you are doing it. The first two are "officially supported" by most window managers and described in specs, and then it descends into fragile hacks.
Semantic
The specs encourage you to use _NET_WM_WINDOW_TYPE rather than setting the position, if it makes sense to do so. See http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2507144
For example, a DIALOG type (or a window with the WM_TRANSIENT_FOR hint set) will usually be centered on its parent window or on the screen, and the _NET_WM_WINDOW_TYPE_SPLASH (splashscreen) type will usually be centered on the screen. "Usually" here means "sensible window managers probably center it, and people using weird window managers are not your problem, let them suffer."
(Another hint along the same lines, though not what you want here, is _NET_WM_STATE_FULLSCREEN, which avoids manually sizing/positioning in order to be fullscreen.)
If semantic hints work, the window manager code to handle the positioning is hopefully smarter than anything one can easily code by hand, for example it might deal with multihead setups. Setting the proper semantic type may also allow the WM to be smart in other ways, beyond positioning.
Gravity
If there's no semantic hint in the specs that helps you, then you can center by hand. It's important to note that window managers are allowed to ignore a manual position request and some of them will. Some may only honor the request if you set the USPosition flag in WM_NORMAL_HINTS (this flag is supposed to be set only if the user explicitly requested the position, for example with a -geometry command line option). Others may ignore the request always. But, you can probably ignore WMs that do this; the user chose to use that WM.
The way you compensate for the window decorations (the titlebar, etc.) is to use the win_gravity field of WM_NORMAL_HINTS, which is originally in the ICCCM (see http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.2.3) but better-specified in an implementation note in the EWMH: http://standards.freedesktop.org/wm-spec/latest/ar01s09.html#id2570420
For WM_NORMAL_HINTS see http://tronche.com/gui/x/xlib/ICC/client-to-window-manager/wm-normal-hints.html#XSizeHints (note: the type of the property is WM_SIZE_HINTS and the name of the property is WM_NORMAL_HINTS, so there are two different atom names involved).
To center, you would set the win_gravity to Center, which allows you to position the center of the window (including its decorations) instead of the top-left corner.
win_gravity is not often used and is likely to be buggy in some window managers because nobody bothered to code/test it, but it should work in the more mainstream ones.
Update, possible confusion point: There are other "gravities" in the X protocol, specifically the CreateWindow request lets you set a "bit_gravity" and "win_gravity"; these are different from the XSizeHints.win_gravity. The CreateWindow gravities describe how the contents (pixels/subwindows) of a window are handled when the window is resized.
Hacks based on guessing decoration size
It's a fragile hack, but... you can try to figure out the decoration size and then incorporate that into your positioning.
To get the size of the window decorations, one way is the _NET_FRAME_EXTENTS hint, see http://standards.freedesktop.org/wm-spec/latest/ar01s05.html#id2569862
For older-school window managers (but not the fancy new compositing ones, though those hopefully support _NET_FRAME_EXTENTS) the window decorations are an X window, so you can get your parent window and look at its size.
The problem with both of these approaches is that you have to map the window before the decorations are added, so you have to map; wait to get the MapNotify event; then get the decoration size; then move the window. This will unfortunately cause user-visible flicker (the window will initially appear and then move). I don't think there's a way to get the window decoration size without mapping first.
Descending further into the realm of awful hacks, you could assume that for windows after the first one you map, the decorations will match previously-mapped windows. (Not that this is a sound assumption: different kinds of windows may have different decorations.)
Implementation note: keep in mind that the decoration window can be destroyed at any time, which would cause an X error in any outstanding Xlib requests you have that mention that window and by default exit your program. To avoid this, set the X error handler when touching windows that don't belong to your client.
Override redirect
Using override redirect is a kind of bazooka with bad side effects, and not at all a good idea if your goal is just to center a window.
If you set the override redirect flag when creating a window, then the window manager won't manage its size, position, stacking order, decorations, or map state (the window manager's redirection of ConfigureRequest and MapRequest is overridden).
This is a really bad idea for anything the user would think of as a window. It's usually used for tooltips and popup menus. If you set override redirect on a window, then all the normal window management UI will be broken, the stacking order will end up basically random (the window will tend to get stuck on top or on bottom, or worse get in an infinite-loop restack fight with another client).
But, the override-redirected window won't have decorations or be touched by the WM, so you can surefire center it with no interference.
(If you just want no decorations, use a semantic type like SPLASH or use the "MWM" hints, don't use override redirect.)
Summary
The short answer is set the semantic hint if any is applicable, and otherwise use XSizeHints.win_gravity=Center.
You can kind of see why people use toolkits and SDL ;-) lots of weird historical baggage and corner cases in the client-to-window-manager interaction generally, setting window positions is just the beginning of the excitement!
win_gravity is not often used and is likely to be buggy in some window managers because nobody bothered to code/test it, but it should work in the more mainstream ones.
Apparently Unity haven't implemented this. Testing shows that XCB_GRAVITY_STATIC is not respected and by taking a quick look at Unity source code I could not find code implementing this part of the specification.

Resources