The first attached file contains the cocoa code snippets that reproduce the problem.

 -  At first we create the Main window
  - Clicking on the Main window creates the Second window
- The tracking rectangle is set for the Second window during the window creation
    (I also tried to set it in the -viewDidMoveToWindow method)
- When the second window appears under the mouse, the mouse enter event is not received. However the Second window tracks the mouse exited/entered events if we manually move the mouse over the window

The second attached file is a test that shows the problem on the Java side. It does the same and passes on the Windows and Ubuntu but fails on the Mac OS X.

 Thanks,
 Alexandr.

On 4/18/2012 8:22 PM, Leonid Romanov wrote:
Hi,
A quick question to help me better understand what is going on in your webrev.  
The common way to track mouse enter/exit events in OS X is to use NSView's 
tracking rectangle or (newer than tracking rectangle) NSTrackingArea class.  In 
our port, we set a tracking rectangle in -viewDidMoveToWindow method of AWTView 
class. So, my question is: have you investigated what is wrong with our current 
approach? That is, why it doesn't work and for what cases?

Thanks,
Leonid.

On 18.04.2012, at 19:40, Alexander Scherbatiy wrote:

Please review a fix for CR 7154048.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7154048

webrev: http://cr.openjdk.java.net/~alexsch/7154048/webrev.00/

Let's see the following test case:
- Frame contains two components JLabel and JButton
- The JLabel component has a mouse listener
   mousePressed: create a Window under the mouse click
   mouseDragged: drag the created window
   mouseReleased: close the Window
- A user clicks on the JLabel component, drags the mouse to the JButton 
component and releases the mouse button

The current JDK 8 implementation shows the following events on Mac OS X:
--------------------------------------------------------
mouse pressed: javax.swing.JLabel
mouse exited: javax.swing.JLabel
mouse entered: javax.swing.JLabel
mouse dragged: javax.swing.JLabel
mouse exited: javax.swing.JLabel
mouse entered: javax.swing.JButton
mouse dragged: javax.swing.JLabel
mouse exited: javax.swing.JButton
mouse entered: Drag Window
mouse exited: Drag Window
mouse entered: javax.swing.JButton
mouse released: javax.swing.JButton
--------------------------------------------------------

There are several issues:
1) The window does not receive the mouse entered event when it is created under 
the mouse
2) There are JLabel exited/JButton entered events during the window dragging
3) JLabel does not receive the mouse released event

The fix synthesizes the mouse entered/exited events manually if they are not 
received.

The entered/exited events synthesizing is added to setFrame, toFront, toBack, 
and zoom methods of the AWTWindow and CWrapper classes.

There is an option to add the events synthesizing to the windowDidResize 
notification. However this notification is sent when a window size is changed 
in both cases, programmatically and when user is resized the window. So in a 
lot of case there is no need for the our use case events generation.

The LWWindowPeer class is updated to not generate extra mouse enter/exit events 
during the mouse dragging.

Tho automated tests are added.

Thanks,
Alexandr.

    // Create Main Window

    NSRect rect = NSMakeRect (100, 100, 300, 300);
    unsigned int styleMask = NSTitledWindowMask | NSClosableWindowMask;    
    
    NSWindow *win = [NSWindow alloc];
    win = [win initWithContentRect: rect 
                         styleMask: styleMask 
                           backing: NSBackingStoreBuffered 
                             defer: NO];
    
    MainView *view  = [[MainView alloc] initWithFrame:rect];

    [view addTrackingRect:[view visibleRect]
                    owner:view
                 userData:NULL
             assumeInside:NO];
        
    [win setContentView: view];
    [win setTitle: @"Main Window"];    
    [win makeKeyAndOrderFront: nil];

=========================================

// Main View creates the second window after clicking on it

@interface MainView : NSView
{
    NSWindow *win;
}
@end

#import "MainView.h"
#import "SecondView.h"

@implementation MainView

- (void)mouseDown:(NSEvent *)theEvent {
    
    NSLog(@"[main win] mouse down");

    NSRect rect = NSMakeRect (200, 200, 100, 100);
    unsigned int styleMask = NSTitledWindowMask | NSClosableWindowMask;    
    
    win = [NSWindow alloc];
    win = [win initWithContentRect: rect 
                         styleMask: styleMask 
                           backing: NSBackingStoreBuffered 
                             defer: NO];
    
    SecondView *view  = [[SecondView alloc] initWithFrame:rect];
    
    [view addTrackingRect:[view visibleRect]
                    owner:view
                 userData:NULL
             assumeInside:NO];
    
    [win setContentView: view];    
    [win setTitle: @"Second Window"];    
    [win makeKeyAndOrderFront: nil];
    
}
@end

===================================

// Second View handles the mouse entered/exited events

@interface SecondView : NSView

@end

#import "SecondView.h"

@implementation SecondView

- (void)mouseEntered:(NSEvent *)theEvent{
    NSLog(@"[second win] mouse entered");
    
}

- (void)mouseExited:(NSEvent *)theEvent{
    NSLog(@"[second win] mouse exited");    
}

@end

package toolbar.test;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import sun.awt.SunToolkit;

public class MouseEnterTest {

    private static volatile int mouseEnteredCount = 0;
    private static JFrame frame;

    public static void main(String[] args) throws Exception {
        Robot robot = new Robot();
        robot.setAutoDelay(50);
        robot.mouseMove(100, 100);

        SwingUtilities.invokeAndWait(new Runnable() {

            @Override
            public void run() {
                frame = new JFrame("Main Frame");
                frame.setSize(300, 200);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                frame.addMouseListener(new MouseAdapter() {

                    @Override
                    public void mouseEntered(MouseEvent e) {
                        mouseEnteredCount++;
                    }
                });

                frame.setVisible(true);
            }
        });


        ((SunToolkit) Toolkit.getDefaultToolkit()).realSync();

        if (mouseEnteredCount != 1) {
            throw new RuntimeException("No Mouse Entered event!");
        }
        System.out.println("PASSED!");
    }
}

Reply via email to