mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-102449 Mac OS + JDK 1.7: dialog sheets go to background if focus is moved from IDEA and then back [Filechooser part added and refactoring]
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ui.mac;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.ui.mac.foundation.Foundation;
|
||||
import com.intellij.ui.mac.foundation.ID;
|
||||
import com.sun.jna.Callback;
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static com.intellij.ui.mac.foundation.Foundation.invoke;
|
||||
|
||||
/**
|
||||
* @author Denis Fokin
|
||||
*/
|
||||
public class JDK7WindowReorderingWorkaround {
|
||||
|
||||
private static AtomicInteger requestorCount = new AtomicInteger();
|
||||
|
||||
private static final Callback windowDidBecomeMainCallback = new Callback() {
|
||||
@SuppressWarnings("UnusedDeclaration") // this is a native up-call
|
||||
public void callback(ID self,
|
||||
ID nsNotification)
|
||||
{
|
||||
if (requestorCount.intValue() == 0) {
|
||||
invoke(self, "oldWindowDidBecomeMain:", nsNotification);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static {
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
|
||||
ID awtWindow = Foundation.getObjcClass("AWTWindow");
|
||||
|
||||
Pointer windowWillEnterFullScreenMethod = Foundation.createSelector("windowDidBecomeMain:");
|
||||
ID originalWindowWillEnterFullScreen = Foundation.class_replaceMethod(awtWindow, windowWillEnterFullScreenMethod,
|
||||
windowDidBecomeMainCallback, "v@::@");
|
||||
|
||||
Foundation.addMethodByID(awtWindow, Foundation.createSelector("oldWindowDidBecomeMain:"),
|
||||
originalWindowWillEnterFullScreen, "v@::@");
|
||||
}
|
||||
}
|
||||
|
||||
static void disableReordering() {
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
|
||||
requestorCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
static void enableReordering () {
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
|
||||
requestorCount.decrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -137,6 +137,7 @@ public class MacFileChooserDialogImpl implements PathChooserDialog {
|
||||
finally {
|
||||
Foundation.cfRelease(self);
|
||||
Foundation.cfRelease(contextInfo);
|
||||
JDK7WindowReorderingWorkaround.enableReordering();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -323,6 +324,7 @@ public class MacFileChooserDialogImpl implements PathChooserDialog {
|
||||
ourImplMap.put(delegate, impl);
|
||||
|
||||
final ID select = toSelect == null ? null : Foundation.nsString(toSelect);
|
||||
JDK7WindowReorderingWorkaround.disableReordering();
|
||||
invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", Foundation.createSelector("showOpenPanel:"), select, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -72,6 +71,7 @@ public class MacMessagesImpl extends MacMessages {
|
||||
resultsFromDocumentRoot.put(documentRoot, new MessageResult(returnCode.intValue(), suppressState.intValue() == 1));
|
||||
queuesFromDocumentRoot.get(windowFromId.get(contextInfo.longValue())).runFromQueue();
|
||||
}
|
||||
JDK7WindowReorderingWorkaround.enableReordering();
|
||||
cfRelease(self);
|
||||
}
|
||||
};
|
||||
@@ -203,6 +203,7 @@ public class MacMessagesImpl extends MacMessages {
|
||||
private MacMessagesImpl() {}
|
||||
|
||||
private static final Callback windowDidBecomeMainCallback = new Callback() {
|
||||
@SuppressWarnings("UnusedDeclaration") // this is a native up-call
|
||||
public void callback(ID self,
|
||||
ID nsNotification)
|
||||
{
|
||||
@@ -357,6 +358,7 @@ public class MacMessagesImpl extends MacMessages {
|
||||
private static void startModal(final Window w, ID windowId) {
|
||||
long windowPtr = windowId.longValue();
|
||||
synchronized (lock) {
|
||||
JDK7WindowReorderingWorkaround.disableReordering();
|
||||
windowFromId.put(windowPtr, w);
|
||||
if (blockedDocumentRoots.keySet().contains(w)) {
|
||||
blockedDocumentRoots.put(w, blockedDocumentRoots.get(w) + 1);
|
||||
@@ -566,7 +568,7 @@ public class MacMessagesImpl extends MacMessages {
|
||||
|
||||
final Window documentRoot = getDocumentRootFromWindow(foremostWindow);
|
||||
|
||||
final ID nativeFocusedWindow = windowIdFromWindow(foremostWindow);
|
||||
final ID nativeFocusedWindow = MacUtil.findWindowFromJavaWindow(foremostWindow);
|
||||
|
||||
paramsWrapper.setNativeWindow(nativeFocusedWindow);
|
||||
|
||||
@@ -591,54 +593,10 @@ public class MacMessagesImpl extends MacMessages {
|
||||
return documentRoot;
|
||||
}
|
||||
|
||||
private static ID windowIdFromWindow (Window w) {
|
||||
|
||||
ID windowId = null;
|
||||
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7") && Registry.is("skip.untitled.windows.for.mac.messages")) {
|
||||
try {
|
||||
Class <?> cWindowPeerClass = w.getPeer().getClass();
|
||||
Method getPlatformWindowMethod = cWindowPeerClass.getDeclaredMethod("getPlatformWindow");
|
||||
Object cPlatformWindow = getPlatformWindowMethod.invoke(w.getPeer());
|
||||
Class <?> cPlatformWindowClass = cPlatformWindow.getClass();
|
||||
Method getNSWindowPtrMethod = cPlatformWindowClass.getDeclaredMethod("getNSWindowPtr");
|
||||
windowId = new ID((Long)getNSWindowPtrMethod.invoke(cPlatformWindow));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
|
||||
} else {
|
||||
String foremostWindowTitle = getWindowTitle(w);
|
||||
windowId = MacUtil.findWindowForTitle(foremostWindowTitle);
|
||||
}
|
||||
|
||||
return windowId;
|
||||
|
||||
}
|
||||
|
||||
private static int convertReturnCodeFromNativeMessageDialog(int result) {
|
||||
return result - 1000;
|
||||
}
|
||||
|
||||
private static String getWindowTitle(Window documentRoot) {
|
||||
String windowTitle;
|
||||
if (documentRoot instanceof Frame) {
|
||||
windowTitle = ((Frame)documentRoot).getTitle();
|
||||
} else if (documentRoot instanceof Dialog) {
|
||||
windowTitle = ((Dialog)documentRoot).getTitle();
|
||||
} else {
|
||||
throw new RuntimeException("The window is not a frame and not a dialog!");
|
||||
}
|
||||
return windowTitle;
|
||||
}
|
||||
|
||||
@Messages.YesNoCancelResult
|
||||
private static int convertReturnCodeFromNativeAlertDialog(int returnCode, String alternateText) {
|
||||
// DEFAULT = 1
|
||||
@@ -744,8 +702,8 @@ public class MacMessagesImpl extends MacMessages {
|
||||
}
|
||||
|
||||
//Actually can, but not in this implementation. If you know a reasonable scenario, please ask Denis Fokin for the improvement.
|
||||
LOG.assertTrue(getWindowTitle(_window) != null, "A window without a title should not be used for showing MacMessages");
|
||||
while (_window != null && getWindowTitle(_window) == null) {
|
||||
LOG.assertTrue(MacUtil.getWindowTitle(_window) != null, "A window without a title should not be used for showing MacMessages");
|
||||
while (_window != null && MacUtil.getWindowTitle(_window) == null) {
|
||||
_window = _window.getOwner();
|
||||
//At least our frame should have a title
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
package com.intellij.ui.mac.foundation;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -27,6 +29,8 @@ import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.AWTEventListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static com.intellij.ui.mac.foundation.Foundation.invoke;
|
||||
import static com.intellij.ui.mac.foundation.Foundation.toStringViaUTF8;
|
||||
@@ -35,6 +39,7 @@ import static com.intellij.ui.mac.foundation.Foundation.toStringViaUTF8;
|
||||
* @author pegov
|
||||
*/
|
||||
public class MacUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.mac.foundation.MacUtil");
|
||||
public static final String MAC_NATIVE_WINDOW_SHOWING = "MAC_NATIVE_WINDOW_SHOWING";
|
||||
|
||||
private MacUtil() {
|
||||
@@ -72,7 +77,7 @@ public class MacUtil {
|
||||
|
||||
return focusedWindow;
|
||||
}
|
||||
|
||||
|
||||
public static synchronized void startModal(JComponent component, String key) {
|
||||
try {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
@@ -91,7 +96,7 @@ public class MacUtil {
|
||||
((MenuComponent)source).dispatchEvent(event);
|
||||
}
|
||||
else {
|
||||
System.err.println("Unable to dispatch: " + event);
|
||||
LOG.debug("Unable to dispatch: " + event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,4 +142,47 @@ public class MacUtil {
|
||||
});
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.KEY_EVENT_MASK);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static ID findWindowFromJavaWindow(final Window w) {
|
||||
ID windowId = null;
|
||||
if (SystemInfo.isJavaVersionAtLeast("1.7") && Registry.is("skip.untitled.windows.for.mac.messages")) {
|
||||
try {
|
||||
//noinspection deprecation
|
||||
Class <?> cWindowPeerClass = w.getPeer().getClass();
|
||||
Method getPlatformWindowMethod = cWindowPeerClass.getDeclaredMethod("getPlatformWindow");
|
||||
Object cPlatformWindow = getPlatformWindowMethod.invoke(w.getPeer());
|
||||
Class <?> cPlatformWindowClass = cPlatformWindow.getClass();
|
||||
Method getNSWindowPtrMethod = cPlatformWindowClass.getDeclaredMethod("getNSWindowPtr");
|
||||
windowId = new ID((Long)getNSWindowPtrMethod.invoke(cPlatformWindow));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
LOG.debug(e);
|
||||
}
|
||||
|
||||
} else {
|
||||
String foremostWindowTitle = getWindowTitle(w);
|
||||
windowId = findWindowForTitle(foremostWindowTitle);
|
||||
}
|
||||
return windowId;
|
||||
}
|
||||
|
||||
|
||||
public static String getWindowTitle(Window documentRoot) {
|
||||
String windowTitle;
|
||||
if (documentRoot instanceof Frame) {
|
||||
windowTitle = ((Frame)documentRoot).getTitle();
|
||||
} else if (documentRoot instanceof Dialog) {
|
||||
windowTitle = ((Dialog)documentRoot).getTitle();
|
||||
} else {
|
||||
throw new RuntimeException("The window is not a frame and not a dialog!");
|
||||
}
|
||||
return windowTitle;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user