Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,12 @@ void onDragSash(Event event) {
((SashFormData)data2).weight = (((long)b2.height << 16) + area.height - 1) / area.height;
}
if (correction || (event.doit && event.detail != SWT.DRAG)) {
boolean isWin32 = "win32".equals(SWT.getPlatform());
if (isWin32) setLayoutDeferred(true);
c1.setBounds(b1);
sash.setBounds(event.x, event.y, event.width, event.height);
c2.setBounds(b2);
if (isWin32) setLayoutDeferred(false);
}
}
/**
Expand Down
42 changes: 41 additions & 1 deletion bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_custom.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,47 @@ JNIEXPORT jlong JNICALL OS_NATIVE(DPI_1AWARENESS_1CONTEXT_1UNAWARE_1GDISCALED)
#else
rc = 0;
#endif
OS_NATIVE_EXIT(env, that, DPI_1AWARENESS_1CONTEXT_1UNAWARE_1GDISCALED_FUNC);

#ifndef NO_DeferWindowPos__J_3J_3I_3I_3I_3I_3I
JNIEXPORT jlong JNICALL OS_NATIVE(DeferWindowPos__J_3J_3I_3I_3I_3I_3I)
(JNIEnv *env, jclass that, jlong arg0, jlongArray arg1, jintArray arg2, jintArray arg3, jintArray arg4, jintArray arg5, jintArray arg6)
{
jlong *lparg1=NULL;
jint *lparg2=NULL;
jint *lparg3=NULL;
jint *lparg4=NULL;
jint *lparg5=NULL;
jint *lparg6=NULL;
jsize len = 0;
jlong rc = 0;
int i;

OS_NATIVE_ENTER(env, that, DeferWindowPos__J_3J_3I_3I_3I_3I_3I_FUNC);

if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail;
if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail;
if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail;
if (arg6) if ((lparg6 = (*env)->GetIntArrayElements(env, arg6, NULL)) == NULL) goto fail;

len = (*env)->GetArrayLength(env, arg1);
rc = arg0;

for (i = 0; i < len; i++) {
if (rc == 0) break;
rc = (jlong)DeferWindowPos((HDWP)rc, (HWND)lparg1[i], (HWND)0, lparg2[i], lparg3[i], lparg4[i], lparg5[i], lparg6[i]);
}

fail:
if (arg6 && lparg6) (*env)->ReleaseIntArrayElements(env, arg6, lparg6, 0);
if (arg5 && lparg5) (*env)->ReleaseIntArrayElements(env, arg5, lparg5, 0);
if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0);
if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0);
if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0);

OS_NATIVE_EXIT(env, that, DeferWindowPos__J_3J_3I_3I_3I_3I_3I_FUNC);
return rc;
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2532,6 +2532,8 @@ public static int HRESULT_FROM_WIN32(int x) {
* @param hWndInsertAfter cast=(HWND)
*/
public static final native long DeferWindowPos (long hWinPosInfo, long hWnd, long hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
/** @method flags=no_gen */
public static final native long DeferWindowPos (long hWinPosInfo, long[] hWnd, int[] X, int[] Y, int[] cx, int[] cy, int[] uFlags);
/**
* @param hWnd cast=(HWND)
* @param wParam cast=(WPARAM)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -977,13 +977,35 @@ boolean resizeChildren (boolean defer, WINDOWPOS [] pwp) {
if (defer) {
hdwp = OS.BeginDeferWindowPos (pwp.length);
if (hdwp == 0) return false;
}
for (WINDOWPOS wp : pwp) {
if (wp != null) {
if (defer) {
hdwp = OS.DeferWindowPos (hdwp, wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
if (hdwp == 0) return false;
} else {
int count = 0;
for (WINDOWPOS wp : pwp) {
if (wp != null) count++;
}
if (count > 0) {
long [] hwnds = new long [count];
int [] xs = new int [count];
int [] ys = new int [count];
int [] cxs = new int [count];
int [] cys = new int [count];
int [] flags = new int [count];
int index = 0;
for (WINDOWPOS wp : pwp) {
if (wp != null) {
hwnds [index] = wp.hwnd;
xs [index] = wp.x;
ys [index] = wp.y;
cxs [index] = wp.cx;
cys [index] = wp.cy;
flags [index] = wp.flags;
index++;
}
}
hdwp = OS.DeferWindowPos (hdwp, hwnds, xs, ys, cxs, cys, flags);
if (hdwp == 0) return false;
}
} else {
for (WINDOWPOS wp : pwp) {
if (wp != null) {
OS.SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (c) 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.tests.junit;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class Test_CompositeDeferredLayout {

public Shell shell;
public Composite composite;

@BeforeEach
public void setUp() {
shell = new Shell();
composite = new Composite(shell, SWT.NONE);
}

@Test
public void test_deferredLayout_movesChildren() {
int numChildren = 5;
Button[] buttons = new Button[numChildren];
for (int i = 0; i < numChildren; i++) {
buttons[i] = new Button(composite, SWT.PUSH);
buttons[i].setBounds(0, 0, 10, 10);
}

composite.setLayoutDeferred(true);

for (int i = 0; i < numChildren; i++) {
buttons[i].setBounds(10 * i, 10 * i, 20, 20);
}

composite.setLayoutDeferred(false);

for (int i = 0; i < numChildren; i++) {
Rectangle bounds = buttons[i].getBounds();
assertEquals(new Rectangle(10 * i, 10 * i, 20, 20), bounds, "Button " + i + " bounds incorrect after deferred layout");
}
}

@Test
public void test_resizeChildren_batching() {
// This test indirectly targets the batching optimization in Composite.resizeChildren
// by verifying that a large number of children are moved correctly.
int numChildren = 100;
Button[] buttons = new Button[numChildren];
for (int i = 0; i < numChildren; i++) {
buttons[i] = new Button(composite, SWT.PUSH);
buttons[i].setBounds(0, 0, 10, 10);
}

composite.setLayoutDeferred(true);

for (int i = 0; i < numChildren; i++) {
buttons[i].setBounds(i, i, 15, 15);
}

// This call triggers resizeChildren with the deferred logic
composite.setLayoutDeferred(false);

for (int i = 0; i < numChildren; i++) {
Rectangle bounds = buttons[i].getBounds();
assertEquals(new Rectangle(i, i, 15, 15), bounds, "Button " + i + " bounds incorrect after large batch deferred layout");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright (c) 2024 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.tests.junit;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Shell;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class Test_org_eclipse_swt_custom_SashForm {

public Shell shell;
public SashForm sashForm;

@BeforeEach
public void setUp() {
shell = new Shell();
sashForm = new SashForm(shell, SWT.HORIZONTAL);
shell.setSize(400, 400);
}

@Test
public void test_initialLayout() {
Button b1 = new Button(sashForm, SWT.PUSH);
Button b2 = new Button(sashForm, SWT.PUSH);
sashForm.setWeights(new int[] {50, 50});

shell.open(); // Trigger layout

Rectangle bounds1 = b1.getBounds();
Rectangle bounds2 = b2.getBounds();

assertTrue(bounds1.width > 0, "Button 1 width should be > 0");
assertTrue(bounds2.width > 0, "Button 2 width should be > 0");
assertEquals(bounds1.width, bounds2.width, 5, "Buttons should have approximately equal width"); // Allow small tolerance
}

@Test
public void test_layoutDeferredDuringResize() {
// This test verifies that we can set layout deferred on SashForm
// (simulating what happens internally on Windows during drag)
// and that the layout updates correctly afterwards.
Button b1 = new Button(sashForm, SWT.PUSH);
Button b2 = new Button(sashForm, SWT.PUSH);
sashForm.setWeights(new int[] {50, 50});
shell.open();

Rectangle initialBounds1 = b1.getBounds();

sashForm.setLayoutDeferred(true);
sashForm.setSize(600, 400); // Resize the sash form
sashForm.setLayoutDeferred(false); // Should trigger layout update

Rectangle newBounds1 = b1.getBounds();
assertTrue(newBounds1.width > initialBounds1.width, "Button 1 should have grown after SashForm resize");
}
}