# HG changeset patch # User lana # Date 1332362244 25200 # Node ID 8c73ea0888627b9da60376b25ec01dc2775a972a # Parent d89e003f290b8ef3f1ce4614ff3abbcdf11aee37# Parent 6b681d75ebe51f44e474123b912fcc46b3bd8768 Merge diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/classes/sun/lwawt/LWToolkit.java --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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() { diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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; } diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java --- a/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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(); /* diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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)); + } + } diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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; } diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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); } diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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); diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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(); /************************ diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/native/sun/awt/AWTView.m --- a/jdk/src/macosx/native/sun/awt/AWTView.m Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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"); diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/native/sun/awt/AWTWindow.m --- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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; } diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/native/sun/awt/CWrapper.m --- a/jdk/src/macosx/native/sun/awt/CWrapper.m Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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 */ diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/native/sun/awt/LWCToolkit.m --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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; } diff -r d89e003f290b -r 8c73ea088862 jdk/src/macosx/native/sun/awt/OSVersion.m --- a/jdk/src/macosx/native/sun/awt/OSVersion.m Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/OSVersion.m Wed Mar 21 13:37:24 2012 -0700 @@ -31,33 +31,31 @@ #import -// 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); } diff -r d89e003f290b -r 8c73ea088862 jdk/src/share/classes/javax/swing/DefaultListSelectionModel.java --- a/jdk/src/share/classes/javax/swing/DefaultListSelectionModel.java Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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); } } diff -r d89e003f290b -r 8c73ea088862 jdk/src/windows/native/sun/windows/awt_Component.cpp --- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Wed Mar 21 13:36:03 2012 -0700 +++ b/jdk/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(); diff -r d89e003f290b -r 8c73ea088862 jdk/test/java/awt/Frame/WindowDragTest/WindowDragTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/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!"); + } + } +} diff -r d89e003f290b -r 8c73ea088862 jdk/test/javax/swing/JTable/7027139/bug7027139.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/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"); + } +}