changeset 5237:e7cc6c5a858c

Merge
author lana
date Wed, 21 Mar 2012 13:37:24 -0700
parents 8fcaac9ef213 9189ec1bb33a
children 1238b2679374
files
diffstat 17 files changed, 325 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/LWToolkit.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/LWToolkit.java	Wed Mar 21 13:37:24 2012 -0700
@@ -522,11 +522,6 @@
         postEvent(targetToAppContext(event.getSource()), event);
     }
 
-    /*
-     * Returns true if the application (one of its windows) owns keyboard focus.
-     */
-    public abstract boolean isApplicationActive();
-
     // use peer's back buffer to implement non-opaque windows.
     @Override
     public boolean needUpdateWindow() {
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Wed Mar 21 13:37:24 2012 -0700
@@ -1067,11 +1067,7 @@
             return false;
         }
 
-        // Cross-app activation requests are not allowed.
-        if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
-            !((LWToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
-        {
-            focusLog.fine("the app is inactive, so the request is rejected");
+        if (platformWindow.rejectFocusRequest(cause)) {
             return false;
         }
 
--- a/src/macosx/classes/sun/lwawt/PlatformWindow.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/PlatformWindow.java	Wed Mar 21 13:37:24 2012 -0700
@@ -27,6 +27,7 @@
 
 import java.awt.*;
 
+import sun.awt.CausedFocusEvent;
 import sun.java2d.SurfaceData;
 
 // TODO Is it worth to generify this interface, like that:
@@ -117,6 +118,8 @@
 
     public void updateFocusableWindowState();
 
+    public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);
+
     public boolean requestWindowFocus();
 
     /*
--- a/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java	Wed Mar 21 13:37:24 2012 -0700
@@ -38,6 +38,8 @@
 public class CEmbeddedFrame extends EmbeddedFrame {
 
     private CPlatformResponder responder;
+    private boolean focused = true;
+    private boolean parentWindowActive = true;
 
     public CEmbeddedFrame() {
         show();
@@ -94,4 +96,31 @@
     public void handleInputEvent(String text) {
         new RuntimeException("Not implemented");
     }
+
+    public void handleFocusEvent(boolean focused) {
+        this.focused = focused;
+        updateOverlayWindowActiveState();
+    }
+
+    public void handleWindowFocusEvent(boolean parentWindowActive) {
+        this.parentWindowActive = parentWindowActive;
+        updateOverlayWindowActiveState();
+    }
+
+    public boolean isParentWindowActive() {
+        return parentWindowActive;
+    }
+
+    /*
+     * May change appearance of contents of window, and generate a
+     * WINDOW_ACTIVATED event.
+     */
+    private void updateOverlayWindowActiveState() {
+        final boolean showAsFocused = parentWindowActive && focused;
+        dispatchEvent(
+            new FocusEvent(this, showAsFocused ?
+                                 FocusEvent.FOCUS_GAINED :
+                                 FocusEvent.FOCUS_LOST));
+     }
+
 }
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java	Wed Mar 21 13:37:24 2012 -0700
@@ -33,17 +33,23 @@
 
 import sun.awt.CGraphicsConfig;
 import sun.awt.CGraphicsDevice;
+import sun.awt.CausedFocusEvent;
 
 import java.awt.*;
 import java.awt.BufferCapabilities.FlipContents;
 
+import sun.util.logging.PlatformLogger;
+
 /*
  * Provides a lightweight implementation of the EmbeddedFrame.
  */
 public class CPlatformEmbeddedFrame implements PlatformWindow {
 
+    private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformEmbeddedFrame");
+
     private CGLLayer windowLayer;
     private LWWindowPeer peer;
+    private CEmbeddedFrame target;
 
     private volatile int screenX = 0;
     private volatile int screenY = 0;
@@ -52,6 +58,7 @@
     public void initialize(Window target, final LWWindowPeer peer, PlatformWindow owner) {
         this.peer = peer;
         this.windowLayer = new CGLLayer(peer);
+        this.target = (CEmbeddedFrame)target;
     }
 
     @Override
@@ -149,6 +156,18 @@
     public void updateFocusableWindowState() {}
 
     @Override
+    public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+        // Cross-app activation requests are not allowed.
+        if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
+            !target.isParentWindowActive())
+        {
+            focusLogger.fine("the embedder is inactive, so the request is rejected");
+            return true;
+        }
+        return false;
+    }
+
+    @Override
     public boolean requestWindowFocus() {
         return true;
     }
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Mar 21 13:37:24 2012 -0700
@@ -65,6 +65,7 @@
 
     // Loger to report issues happened during execution but that do not affect functionality
     private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
