mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-142305 Changes to files are not saved on frame deactivation
This commit is contained in:
@@ -27,7 +27,7 @@ import java.util.regex.Pattern;
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class UnscrambleListener implements ApplicationActivationListener {
|
||||
public class UnscrambleListener extends ApplicationActivationListener.Adapter {
|
||||
private static final int MAX_STACKTRACE_SIZE = 100 * 1024;
|
||||
private String stacktrace = null;
|
||||
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class QuickDocOnMouseOverManager {
|
||||
|
||||
ApplicationManager.getApplication().getMessageBus().connect().subscribe(
|
||||
ApplicationActivationListener.TOPIC,
|
||||
new ApplicationActivationListener() {
|
||||
new ApplicationActivationListener.Adapter() {
|
||||
@Override
|
||||
public void applicationActivated(IdeFrame ideFrame) {
|
||||
myApplicationActive = true;
|
||||
|
||||
+13
@@ -34,11 +34,24 @@ public interface ApplicationActivationListener {
|
||||
*/
|
||||
void applicationDeactivated(IdeFrame ideFrame);
|
||||
|
||||
/**
|
||||
* This is more precise notification than {code applicationDeactivated} callback.
|
||||
* It is intended for focus subsystem and purposes where we do not want
|
||||
* to be bothered by false application deactivation events.
|
||||
*
|
||||
* The shortcoming of the method is that a notification is delivered
|
||||
* with a delay. See {code app.deactivation.timeout} key in the registry
|
||||
*/
|
||||
void delayedApplicationDeactivated(IdeFrame ideFrame);
|
||||
|
||||
abstract class Adapter implements ApplicationActivationListener {
|
||||
@Override
|
||||
public void applicationActivated(IdeFrame ideFrame) { }
|
||||
|
||||
@Override
|
||||
public void applicationDeactivated(IdeFrame ideFrame) { }
|
||||
|
||||
@Override
|
||||
public void delayedApplicationDeactivated(IdeFrame ideFrame) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class FrameStateManagerImpl extends FrameStateManager {
|
||||
myShouldSynchronize = false;
|
||||
mySyncAlarm = new Alarm();
|
||||
|
||||
app.getMessageBus().connect().subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener() {
|
||||
app.getMessageBus().connect().subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener.Adapter() {
|
||||
@Override
|
||||
public void applicationActivated(IdeFrame ideFrame) {
|
||||
myActive.onReady();
|
||||
|
||||
@@ -811,12 +811,15 @@ public class IdeEventQueue extends EventQueue {
|
||||
if (we.getID() == WindowEvent.WINDOW_ACTIVATED || we.getID() == WindowEvent.WINDOW_GAINED_FOCUS) {
|
||||
appImpl.myCancelDeactivation = true;
|
||||
if (!appImpl.isActive()) {
|
||||
appImpl.tryToApplyActivationState(true, eventWindow);
|
||||
OpenAPIAccessor.getApplicationImplAccessor().applyActivation(appImpl, eventWindow);
|
||||
}
|
||||
}
|
||||
else if (we.getID() == WindowEvent.WINDOW_DEACTIVATED) {
|
||||
requestToDeactivateTime.getAndSet(System.currentTimeMillis());
|
||||
|
||||
// For stuf that cannot wait timeout we notify about deactivation
|
||||
OpenAPIAccessor.getApplicationImplAccessor().applyDeactivation(appImpl, eventWindow);
|
||||
|
||||
// We do not know for sure that application is going to be inactive,
|
||||
// we could just be showing a popup or another transient window.
|
||||
// So let's postpone the application deactivation for a while
|
||||
@@ -824,8 +827,8 @@ public class IdeEventQueue extends EventQueue {
|
||||
|
||||
Timer timer = new Timer(Registry.intValue("app.deactivation.timeout"), new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
if (appImpl.isActive() && !appImpl.isDeactivationCanceled()) {
|
||||
appImpl.tryToApplyActivationState(false, eventWindow);
|
||||
if (appImpl.isActiveDelayed() && !appImpl.isDeactivationCanceled()) {
|
||||
OpenAPIAccessor.getApplicationImplAccessor().applyDelayedDeactivation(appImpl, eventWindow);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.ide;
|
||||
|
||||
import com.intellij.openapi.application.impl.ApplicationImpl;
|
||||
import com.intellij.util.concurrency.AtomicFieldUpdater;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Provides ability to access ApplicationImpl package-private methods
|
||||
* without reflection
|
||||
*/
|
||||
public final class OpenAPIAccessor {
|
||||
|
||||
|
||||
private OpenAPIAccessor() {}
|
||||
|
||||
private static ApplicationImplAccessor applicationImplAccessor;
|
||||
private static final Unsafe unsafe = AtomicFieldUpdater.getUnsafe();
|
||||
|
||||
public interface ApplicationImplAccessor {
|
||||
|
||||
boolean applyActivation (ApplicationImpl app, Window window);
|
||||
|
||||
boolean applyDeactivation (ApplicationImpl app, Window window);
|
||||
|
||||
boolean applyDelayedDeactivation (ApplicationImpl app, Window window);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an accessor object for the com.intellij.openapi.application.impl.ApplicationImpl class.
|
||||
*/
|
||||
public static void setApplicationImplAccessor(ApplicationImplAccessor aia) {
|
||||
applicationImplAccessor = aia;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the accessor object for the com.intellij.openapi.application.impl.ApplicationImpl class.
|
||||
*/
|
||||
public static ApplicationImplAccessor getApplicationImplAccessor() {
|
||||
if (applicationImplAccessor == null) {
|
||||
unsafe.ensureClassInitialized(ApplicationImpl.class);
|
||||
}
|
||||
|
||||
return applicationImplAccessor;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1420,7 +1420,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
|
||||
addActionListener(this);
|
||||
setRepeats(true);
|
||||
final MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect();
|
||||
connection.subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener() {
|
||||
connection.subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener.Adapter() {
|
||||
@Override
|
||||
public void applicationActivated(IdeFrame ideFrame) {
|
||||
setDelay(TIMER_DELAY);
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ import java.awt.*;
|
||||
* @author Anton Katilin
|
||||
* @author Vladimir Kondratyev
|
||||
*/
|
||||
public final class ActionPopupMenuImpl implements ActionPopupMenu, ApplicationActivationListener {
|
||||
public final class ActionPopupMenuImpl extends ApplicationActivationListener.Adapter implements ActionPopupMenu {
|
||||
|
||||
private final MyMenu myMenu;
|
||||
private final ActionManagerImpl myManager;
|
||||
|
||||
+60
-15
@@ -131,10 +131,36 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
@NonNls private static final String WAS_EVER_SHOWN = "was.ever.shown";
|
||||
|
||||
private volatile boolean myActive;
|
||||
private volatile boolean myActiveDelayed;
|
||||
public volatile boolean myCancelDeactivation;
|
||||
|
||||
private static final int IS_EDT_FLAG = 1<<30; // we don't mess with sign bit since we want to do arithmetic
|
||||
private static final int IS_READ_LOCK_ACQUIRED_FLAG = 1<<29;
|
||||
|
||||
static {
|
||||
OpenAPIAccessor.setApplicationImplAccessor(new OpenAPIAccessor.ApplicationImplAccessor() {
|
||||
|
||||
@Override
|
||||
public boolean applyActivation(ApplicationImpl app, Window window) {
|
||||
return app.applyActivation(window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyDeactivation(ApplicationImpl app, Window window) {
|
||||
return app.applyDeactivation(window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyDelayedDeactivation(ApplicationImpl app, Window window) {
|
||||
return app.applyDelayedDeactivation(window);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isActiveDelayed() {
|
||||
return myActiveDelayed;
|
||||
}
|
||||
|
||||
private static class Status {
|
||||
// higher three bits are for IS_* flags
|
||||
// lower bits are for edtSafe counter
|
||||
@@ -1177,28 +1203,47 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
return myCancelDeactivation;
|
||||
}
|
||||
|
||||
public boolean tryToApplyActivationState(boolean active, Window window) {
|
||||
final Component frame = UIUtil.findUltimateParent(window);
|
||||
boolean applyActivation (Window window) {
|
||||
if (!isActive()) {
|
||||
myActive = true;
|
||||
myActiveDelayed = true;
|
||||
IdeFrame ideFrame = getIdeFrameFromWindow(window);
|
||||
if (ideFrame != null) {
|
||||
getMessageBus().syncPublisher(ApplicationActivationListener.TOPIC).applicationActivated(ideFrame);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (frame instanceof IdeFrame) {
|
||||
final IdeFrame ideFrame = (IdeFrame)frame;
|
||||
if (isActive() != active) {
|
||||
myActive = active;
|
||||
System.setProperty("idea.active", String.valueOf(myActive));
|
||||
ApplicationActivationListener publisher = getMessageBus().syncPublisher(ApplicationActivationListener.TOPIC);
|
||||
if (active) {
|
||||
publisher.applicationActivated(ideFrame);
|
||||
}
|
||||
else {
|
||||
publisher.applicationDeactivated(ideFrame);
|
||||
}
|
||||
boolean applyDeactivation (Window window) {
|
||||
if (isActive()) {
|
||||
myActive = false;
|
||||
IdeFrame ideFrame = getIdeFrameFromWindow(window);
|
||||
if (ideFrame != null) {
|
||||
getMessageBus().syncPublisher(ApplicationActivationListener.TOPIC).applicationDeactivated(ideFrame);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean applyDelayedDeactivation (Window window) {
|
||||
if (isActiveDelayed()) {
|
||||
myActiveDelayed = false;
|
||||
IdeFrame ideFrame = getIdeFrameFromWindow(window);
|
||||
if (ideFrame != null) {
|
||||
getMessageBus().syncPublisher(ApplicationActivationListener.TOPIC).delayedApplicationDeactivated(ideFrame);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IdeFrame getIdeFrameFromWindow (Window window) {
|
||||
final Component frame = UIUtil.findUltimateParent(window);
|
||||
return (frame instanceof IdeFrame) ? (IdeFrame)frame : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
if (isUnitTestMode()) return true;
|
||||
|
||||
@@ -1068,16 +1068,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
callback.setRejected();
|
||||
}
|
||||
|
||||
private class AppListener implements ApplicationActivationListener {
|
||||
@Override
|
||||
public void applicationDeactivated(IdeFrame ideFrame) {
|
||||
final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
Component parent = UIUtil.findUltimateParent(owner);
|
||||
|
||||
if (parent == ideFrame) {
|
||||
myLastFocusedAtDeactivation.put(ideFrame, owner);
|
||||
}
|
||||
}
|
||||
private class AppListener extends ApplicationActivationListener.Adapter {
|
||||
|
||||
@Override
|
||||
public void applicationActivated(final IdeFrame ideFrame) {
|
||||
@@ -1093,6 +1084,16 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delayedApplicationDeactivated(IdeFrame ideFrame) {
|
||||
final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
Component parent = UIUtil.findUltimateParent(owner);
|
||||
|
||||
if (parent == ideFrame) {
|
||||
myLastFocusedAtDeactivation.put(ideFrame, owner);
|
||||
}
|
||||
}
|
||||
|
||||
private void focusLastFocusedComponent(IdeFrame ideFrame) {
|
||||
final KeyboardFocusManager mgr = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
if (mgr.getFocusOwner() == null) {
|
||||
|
||||
Reference in New Issue
Block a user