Global hotkey, iconifying and application activation, help text.
This commit is contained in:
parent
f5c0c4d787
commit
3fc8acba70
@ -11,6 +11,7 @@ dependencies {
|
|||||||
implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p2'
|
implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p2'
|
||||||
implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.2'
|
implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.2'
|
||||||
implementation group: 'com.yuvimasory', name: 'orange-extensions', version: '1.3.0'
|
implementation group: 'com.yuvimasory', name: 'orange-extensions', version: '1.3.0'
|
||||||
|
implementation group: 'com.github.tulskiy', name: 'jkeymaster', version: '1.2'
|
||||||
|
|
||||||
compile project( ':masterpassword-model' )
|
compile project( ':masterpassword-model' )
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@ import com.lyndir.lhunath.opal.system.logging.Logger;
|
|||||||
import com.lyndir.masterpassword.gui.util.Platform;
|
import com.lyndir.masterpassword.gui.util.Platform;
|
||||||
import com.lyndir.masterpassword.gui.util.Res;
|
import com.lyndir.masterpassword.gui.util.Res;
|
||||||
import com.lyndir.masterpassword.gui.view.MasterPasswordFrame;
|
import com.lyndir.masterpassword.gui.view.MasterPasswordFrame;
|
||||||
|
import com.tulskiy.keymaster.common.Provider;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,9 +22,18 @@ public class GUI {
|
|||||||
public GUI() {
|
public GUI() {
|
||||||
Platform.get().installAppForegroundHandler( this::open );
|
Platform.get().installAppForegroundHandler( this::open );
|
||||||
Platform.get().installAppReopenHandler( this::open );
|
Platform.get().installAppReopenHandler( this::open );
|
||||||
|
|
||||||
|
KeyStroke keyStroke = KeyStroke.getKeyStroke( KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK | InputEvent.META_DOWN_MASK );
|
||||||
|
Provider.getCurrentProvider( true ).register( keyStroke, hotKey -> open() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open() {
|
public void open() {
|
||||||
Res.ui( () -> frame.setVisible( true ) );
|
Res.ui( () -> {
|
||||||
|
frame.setAlwaysOnTop( true );
|
||||||
|
frame.setVisible( true );
|
||||||
|
frame.setExtendedState( Frame.NORMAL );
|
||||||
|
frame.setAlwaysOnTop( false );
|
||||||
|
Platform.get().requestForeground();
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,12 @@
|
|||||||
|
|
||||||
package com.lyndir.masterpassword.gui.util;
|
package com.lyndir.masterpassword.gui.util;
|
||||||
|
|
||||||
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -30,9 +32,9 @@ import javax.annotation.Nullable;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
import javax.swing.border.CompoundBorder;
|
import javax.swing.border.CompoundBorder;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.*;
|
||||||
import javax.swing.event.DocumentListener;
|
|
||||||
import javax.swing.text.DefaultFormatterFactory;
|
import javax.swing.text.DefaultFormatterFactory;
|
||||||
|
import org.jetbrains.annotations.NonNls;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,6 +43,8 @@ import javax.swing.text.DefaultFormatterFactory;
|
|||||||
@SuppressWarnings({ "SerializableStoresNonSerializable", "serial" })
|
@SuppressWarnings({ "SerializableStoresNonSerializable", "serial" })
|
||||||
public abstract class Components {
|
public abstract class Components {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.get( Components.class );
|
||||||
|
|
||||||
public static final float TEXT_SIZE_HEADING = 19f;
|
public static final float TEXT_SIZE_HEADING = 19f;
|
||||||
public static final float TEXT_SIZE_CONTROL = 13f;
|
public static final float TEXT_SIZE_CONTROL = 13f;
|
||||||
public static final int SIZE_MARGIN = 12;
|
public static final int SIZE_MARGIN = 12;
|
||||||
@ -100,11 +104,11 @@ public abstract class Components {
|
|||||||
showDialog( dialog );
|
showDialog( dialog );
|
||||||
|
|
||||||
Object selectedValue = pane.getValue();
|
Object selectedValue = pane.getValue();
|
||||||
if(selectedValue == null)
|
if (selectedValue == null)
|
||||||
return JOptionPane.CLOSED_OPTION;
|
return JOptionPane.CLOSED_OPTION;
|
||||||
|
|
||||||
Object[] options = pane.getOptions();
|
Object[] options = pane.getOptions();
|
||||||
if(options == null)
|
if (options == null)
|
||||||
return (selectedValue instanceof Integer)? (Integer) selectedValue: JOptionPane.CLOSED_OPTION;
|
return (selectedValue instanceof Integer)? (Integer) selectedValue: JOptionPane.CLOSED_OPTION;
|
||||||
|
|
||||||
int option = Arrays.binarySearch( options, selectedValue );
|
int option = Arrays.binarySearch( options, selectedValue );
|
||||||
@ -337,7 +341,7 @@ public abstract class Components {
|
|||||||
BorderFactory.createEmptyBorder( 4, 4, 4, 4 ) );
|
BorderFactory.createEmptyBorder( 4, 4, 4, 4 ) );
|
||||||
DefaultFormatterFactory formatterFactory = new DefaultFormatterFactory();
|
DefaultFormatterFactory formatterFactory = new DefaultFormatterFactory();
|
||||||
if (model instanceof UnsignedIntegerModel)
|
if (model instanceof UnsignedIntegerModel)
|
||||||
formatterFactory.setDefaultFormatter( ((UnsignedIntegerModel)model).getFormatter() );
|
formatterFactory.setDefaultFormatter( ((UnsignedIntegerModel) model).getFormatter() );
|
||||||
((DefaultEditor) getEditor()).getTextField().setFormatterFactory( formatterFactory );
|
((DefaultEditor) getEditor()).getTextField().setFormatterFactory( formatterFactory );
|
||||||
((DefaultEditor) getEditor()).getTextField().setBorder( editorBorder );
|
((DefaultEditor) getEditor()).getTextField().setBorder( editorBorder );
|
||||||
setAlignmentX( LEFT_ALIGNMENT );
|
setAlignmentX( LEFT_ALIGNMENT );
|
||||||
@ -474,6 +478,24 @@ public abstract class Components {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JEditorPane linkLabel(@NonNls final String html) {
|
||||||
|
return new JEditorPane( "text/html", "<html><body style='width:640'>" + html ) {
|
||||||
|
{
|
||||||
|
setOpaque( false );
|
||||||
|
setEditable( false );
|
||||||
|
addHyperlinkListener( event -> {
|
||||||
|
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
|
||||||
|
try {
|
||||||
|
Platform.get().open( event.getURL().toURI() );
|
||||||
|
}
|
||||||
|
catch (final URISyntaxException e) {
|
||||||
|
logger.err( e, "After triggering hyperlink: %s", event );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static class GradientPanel extends JPanel {
|
public static class GradientPanel extends JPanel {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -138,6 +138,10 @@ public abstract class Res {
|
|||||||
return icon( "media/icon_import.png" );
|
return icon( "media/icon_import.png" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Icon help() {
|
||||||
|
return icon( "media/icon_help.png" );
|
||||||
|
}
|
||||||
|
|
||||||
public Icon export() {
|
public Icon export() {
|
||||||
return icon( "media/icon_export.png" );
|
return icon( "media/icon_export.png" );
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ package com.lyndir.masterpassword.gui.util.platform;
|
|||||||
import com.apple.eawt.*;
|
import com.apple.eawt.*;
|
||||||
import com.apple.eio.FileManager;
|
import com.apple.eio.FileManager;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.base.Throwables;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileNotFoundException;
|
import java.net.URI;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,7 +13,8 @@ import java.io.FileNotFoundException;
|
|||||||
*/
|
*/
|
||||||
public class ApplePlatform implements IPlatform {
|
public class ApplePlatform implements IPlatform {
|
||||||
|
|
||||||
static Application application = Preconditions.checkNotNull(
|
private static final Logger logger = Logger.get( ApplePlatform.class );
|
||||||
|
private static final Application application = Preconditions.checkNotNull(
|
||||||
Application.getApplication(), "Not an Apple Java application." );
|
Application.getApplication(), "Not an Apple Java application." );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -37,12 +38,31 @@ public class ApplePlatform implements IPlatform {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requestForeground() {
|
||||||
|
application.requestForeground( true );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean show(final File file) {
|
public boolean show(final File file) {
|
||||||
try {
|
try {
|
||||||
return FileManager.revealInFinder( file );
|
return FileManager.revealInFinder( file );
|
||||||
}
|
}
|
||||||
catch (final FileNotFoundException ignored) {
|
catch (final FileNotFoundException e) {
|
||||||
|
logger.err( e, "While showing: %s", file );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean open(final URI url) {
|
||||||
|
try {
|
||||||
|
FileManager.openURL( url.toString() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
logger.err( e, "While opening: %s", url );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.lyndir.masterpassword.gui.util.platform;
|
package com.lyndir.masterpassword.gui.util.platform;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,8 +19,18 @@ public class BasePlatform implements IPlatform {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requestForeground() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean show(final File file) {
|
public boolean show(final File file) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean open(final URI url) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.lyndir.masterpassword.gui.util.platform;
|
package com.lyndir.masterpassword.gui.util.platform;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,5 +14,9 @@ public interface IPlatform {
|
|||||||
|
|
||||||
boolean installAppReopenHandler(Runnable handler);
|
boolean installAppReopenHandler(Runnable handler);
|
||||||
|
|
||||||
|
boolean requestForeground();
|
||||||
|
|
||||||
boolean show(File file);
|
boolean show(File file);
|
||||||
|
|
||||||
|
boolean open(URI url);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package com.lyndir.masterpassword.gui.util.platform;
|
package com.lyndir.masterpassword.gui.util.platform;
|
||||||
|
|
||||||
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.desktop.*;
|
import java.awt.desktop.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,9 +14,12 @@ import java.io.File;
|
|||||||
@SuppressWarnings("Since15")
|
@SuppressWarnings("Since15")
|
||||||
public class JDK9Platform implements IPlatform {
|
public class JDK9Platform implements IPlatform {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.get( JDK9Platform.class );
|
||||||
|
private static final Desktop desktop = Desktop.getDesktop();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean installAppForegroundHandler(final Runnable handler) {
|
public boolean installAppForegroundHandler(final Runnable handler) {
|
||||||
Desktop.getDesktop().addAppEventListener( new AppForegroundListener() {
|
desktop.addAppEventListener( new AppForegroundListener() {
|
||||||
@Override
|
@Override
|
||||||
public void appRaisedToForeground(final AppForegroundEvent e) {
|
public void appRaisedToForeground(final AppForegroundEvent e) {
|
||||||
handler.run();
|
handler.run();
|
||||||
@ -28,7 +34,13 @@ public class JDK9Platform implements IPlatform {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean installAppReopenHandler(final Runnable handler) {
|
public boolean installAppReopenHandler(final Runnable handler) {
|
||||||
Desktop.getDesktop().addAppEventListener( (AppReopenedListener) e -> handler.run() );
|
desktop.addAppEventListener( (AppReopenedListener) e -> handler.run() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requestForeground() {
|
||||||
|
desktop.requestForeground( true );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +49,19 @@ public class JDK9Platform implements IPlatform {
|
|||||||
if (!file.exists())
|
if (!file.exists())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Desktop.getDesktop().browseFileDirectory( file );
|
desktop.browseFileDirectory( file );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean open(final URI url) {
|
||||||
|
try {
|
||||||
|
desktop.browse( url );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
logger.err( e, "While opening: %s", url );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
"Add a new user to Master Password." );
|
"Add a new user to Master Password." );
|
||||||
private final JButton importButton = Components.button( Res.icons().import_(), event -> importUser(),
|
private final JButton importButton = Components.button( Res.icons().import_(), event -> importUser(),
|
||||||
"Import a user from a backup file into Master Password." );
|
"Import a user from a backup file into Master Password." );
|
||||||
|
private final JButton helpButton = Components.button( Res.icons().help(), event -> showHelp(),
|
||||||
|
"Show information on how to use Master Password." );
|
||||||
|
|
||||||
private final JPanel userToolbar = Components.panel( BoxLayout.PAGE_AXIS );
|
private final JPanel userToolbar = Components.panel( BoxLayout.PAGE_AXIS );
|
||||||
private final JPanel siteToolbar = Components.panel( BoxLayout.PAGE_AXIS );
|
private final JPanel siteToolbar = Components.panel( BoxLayout.PAGE_AXIS );
|
||||||
@ -208,7 +210,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
this, strf( "<html>Couldn't read import file:<br><pre>%s</pre></html>.", e.getLocalizedMessage() ),
|
this, strf( "<html>Couldn't read import file:<br><pre>%s</pre></html>.", e.getLocalizedMessage() ),
|
||||||
"Import Failed", JOptionPane.ERROR_MESSAGE );
|
"Import Failed", JOptionPane.ERROR_MESSAGE );
|
||||||
}
|
}
|
||||||
catch (MPMarshalException e) {
|
catch (final MPMarshalException e) {
|
||||||
logger.err( e, "While parsing user import file." );
|
logger.err( e, "While parsing user import file." );
|
||||||
JOptionPane.showMessageDialog(
|
JOptionPane.showMessageDialog(
|
||||||
this, strf( "<html>Couldn't parse import file:<br><pre>%s</pre></html>.", e.getLocalizedMessage() ),
|
this, strf( "<html>Couldn't parse import file:<br><pre>%s</pre></html>.", e.getLocalizedMessage() ),
|
||||||
@ -216,6 +218,31 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showHelp() {
|
||||||
|
JOptionPane.showMessageDialog( this, Components.linkLabel( strf(
|
||||||
|
"<h1>Master Password</h1>"
|
||||||
|
+ "<p>The primary goal of this application is to provide a reliable security solution that also "
|
||||||
|
+ "makes you independent from your computer. If you lose access to this computer or your data, "
|
||||||
|
+ "the application can regenerate all your secrets from scratch on any new device.</p>"
|
||||||
|
+ "<h2>Opening Master Password</h2>"
|
||||||
|
+ "<p>To use Master Password, simply open the application on your computer. "
|
||||||
|
+ "Once running, you can bring up the user interface at any time by pressing the keys "
|
||||||
|
+ "<strong><code>%s + %s + p</code></strong>."
|
||||||
|
+ "<h2>Persistence</h2>"
|
||||||
|
+ "<p>Though at the core, Master Password does not require the use of any form of data "
|
||||||
|
+ "storage, the application does remember the names of the sites you've used in the past to "
|
||||||
|
+ "make it easier for you to use them again in the future. All user information is saved in "
|
||||||
|
+ "files on your computer at the following location:<br><pre>%s</pre></p>"
|
||||||
|
+ "<p>You can read, modify, backup or place new files in this location as you see fit. "
|
||||||
|
+ "Some people even configure this location to be synced between their different computers "
|
||||||
|
+ "using services such as those provided by SpiderOak or Dropbox.</p>"
|
||||||
|
+ "<hr><p><a href='https://masterpassword.app'>https://masterpassword.app</a> — by Maarten Billemont</p>",
|
||||||
|
KeyEvent.getKeyText( KeyEvent.VK_CONTROL ),
|
||||||
|
KeyEvent.getKeyText( KeyEvent.VK_META ),
|
||||||
|
MPFileUserManager.get().getPath().getAbsolutePath() ) ),
|
||||||
|
"About Master Password", JOptionPane.INFORMATION_MESSAGE );
|
||||||
|
}
|
||||||
|
|
||||||
private enum ContentMode {
|
private enum ContentMode {
|
||||||
NO_USER,
|
NO_USER,
|
||||||
AUTHENTICATE,
|
AUTHENTICATE,
|
||||||
@ -239,6 +266,8 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
|
|
||||||
userToolbar.add( addButton );
|
userToolbar.add( addButton );
|
||||||
userToolbar.add( importButton );
|
userToolbar.add( importButton );
|
||||||
|
userToolbar.add( Box.createGlue() );
|
||||||
|
userToolbar.add( helpButton );
|
||||||
|
|
||||||
add( Box.createGlue() );
|
add( Box.createGlue() );
|
||||||
add( Components.heading( "Select a user to proceed." ) );
|
add( Components.heading( "Select a user to proceed." ) );
|
||||||
@ -275,6 +304,8 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
userToolbar.add( exportButton );
|
userToolbar.add( exportButton );
|
||||||
userToolbar.add( deleteButton );
|
userToolbar.add( deleteButton );
|
||||||
userToolbar.add( resetButton );
|
userToolbar.add( resetButton );
|
||||||
|
userToolbar.add( Box.createGlue() );
|
||||||
|
userToolbar.add( helpButton );
|
||||||
|
|
||||||
add( Components.heading( user.getFullName(), SwingConstants.CENTER ) );
|
add( Components.heading( user.getFullName(), SwingConstants.CENTER ) );
|
||||||
add( Components.strut() );
|
add( Components.strut() );
|
||||||
@ -461,6 +492,8 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
userToolbar.add( addButton );
|
userToolbar.add( addButton );
|
||||||
userToolbar.add( userButton );
|
userToolbar.add( userButton );
|
||||||
userToolbar.add( logoutButton );
|
userToolbar.add( logoutButton );
|
||||||
|
userToolbar.add( Box.createGlue() );
|
||||||
|
userToolbar.add( helpButton );
|
||||||
|
|
||||||
siteToolbar.add( settingsButton );
|
siteToolbar.add( settingsButton );
|
||||||
siteToolbar.add( questionsButton );
|
siteToolbar.add( questionsButton );
|
||||||
@ -615,8 +648,14 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
|
|
||||||
Res.ui( () -> {
|
Res.ui( () -> {
|
||||||
Window window = SwingUtilities.windowForComponent( UserContentPanel.this );
|
Window window = SwingUtilities.windowForComponent( UserContentPanel.this );
|
||||||
if (window != null)
|
if (window instanceof Frame) {
|
||||||
window.dispatchEvent( new WindowEvent( window, WindowEvent.WINDOW_CLOSING ) );
|
((Frame) window).setExtendedState( Frame.ICONIFIED );
|
||||||
|
window.dispatchEvent( new WindowEvent( window, WindowEvent.WINDOW_DEACTIVATED ) );
|
||||||
|
window.dispatchEvent( new WindowEvent( window, WindowEvent.WINDOW_ICONIFIED ) );
|
||||||
|
window.dispatchEvent( new WindowEvent( window, WindowEvent.WINDOW_LOST_FOCUS ) );
|
||||||
|
window.dispatchEvent( new WindowEvent( window, WindowEvent.WINDOW_CLOSED ) );
|
||||||
|
}
|
||||||
|
// window.dispatchEvent( new WindowEvent( window, WindowEvent.WINDOW_ICONIFIED ) );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
Loading…
Reference in New Issue
Block a user