Skip to content
Permalink
Browse files
8213535: Windows HiDPI html lightweight tooltips are truncated
Backport-of: a1b5e01
  • Loading branch information
Ekaterina Vergizova authored and Yuri Nesterenko committed Nov 26, 2020
1 parent e9fdf00 commit 170d1a615daa0a939ea54b68fd281b09b3476eda
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2020, 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
@@ -25,19 +25,30 @@

package javax.swing;

import sun.awt.EmbeddedFrame;
import sun.awt.OSInfo;
import sun.swing.SwingAccessor;

import java.applet.Applet;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import sun.awt.EmbeddedFrame;
import sun.awt.OSInfo;
import sun.swing.SwingAccessor;

import static javax.swing.ClientPropertyKey.PopupFactory_FORCE_HEAVYWEIGHT_POPUP;

/**
@@ -826,13 +837,12 @@ public void show() {
} else {
parent.add(component);
}
pack();
component.setVisible(true);
}

Component createComponent(Component owner) {
JComponent component = new JPanel(new BorderLayout(), true);

component.setOpaque(true);
return component;
return new JPanel(new BorderLayout(), true);
}

//
@@ -847,11 +857,10 @@ void reset(Component owner, Component contents, int ownerX,
super.reset(owner, contents, ownerX, ownerY);

JComponent component = (JComponent)getComponent();

component.setOpaque(contents.isOpaque());
component.setVisible(false);
component.setLocation(ownerX, ownerY);
component.setOpaque(contents.isOpaque());
component.add(contents, BorderLayout.CENTER);
contents.invalidate();
pack();
}
}
@@ -960,27 +969,22 @@ public void show() {
(parent!=null)) {
parent = parent.getParent();
}
// Set the visibility to false before adding to workaround a
// bug in Solaris in which the Popup gets added at the wrong
// location, which will result in a mouseExit, which will then
// result in the ToolTip being removed.

if (parent instanceof RootPaneContainer) {
parent = ((RootPaneContainer)parent).getLayeredPane();
Point p = SwingUtilities.convertScreenLocationToParent(parent,
x, y);
component.setVisible(false);
component.setLocation(p.x, p.y);
parent.add(component, JLayeredPane.POPUP_LAYER,
0);
} else {
Point p = SwingUtilities.convertScreenLocationToParent(parent,
x, y);
parent = ((RootPaneContainer) parent).getLayeredPane();
}

component.setLocation(p.x, p.y);
component.setVisible(false);
Point p = SwingUtilities.convertScreenLocationToParent(parent,
x, y);
component.setLocation(p.x, p.y);
if (parent instanceof JLayeredPane) {
parent.add(component, JLayeredPane.POPUP_LAYER, 0);
} else {
parent.add(component);
}
pack();
component.setVisible(true);
component.revalidate();
}

Component createComponent(Component owner) {
@@ -1004,11 +1008,9 @@ void reset(Component owner, Component contents, int ownerX,
super.reset(owner, contents, ownerX, ownerY);

Component component = getComponent();

component.setVisible(false);
component.setLocation(ownerX, ownerY);
rootPane.getContentPane().add(contents, BorderLayout.CENTER);
contents.invalidate();
component.validate();
pack();
}

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, 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
@@ -21,7 +21,6 @@
* questions.
*/

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
@@ -33,6 +32,7 @@
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
@@ -48,25 +48,30 @@
import javax.swing.JTextField;
import javax.swing.JToolTip;
import javax.swing.JTree;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SpinnerListModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.tree.DefaultMutableTreeNode;

import sun.swing.MenuItemLayoutHelper;

import static javax.swing.UIManager.getInstalledLookAndFeels;

/**
* @test
* @key headful
* @bug 8201552 8213843
* @bug 8201552 8213843 8213535
* @summary Initial layout of the component should use correct graphics config.
* It is checked by SwingUtilities.updateComponentTreeUI(), if layout
* was correct the call to updateComponentTreeUI() will be no-op.
* @modules java.desktop/sun.swing
* @compile -encoding utf-8 StalePreferredSize.java
* @run main/othervm/timeout=200 StalePreferredSize
* @run main/othervm/timeout=200 -Dsun.java2d.uiScale=1 StalePreferredSize
* @run main/othervm/timeout=200 -Dsun.java2d.uiScale=2.25 StalePreferredSize
* @run main/othervm/timeout=400 StalePreferredSize
* @run main/othervm/timeout=400 -Dsun.java2d.uiScale=1 StalePreferredSize
* @run main/othervm/timeout=400 -Dsun.java2d.uiScale=2.25 StalePreferredSize
*/
public final class StalePreferredSize {

@@ -82,20 +87,26 @@
"Съешь ещё этих мягких французских булок да выпей же чаю"};

