How do I get the monitor of an active window in GNOME?
Asked Answered
N

1

2

I am very new to GNOME extension development, and I am having a hard time working with it, due to a profound lack of documentation (or maybe my Internet is clandestinely censored) of the API. I started by modifying an existing extension, so that it is easier to make my way around it.

The issue is, I can obtain the active window using global.display.focus_window, and also a list of monitors connected to the computer using Main.layoutManager.monitors. Now, what I would like to do, is find out which monitor the obtained window is sitting on (so I can move the top panel to that monitor, as it probably means I am working on that monitor at the moment). I tried various things, like .screen, .monitor etc., but with no success. I have no IntelliSense completion on this, and I am trying to guess what the members could be, as I cannot seem to find any docs on it.

I appreciate the fact that GNOME is way more customizable than what I used before (Unity, which provided no customization at all), but I don't know how to work with it and resources are scarce. I tried looking into the source code, but I am not familiar with how it is organized and I could not find the relevant portion of code where the members I need, if they exist, are declared.

I am coding the .js files, so I need some JavaScript code, I guess.

Thank you very much.

Noakes answered 28/4, 2018 at 19:44 Comment(0)
D
6

While most of the user-visible parts of Gnome Shell are written in JavaScript, these are often just bindings for the underlying C libraries. If you're working with Windows, Monitors and Screens then you're going to want to reference the Mutter documentation and probably the Shell documentation as well:

There is a property on the global object called screen (so global.screen) which is no doubt a MetaScreen which has a function get_n_monitors(), as well as get_primary_monitor(), get_current_monitor() and others. MetaWindow, on the other hand, contains a function called get_monitor() which returns an integer. I gather that monitors are referred to by integer number, which is passed to various functions of MetaScreen and MetaWindow, since there doesn't seem to be an object for that in the Mutter documentation.

Most of the related JavaScript for what you want to do seems to be in layout.js, which probably has better examples of how Mutter is used in Gnome Shell than I can give you. It also includes a Monitor class, which seems to just be a JS wrapper around the monitor index. This class is used in the LayoutManager class (which is the definition of the instance Main.layoutManager).

A note about documentation

Originally, the rationale for not having "proper" gnome-shell documentation was that the (internal JavaScript) API was pretty unstable. The deal was, you don't get a stable API but you get to read the source in the same language you're going to write it in. In some ways this makes sense, given that you can modify the prototype of live objects and monkey-patch at whim.

The API has settled down a lot, but no one has really stepped up to write a script to auto-document it, yet. My best advice would be to bookmark the Mutter, Shell and St documentation and use Github or GitLab's search to make things easier.

There is however documentation for the Gnome API as well some of the built-in modules that are worth a skim:

Directrix answered 28/4, 2018 at 21:25 Comment(7)
Excellent, you're a time saver! Pointed me in the right direction. I am able to move the top panel to the monitor which contains the active window using: Mainloop.timeout_add(10, function () { var mon = global.display.focus_window.get_monitor(); Main.panel.actor.get_parent().set_x(Main.layoutManager.monitors[mon].x); Main.panel.actor.get_parent().width = Main.layoutManager.monitors[mon].width; }); Thank you very much, brilliant solution and a clarifying explanation about the docs as well. Now I need to figure out a way to have this code executed when windows are moved on screen.Noakes
Maybe I could attempt to publish this in the GNOME Shell Extensions, should something similar not exist, and provided that I take the time to migrate the code to my own extension (I am editing someone else's at the moment, for convenience, and also because initially I intended just to edit a few small things and it turned out to be a bigger project than expected). Basically, what I am trying to do is have the top panel migrate to the monitor the active window is currently on (so that extensions like "window buttons", "no title bar", "GNOME global menu" work and make sense on multiple screens).Noakes
Okay, so I did what I wanted by subscribing to the "window-entered-monitor" event like so: this.event = global.screen.connect_after( 'window-entered-monitor', Lang.bind(this, this._updatePanel) ); . Now, the top panel follows the window I am moving from screen to screen.Noakes
Glad to help, you might want the have a look at the GJS wiki section for Lang, since it's now considered deprecated (gitlab.gnome.org/GNOME/gjs/wikis/Modules#lang) as well as some of the other pages there. Sometime people carry forward, or copy, awkward habits that aren't necessary since GJS adopted ES6 JavaScript.Directrix
Gnome API link is currently dead.Goodish
I'm struggling to reconcile that this is possible, with those general assertions about Gnome being closed by design for traversal of the active windows. Is global.display.focus_window available only for Gnome extensions?Difficult
global equates to Shell.Global which is a class of the internal library of gnome-shell. global.display holds a pointer to the internal instance of Meta.Display used by the gnome-shell process. Thus, global.display.focus_window is the property getter for Meta.Display:focus-window. You can not retrieve the value of this property from outside the gnome-shell process merely because you're using the same library.Directrix

© 2022 - 2024 — McMap. All rights reserved.