GP-1512 - fixed failing screenshot

This commit is contained in:
dragonmacher 2021-11-18 15:03:59 -05:00
parent 1eafc9a78a
commit e30884b229
3 changed files with 49 additions and 45 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Before After
Before After

View file

@ -15,7 +15,7 @@
*/ */
package help.screenshot; package help.screenshot;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.*;
import java.awt.*; import java.awt.*;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
@ -286,8 +286,8 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
/** /**
* The same as {@link GhidraScreenShotGenerator#captureIsolatedProvider(Class, int, int)} * The same as {@link GhidraScreenShotGenerator#captureIsolatedProvider(Class, int, int)}
* except this method will also capture the containing window. * except this method will also capture the containing window.
* *
* @param clazz the provider class * @param clazz the provider class
* @param width the width of the capture * @param width the width of the capture
* @param height the height of the capture * @param height the height of the capture
*/ */
@ -464,10 +464,10 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
} }
/** /**
* Captures the provider by using a screen shot and not by painting the provider directly * Captures the provider by using a screen shot and not by painting the provider directly
* (as does {@link #captureProvider(ComponentProvider)}). Use this method if you need to * (as does {@link #captureProvider(ComponentProvider)}). Use this method if you need to
* capture the provider along with any popup windows. * capture the provider along with any popup windows.
* *
* @param provider the provider * @param provider the provider
*/ */
public void captureProviderWithScreenShot(ComponentProvider provider) { public void captureProviderWithScreenShot(ComponentProvider provider) {
@ -487,14 +487,14 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
} }
/** /**
* Captures the window, including decorations. This will use a {@link Robot} to create a * Captures the window, including decorations. This will use a {@link Robot} to create a
* screen capture, which has the effect of getting all items within the window bounds. This * screen capture, which has the effect of getting all items within the window bounds. This
* method is needed if you wish to capture child windows, like popups/hovers. * method is needed if you wish to capture child windows, like popups/hovers.
* *
* <P>Other capture methods will not use the screen capture mechanism, but rather will * <P>Other capture methods will not use the screen capture mechanism, but rather will
* directly render the given component. In this case, subordinate windows will not be * directly render the given component. In this case, subordinate windows will not be
* captured. For example, see {@link #captureProvider(Class)}. * captured. For example, see {@link #captureProvider(Class)}.
* *
* @param name the provider's name * @param name the provider's name
*/ */
public void captureProviderWindow(String name) { public void captureProviderWindow(String name) {
@ -504,14 +504,14 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
} }
/** /**
* Captures the window, including decorations. This will use a {@link Robot} to create a * Captures the window, including decorations. This will use a {@link Robot} to create a
* screen capture, which has the effect of getting all items within the window bounds. This * screen capture, which has the effect of getting all items within the window bounds. This
* method is needed if you wish to capture child windows, like popups/hovers. * method is needed if you wish to capture child windows, like popups/hovers.
* *
* <P>Other capture methods will not use the screen capture mechanism, but rather will * <P>Other capture methods will not use the screen capture mechanism, but rather will
* directly render the given component. In this case, subordinate windows will not be * directly render the given component. In this case, subordinate windows will not be
* captured. For example, see {@link #captureProvider(Class)}. * captured. For example, see {@link #captureProvider(Class)}.
* *
* @param clazz the provider's class * @param clazz the provider's class
*/ */
public void captureProviderWindow(Class<? extends ComponentProvider> clazz) { public void captureProviderWindow(Class<? extends ComponentProvider> clazz) {
@ -520,14 +520,14 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
} }
/** /**
* Captures the window, including decorations. This will use a {@link Robot} to create a * Captures the window, including decorations. This will use a {@link Robot} to create a
* screen capture, which has the effect of getting all items within the window bounds. This * screen capture, which has the effect of getting all items within the window bounds. This
* method is needed if you wish to capture child windows, like popups/hovers. * method is needed if you wish to capture child windows, like popups/hovers.
* *
* <P>Other capture methods will not use the screen capture mechanism, but rather will * <P>Other capture methods will not use the screen capture mechanism, but rather will
* directly render the given component. In this case, subordinate windows will not be * directly render the given component. In this case, subordinate windows will not be
* captured. For example, see {@link #captureProvider(Class)}. * captured. For example, see {@link #captureProvider(Class)}.
* *
* @param provider the provider * @param provider the provider
*/ */
public void captureProviderWindow(ComponentProvider provider) { public void captureProviderWindow(ComponentProvider provider) {
@ -536,14 +536,14 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
} }
/** /**
* Captures the window, including decorations. This will use a {@link Robot} to create a * Captures the window, including decorations. This will use a {@link Robot} to create a
* screen capture, which has the effect of getting all items within the window bounds. This * screen capture, which has the effect of getting all items within the window bounds. This
* method is needed if you wish to capture child windows, like popups/hovers. * method is needed if you wish to capture child windows, like popups/hovers.
* *
* <P>Other capture methods will not use the screen capture mechanism, but rather will * <P>Other capture methods will not use the screen capture mechanism, but rather will
* directly render the given component. In this case, subordinate windows will not be * directly render the given component. In this case, subordinate windows will not be
* captured. For example, see {@link #captureProvider(Class)}. * captured. For example, see {@link #captureProvider(Class)}.
* *
* @param name the provider's name * @param name the provider's name
* @param width the desired width * @param width the desired width
* @param height the desired height * @param height the desired height
@ -557,14 +557,14 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
} }
/** /**
* Captures the window, including decorations. This will use a {@link Robot} to create a * Captures the window, including decorations. This will use a {@link Robot} to create a
* screen capture, which has the effect of getting all items within the window bounds. This * screen capture, which has the effect of getting all items within the window bounds. This
* method is needed if you wish to capture child windows, like popups/hovers. * method is needed if you wish to capture child windows, like popups/hovers.
* *
* <P>Other capture methods will not use the screen capture mechanism, but rather will * <P>Other capture methods will not use the screen capture mechanism, but rather will
* directly render the given component. In this case, subordinate windows will not be * directly render the given component. In this case, subordinate windows will not be
* captured. For example, see {@link #captureProvider(Class)}. * captured. For example, see {@link #captureProvider(Class)}.
* *
* @param provider the provider's name * @param provider the provider's name
* @param width the desired width * @param width the desired width
* @param height the desired height * @param height the desired height
@ -607,7 +607,7 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
// The image returned here must be a BufferedImage, so create one // The image returned here must be a BufferedImage, so create one
// if not. It may be a ToolkitImage (eg: if the icon in question // if not. It may be a ToolkitImage (eg: if the icon in question
// is retrieved from Icons.java), which would fail on a cast to // is retrieved from Icons.java), which would fail on a cast to
// BufferedImage during the save operation. // BufferedImage during the save operation.
image = ImageUtils.getBufferedImage(image); image = ImageUtils.getBufferedImage(image);
}); });
@ -763,7 +763,7 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
public void generateImage(Component c) { public void generateImage(Component c) {
// Note: using the screen image has the downside of capturing non-Ghidra windows when // Note: using the screen image has the downside of capturing non-Ghidra windows when
// focus is lost. Prefer the component painting itself. This will not work // focus is lost. Prefer the component painting itself. This will not work
// for native constructs like window decorations. // for native constructs like window decorations.
if (!(c instanceof Window)) { if (!(c instanceof Window)) {
@ -1275,13 +1275,16 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
} }
public void positionListingTop(final long address) { public void positionListingTop(long address) {
runSwing(() -> { boolean didGoTo = runSwing(() -> {
CodeBrowserPlugin plugin = getPlugin(tool, CodeBrowserPlugin.class); CodeBrowserPlugin plugin = getPlugin(tool, CodeBrowserPlugin.class);
FieldPanel fieldPanel = plugin.getFieldPanel(); FieldPanel fieldPanel = plugin.getFieldPanel();
plugin.goToField(addr(address), AddressFieldFactory.FIELD_NAME, 0, 0); boolean result = plugin.goToField(addr(address), AddressFieldFactory.FIELD_NAME, 0, 0);
fieldPanel.positionCursor(0); fieldPanel.positionCursor(0);
return result;
}); });
assertTrue("Go To failed for address: " + address, didGoTo);
} }
public void positionListingCenter(final long address) { public void positionListingCenter(final long address) {
@ -1386,16 +1389,16 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
* Draws a rectangle around the given component. The root parameter is used to calculate * Draws a rectangle around the given component. The root parameter is used to calculate
* screen coordinates. This allows you to capture a sub-component of a UI, drawing * screen coordinates. This allows you to capture a sub-component of a UI, drawing
* rectangles around children of said sub-component. * rectangles around children of said sub-component.
* *
* <P>If you are unsure of what to pass for <code>root</code>, the call * <P>If you are unsure of what to pass for <code>root</code>, the call
* {@link #drawRectangleAround(JComponent, Color, int)} instead. * {@link #drawRectangleAround(JComponent, Color, int)} instead.
* *
* @param component the component to be en-rectangled * @param component the component to be en-rectangled
* @param root the outermost container widget being displayed; null implies a * @param root the outermost container widget being displayed; null implies a
* top-level parent * top-level parent
* @param color the rectangle color * @param color the rectangle color
* @param padding the space between the rectangle and the component; more space makes * @param padding the space between the rectangle and the component; more space makes
* the component more visible * the component more visible
* @return the bounds of the drawn rectangle * @return the bounds of the drawn rectangle
*/ */
public Rectangle drawRectangleAround(JComponent component, JComponent root, Color color, public Rectangle drawRectangleAround(JComponent component, JComponent root, Color color,
@ -1583,9 +1586,9 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
/** /**
* Crops a part of the current image, keeping what is inside the given bounds. This method * Crops a part of the current image, keeping what is inside the given bounds. This method
* creates a shape such that the top and bottom of the cropped image have a jagged line, * creates a shape such that the top and bottom of the cropped image have a jagged line,
* looking somewhat like a sideways lightening bolt. * looking somewhat like a sideways lightening bolt.
* *
* @param bounds the bounds to keep * @param bounds the bounds to keep
* @return the snippet * @return the snippet
*/ */

View file

@ -144,15 +144,16 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator {
@Test @Test
public void testCaptureSelectionTable() { public void testCaptureSelectionTable() {
setToolSize(1100, 700); setToolSize(1100, 700);
positionListingTop(0x0406bd7); positionListingTop(0x0406bd5);
makeSelection(0x0406be1, 0x0406bf1); makeSelection(0x0406be1, 0x0406bf6);
performAction("Create Table From Selection", "CodeBrowserPlugin", true); performAction("Create Table From Selection", "CodeBrowserPlugin", true);
Window window = waitForWindowByTitleContaining("Selection Table"); Window window = waitForWindowByTitleContaining("Selection Table");
Point loc = plugin.getListingPanel().getLocationOnScreen(); Point loc = plugin.getListingPanel().getLocationOnScreen();
Dimension size = window.getSize(); Dimension size = window.getSize();
window.setBounds(loc.x + 300, loc.y + 150, size.width, 300); window.setBounds(loc.x + 300, loc.y + 150, size.width, 300);
captureProvider(CodeViewerProvider.class); CodeViewerProvider provider = getProvider(CodeViewerProvider.class);
captureProviderWithScreenShot(provider);
} }
@Test @Test