Skip to content

[Win32] Possible ERROR_GRAPHIC_DISPOSED error during painting #924

@tmssngr

Description

@tmssngr

Describe the bug
A couple of users reported following exception

org.eclipse.swt.SWTException: Graphic is disposed
	at org.eclipse.swt.SWT.error(SWT.java:4918)
	at org.eclipse.swt.SWT.error(SWT.java:4833)
	at org.eclipse.swt.SWT.error(SWT.java:4804)
	at org.eclipse.swt.graphics.GC.fillRectangleInPixels(GC.java:3003)
	at org.eclipse.swt.graphics.GC.fillRectangle(GC.java:2999)
	at smartgit.MH.a(SourceFile:347)
	at smartgit.ML.handleEvent(SourceFile:629)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4257)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1066)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1090)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1075)
	at org.eclipse.swt.widgets.Composite.WM_PAINT(Composite.java:1536)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4803)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:5043)
	at org.eclipse.swt.internal.win32.OS.DispatchMessage(Native Method)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3649)
...

It looks like Composite.WM_PAINT creates an Event with a gc with handle == 0. This can happen in this part of the Composite.WM_PAINT code:

				long [] phdc = new long [1];
				int flags = OS.BPBF_COMPATIBLEBITMAP;
				RECT prcTarget = new RECT ();
				OS.SetRect (prcTarget, ps.left, ps.top, ps.right, ps.bottom);
				long hBufferedPaint = OS.BeginBufferedPaint (hDC, prcTarget, flags, null, phdc);
				GCData data = new GCData ();
				data.device = display;
				data.foreground = getForegroundPixel ();
				Control control = findBackgroundControl ();
				if (control == null) control = this;
				data.background = control.getBackgroundPixel ();
				data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
				data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
				if ((style & SWT.NO_BACKGROUND) != 0) {
					/* This code is intentionally commented because it may be slow to copy bits from the screen */
					//paintGC.copyArea (image, ps.left, ps.top);
				} else {
					RECT rect = new RECT ();
					OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
					drawBackground (phdc [0], rect);
				}
				GC gc = GC.win32_new (phdc [0], data);
				Event event = new Event ();
				event.gc = gc;
				event.setBoundsInPixels(new Rectangle(ps.left, ps.top, width, height));
				sendEvent (SWT.Paint, event);

According to https://learn.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-beginbufferedpaint the call OS.BeginBufferedPaint might fail, return a hBufferedPaint == 0 and setting/keeping phdc[0] == 0. This case is not covered here.

To Reproduce
Unfortunately, not possible.

Expected behavior
Check the phdc [0] == 0 in Composite.WM_PAINT (and maybe silently accept it).

Environment:

  1. Select the platform(s) on which the behavior is seen:
    • All OS
    • Windows
    • Linux
    • macOS
  1. Additional OS info (e.g. OS version, Linux Desktop, etc)
    Windows 10

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions