如何始终在特定的显示器上启动应用程序?


11

我具有双显示器配置,并且希望所有新旧应用程序都在右侧的主显示器上启动。但是,无论焦点/鼠标指针在哪里,某些应用程序都从第二个屏幕开始。我认为这是因为top:left corner 0:0在第二个监视器上。而且其规模大于主要因素,这可能是原因吗?

次要是我在其中运行kodi的电视,该电视具有可以选择显示的设置。

可能有一些应用程序会记住每个应用程序的位置和显示,并且在关闭秒针时也要小心-记住位置直到显示器再次打开。在较早版本的ubuntu compiz中可以这样做,但仅此而已。

更新:将DE更改为肉桂


我也在寻找这个,你有运气吗?
费利佩

@Felipe没有运气
LeonidMew

在肉桂的应用程序列表中,我有菜单选项可将应用程序移动到其他监视器,特别是在关闭辅助菜单时,它很有用。但这不是解决问题的方法。
LeonidMew19年

1
解决方案可能有点像恶魔般的过程,要当心新窗口,将其移至主屏幕。那是可以接受的解决方案吗?您甚至可能看不到它被移动。
Jacob Vlijm '19年

@JacobVlijm是的,这可以解决。但我不知道怎么写,你可以请给两个代码片段-如何确定新的窗口,如何移动
LeonidMew

Answers:


13

准备弄脏您的手
在我认为可以要求用户做的事情的边缘,但是,另一方面,当说明明确时,为什么不这样做呢?所以我们开始...


设置应在哪个监视器上显示新窗口的后台进程

瓦拉片段

using Wnck;
using Gdk;
using Gtk;

// compile:
// valac --pkg gtk+-3.0 --pkg gio-2.0 --pkg libwnck-3.0 -X "-D WNCK_I_KNOW_THIS_IS_UNSTABLE" 'file.vala'

namespace move_newwins {

    private int[] monitor_geo_x;
    private int[] monitor_geo_y;
    private int monitorindex;
    private string currmon;

    private void getwins() {
        var dsp = Gdk.Display.get_default();
        unowned Wnck.Screen scr = Wnck.Screen.get_default();
        scr.force_update();
        get_monitors(dsp);
        scr.window_opened.connect(newwin);
    }

    private void newwin (Wnck.Window newwin) {
        newwin.unmaximize();
        int winx;
        int winy;
        int winwidth;
        int winheight;
        newwin.get_geometry(out winx, out winy, out winwidth, out winheight);
        Wnck.WindowType type = newwin.get_window_type();
        if (type == Wnck.WindowType.NORMAL) {
            newwin.set_geometry(
                Wnck.WindowGravity.NORTHWEST,
                Wnck.WindowMoveResizeMask.X |
                Wnck.WindowMoveResizeMask.Y |
                Wnck.WindowMoveResizeMask.WIDTH |
                Wnck.WindowMoveResizeMask.HEIGHT,
                monitor_geo_x[monitorindex] + 100,
                monitor_geo_y[monitorindex] + 100,
                winwidth, winheight
            );
        }
    }

    private int get_stringindex (string s, string[] arr) {
        for (int i=0; i < arr.length; i++) {
            if(s == arr[i]) return i;
        } return -1;
    }

    private void get_monitors(Gdk.Display dsp) {
        int nmons = dsp.get_n_monitors();
        string[] monitornames = {};
        for (int i=0; i < nmons; i++) {
            Gdk.Monitor newmon = dsp.get_monitor(i);
            monitornames += newmon.get_model();
            Rectangle geo = newmon.get_geometry();
            monitor_geo_x += geo.x;
            monitor_geo_y += geo.y;
            monitorindex = get_stringindex(
                currmon, monitornames
            );
        }
    }

