sierra para mac high gratis for antiguo java macos swing fullscreen keyboard-events

para - Los componentes FullScreen Swing no pueden recibir entrada de teclado en Java 7 en Mac OS X Mountain Lion



java se 6 mac download (3)

Creo que finalmente encontré una solución, registrando click listeners contra JFrame. (Esta es una clase que extiende JFrame, de ahí todas las referencias "this").

/** * Toggles full screen mode. Requires a lot of references to the JFrame. */ public void setFullScreen(boolean fullScreen){ GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice dev = env.getDefaultScreenDevice();//Gets the main screen if(!fullScreen){//Checks if a full screen application isn''t open this.dispose();//Restarts the JFrame this.setVisible(false); this.setResizable(true);//Re-enables resize-ability. this.setUndecorated(false);//Adds title bar back this.setVisible(true);//Shows restarted JFrame this.removeMouseListener(macWorkAround); this.pack(); this.setExtendedState(this.getExtendedState()|JFrame.MAXIMIZED_BOTH);//Returns to maximized state this.fullScreen = false; } else{ this.dispose();//Restarts the JFrame this.setResizable(false);//Disables resizing else causes bugs this.setUndecorated(true);//removes title bar this.setVisible(true);//Makes it visible again this.revalidate(); this.setSize(Toolkit.getDefaultToolkit().getScreenSize()); try{ dev.setFullScreenWindow(this);//Makes it full screen if(System.getProperty("os.name").indexOf("Mac OS X") >= 0){ this.setVisible(false); this.setVisible(true); this.addMouseListener(macWorkAround); } this.repaint(); this.revalidate(); } catch(Exception e){ dev.setFullScreenWindow(null);//Fall back behavior } this.requestFocus(); this.fullScreen = true; } } private MouseAdapter macWorkAround = new MouseAdapter(){ public void mouseClicked(MouseEvent e){ MainGUI.this.setVisible(false); MainGUI.this.setVisible(true); } };

Actualización 12/21:

7u10 fue lanzado recientemente. Confirmado que:

  1. El problema aún persiste
  2. ¡Afortunadamente, la solución aún funciona!

Actualización 11/7:

¡Y tenemos una solución alternativa!

Leonid Romanov de Oracle en la lista de correo openjdk.java.net brindó alguna información sobre lo que está sucediendo :

Bueno, aunque todavía no estoy 100% seguro, parece que cuando ingresamos a pantalla completa alguna otra ventana se convierte en la primera que responde, de ahí el pitido. Podría intentar la siguiente solución alternativa: después de llamar a setFullScreenWindow () en un marco, llame a setVisible (falso) seguido de setVisible (verdadero). Esto, en teoría, debería restaurar el primer respondedor correcto.

El fragmento de código que parece funcionar es simple:

dev.setFullScreenWindow(f); f.setVisible(false); f.setVisible(true);

He actualizado el código de muestra con la capacidad de activar y desactivar esta corrección; se requiere cada vez que una ventana ingresa a pantalla completa.

En el contexto más amplio de mi aplicación más compleja, todavía me encuentro con problemas de enfoque del teclado en los subcomponentes dentro de la ventana de pantalla completa, donde un clic del mouse hace que mi ventana pierda el foco. (Supongo que irá a la ventana de respuesta no deseada mencionada anteriormente). Informaré cuando tenga más información sobre este caso; aún no puedo reproducirla en la muestra más pequeña.

Actualización 10/31:

Actualización importante del código de muestra:

  • Incluye alternar entre los modos FullScreen exclusivo y Lion-style FullScreen
  • Escucha al KeyboardFocusManager para mostrar la jerarquía del componente actualmente enfocado
  • Utiliza mapas de entrada y KeyListener para intentar capturar entrada

También investigamos un poco más con los compañeros de trabajo para tratar de aislar los problemas:

En un frente, tratamos de sobreescribir algunos métodos en RT.jar para ver si había problemas con la forma en que se seleccionaba el dispositivo de pantalla. También se probaron los puntos de entrada a la funcionalidad Toolkit.beep () para ver si los sonidos de alerta provenían del lado de Java: parece que no.

En otro frente, estaba claro que ni siquiera el lado nativo está recibiendo eventos de teclado. Un compañero de trabajo lo atribuye a un cambio de AWTView a NSWindow en 7u6.

Se ha encontrado una selección de errores de Oracle existentes, que puede buscar here :

Actualización 10/26:

Gracias al comentario de @maslovalex a continuación sobre un Applet que trabaja en 7u5, volví atrás y examiné minuciosamente la compatibilidad con las versiones JDK para OSX:

  • 10.7.1 con 7u4: ¡La pantalla completa funciona!
  • 10.7.1 con 7u5: ¡La pantalla completa funciona!
  • 10.7.5 con 7u5: ¡La pantalla completa funciona!
  • 10.7.5 con 7u6: Breaks de pantalla completa :(

En combinación con las otras pruebas observadas en otros lugares, está claro que se presentó un problema con 7u6 que permanece en 7u7 y 7u9, y afecta tanto a Lion 10.7 como a Mountain Lion 10.8.

7u6 fue un lanzamiento importante, que brinda soporte total de JRE y JDK para Mac OS X y también incluye Java FX como parte de la distribución. Más información está disponible en las Notas de la versión y la Roadmap . No es tremendamente sorprendente que un problema así pueda surgir a medida que el soporte se traslada a Java FX.

La pregunta es:

  1. ¿Oracle arreglará esto en una versión a corto plazo del JDK? (Si tiene enlaces a errores existentes, inclúyalos aquí).
  2. ¿Es posible una solución alternativa mientras tanto?

Otras actualizaciones de hoy:

  • Incorporé el enfoque de las extensiones de Apple al modo de pantalla completa como una ruta alternativa de exploración (código de muestra actualizado pendiente de limpieza). La buena noticia: ¡la entrada funciona! Las malas noticias: realmente no parece haber ninguna opción de quiosco / aislamiento.
    Traté de matar al Dock, directly o con una App , ya que entiendo que Dock es responsable del cambio de la aplicación Command-Tab, Mission Control y Launch Pad, ¡solo para descubrir que también es responsable del manejo de las aplicaciones de pantalla completa! Como tal, las llamadas de Java se vuelven no funcionales y nunca regresan.
    Si hay una forma de deshabilitar Command-Tab (y Mission Control y Launchpad and Spaces) sin afectar el manejo a pantalla completa del Dock, eso sería extremadamente útil. Alternativamente, uno puede tratar de reasignar ciertas claves como Command, pero eso afectará la capacidad de usar ese modificador en cualquier parte del programa y del sistema en sí (no exactamente ideal, cuando se necesita Command-C para copiar algo de texto).

  • No he tenido suerte con KeyListeners (no recibo ninguna devolución de llamada), pero tengo algunas opciones más para probar.

  • Basado en la sugerencia de un compañero de trabajo, probé ((sun.lwawt.macosx.LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive() través de la reflexión. La idea era que:
    es un método nativo con el comentario "Devuelve verdadero si la aplicación (una de sus ventanas) posee el foco del teclado". Las llamadas a este método se agregaron en CPlatformWindow.java en los últimos meses relacionadas con la lógica de enfoque. Si devuelve falso en su código de prueba, es probable que sea parte del problema.
    Desafortunadamente, en todos los lugares donde lo comprobé, el método devolvió verdadero. Entonces, incluso de acuerdo con el sistema de bajo nivel, mis ventanas deberían tener el foco del teclado.

  • Mi optimismo anterior con respecto a la corrección JAlbum se ha desvanecido. El desarrollador publicó una respuesta en su foro que explica cómo simplemente eliminaron la compatibilidad adecuada de pantalla completa en OS X mientras ejecutaban Java 7. Tienen un error en Oracle (y espero obtener el número de error).

Actualización 10/25:

Ahora también he probado Java 7u9 en Lion 10.7.4 y he visto exactamente el mismo problema, por lo que es JDK, no es específico de OS.

La pregunta principal ha sido si puedes insertar en una ventana a pantalla completa Swing Components que tienen un manejo predeterminado para la entrada de teclado ( JTextField/JTextArea o incluso cuadros combinados editables) y esperar que se comporten normalmente (sin tener que recurrir a la reconstrucción de sus enlaces de teclas básicas a mano). También está en cuestión si deberían funcionar otros incondicionales de diseños en ventanas, como usar la pestaña para el recorrido del enfoque.

El objetivo ideal sería tener la capacidad de tomar una aplicación Swing en ventana con todos sus botones, pestañas, campos, etc. y ejecutarla en modo de pantalla completa exclusiva / kiosco con la mayor parte de la funcionalidad intacta. (Anteriormente, he visto que las ventanas emergentes de Dialog o las listas desplegables de ComboBox no funcionan en pantalla completa en Java 6 en OS X, pero otros componentes se comportan bien).

Buscaré en las capacidades completas de FullScreen, que serán interesantes si son compatibles con las opciones de bloqueo del kiosco, como la eliminación de la conmutación de aplicaciones Command-Tab.

Pregunta Original:

Tengo una aplicación Swing que durante años ha sido compatible con el modo FullScreen (exclusivo) en Mac OS X hasta Java 6. He estado haciendo pruebas de compatibilidad con la última versión de Mountain Lion (Suplementario 10.8.2) y JDK 7 de Oracle y noté una problema evidente mientras está en ese modo: el movimiento del mouse y los clics funcionan bien, pero la entrada del teclado no se entrega a los componentes.

(He reducido esto en un caso de prueba a continuación para no poder escribir en un simple JTextField mientras estoy en modo de pantalla completa).

Un síntoma es que cada pulsación de tecla da como resultado un pitido del sistema, como si el SO estuviera impidiendo que los eventos del teclado se entregaran a la aplicación.

Por separado, mi aplicación tiene un gancho de salida instalado, y el combo Command-Q activará ese gancho; está claro que el sistema operativo está escuchando combinaciones de teclas estándar.

He probado esto por separado en tres Mac diferentes con varias instalaciones:

  • En Apple Java 6u35 y 6u37: los modos de ventana y pantalla completa reciben entrada.
  • En Oracle Java 7u7 y 7u9: el modo de ventana funciona como se esperaba, mientras que la pantalla completa tiene los síntomas anteriores.

Es posible que se haya informado anteriormente: Modo de pantalla completa de gráficos de Java no registra la entrada de teclado . Sin embargo, esa pregunta no es específica sobre la versión o plataforma de Java.

La búsqueda adicional ha aparecido en una opción de pantalla completa presentada en Lion: función de pantalla completa para aplicaciones Java en OSX Lion . Todavía tengo que intentar usar este enfoque, ya que la entrada del teclado parece integral para los casos de uso de destino del modo exclusivo de FullScreen, como los juegos.

En JavaDoc se menciona en este modo que los métodos de entrada pueden estar deshabilitados. Intenté llamar al Component.enableInputMethods(false) sugerido, pero parecía no tener ningún efecto .

Estoy algo optimista de que hay una solución a este problema basada en una entrada en las notas de la versión de una aplicación Java que encontré (JAlbum). Una solución establecida para 10.10.6 : "La compatibilidad con el teclado no funcionaba cuando se ejecutaba la presentación de diapositivas a pantalla completa en Mac y Java 7"

Mi caso de prueba está abajo. Se modificó ligeramente desde el segundo ejemplo en este tema (que, sin modificar, también muestra mi problema): ¿Cómo manejar eventos del teclado y el mouse en modo exclusivo de pantalla completa en Java? En particular, agrega un botón para alternar a pantalla completa.

import java.lang.reflect.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.beans.*; /** @see https://stackoverflow.com/questions/13064607/ */ public class FullScreenTest extends JPanel { private GraphicsDevice dev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); private JFrame f = new JFrame("FullScreenTest"); private static final String EXIT = "Exit"; private Action exit = new AbstractAction(EXIT) { @Override public void actionPerformed(ActionEvent e) { Object o = dev.getFullScreenWindow(); if(o != null) { dev.setFullScreenWindow(null); } f.dispatchEvent(new WindowEvent(f, WindowEvent.WINDOW_CLOSING)); } }; private JButton exitBTN = new JButton(exit); private JTextField jtf = new JTextField("Uneditable in FullScreen with Java7u6+ on Mac OS X 10.7.3+"); private JLabel keystrokeLabel = new JLabel("(Last Modifier+Key Pressed in JTextField)"); private JLabel jtfFocusLabel = new JLabel("(JTextField Focus State)"); private JLabel focusLabel = new JLabel("(Focused Component Hierarchy)"); private JCheckBox useOSXFullScreenCB = new JCheckBox("Use Lion-Style FullScreen Mode"); private JCheckBox useWorkaroundCB = new JCheckBox("Use Visibility Workaround to Restore 1st Responder Window"); private static final String TOGGLE = "Toggle FullScreen (Command-T or Enter)"; private Action toggle = new AbstractAction(TOGGLE) { @Override public void actionPerformed(ActionEvent e) { Object o = dev.getFullScreenWindow(); if(o == null) { f.pack(); /** * !! Neither of these calls seem to have any later effect. * One exception: I have a report of a * Mini going into an unrecoverable black screen without setVisible(true); * May be only a Java 6 compatibility issue. !! */ //f.setVisible(true); //f.setVisible(false); if(!useOSXFullScreenCB.isSelected()) { // No keyboard input after this call unless workaround is used dev.setFullScreenWindow(f); /** * Workaround provided by Leonid Romanov at Oracle. */ if(useWorkaroundCB.isSelected()) { f.setVisible(false); f.setVisible(true); //Not necessary to invoke later... /*SwingUtilities.invokeLater(new Runnable() { public void run() { f.setVisible(false); f.setVisible(true); } });*/ } } else { toggleOSXFullscreen(f); } } else { dev.setFullScreenWindow(null); f.pack(); f.setVisible(true); } isAppActive(); } }; private JButton toggleBTN = new JButton(toggle); public FullScreenTest() { // -- Layout -- this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); exitBTN.setAlignmentX(JComponent.CENTER_ALIGNMENT); exitBTN.setMaximumSize(new Dimension(Short.MAX_VALUE, 50)); this.add(exitBTN); jtf.setAlignmentX(JComponent.CENTER_ALIGNMENT); jtf.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE)); this.add(jtf); keystrokeLabel.setAlignmentX(JComponent.CENTER_ALIGNMENT); keystrokeLabel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50)); keystrokeLabel.setHorizontalAlignment(SwingConstants.CENTER); keystrokeLabel.setForeground(Color.DARK_GRAY); this.add(keystrokeLabel); jtfFocusLabel.setAlignmentX(JComponent.CENTER_ALIGNMENT); jtfFocusLabel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50)); jtfFocusLabel.setHorizontalAlignment(SwingConstants.CENTER); jtfFocusLabel.setForeground(Color.DARK_GRAY); this.add(jtfFocusLabel); focusLabel.setAlignmentX(JComponent.CENTER_ALIGNMENT); focusLabel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50)); focusLabel.setHorizontalAlignment(SwingConstants.CENTER); focusLabel.setForeground(Color.DARK_GRAY); this.add(focusLabel); useOSXFullScreenCB.setAlignmentX(JComponent.CENTER_ALIGNMENT); useOSXFullScreenCB.setMaximumSize(new Dimension(Short.MAX_VALUE, 50)); useOSXFullScreenCB.setHorizontalAlignment(SwingConstants.CENTER); this.add(useOSXFullScreenCB); useWorkaroundCB.setAlignmentX(JComponent.CENTER_ALIGNMENT); useWorkaroundCB.setMaximumSize(new Dimension(Short.MAX_VALUE, 50)); useWorkaroundCB.setHorizontalAlignment(SwingConstants.CENTER); this.add(useWorkaroundCB); toggleBTN.setAlignmentX(JComponent.CENTER_ALIGNMENT); toggleBTN.setMaximumSize(new Dimension(Short.MAX_VALUE, 50)); this.add(toggleBTN); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setResizable(false); f.setUndecorated(true); f.add(this); f.pack(); enableOSXFullscreen(f); // -- Listeners -- // Default BTN set to see how input maps respond in fullscreen f.getRootPane().setDefaultButton(toggleBTN); // Explicit input map test with Command-T toggle action from anywhere in the window this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), toggle.getValue(Action.NAME)); this.getActionMap().put(toggle.getValue(Action.NAME), toggle); // KeyListener test jtf.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { String ktext = "KeyPressed: "+e.getKeyModifiersText(e.getModifiers()) + "_"+ e.getKeyText(e.getKeyCode()); keystrokeLabel.setText(ktext); System.out.println(ktext); } }); // FocusListener test jtf.addFocusListener(new FocusListener() { public void focusGained(FocusEvent fe) { focused(fe); } public void focusLost(FocusEvent fe) { focused(fe); } private void focused(FocusEvent fe) { boolean allGood = jtf.hasFocus() && jtf.isEditable() && jtf.isEnabled(); jtfFocusLabel.setText("JTextField has focus (and is enabled/editable): " + allGood); isAppActive(); } }); // Keyboard Focus Manager KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); focusManager.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { if (!("focusOwner".equals(e.getPropertyName()))) return; Component comp = (Component)e.getNewValue(); if(comp == null) { focusLabel.setText("(No Component Focused)"); return; } String label = comp.getClass().getName(); while(true) { comp = comp.getParent(); if(comp == null) break; label = comp.getClass().getSimpleName() + " -> " + label; } focusLabel.setText("Focus Hierarchy: " + label); isAppActive(); } }); } /** * Hint that this Window can enter fullscreen. Only need to call this once per Window. * @param window */ @SuppressWarnings({"unchecked", "rawtypes"}) public static void enableOSXFullscreen(Window window) { try { Class util = Class.forName("com.apple.eawt.FullScreenUtilities"); Class params[] = new Class[]{Window.class, Boolean.TYPE}; Method method = util.getMethod("setWindowCanFullScreen", params); method.invoke(util, window, true); } catch (ClassNotFoundException e1) { } catch (Exception e) { System.out.println("Failed to enable Mac Fullscreen: "+e); } } /** * Toggle OSX fullscreen Window state. Must call enableOSXFullscreen first. * Reflection version of: com.apple.eawt.Application.getApplication().requestToggleFullScreen(f); * @param window */ @SuppressWarnings({"unchecked", "rawtypes"}) public static void toggleOSXFullscreen(Window window) { try { Class appClass = Class.forName("com.apple.eawt.Application"); Method method = appClass.getMethod("getApplication"); Object appInstance = method.invoke(appClass); Class params[] = new Class[]{Window.class}; method = appClass.getMethod("requestToggleFullScreen", params); method.invoke(appInstance, window); } catch (ClassNotFoundException e1) { } catch (Exception e) { System.out.println("Failed to toggle Mac Fullscreen: "+e); } } /** * Quick check of the low-level window focus state based on Apple''s Javadoc: * "Returns true if the application (one of its windows) owns keyboard focus." */ @SuppressWarnings({"unchecked", "rawtypes"}) public static void isAppActive() { try { Class util = Class.forName("sun.lwawt.macosx.LWCToolkit"); Method method = util.getMethod("isApplicationActive"); Object obj = method.invoke(Toolkit.getDefaultToolkit()); System.out.println("AppActive: "+obj); } catch (ClassNotFoundException e1) { } catch (Exception e) { System.out.println("Failed to check App: "+e); } } public static void main(String[] args) { System.out.println("Java Version: " + System.getProperty("java.version")); System.out.println("OS Version: " + System.getProperty("os.version")); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { FullScreenTest fst = new FullScreenTest(); if(!fst.dev.isFullScreenSupported()) { System.out.println("FullScreen not supported on this graphics device. Exiting."); System.exit(0); } fst.toggle.actionPerformed(null); } }); } }


En su lugar, use enlaces de teclas , como se muestra en este FullScreenTest . Además, considere un DocumentListener , que se muestra here , para los componentes de texto.


Esto se debe a que el componente al que agregó el otro ahora ha perdido el foco, puede solucionarlo mediante:

  • llamando a requestFocus() en la instancia del componente a la que agrega KeyBinding s

o

  • alternativamente use JComponent.WHEN_IN_FOCUSED_WINDOW con KeyBinding s:

    component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "doSomething"); component.getActionMap().put("doSomething", anAction);

Referencia: