如何防止在多显示器设置中放错位置的新窗口 - 顶部栏隐藏?

Nat*_*oen 5 window-manager multiple-monitors window

我使用的是 Ubuntu 18.04 桌面和默认的 Image Viewer 软件。

当我打开具有特定尺寸(今天为 960x960)的图像时,有一个奇怪且令人沮丧的情况,该窗口将始终出现在我的辅助屏幕的左上角,顶部栏(我们用来拖动的那个)它周围,我不记得名字)像这样躲起来在此处输入图片说明 我使用一对屏幕,左边的大作为主要,右边的小作为次要。侧边栏位于辅助屏幕中。

奇怪的是其他尺寸,如 400x400在此处输入图片说明 或 1920x1200在此处输入图片说明 没事。

所以我的问题是,是否可以在当前监视器中打开它而不会丢失顶部栏?

Jac*_*ijm 0

我们只能猜测问题的原因是什么,但我不知道真正的解决办法。然而,我们可以通过解决方法来修复错误的窗口放置。

原则

这个类似守护进程的小进程将等待在任何监视器上创建任何窗口,并在监视器上放置“负”位置(x 或 y),并将其移动到 x=80px、y=80px 的位置在相应的显示器上:

在此输入图像描述

它通过查看新创建的窗口的东南角来实现这一点。SE 被认为是它应该完全放置在其上的显示器。然后,窗口西北角的位置将触发执行操作(将窗口移动到更好的位置)或保留窗口:它不应该位于显示器 SE 开启的左侧或上方。

在所有其他情况下,窗口完全不受影响。注意:

  • 这个过程在任何方面都不是负担,它只是等待机会发生,只有在新窗口放错位置时才起作用(不是轮询过程)。
  • 我无法在您的设置中测试它,因为我没有三个显示器。不过我预计不会有任何问题。
  • 该过程是缩放精明的,在处理缩放时依赖于 Wnck 和 Gdk 之间的“翻译”。

代码

#!/usr/bin/env python3

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

class WatchOut:
    def __init__(self):
        self.wnckscr = Wnck.Screen.get_default()
        self.gdkdsp = Gdk.Display.get_default()
        self.wnckscr.connect("window_opened", self.checkonwin)
        Gtk.main()

    def actoncreate(self, window):
        wingeo = window.get_geometry();
        # get window geo, take SE as reference, abs numbers
        nw_x = wingeo.xp
        nw_y = wingeo.yp
        se_x = nw_x + wingeo.widthp
        se_y = nw_y + wingeo.heightp
        # get scale
        defmon = self.gdkdsp.get_primary_monitor()
        scale = defmon.get_scale_factor()
        # get monitor with window, gdk uses scaled(!)
        currmon = self.gdkdsp.get_monitor_at_point(se_x/scale, se_y/scale)
        # gdk uses scaled numbers!
        mongeo = currmon.get_geometry() 
        mondata = [n * scale for n in [
            mongeo.x, mongeo.y, mongeo.width, mongeo.height
        ]]
        # check if action is needed, calc in abs numbers!
        # if winx < monitorx -and/or- winy < monitory, move window
        if any([nw_x < mondata[0], nw_y < mondata[1]]):
            self.move(
                window, mondata[0] + 80, mondata[1] + 80, 700, 700
            )

    def move(self, win, x, y, w, h):
        g = Wnck.WindowGravity.NORTHWEST
        flags = Wnck.WindowMoveResizeMask.X | \
            Wnck.WindowMoveResizeMask.Y | \
            Wnck.WindowMoveResizeMask.WIDTH | \
            Wnck.WindowMoveResizeMask.HEIGHT
        win.set_geometry(g, flags, x, y, w, h)

    def checkonwin(self, scr, newwin):
        if newwin.get_window_type () == Wnck.WindowType.NORMAL:
            self.actoncreate(newwin)

WatchOut()
Run Code Online (Sandbox Code Playgroud)

如何使用

  1. 将上面的代码复制到一个空文件中,另存为watchout.py
  2. 通过以下命令从终端测试运行它:

    python3 /path/to/watchout.py
    
    Run Code Online (Sandbox Code Playgroud)

    尝试以行为不当的位置打开应用程序,看看您的问题,这应该是可以预见的。

  3. 如果一切正常,请将其添加到启动应用程序中。可能您需要在启动该过程之前设置一个小中断,以确保它不会在未完成的桌面加载时中断。