Search code examples
pythonterminalpygtkwnck

window position a little off just after spawning and moving using python-wnck


I made this Python script:

from gi.repository import Gtk, Gdk, GdkX11, Wnck
from subprocess import PIPE, Popen


class WindowError(Exception):
    pass


def undecorate(aWindow):
    gdkdis = GdkX11.X11Display.get_default()
    gdkwin = GdkX11.X11Window.foreign_new_for_display(gdkdis, aWindow.get_xid())
    gdkwin.set_decorations(Gdk.WMDecoration.BORDER)

def dropdown(aTitle):
    Gtk.main_iteration()

    screen = Wnck.Screen.get_default()
    screen.force_update()

    for window in screen.get_windows():
        if window.get_name() == aTitle:
            timestamp = Gtk.get_current_event_time()

            undecorate(window)

            window.set_skip_pager(True)
            window.set_skip_tasklist(True)
            window.stick()
            window.pin()

            window.maximize_horizontally()
            window.set_geometry(Wnck.WindowGravity.STATIC, 
                                Wnck.WindowMoveResizeMask.Y, 
                                0, 0, -1, -1)

            window.activate(timestamp)
            window.unminimize(timestamp)

            break
    else:
        raise WindowError('Window with title "{}" not found'.format(aTitle))

def getActive():
    Gtk.main_iteration()

    screen = Wnck.Screen.get_default()
    screen.force_update()

    return screen.get_active_window()


def main():
    active = getActive()

    if active.get_name() == 'Dropdown Terminal':
        if active.is_minimized():
            dropdown('Dropdown Terminal')
        else:
            active.minimize()
            return
    else:
        try:
            dropdown('Dropdown Terminal')
        except WindowError:
            Popen(['roxterm', '--profile=Dropdown'], stdout=PIPE, stderr=PIPE)
            dropdown('Dropdown Terminal')


if __name__ == "__main__":
    main()

What it does is it makes roxterm act like Guake. The only problem I have with it is when I Popen a new roxterm instance and move the window to (0,0) right after, the final y-position of the window is a few visible pixels down. I used the set_geometry function in the wnck library to do this. Any ideas on how to fix it? Thanks.


Solution

  • Oops, forgot to mention that I solved this issue. I changed some stuff in the code, but I think using GdkWindow to reposition instead of Wnck fixed the positioning problem. This version keeps the dropdown terminal open until the hotkey is pressed again. BTW, I mapped the hotkey to this script by adding a custom hotkey in Gnome's keyboard preferences.

    from gi.repository import Gtk, Gdk, GdkX11, Wnck
    from subprocess import PIPE, Popen
    
    
    class WindowError(Exception):
        pass
    
    
    def getScreen():
        Gtk.main_iteration()
    
        screen = Wnck.Screen.get_default()
        screen.force_update()
    
        return screen
    
    def getGDKWindow(aWindow):
        gdkdisplay = GdkX11.X11Display.get_default()
        gdkwindow  = GdkX11.X11Window.foreign_new_for_display(gdkdisplay, aWindow.get_xid())
    
        return gdkwindow
    
    def getWindow(aTitle):
        screen = getScreen()
        active = screen.get_active_window()
    
        if active.get_name() == aTitle:
            return active
    
        for window in screen.get_windows():
            if window.get_name() == aTitle:
                return window
    
        return None
    
    def adjust(aWindow):
        gdkwindow = getGDKWindow(aWindow)
    
        gdkwindow.set_decorations(Gdk.WMDecoration.BORDER)
        gdkwindow.move(0,0)
    
        aWindow.set_skip_pager(True)
        aWindow.set_skip_tasklist(True)
    
        aWindow.maximize_horizontally()
    
        aWindow.stick()
        aWindow.make_above()
    
    
    def onWindowOpen(aScreen, aWindow, aData):
        if aWindow.get_name() == aData:
            adjust(aWindow)
    
            Gtk.main_quit()
    
    
    def main():
        timestamp = Gtk.get_current_event_time()
        window      = getWindow('Dropdown Terminal')
    
        if window:
            if window.is_minimized():
                window.activate(timestamp)
                window.unminimize(timestamp)
            else:
                window.minimize()
        else:
            Popen(['roxterm', '--separate', '--profile=Dropdown', '--directory=.'])
    
            getScreen().connect('window-opened', onWindowOpen, 'Dropdown Terminal')
    
            Gtk.main()
    
    
    if __name__ == "__main__":
        main()