7

I intend to change the monitor where I show a fullscreen window. This is especially interesting when having a projector hooked up.

I've tried to use fullscreen_on_monitor but that doesn't produce any visible changes.

Here is a non-working example:

#!/usr/bin/env python
import sys

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk

w = Gtk.Window()

screen = Gdk.Screen.get_default()
print ("Montors: %d" % screen.get_n_monitors())
if len(sys.argv) > 1:
    n = int(sys.argv[1])
else:
    n = 0

l = Gtk.Button(label="Hello, %d monitors!" % screen.get_n_monitors())
w.add(l)
w.show_all()

w.fullscreen_on_monitor(screen, n)
l.connect("clicked", Gtk.main_quit)
w.connect("destroy", Gtk.main_quit)
Gtk.main()

I get to see the window on the very same monitor (out of 3), regardless of the value I provide.

My question is: how do I make the fullscreen window appear on a different monitor?

Frederick Nord
  • 1,246
  • 1
  • 14
  • 31

2 Answers2

5

The problem seems to be that Gtk just ignores the monitor number, it will always fullscreen the window on the monitor on which the window currently is positioned. This sucks, but we can use that to make it work the way we want to.

But first some theory about multiple monitors, they aren't actually separate monitors for your pc. It considers them to collectively form one screen which share the same global origin. On that global screen each monitor has a origin relative to the global origin, just like windows.

Because we know that Gtk will always fullscreen on the monitor on which the window is we can simply move the window to the origin of the monitor using window.move(x,y) and then call window.fullscreen().

(The move function will move the window to a position (x,y) relative to it's parent, which in the case of the main window is the global screen.)

Combining all this we get this, which works perfectly on Windows 10:

def fullscreen_at_monitor(window, n):
    screen = Gdk.Screen.get_default()

    monitor_n_geo = screen.get_monitor_geometry(n)
    x = monitor_n_geo.x
    y = monitor_n_geo.y

    window.move(x,y)

    window.fullscreen()
B8vrede
  • 4,432
  • 3
  • 27
  • 40
  • can you back up "Gtk just ignores the monitor number" with code? `gtk_window_fullscreen_on_monitor` as defined here: https://git.gnome.org/browse/gtk+/tree/gtk/gtkwindow.c#n10502 eventually calls `gdk_window_fullscreen_on_monitor` defined here: https://git.gnome.org/browse/gtk+/tree/gdk/gdkwindow.c?id=ea1295c9ab40ab8c1b5b80ccf1575710c5ff6b86#n10820 then I don't know how to further follow. – Frederick Nord Sep 08 '16 at 21:39
  • If you look at the sourcecode, everything indeed appears fine. So the root of the problem is most likely either in the GTK Python Bindings or in the Window Manager. To back up this statement your own code already shows it, setting a different monitor number doesn't result in different behavior. The code at the bottom however does work :) – B8vrede Sep 09 '16 at 07:17
  • 1
    I confirm that it works. Thanks! FTR: I'm running a GNOME 3.18 on Ubuntu 16.04. – Frederick Nord Sep 13 '16 at 12:54
  • maybe this bug report: https://bugzilla.gnome.org/show_bug.cgi?id=752677 – Frederick Nord Sep 13 '16 at 13:16
3

Here is an updated version of @B8vrede's answer, because get_monitor_geometry is deprecated since 3.22.

def fullscreen_at_monitor(window, n):
    display = Gdk.Display.get_default()
    monitor = Gdk.Display.get_monitor(display, n)
    geometry = monitor.get_geometry()
    x = geometry.x
    y = geometry.y
    window.move(x, y)
    window.fullscreen()
Nicolai Weitkemper
  • 403
  • 1
  • 9
  • 18