Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8238734

[HiDPI] Hotspot of the custom cursor is in wrong position

    Details

    • Subcomponent:
    • Introduced In Version:
      9
    • CPU:
      x86_64
    • OS:
      windows_10

      Description

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10

      A DESCRIPTION OF THE PROBLEM :
      The hotspot is in the wrong position, even in the latest available JDK version15 EA Build 6.

      It is reproducible every time on a screen having scaling set to 200% (probably on all scaling levels >100%).

      Constructing the cursor sized according to Toolkit.getBestCursorSize() fixes the problem. However, the hotspot should also be set correctly when the image is smaller.

      It is quite apparent from the JDK source code
      https://github.com/openjdk/jdk/blob/6bab0f539fba8fb441697846347597b4a0ade428/src/java.desktop/share/classes/sun/awt/CustomCursor.java
      that the cursor image is scaled in certain cases (line 71), but the hotspot is not scaled accordingly.

      Fixing this should be quite trivial. Please solve this problem after being open for 4 years.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Execute the attached test program and click into the opened window.



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The rectangles drawn on click should appear at the very center of the haircross.
      ACTUAL -
      The drawn rectangles appear in the top left quadrant, off the center of the haircross.
      (Too bad not screenshots can be submitted here.)

      ---------- BEGIN SOURCE ----------
      import java.awt.*;
      import java.awt.event.MouseEvent;
      import java.awt.event.MouseListener;
      import java.awt.image.BufferedImage;

      public class CustomCursorHotspot {
          public static void main(String[] args)
          {
              Dimension bestCursorSize = Toolkit.getDefaultToolkit().getBestCursorSize(32, 32);
              assert bestCursorSize.width == bestCursorSize.height;

              final int cursorSize = 32; // this triggers the bug

              //final int cursorSize = bestCursorSize.width; // this is the workaround

              // construct framed haircross
              BufferedImage bufferedImage = new BufferedImage(cursorSize, cursorSize, BufferedImage.TYPE_INT_ARGB);
              Graphics2D bg = bufferedImage.createGraphics();
              bg.setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));
              bg.clearRect(0, 0, cursorSize, cursorSize);
              bg.setColor(Color.BLACK);
              bg.drawRect(0, 0, cursorSize - 1, cursorSize - 1);
              bg.setStroke(new BasicStroke(2));
              bg.drawLine(cursorSize / 2, 0, cursorSize / 2, cursorSize);
              bg.drawLine(0, cursorSize / 2, cursorSize, cursorSize / 2);

              Frame frame = new Frame();
              frame.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(
                      bufferedImage, new Point(cursorSize / 2, cursorSize / 2), "haircross"));
              frame.setSize(new Dimension(500, 500));
              frame.setVisible(true);

              frame.addMouseListener(new MouseListener() {
                  @Override
                  public void mouseClicked(MouseEvent e) {
                      Graphics graphics = frame.getGraphics();
                      graphics.setColor(Color.RED);
                      graphics.drawRect(e.getX() - 1, e.getY() - 1, 3, 3);
                  }

                  @Override
                  public void mousePressed(MouseEvent e) { }
                  @Override
                  public void mouseReleased(MouseEvent e) { }
                  @Override
                  public void mouseEntered(MouseEvent e) { }
                  @Override
                  public void mouseExited(MouseEvent e) { }
              });
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Provide the cursor image in a size matching Toolkit.getBestCursorSize().
      To test this, uncomment the second line setting cursorSize, and comment out the first one.

      FREQUENCY : always


        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                serb Sergey Bylokhov
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: