Полноэкранный эксклюзивный режим Java и Ubuntu 14.04

У меня есть базовый код Java для установки JFrame в полноэкранном режиме и изменения разрешения экрана. Этот код совпадает с примером кода из учебных пособий Oracle.

Все работает в Ubuntu 14.04 с последними версиями Java 7.0 и Java 8.0, но строка заголовка и строка меню по-прежнему отображаются поверх полноэкранного окна.

В других ответах предлагается включить «устаревшую полноэкранную поддержку» в диспетчере Compiz, но я сделал это, и ничего не изменилось.

Есть ли другой обходной путь?

Ссылка на пример кода: http://docs.oracle.com/javase/tutorial/extra/fullscreen/examples/MultiBufferTest.java

В примере кода используется Frame, а не JFrame, но у меня не получилось ни того, ни другого.


person Timothy Wright    schedule 12.01.2015    source источник
comment
По словам автора, frame.setUndecorated(true) уже есть в коде. Это Убунту.   -  person ruediste    schedule 12.01.2015
comment
Да, похоже, это проблема Ubuntu. Я видел другие сообщения о Minecraft, демонстрирующие такое же поведение. Но предложенные исправления не сработали.   -  person Timothy Wright    schedule 12.01.2015


Ответы (1)


Если вы не возражаете против использования JNA, я делаю это следующим образом:

private static final int _NET_WM_STATE_REMOVE = 0;

private static final int _NET_WM_STATE_ADD = 1;

private static final int TRUE = 1;

public static boolean setFullScreenWindow(Window w, boolean fullScreen) {
    X11 x = X11.INSTANCE;
    Display display = null;
    try {
        display = x.XOpenDisplay(null);
        int result = sendClientMessage(display, Native.getWindowID(w), "_NET_WM_STATE", new NativeLong(fullScreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE), x.XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", false));
        return result != 0;
    }
    finally {
        if(display != null) {
            x.XCloseDisplay(display);
        }
    }
}

private static int sendClientMessage(Display display, long wid, String msg, NativeLong data0, NativeLong data1) {
    X11 x = X11.INSTANCE;
    XEvent event = new XEvent();
    event.type = X11.ClientMessage;
    event.setType(XClientMessageEvent.class);
    event.xclient.type = X11.ClientMessage;
    event.xclient.serial = new NativeLong(0L);
    event.xclient.send_event = TRUE;
    event.xclient.message_type = x.XInternAtom(display, msg, false);
    event.xclient.window = new com.sun.jna.platform.unix.X11.Window(wid);
    event.xclient.format = 32;
    event.xclient.data.setType(NativeLong[].class);
    event.xclient.data.l[0] = data0;
    event.xclient.data.l[1] = data1;
    event.xclient.data.l[2] = new NativeLong(0L);
    event.xclient.data.l[3] = new NativeLong(0L);
    event.xclient.data.l[4] = new NativeLong(0L);
    NativeLong mask = new NativeLong(X11.SubstructureRedirectMask | X11.SubstructureNotifyMask);
    int result = x.XSendEvent(display, x.XDefaultRootWindow(display), 0, mask, event);
    x.XFlush(display);
    return result;
}

Вам нужно добавить JNA и банк JNA Platform в свой проект.

У меня это работает на Kubuntu 14.10.

Первоначально я написал этот код как часть моего проекта vlcj здесь https://github.com/caprica/vlcj/blob/vlcj-3.1.0/src/main/java/uk/co/caprica/vlcj/runtime/x/LibXUtil.java.

person caprica    schedule 12.01.2015
comment
Ух ты. Я никогда не использовал JNA, только JNI с SWIG. Это выглядит интересно. Но я был уверен, что надеялся на что-то более простое для понимания новичком. - person Timothy Wright; 12.01.2015
comment
Я потратил много времени, пытаясь заставить его работать с чистой Java. Для меня, даже в Windows, использование такого собственного вызова было единственным способом заставить его вести себя так, как я хотел. Если вы беспокоитесь о том, что это будет непросто, просто вставьте его в служебный класс и забудьте о реализации, на самом деле это не так важно понимать. - person caprica; 12.01.2015