Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [platform-swt-dev] Problem with Shell._setSize()

Jeffrey Morgan <kuzman@xxxxxxxxxxxxxxxx> writes:
> 
> I am having trouble testing my changes.  Whenever I start
> my test applications I always get in an infinite loop in
> the _setSize method of the Shell class.   The while loop
> and the values of s.x and s.y never increase.  It appears
> that the OS.gtk_window_resize method doesn't work.  Have
> you experienced the same?
>

void _setSize(int width, int height) {
	OS.gtk_signal_handler_block_by_data (shellHandle, SWT.Resize);
	OS.gtk_window_resize(shellHandle, width, height);
	boolean done = false;
	Point s = _getSize();
	while ((s.x!=width) || (s.y!=height)) {
		OS.gtk_main_iteration();
		s = _getSize();
	}
	OS.gtk_signal_handler_unblock_by_data (shellHandle, SWT.Resize);
}

This code is just wrong - a) it's a busy loop and b) it assumes the
resize will be honored and breaks if not.

As everyone probably knows, under the X Window System, there is no way
to guarantee you'll get the size you ask for. You can wish you could
have this guarantee all day; you can have an API that assumes it; but
you lose, there is no way to get this guarantee. Any app that crashes
when given a size other than what it requested is unequivocally
buggy. We have to live with this in GTK and GTK users have to live
with it too.

It may be necessary to maintain a "SWT fantasy bogus size" on the
client side. This is what _setSize() and _getSize() would manipulate.
_setSize() would then have the odd side effect of asking the X server
(via GTK) to sync with the current SWT size. You could get rid of the
busy loop at that point. This is essentially the same strategy as
EclipseFixed. Broken but without changing the SWT API guarantees you
are pretty much stuck with broken, and this is the least-broken
possibility that I see.

If you must run the main loop you want to do a blocking main loop of
some kind, instead of doing continuous iterations at 100% CPU usage.
e.g. do a g_main_loop_run()/gtk_main() and quit the loop when you get
a ConfigureEvent, or something. There's no way to distinguish the
configure event caused by your resize from other random configure
events from user action or pending event queue, though.

But however you run the main loop, you are not actually solving the
problem you want to solve; because the problem you're trying to solve
is to create a synchronous API. i.e. you're trying to make this code 
work:

 setSize (X, Y);
 p = getSize ();
 assert (p.x == X);
 assert (p.y == Y);

You handle that simple case with the main loop, but guess what -
running the main loop introduces reentrancy concerns. So you are
running code out of the guts of the setSize() call that may see the
old size, even though setSize() has been invoked. And of course the
reentrancy tends to cause bugs since no one is expecting reentrancy
during a simple setSize() call. There could be intermediate resize
events during the main loop iterations for example, all kinds of fun
stuff.

Anyway, introducing SWT-specific state variables to maintain SWT's
internal consistency may make sense.

Havoc


Back to the top