Project: SWT
Bug 81399 Pixel Corruption caused by Tracker on a Composite with children
Reported: 2004-12-16 09:37:20 | Status: resolved fixed

(Platform: WinXP-SP2, SWT 3.0.1 (swt-win32-3063.dll)) The following Snippet uses a Tracker(SWT.RESIZE) for rubber-band selections of the Composite's children. The selection occurs in terms of changing the background color of the children. If yo select some of the chilren with the tracker, and then downsize the tracker so that they are again deselected, the pixel coruption occurs. (The tracker leaves trace-marks on the children). On the Snippet below, children[i].redraw in void changeSelections(Rectangle) has no effect and does not redraw the whole area of the child. Possible work-around: Changing the above mentioned line to : children[i].redraw(0, 0, children[i].getBounds().width, children[i].getBounds().height, true); fixes the problem. Yet, I think that the Tracker does not show the expected behaviour in the first place... /* ******** TrackerSnippet.java ********* */ import org.eclipse.swt.widgets.*; import org.eclipse.swt.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; public class TrackerSnippet { private boolean isDragging = false; private Shell shell; public static void main(String[] args) { TrackerSnippet trackerSnippet = new TrackerSnippet(); } public TrackerSnippet() { Display display = new Display(); shell = new Shell(display, SWT.SHELL_TRIM); shell.setText("TrackerSnippet"); shell.setBounds(50, 50, 500, 300); RowLayout rl = new RowLayout(SWT.HORIZONTAL); rl.pack = true; rl.wrap = true; shell.setLayout(rl); for (int i=0; i<10; i++) createChild(shell); shell.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { isDragging = true; } public void mouseUp(MouseEvent e) { isDragging = false; } }); shell.addMouseMoveListener(new MouseMoveListener() { public void mouseMove(MouseEvent e) { if (isDragging) trackIt(e.x, e.y); } }); shell.layout(true); shell.open(); while(!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } private void createChild(Composite parent) { final Composite child = new Composite(parent, SWT.NONE); child.setLayout(new FillLayout()); final Canvas iconCanvas = new Canvas(child, SWT.NO_FOCUS | SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND | SWT.NO_MERGE_PAINTS); final Image icon = parent.getDisplay().getSystemImage(SWT.ICON_WARNING); iconCanvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Rectangle canvasSize = iconCanvas.getBounds(); Image offscreen = new Image(iconCanvas.getDisplay(), canvasSize.width, canvasSize.height); GC gc = new GC(offscreen); gc.setBackground(iconCanvas.getParent().getBackground()); gc.fillRectangle(0, 0, canvasSize.width, canvasSize.height); gc.drawImage(icon, (int)(canvasSize.width - icon.getBounds().width)/2, (int)(canvasSize.height - icon.getBounds().height)/2); e.gc.drawImage(offscreen, 0, 0); gc.dispose(); offscreen.dispose(); } }); // make the composite 20 pixels larger than the icon image RowData data = new RowData(icon.getBounds().width + 20, icon.getBounds().height + 20); child.setLayoutData(data); setSelected(child, false); } private void setSelected(Control child, boolean selected) { Color c = (selected)? child.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION): child.getParent().getBackground(); child.setBackground(c); if (child.getClass().equals(Composite.class)) { // change the background of the children (generally, the canvas) Control[] controls = ((Composite)child).getChildren(); for (int i=0; i<controls.length; i++) controls[i].setBackground(c); } } private void trackIt(int x, int y) { Tracker tracker = new Tracker(shell, SWT.RESIZE); tracker.setRectangles (new Rectangle [] {new Rectangle (x, y, 1, 1)}); tracker.setStippled(false); tracker.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { changeSelections(((Tracker)e.getSource()).getRectangles()[0]); } }); tracker.open (); changeSelections(tracker.getRectangles()[0]); tracker.dispose(); isDragging = false; } private void changeSelections(Rectangle selection) { Control[] children = shell.getChildren(); for (int i=0; i<children.length; i++) { if (selection.intersects(children[i].getBounds()) || children[i].getBounds().contains(selection.x, selection.y)) { setSelected(children[i], true); } else { setSelected(children[i], false); } // children[i].redraw(0, 0, // WORK-AROUND // children[i].getBounds().width, // children[i].getBounds().height, true); children[i].redraw(); //HAS NO EFFECT } } } /* ******** EOF TrackerSnippet.java ***** */

Files changed in fix:
bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Tracker.java bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tracker.java bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tracker.java