Summary: | DND feedback and a drag event with image cause repaint issues on Windows | ||
---|---|---|---|
Product: | [Tools] GEF | Reporter: | Peter Severin <peter> |
Component: | GEF-Legacy GEF (MVC) | Assignee: | gef-inbox <gef-inbox> |
Status: | NEW --- | QA Contact: | |
Severity: | normal | ||
Priority: | P3 | CC: | nyssen |
Version: | 3.8 | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | Windows All | ||
Whiteboard: | |||
Bug Depends on: | 393868 | ||
Bug Blocks: | |||
Attachments: |
Description
Peter Severin
2012-11-04 23:34:16 EST
Created attachment 223156 [details]
Pure SWT test case
The test case shows the differences between calling and not calling Control#update method in drag over event.
Created attachment 223157 [details]
Screenshot of repaint bug with logic example
Created attachment 223158 [details]
Screenshot of repaint bug with SWT test case
After looking more into it I could find a workaround for GEF. I am convinced that the underlying problem is an SWT bug but meantime here's how to fix it. The main fix is to disable the call to Control#update() in NativeGraphicsSource#getGraphics(e) during drag & drop. I am not sure this call is needed at all. The way I did it is by copying NativeGraphicsSource and adding a flag "dndInProgress" and conditioning the call to Control#update() using this flag: public Graphics getGraphics(Rectangle r) { canvas.redraw(r.x, r.y, r.width, r.height, false); if (!dndInProgress) canvas.update(); return null; } Next I replaced the original graphics source by extending ScrollingGraphicalViewer and by hacking hookControl method like this: protected void hookControl() { super.hookControl(); Control c = getControl(); if ((c.getStyle() & SWT.DOUBLE_BUFFERED) != 0) { graphicsSource = new WindowsGraphicsSource(c); UpdateManager updateManager = getLightweightSystem() .getUpdateManager(); updateManager.setGraphicsSource(graphicsSource); } } In hookDropTarget I added an drop listener that positions the dndInProgress flag like this: protected void hookDropTarget() { super.hookDropTarget(); getDropTarget().addDropListener(new DropTargetAdapter() { @Override public void dragEnter(DropTargetEvent event) { if (graphicsSource != null) graphicsSource.setDndInProgress(true); } @Override public void dragOperationChanged(DropTargetEvent event) { flush(); } @Override public void dragLeave(DropTargetEvent event) { if (graphicsSource != null) graphicsSource.setDndInProgress(false); } }); } There is also a call to flush() method in dragOperationChanged method. Without this call there is still a redraw artifact although less visible than before. This might be another SWT issue. The call to flush() should have been actually done in GraphicalViewerImpl#hookDropTarget. I hope this workaround will be helpful for others and also for fixing this issue. Peter, can you please file an SWT related bugzilla (containing your pure SWT test case), so the SWT team gets notified about the issue (and we can create a dependency on it)? Alexander, I created Bug 393868 with a better analysis since I now have a better understanding of the problem. Added dependency to underlying SWT bug #393868 |