static JFrame frame;
static Component component;
static Popup popup;
static JComponent component;
static int typeFont = 0; // 0 - default, 1 - bold, 2 - italic
static boolean addViaPopup;

public static void main(final String[] args) throws Exception {
for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) {
EventQueue.invokeAndWait(() -> setLookAndFeel(laf));
for (typeFont = 0; typeFont < 3; typeFont++) {
System.err.println("typeFont = " + typeFont);
for (final boolean html : new boolean[]{true, false}) {
for (String text : TEXT) {
if (html) {
text = "<html>" + text + "</html>";
for (boolean usePopup : new boolean[]{true, false}) {
addViaPopup = usePopup;
System.err.println("Use popup: " + usePopup);
for (final boolean html : new boolean[]{true, false}) {
for (String text : TEXT) {
if (html) {
text = "<html>" + text + "</html>";
}
test(text);
}
test(text);
}
}
}
@@ -105,7 +116,7 @@ public static void main(final String[] args) throws Exception {
private static void test(String text) throws Exception {
System.err.println("text = " + text);
// Each Callable create a component to be tested
final List<Callable<Component>> comps = List.of(
final List<Callable<JComponent>> comps = List.of(
() -> new JLabel(text),
() -> new JButton(text),
() -> new JMenuItem(text),
@@ -136,12 +147,12 @@ private static void test(String text) throws Exception {
}
);

for (final Callable<Component> creator : comps) {
for (final Callable<JComponent> creator : comps) {
checkComponent(creator);
}
}

static void checkComponent(Callable<Component> creator) throws Exception {
static void checkComponent(Callable<JComponent> creator) throws Exception {
EventQueue.invokeAndWait(() -> {

try {
@@ -150,6 +161,7 @@ static void checkComponent(Callable<Component> creator) throws Exception {
throw new RuntimeException(e);
}

component.setEnabled(false); // minimize paint/focus events amount
Font font = component.getFont();
if (typeFont == 1) {
component.setFont(new Font(font.deriveFont(Font.BOLD).getAttributes()));
@@ -159,14 +171,35 @@ static void checkComponent(Callable<Component> creator) throws Exception {
}

frame = new JFrame();
// incorrect initial insets may ruin our size calculation
frame.setUndecorated(true); // TODO JDK-8244388
frame.setLayout(new FlowLayout());
frame.add(new JScrollPane(component));
frame.setSize(300, 100);
frame.setSize(700, 400);
frame.setLocationRelativeTo(null);
if (addViaPopup) {
// doing our best to show lightweight or mediumweight popup
int x = frame.getX() + 50;
int y = frame.getY() + 200;
PopupFactory factory = PopupFactory.getSharedInstance();
popup = factory.getPopup(frame, component, x, y);
if (component instanceof JMenuItem) {
// TODO JDK-8244400
MenuItemLayoutHelper.clearUsedParentClientProperties((JMenuItem)component);
}
} else {
frame.add(new JScrollPane(component));
}
frame.setVisible(true);
if (popup != null) {
popup.show();
}
});

EventQueue.invokeAndWait(() -> {
if (!component.isValid()) {
dispose();
throw new RuntimeException("Component must be valid");
}

// After the frame was shown we change nothing, so current layout
// should be optimal and updateComponentTreeUI() should be no-op
@@ -179,7 +212,7 @@ static void checkComponent(Callable<Component> creator) throws Exception {
component.setFont(component.getFont().deriveFont(35f));
Dimension last = component.getPreferredSize();

frame.dispose();
dispose();

if (!Objects.equals(before, after)) {
System.err.println("Component: " + component);
@@ -197,6 +230,14 @@ static void checkComponent(Callable<Component> creator) throws Exception {
});
}

private static void dispose() {
if (popup != null) {
popup.hide();
popup = null;
}
frame.dispose();
}

private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) {
try {
UIManager.setLookAndFeel(laf.getClassName());
@@ -1,6 +1,6 @@
/*
* Copyright 2012 Red Hat, Inc. All Rights Reserved.
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, 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
@@ -131,6 +131,7 @@ public static void createAndShowUI() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar(menuBar);
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);

PopupListener listener = new PopupListener();
menu.getPopupMenu().addPropertyChangeListener(listener);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, 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
@@ -114,6 +114,7 @@ private static void createAndShowGUI() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);

button = new JButton("Press me");
button.setToolTipText("test");
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, 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
@@ -49,6 +49,7 @@ public NonOpaquePopupMenuTest() {
fileMenu.getPopupMenu().setOpaque(false);

setSize(new Dimension(640, 480));
setLocationRelativeTo(null);
setVisible(true);
}

1 comment on commit 170d1a6

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on 170d1a6 Nov 26, 2020

Please sign in to comment.