    public static void main (string[] args) {
        currmon = args[1];
        Gtk.init(ref args);
        getwins();
        Gtk.main();
    }
}
  1. Vala代码段需要进行编译。为此,您需要安装一些东西:

    sudo apt install valac libwnck-3-dev libgtk-3-dev
    
  2. 复制以下代码段,另存为 win_tomonitor.vala

  3. 使用以下命令编译代码段:

    valac --pkg gtk+-3.0 --pkg gio-2.0 --pkg libwnck-3.0 -X "-D WNCK_I_KNOW_THIS_IS_UNSTABLE" '/path/to/win_tomonitor.vala' 
    

    (我知道,wnck参数很愚蠢,但是需要),将在工作目录中生成一个可执行文件。

  4. 通过xrandr在终端中运行命令来查找主监视器的名称。
  5. 以目标监视器为参数运行可执行文件,例如

    /path/to/win_tomonitor HDMI-1
    

新(“正常”)窗口将出现在目标监视器左上角100px(x + y)处。

NB

将其添加为启动项时,可能需要在运行前添加几秒钟的时间。如果您在登录/启动时遇到问题,请提及。


编辑

在经过编辑的版本下方(应要求提供)。差异:

  • 此版本跳过目标监视器上已经存在的窗口上的操作。
  • 此版本允许设置排除的WM_CLASS-es。要排除一个或多个类,请执行以下操作:在目标monitor-param 之后添加其他参数。一个例子:

    /path/to/win_tomonitor HDMI-1 Tilix Gedit
    

    将Tilix和gedit窗口都排除在外。

安装程序与第一个版本完全相同。玩得开心!

找出视窗的WM_CLASS

  • 打开终端窗口
  • 类型xprop,按Return
  • 点击目标窗口,WM_CLASS出现在终端

编码

using Wnck;
using Gdk;
using Gtk;

// compile:
// valac --pkg gtk+-3.0 --pkg gio-2.0 --pkg libwnck-3.0 -X "-D WNCK_I_KNOW_THIS_IS_UNSTABLE" 'file.vala'

namespace move_newwins {

    private int[] monitor_geo_x;
    private int[] monitor_geo_y;
    private int monitorindex;
    private string currmon;
    Gdk.Display dsp;
    string[] blacklist;

    private void getwins() {
        dsp = Gdk.Display.get_default();
        unowned Wnck.Screen scr = Wnck.Screen.get_default();
        scr.force_update();
        get_monitors(dsp);
        scr.window_opened.connect(newwin);
    }

    private void newwin (Wnck.Window newwin) {
        newwin.unmaximize();
        int winx;
        int winy;
        int winwidth;
        int winheight;
        newwin.get_geometry(out winx, out winy, out winwidth, out winheight);
        string wins_monitor = dsp.get_monitor_at_point(winx, winy).get_model();
        Wnck.WindowType type = newwin.get_window_type();
        string wm_class = newwin.get_class_group_name();
        bool blacklisted = get_stringindex(wm_class, blacklist) != -1;

        if (
            type == Wnck.WindowType.NORMAL &&
            wins_monitor != currmon &&
            !blacklisted
        ) {
            newwin.set_geometry(
                Wnck.WindowGravity.NORTHWEST,
                Wnck.WindowMoveResizeMask.X |
                Wnck.WindowMoveResizeMask.Y |
                Wnck.WindowMoveResizeMask.WIDTH |
                Wnck.WindowMoveResizeMask.HEIGHT,
                monitor_geo_x[monitorindex] + 100,
                monitor_geo_y[monitorindex] + 100,
                winwidth, winheight
            );
        }
    }

    private int get_stringindex (string s, string[] arr) {
        for (int i=0; i < arr.length; i++) {
            if(s == arr[i]) return i;
        } return -1;
    }

    private void get_monitors(Gdk.Display dsp) {
        int nmons = dsp.get_n_monitors();
        string[] monitornames = {};
        for (int i=0; i < nmons; i++) {
            Gdk.Monitor newmon = dsp.get_monitor(i);
            monitornames += newmon.get_model();
            Rectangle geo = newmon.get_geometry();
            monitor_geo_x += geo.x;
            monitor_geo_y += geo.y;
            monitorindex = get_stringindex(
                currmon, monitornames
            );
        }
    }

    public static void main (string[] args) {
        currmon = args[1];
        blacklist = args[1:args.length];
        Gtk.init(ref args);
        getwins();
        Gtk.main();
    }
}

找不到命令valac。当我尝试使用apt install valac进行安装时,脚本未找到某些IP
Rodolfo Velasco
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.