+    private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformWindow");
 
     // for client properties
     public static final String WINDOW_BRUSH_METAL_LOOK = "apple.awt.brushMetalLook";
@@ -112,6 +113,7 @@
     static final int MINIMIZABLE = 1 << 8;
 
     static final int RESIZABLE = 1 << 9; // both a style bit and prop bit
+    static final int NONACTIVATING = 1 << 24;
 
     static final int _STYLE_PROP_BITMASK = DECORATED | TEXTURED | UNIFIED | UTILITY | HUD | SHEET | CLOSEABLE | MINIMIZABLE | RESIZABLE;
 
@@ -127,9 +129,6 @@
 
     static final int _METHOD_PROP_BITMASK = RESIZABLE | HAS_SHADOW | ZOOMABLE | ALWAYS_ON_TOP | HIDES_ON_DEACTIVATE | DRAGGABLE_BACKGROUND | DOCUMENT_MODIFIED | FULLSCREENABLE;
 
-    // not sure
-    static final int POPUP = 1 << 14;
-
     // corresponds to callback-based properties
     static final int SHOULD_BECOME_KEY = 1 << 12;
     static final int SHOULD_BECOME_MAIN = 1 << 13;
@@ -264,10 +263,6 @@
         // defaults style bits
         int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE;
 
-        if (target.getName() == "###overrideRedirect###") {
-            styleBits = SET(styleBits, POPUP, true);
-        }
-
         if (isNativelyFocusableWindow()) {
             styleBits = SET(styleBits, SHOULD_BECOME_KEY, true);
             styleBits = SET(styleBits, SHOULD_BECOME_MAIN, true);
@@ -275,6 +270,7 @@
 
         final boolean isFrame = (target instanceof Frame);
         final boolean isDialog = (target instanceof Dialog);
+        final boolean isPopup = (target.getType() == Window.Type.POPUP);
         if (isDialog) {
             styleBits = SET(styleBits, MINIMIZABLE, false);
         }
@@ -304,8 +300,10 @@
         }
 
         // If the target is a dialog, popup or tooltip we want it to ignore the brushed metal look.
