//package com.oracle.java.javafx;

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.beans.binding.StringExpression; 
import javafx.beans.value.ChangeListener; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Alert; 
import javafx.scene.control.Alert.AlertType; 
import javafx.scene.control.Label; 
import javafx.scene.control.Menu; 
import javafx.scene.control.MenuBar; 
import javafx.scene.control.MenuItem; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Pane; 
import javafx.stage.Stage; 
import javafx.stage.Window; 
import javafx.stage.WindowEvent; 

/** 
 * This small programme demonstrates an issue with closing a dialog using the 
 * native "x" on Red Hat 6 OS. The issue does not occur on Windows 7. 
 * 
 * Once a dialog is opened (using the "Open Dialog (Broken)" menuitem), click 
 * outside the dialog but within the primary stage area and then click the "x" 
 * icon. Focus should be returned to the primary stage. On Red Hat this does not 
 * happen, on Windows it does. 
 * 
 * Once in this state, the menubar is no longer usable (you will see that the 
 * content of the primary stage shows "Has focus? false" at this point). The 
 * only way to regain focus is to move the application window around or switch 
 * focus to another application and then back again. In my runtime scenario 
 * neither of these is possible as the application runs full screen and the user 
 * can't switch to any other applications. 
 * 
 * The "Open Dialog (Workaround)" menuitem shows a workaround that I am using in 
 * order to filter the WINDOW_CLOSE_REQUEST if the dialog does not currently 
 * have focus, and reissue this event once focus is gained. 
 * 
 */ 
public class JI_9044811 extends Application { 

public static void main(final String[] args) { 
launch(args); 
} 

@Override 
public void start(final Stage primaryStage) { 
try { 
final BorderPane root = new BorderPane(); 
root.setTop(createMenu(primaryStage)); 
root.setCenter(createContent(primaryStage)); 
primaryStage.setScene(new Scene(root, 400, 300)); 
primaryStage.show(); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 

private Pane createContent(final Stage primaryStage) { 
final HBox pane = new HBox(); 
pane.setPadding(new Insets(15, 12, 15, 12)); 
pane.setSpacing(10); 
pane.getChildren().add(new Label("Has focus?")); 
final Label focusLabel = new Label(); 
focusLabel.textProperty().bind(StringExpression.stringExpression(primaryStage.focusedProperty())); 
pane.getChildren().add(focusLabel); 
return pane; 
} 

private MenuBar createMenu(final Stage primaryStage) { 
final Menu menu = new Menu("Dialog Menu"); 
final MenuItem menuItem = new MenuItem("Open Dialog (Broken)"); 
menuItem.setOnAction(ae -> { 
final Alert alert = createAlert(primaryStage); 
alert.showAndWait(); 
}); 
menu.getItems().add(menuItem); 

final MenuItem workaroundMenuItem = new MenuItem("Open Dialog (Workaround)"); 
workaroundMenuItem.setOnAction(ae -> { 
final Alert alert = createAlert(primaryStage); 
// This method contains the workaround code 
applyWorkaround(alert.getDialogPane().getScene().getWindow()); 
alert.showAndWait(); 
}); 
menu.getItems().add(workaroundMenuItem); 

return new MenuBar(menu); 
} 

private Alert createAlert(final Stage stage) { 
final Alert alert = new Alert(AlertType.CONFIRMATION, "some content"); 
alert.initOwner(stage); 
return alert; 
} 

/** 
* On Red Hat OS, If the dialog window is not currently focused when closing 
* the window via a native window close event (WINDOW_CLOSE_REQUEST) then 
* the main stage will no longer be focused correctly upon closing the 
* dialog. This doesn't occur when running on Windows. 
* 
* In order to work around this, if the dialog does not have focus upon the 
* WINDOW_CLOSE_REQUEST, then request focus and add a listener to fire the 
* WINDOW_CLOSE_REQUEST event upon receiving the focus again. Finally, 
* consume the original WINDOW_CLOSE_REQUEST so that the Dialog is not 
* closed without focus. 
*/ 
public void applyWorkaround(final Window window) { 
if (window == null) { 
return; 
} 

window.addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST, event -> { 
if (event.getSource() instanceof Window) { 
final Window source = (Window) event.getSource(); 
if (!source.isFocused()) { 
Platform.runLater(() -> { 
source.focusedProperty() 
.addListener((ChangeListener<Boolean>) (observable, oldValue, newValue) -> { 
if (newValue) { 
source.fireEvent(new WindowEvent(source, WindowEvent.WINDOW_CLOSE_REQUEST)); 
} 
}); 
source.requestFocus(); 
}); 
event.consume(); 
} 
} 
}); 
} 
} 

