如何在 Linux 上使用 Java 将 GEdit 置于最前面

How to bring GEdit to front using Java on Linux

我们的 Java/SWT-based 应用程序可以启动用户可编辑的第三方应用程序,例如编辑。例如,在 Linux(CentOS 7、Gnome 3.28.2)上,当启动 "gedit" 时,它可以正常打开,但落后于我们应用程序的 window。奇怪的是,当从终端 (gnome-terminal) 启动 "gedit " 时,GEdit 出现在最前面 window.

如何告诉 "gedit"(或其他人)作为最前面的应用程序启动?

更新: 当我从 IDE (IDEA) 启动我的 Java-应用程序时,它按预期工作(Gedit 在前面)。如果我从 shell 脚本启动我的应用程序,它会按预期工作。如果我从指向 shell-脚本的 .desktop 文件启动应用程序,Gedit 不仅会打开文件 ,还会显示准备就绪的通知 。也许这会以某种方式混淆应用程序的 z 顺序 windows?或者它取决于环境变量:如果从 .desktop 文件启动,环境变量 DESKTOP_STARTUP_IDGIO_LAUNCHED_DESKTOP_FILEGIO_LAUNCHED_DESKTOP_FILE_PID 额外可用并且 HISTCONTROL 设置为 ignoredups 而不是 ignorespaceSHLVL2 而不是 4TERM 被设置为 dump 而不是 xterm-256color

根据 Stephan Schlecht 的代码,我发现以下 Java 代码应该重现问题:

import java.io.*;
import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class EditorOpener {

    public static void main(String[] args) {
        final Map<String, String> getenv = System.getenv();
        System.out.println(getenv);

        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setSize(500, 200);
        shell.setText("Editor Opener");
        shell.setLayout(new RowLayout());

        final Button button = new Button(shell, SWT.PUSH);
        button.setText("open gedit");

        button.addListener(SWT.Selection, event -> new Thread(() -> {
            final ProcessBuilder processBuilder = new ProcessBuilder();
            processBuilder.command("/usr/bin/gedit");
            final Map<String, String> environment = processBuilder.environment();
            System.out.println(environment);
            try {
                final Process process = processBuilder.start();
                process.waitFor();
            }
            catch (IOException | InterruptedException ex) {
                ex.printStackTrace();
            }
        }).start());

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }
}

环境变量的2次访问必不可少

有这个实用程序 wmctrl 可以轻松地做你想做的事。

对于您的用例,您将使用 wmctrl -a "gedit" 或类似的东西。来自手册页:

-a

Switch to the desktop containing the window <WIN>, raise the window, and give it focus.

或者,您可以将程序最小化并在 gedit 完成后再次恢复它。

现在可以做出许多假设(例如 the.desktop 文件的内容),但最好有一个关于它如何工作的分步指南,例如像这样:

测试程序

此 SWT 程序通过 Runtime.getRuntime().exec 启动 'gedit'。

import java.io.IOException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class EditorOpener {

    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setSize(500, 200);
        shell.setText("Editor Opener");
        shell.setLayout(new RowLayout());

        final Button button = new Button(shell, SWT.PUSH);
        button.setText("open gedit");

        button.addSelectionListener(new SelectionListener() {

            public void widgetSelected(SelectionEvent event) {
                String[] cmdArray = new String[] { "/usr/bin/gedit" };
                try {
                    Runtime.getRuntime().exec(cmdArray);
                }
                catch(IOException ex) {
                    ex.printStackTrace();
                }
            }

            public void widgetDefaultSelected(SelectionEvent event) {
            }
        });

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }
}

调用Java程序

Java 程序是从如下所示的 shell 脚本调用的:

#!/usr/bin/bash
java -cp /path/to/swt.jar:/path/to/classes EditorOpener

.桌面文件

指向 shell 文件的 .desktop 文件如下所示:

[Desktop Entry]
Type=Application
Terminal=false
Name=Opener
Icon=utilities-terminal
Exec='/home/stephan/Documents/opener.sh'
Categories=Application;

结果

通过单击 open gedit 按钮,gedit 将按预期启动,高于所有其他 windows。

演示

测试是在CentOS上完成的Linux 7:

gnome-shell --version

给出输出:

GNOME Shell 3.28.3

原因是我们的 .desktop 文件包含行

StartupNotify=true
StartupWMClass=<main-class>

删除第一行会使问题消失。