-        if (!isDialog && IS(styleBits, POPUP)) {
+        if (isPopup) {
             styleBits = SET(styleBits, TEXTURED, true);
+            // Popups in applets don't activate applet's process
+            styleBits = SET(styleBits, NONACTIVATING, true);
         }
 
         if (target instanceof javax.swing.RootPaneContainer) {
@@ -498,11 +496,18 @@
             // If it ain't blocked, or is being hidden, go regular way
             if (visible) {
                 CWrapper.NSWindow.makeFirstResponder(nsWindowPtr, contentView.getAWTView());
+
+                boolean isPopup = (target.getType() == Window.Type.POPUP);
+                if (isPopup) {
+                    // Popups in applets don't activate applet's process
+                    CWrapper.NSWindow.orderFrontRegardless(nsWindowPtr);
+                } else {
+                    CWrapper.NSWindow.orderFront(nsWindowPtr);
+                }
+
                 boolean isKeyWindow = CWrapper.NSWindow.isKeyWindow(nsWindowPtr);
                 if (!isKeyWindow) {
-                    CWrapper.NSWindow.makeKeyAndOrderFront(nsWindowPtr);
-                } else {
-                    CWrapper.NSWindow.orderFront(nsWindowPtr);
+                    CWrapper.NSWindow.makeKeyWindow(nsWindowPtr);
                 }
             } else {
                 CWrapper.NSWindow.orderOut(nsWindowPtr);
@@ -600,7 +605,20 @@
     }
 
     @Override
+    public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+        // Cross-app activation requests are not allowed.
+        if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
+            !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
+        {
+            focusLogger.fine("the app is inactive, so the request is rejected");
+            return true;
+        }
+        return false;
+    }
+
+    @Override
     public boolean requestWindowFocus() {
+
         long ptr = getNSWindowPtr();
         if (CWrapper.NSWindow.canBecomeMainWindow(ptr)) {
             CWrapper.NSWindow.makeMainWindow(ptr);
@@ -751,6 +769,11 @@
      * Callbacks from the AWTWindow and AWTView objc classes.
      *************************************************************/
     private void deliverWindowFocusEvent(boolean gained){
+        // Fix for 7150349: ingore "gained" notifications when the app is inactive.
+        if (gained && !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()) {
+            focusLogger.fine("the app is inactive, so the notification is ignored");
+            return;
+        }
         peer.notifyActivation(gained);
     }
 
--- a/src/macosx/classes/sun/lwawt/macosx/CWrapper.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CWrapper.java	Wed Mar 21 13:37:24 2012 -0700
@@ -47,6 +47,7 @@
         public static native void setLevel(long window, int level);
 
         public static native void makeKeyAndOrderFront(long window);
+        public static native void makeKeyWindow(long window);
         public static native void makeMainWindow(long window);
         public static native boolean canBecomeMainWindow(long window);
         public static native boolean isKeyWindow(long window);
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Wed Mar 21 13:37:24 2012 -0700
@@ -686,7 +686,10 @@
         return sunAwtDisableCALayers.booleanValue();
     }
 
-    @Override
+
+    /*
+     * Returns true if the application (one of its windows) owns keyboard focus.
+     */
     public native boolean isApplicationActive();
 
     /************************
--- a/src/macosx/native/sun/awt/AWTView.m	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/native/sun/awt/AWTView.m	Wed Mar 21 13:37:24 2012 -0700
@@ -812,7 +812,7 @@
     // Unicode value.
     NSUInteger utf8Length = [aString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
 
-    if ([self hasMarkedText] || !fProcessingKeystroke || (utf8Length > 2)) {
+    if ([self hasMarkedText] || !fProcessingKeystroke || (utf8Length > 1)) {
         JNIEnv *env = [ThreadUtilities getJNIEnv];
 
         static JNF_MEMBER_CACHE(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V");
--- a/src/macosx/native/sun/awt/AWTWindow.m	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/native/sun/awt/AWTWindow.m	Wed Mar 21 13:37:24 2012 -0700
@@ -102,11 +102,12 @@
         type |= NSBorderlessWindowMask;
     }
 
-    if (IS(styleBits, TEXTURED))    type |= NSTexturedBackgroundWindowMask;
-    if (IS(styleBits, UNIFIED))     type |= NSUnifiedTitleAndToolbarWindowMask;
-    if (IS(styleBits, UTILITY))     type |= NSUtilityWindowMask;
-    if (IS(styleBits, HUD))         type |= NSHUDWindowMask;
-    if (IS(styleBits, SHEET))       type |= NSDocModalWindowMask;
+    if (IS(styleBits, TEXTURED))      type |= NSTexturedBackgroundWindowMask;
+    if (IS(styleBits, UNIFIED))       type |= NSUnifiedTitleAndToolbarWindowMask;
+    if (IS(styleBits, UTILITY))       type |= NSUtilityWindowMask;
+    if (IS(styleBits, HUD))           type |= NSHUDWindowMask;
+    if (IS(styleBits, SHEET))         type |= NSDocModalWindowMask;
+    if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;
 
     return type;
 }
--- a/src/macosx/native/sun/awt/CWrapper.m	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/native/sun/awt/CWrapper.m	Wed Mar 21 13:37:24 2012 -0700
@@ -76,6 +76,26 @@
 
 /*
  * Class:     sun_lwawt_macosx_CWrapper$NSWindow
+ * Method:    makeKeyWindow
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_lwawt_macosx_CWrapper_00024NSWindow_makeKeyWindow
+(JNIEnv *env, jclass cls, jlong windowPtr)
+{
+JNF_COCOA_ENTER(env);
+
+    NSWindow *window = (NSWindow *)jlong_to_ptr(windowPtr);
+    [JNFRunLoop performOnMainThread:@selector(makeKeyWindow)
+                                 on:window
+                         withObject:nil
+                      waitUntilDone:NO];
+
+JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class:     sun_lwawt_macosx_CWrapper$NSWindow
  * Method:    makeMainWindow
  * Signature: (J)V
  */
--- a/src/macosx/native/sun/awt/LWCToolkit.m	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/native/sun/awt/LWCToolkit.m	Wed Mar 21 13:37:24 2012 -0700
@@ -401,18 +401,21 @@
 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isApplicationActive
 (JNIEnv *env, jclass clazz)
 {
-        __block jboolean active = JNI_FALSE;
+    __block jboolean active = JNI_FALSE;
 
-AWT_ASSERT_NOT_APPKIT_THREAD;
 JNF_COCOA_ENTER(env);
 
+    if ([NSThread isMainThread]) {
+        active = (jboolean)[NSRunningApplication currentApplication].active;
+    } else {
         [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^() {
-                active = (jboolean)[NSRunningApplication currentApplication].active;
+            active = (jboolean)[NSRunningApplication currentApplication].active;
         }];
+    }
 
 JNF_COCOA_EXIT(env);
 
-        return active;
+    return active;
 }
 
 
--- a/src/macosx/native/sun/awt/OSVersion.m	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/macosx/native/sun/awt/OSVersion.m	Wed Mar 21 13:37:24 2012 -0700
@@ -31,33 +31,31 @@
 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
 
 
-// returns 10.7 for Lion, 10.6 for SnowLeopard etc.
-double getOSXMajorVersion() {
-    char *version = JRSCopyOSVersion();
-
-    if (version == NULL) return 0.0;
-
-    char temp[32];
-    strlcpy(temp, version, sizeof(temp));
-    free(version);
-
-    if (strlen(temp) < 3) {
-        return 0.0;
+// returns 107 for Lion, 106 for SnowLeopard etc.
+int getOSXMajorVersion() {
+    char *ver = JRSCopyOSVersion();
+    if (ver == NULL) { 
+        return 0;
     }
 
-    if (temp[2] != '.')  { // Third char must be a '.'
-        return 0.0;
+    int len = strlen(ver);
+    int v = 0;
+    
+    // Third char must be a '.'    
+    if (len >= 3 && ver[2] == '.') {
+        int i;
+        
+        v = (ver[0] - '0') * 10 + (ver[1] - '0');
+        for (i = 3; i < len && isdigit(ver[i]); ++i) {
+            v = v * 10 + (ver[i] - '0');
+        }
     }
 
-    char *ptr = strchr(temp+3, '.'); // remove the second . if one exists.
-    if (ptr != NULL) {
-        *ptr = 0;
-    }
-
-    return atof(temp);
+    free(ver);
+    
+    return v;
 }
 
-
 BOOL isSnowLeopardOrLower() {
-    return (getOSXMajorVersion() < 10.7);
+    return (getOSXMajorVersion() < 107);
 }
--- a/src/share/classes/javax/swing/DefaultListSelectionModel.java	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/share/classes/javax/swing/DefaultListSelectionModel.java	Wed Mar 21 13:37:24 2012 -0700
@@ -252,6 +252,10 @@
 
     // Updates first and last change indices
     private void markAsDirty(int r) {
+        if (r == -1) {
+            return;
+        }
+
         firstAdjustedIndex = Math.min(firstAdjustedIndex, r);
         lastAdjustedIndex =  Math.max(lastAdjustedIndex, r);
     }
@@ -358,16 +362,12 @@
     private void updateLeadAnchorIndices(int anchorIndex, int leadIndex) {
         if (leadAnchorNotificationEnabled) {
             if (this.anchorIndex != anchorIndex) {
-                if (this.anchorIndex != -1) { // The unassigned state.
-                    markAsDirty(this.anchorIndex);
-                }
+                markAsDirty(this.anchorIndex);
                 markAsDirty(anchorIndex);
             }
 
             if (this.leadIndex != leadIndex) {
-                if (this.leadIndex != -1) { // The unassigned state.
-                    markAsDirty(this.leadIndex);
-                }
+                markAsDirty(this.leadIndex);
                 markAsDirty(leadIndex);
             }
         }
--- a/src/windows/native/sun/windows/awt_Component.cpp	Wed Mar 21 13:36:03 2012 -0700
+++ b/src/windows/native/sun/windows/awt_Component.cpp	Wed Mar 21 13:37:24 2012 -0700
@@ -302,6 +302,7 @@
         delete m_childList;
 
     DestroyDropTarget();
+    ReleaseDragCapture(0);
 
     if (m_myControlID != 0) {
         AwtComponent* parent = GetParent();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/Frame/WindowDragTest/WindowDragTest.java	Wed Mar 21 13:37:24 2012 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+  @test
+  @bug 7128738
+  @summary dragged dialog freezes system on dispose
+  @author Oleg Pekhovskiy: area=awt.toplevel
+  @library ../../regtesthelpers
+  @run main WindowDragTest
+*/
+
+import java.awt.Frame;
+import java.awt.event.InputEvent;
+import java.awt.AWTException;
+import test.java.awt.regtesthelpers.Util;
+import java.awt.Robot;
+import java.awt.Point;
+import java.awt.Dimension;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class WindowDragTest {
+
+    static boolean passed = false;
+
+    public static void main(String[] args) {
+        try {
+            Robot robot = new Robot();
+            robot.setAutoDelay(1000);
+
+            Frame frame1 = new Frame();
+            frame1.setBounds(50, 50, 300, 200);
+            frame1.setVisible(true);
+            frame1.toFront();
+            frame1.addMouseListener(new MouseAdapter() {
+                @Override
+                public void mouseClicked(MouseEvent e) {
+                    // Clicking frame1 succeeded - mouse is not captured
+                    passed = true;
+                }
+            });
+            robot.delay(1000);
+
+            Frame frame2 = new Frame();
+            frame2.setBounds(100, 100, 300, 200);
+            frame2.setVisible(true);
+            frame2.toFront();
+            robot.delay(1000);
+
+            Point p = frame2.getLocationOnScreen();
+            Dimension d = frame2.getSize();
+
+            // Move cursor to frame2 title bar to drag
+            robot.mouseMove(p.x + (int)(d.getWidth() / 2), p.y + (int)frame2.getInsets().top / 2);
+            Util.waitForIdle(robot);
+
+            // Start window dragging
+            robot.mousePress(InputEvent.BUTTON1_MASK);
+            Util.waitForIdle(robot);
+
+            // Dispose window being dragged
+            frame2.dispose();
+            Util.waitForIdle(robot);
+
+            // Release mouse button to be able to get MOUSE_CLICKED event on Util.clickOnComp()
+            robot.mouseRelease(InputEvent.BUTTON1_MASK);
+            Util.waitForIdle(robot);
+
+            // Click frame1 to check whether mouse is not captured by frame2
+            Util.clickOnComp(frame1, robot);
+            Util.waitForIdle(robot);
+
+            frame1.dispose();
+            if (passed) {
+                System.out.println("Test passed.");
+            }
+            else {
+                System.out.println("Test failed.");
+                throw new RuntimeException("Test failed.");
+            }
+        }
+        catch (AWTException e) {
+            throw new RuntimeException("AWTException occurred - problem creating robot!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/JTable/7027139/bug7027139.java	Wed Mar 21 13:37:24 2012 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 7027139
+   @summary getFirstIndex() does not return the first index that has changed
+   @author Pavel Porvatov
+*/
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+public class bug7027139 {
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                JTable orderTable = new JTable(new String[][]{
+                        {"Item 1 1", "Item 1 2"},
+                        {"Item 2 1", "Item 2 2"},
+                        {"Item 3 1", "Item 3 2"},
+                        {"Item 4 1", "Item 4 2"},
+                },
+                        new String[]{"Col 1", "Col 2"});
+
+                ListSelectionModel selectionModel = orderTable.getSelectionModel();
+                selectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+                selectionModel.addListSelectionListener(new ListSelectionListener() {
+                    public void valueChanged(ListSelectionEvent e) {
+                        if (e.getValueIsAdjusting()) {
+                            return;
+                        }
+
+                        if (e.getFirstIndex() < 0) {
+                            throw new RuntimeException("Test bug7027139 failed");
+                        }
+                    }
+                });
+
+                orderTable.selectAll();
+            }
+        });
+
+        System.out.println("Test bug7027139 passed");
+    }
+}