[I7, Glk] press key after opening graphics window [SOLVED]

Include Basic Screen Effects by Emily Short.
Include Glulx Entry Points by Emily Short.

[A lot of this code below is swiped from Emily Short's Simple Graphical Window, which had many more features than I needed but is otherwise a great extension.]

Glulx input handling rule for a hyperlink-event:
	clear only the main screen;
	reveal the full illustration of Figure 2;
	wait for any key;
	remove the illustration;
	try looking.

To reveal the full illustration of (F - a figure-name):
	(- 
		if (gg_illustration_window == 0) {
			gg_illustration_window = glk_window_open(gg_mainwin, (winmethod_Above+winmethod_Proportional), 100, wintype_Graphics, GG_ILLUSTRATION_ROCK );
		}
		if (gg_illustration_window) { ! testing to see if the window exists
			BlackBackground();
			DisplayPicture(ResourceIDsOfFigures-->{F});
		}
	-).

Include (-
[ BlackBackground color result graph_width graph_height;
	if (gg_illustration_window) {  
		result = glk_window_get_size(gg_illustration_window, gg_arguments, gg_arguments+WORDSIZE);
			graph_width  = gg_arguments-->0;
			graph_height = gg_arguments-->1; 
		glk_window_fill_rect(gg_illustration_window, 0, 0, 0, graph_width, graph_height);
	}
];
-).

Include (-	
[ DisplayPicture  cur_pic result graph_width graph_height img_width img_height h_total w_total h_offset w_offset;
	if (gg_illustration_window) {  

		result = glk_window_get_size(gg_illustration_window, gg_arguments, gg_arguments+WORDSIZE);
			graph_width  = gg_arguments-->0;
			graph_height = gg_arguments-->1;

		result = glk_image_get_info( cur_pic, gg_arguments,  gg_arguments+WORDSIZE);
			img_width  = gg_arguments-->0;
			img_height = gg_arguments-->1;

		w_total = img_width;
		h_total = img_height;

		if (graph_height - h_total < 0) {	! if the image won't fit, find the scaling factor
			w_total = (graph_height * w_total)/h_total;
			h_total = graph_height;
		}

		if (graph_width - w_total < 0) {
			h_total = (graph_width * h_total)/w_total;
			w_total = graph_width;
		}

		w_offset = (graph_width - w_total)/2; if (w_offset < 0) w_offset = 0;
		h_offset = (graph_height - h_total)/2; if (h_offset < 0) h_offset = 0;

		glk_image_draw_scaled(gg_illustration_window, cur_pic, w_offset, h_offset, w_total, h_total); 
	}
];
-).

To remove the illustration:
	(- if (gg_illustration_window) { glk_window_close(gg_illustration_window); } -).

What should be happening is: when the player clicks a hyperlink, a graphical window opens, covering the main window entirely, and a picture is displayed within it. Then, when the player presses any key, the graphical window closes, revealing the main window once more. (And a look action is trigged, so the player isn’t left with a totally blank screen).

The first half of this (the hyperlink, opening the window, displaying the picture) works fine. But the second half (pressing any key to close it again) does not. The game won’t respond to any key press – the picture stays up, the window stays open. What’s going wrong?

Thanks for any help.

I’d guess that you’re requesting a keypress on only the main window, and whichever terp your using won’t pass them to the main window if the graphics window is completely covering it. If you request a keypress event on the graphics window that should be enough. (I don’t think that Basic Screen Effects checks which window it is.)

Ok, wow. I added a line to request a character event after the window is opened, like so:

To reveal the full illustration of (F - a figure-name): (- if (gg_illustration_window == 0) { gg_illustration_window = glk_window_open(gg_mainwin, (winmethod_Above+winmethod_Proportional), 100, wintype_Graphics, GG_ILLUSTRATION_ROCK ); } if (gg_illustration_window) { ! testing to see if the window exists BlackBackground(); DisplayPicture(ResourceIDsOfFigures-->{F}); glk_request_char_event(gg_illustration_window); } -).

The result is that immediately upon startup, the screen clears and will not allow player input until you’ve hit about 3 keys, at which point it finally starts printing a command line and accepting input. This happens as soon as play begins, which is pretty impressive considering there’s no way any of the above code could have run yet.

Haha, the ways of Glulx and Glk are mysterious. Sorry I’m not in a position to test it currently.

But I only just noticed that you’re clearing the main window before showing the illustration. Popover windows like this are really only useful if you’re trying to keep the main window intact. If you’re going to clear it you might as well just close it, reopen it as a graphics window, and then close and reopen it as a text window when you’re ready for that. That should simplify the events etc too.

It’s been a long time since I’ve done anything with this stuff, but starting a new event loop from within event-handling code can be dangerous. Does zarf’s new Unified Input extension make chained inputs of this sort easier?

Also, unless the Glk spec has changed*, requesting char input in a graphics window is illegal.

  • I think there was some talk of changing that, so it may well have happened.

I’ve made a note in the spec but nothing’s implemented it yet.

You’d have to look at the guts of Entry Points to see whether the code above is safe. UGI is definitely not built for re-entrant event input; you’d want to structure the code differently. (Two different input-handling rules and a state variable.)

Oh, I forgot that you couldn’t request char input in graphics windows. In that case my open the main window as a graphics window suggestion won’t work.

I’m even more convinced that we need an event loop even more flexible than UGI now :stuck_out_tongue:

You can close gg_mainwin? I didn’t think that was allowed.

But that would also close the status line, wouldn’t it? I want to keep that intact.

Yeah you can close gg_mainwin. Glk creates pair windows when you split windows, so that status line would remain open even when you close the main window. (It’s different in Flexible Windows though, as it has its own representation of window hierarchies.)

However as Erik and zarf pointed out, you can’t request character events on graphics windows, so you’ll need to keep the main window open anyway.

I’m not sure you need to worry about where the char input is, at least currently. I think all the major interpreters, at least, allow for char input in the main window even when there is a popover window of another type. Kerkerkruip and other demos I’ve put together do this and it hasn’t been a problem.

(Obviously, it will be better to actually call the char input in the graphics window once terps start offering that…)

To phrase this the way Glk understands it: if just one window has requested keyboard input, all keystrokes received by the app should go to that window. The spec does not require this but it’s good UI.

(Glk doesn’t have a notion of “popover” windows or a “main” window per se. There are just some windows.)