如何在Linux上使用Java将GEdit推向前台

如何在Linux上使用Java将GEdit推向前台,linux,xorg,Linux,Xorg,我们基于Java/SWT的应用程序可以启动用户可编辑的第三方应用程序,例如编辑器。例如,在Linux(CentOS 7,Gnome 3.28.2)上,当启动“gedit”时,它可以很好地打开,但在应用程序窗口后面。奇怪的是,当从终端(gnome终端)启动“gedit”时,gedit作为最前面的窗口出现 如何告诉“gedit”(或其他)作为最前端的应用程序启动 更新: 当我从IDE(IDEA)启动Java应用程序时,它可以按预期工作(Gedit在前面)。如果我从shell脚本启动我的应用程序,它将

我们基于Java/SWT的应用程序可以启动用户可编辑的第三方应用程序,例如编辑器。例如,在Linux(CentOS 7,Gnome 3.28.2)上,当启动“gedit”时,它可以很好地打开,但在应用程序窗口后面。奇怪的是,当从终端(
gnome终端
)启动“gedit”时,gedit作为最前面的窗口出现

如何告诉“gedit”(或其他)作为最前端的应用程序启动

更新: 当我从IDE(IDEA)启动Java应用程序时,它可以按预期工作(Gedit在前面)。如果我从shell脚本启动我的应用程序,它将按预期工作。如果我从指向shell脚本的.desktop文件启动应用程序,Gedit不仅会打开文件,还会显示一个准备就绪的通知。也许这会混淆应用程序窗口的z顺序?或者它取决于环境变量:如果从.desktop文件启动,环境变量
desktop\u STARTUP\u ID
GIO\u-launted\u desktop\u文件
GIO\u-launted\u desktop\u文件
可额外使用,
HISTCONTROL
设置为
ignoredups
,而不是
ignorespace
SHLVL
2
而不是
4
TERM
被设置为
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();
    }
}
import java.io.*;
导入java.util.*;
导入org.eclipse.swt.*;
导入org.eclipse.swt.layout.*;
导入org.eclipse.swt.widgets.*;
公共类编辑员{
公共静态void main(字符串[]args){
最终映射getenv=System.getenv();
System.out.println(getenv);
显示=新显示();
外壳=新外壳(显示);
外壳尺寸(500200);
shell.setText(“编辑器开启器”);
setLayout(新的RowLayout());
最终按钮=新按钮(外壳,SWT.按钮);
button.setText(“打开gedit”);
addListener(SWT.Selection,事件->新线程(()->{
最终ProcessBuilder ProcessBuilder=新的ProcessBuilder();
processBuilder.command(“/usr/bin/gedit”);
最终映射环境=processBuilder.environment();
System.out.println(环境);
试一试{
最终流程=processBuilder.start();
process.waitFor();
}
捕获(IOException | InterruptedException ex){
例如printStackTrace();
}
}).start());
shell.open();
而(!shell.isDisposed()){
如果(!display.readAndDispatch()){
display.sleep();
}
}
display.dispose();
}
}
对环境变量的两个访问是必不可少的。

有一个实用程序可以轻松地完成您想要的任务

对于您的用例,您将使用
wmctrl-a“gedit”
或类似的东西。从手册页:

-a

切换到包含窗口的桌面,升起窗口并使其聚焦。
或者,您可以最小化您的程序,并在
gedit
完成时再次恢复它。

有一个实用程序可以轻松地完成您想要的任务

对于您的用例,您将使用
wmctrl-a“gedit”
或类似的东西。从手册页:

-a

切换到包含窗口的桌面,升起窗口并使其聚焦。

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

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

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

此SWT程序通过Runtime.getRuntime().exec启动“gedit”

调用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将按预期在所有其他窗口上启动

演示

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

gnome-shell --version
给出输出:

GNOME Shell 3.28.3

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

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

此SWT程序通过Runtime.getRuntime().exec启动“gedit”

调用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将按预期在所有其他窗口上启动

演示

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

gnome-shell --version
给出输出:

GNOME Shell 3.28.3

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

StartupNotify=true
StartupWMClass=<main-class>
StartupNotify=true
创业班=

删除第一行会导致问题消失。

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

StartupNotify=true
StartupWMClass=<main-class>
StartupNotify=true
创业班=

删除第一行会导致问题消失。

我想我们不能使用wmctrl,因为它不是默认安装的。我想我们不能使用wmctrl,因为它不是默认安装的。
但是在我们的应用程序窗口后面
也许你的应用程序设置了“始终在顶部”属性?你不能以其他程序获取焦点的方式影响它们的启动(视窗人)