/* Forward declarations */
static int finish_text_buffer_line_input(winid_t win, gboolean emit_signal);
static int finish_text_grid_line_input(winid_t win, gboolean emit_signal);
+static void cancel_old_input_request(winid_t win);
/* Internal function: code common to both flavors of char event request */
void
request_char_event_common(winid_t win, gboolean unicode)
{
VALID_WINDOW(win, return);
- g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE);
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
+ cancel_old_input_request(win);
+
flush_window_buffer(win);
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
{
VALID_WINDOW(win, return);
g_return_if_fail(buf);
- g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE);
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
g_return_if_fail(initlen <= maxlen);
+ cancel_old_input_request(win);
+
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
/* Register the buffer */
{
VALID_WINDOW(win, return);
g_return_if_fail(buf);
- g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE);
g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid);
g_return_if_fail(initlen <= maxlen);
+ cancel_old_input_request(win);
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
/* Register the buffer */
int chars_written = 0;
+ gdk_threads_enter();
if(win->type == wintype_TextGrid) {
chars_written = finish_text_grid_line_input(win, FALSE);
} else if(win->type == wintype_TextBuffer) {
g_signal_handler_block(window_buffer, win->insert_text_handler);
chars_written = finish_text_buffer_line_input(win, FALSE);
}
+ gdk_threads_leave();
ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
if(glk_data->unregister_arr)
}
}
+/* Helper function: Turn off shutdown key-press-event signal handler */
+static gboolean
+turn_off_handler(GNode *node)
+{
+ winid_t win = node->data;
+ g_signal_handler_block(win->widget, win->shutdown_keypress_handler);
+ return FALSE; /* don't stop */
+}
+
+/* Internal function: Callback for signal key-press-event while waiting for shutdown. */
+gboolean
+on_shutdown_key_press_event(GtkWidget *widget, GdkEventKey *event, winid_t win)
+{
+ ChimaraGlk *glk = CHIMARA_GLK(gtk_widget_get_ancestor(widget, CHIMARA_TYPE_GLK));
+ g_assert(glk);
+ CHIMARA_GLK_USE_PRIVATE(glk, priv);
+
+ /* Turn off all the signal handlers */
+ if(priv->root_window)
+ g_node_traverse(priv->root_window, G_IN_ORDER, G_TRAVERSE_LEAVES, -1, (GNodeTraverseFunc)turn_off_handler, NULL);
+
+ /* Signal the Glk library that it can shut everything down now */
+ g_mutex_lock(priv->shutdown_lock);
+ g_cond_signal(priv->shutdown_key_pressed);
+ g_mutex_unlock(priv->shutdown_lock);
+
+ return TRUE; /* block the event */
+}
+
/* Internal function: General callback for signal key-press-event on a text buffer or text grid window. Used in character input on both text buffers and grids. Blocked when not in use. */
gboolean
on_char_input_key_press_event(GtkWidget *widget, GdkEventKey *event, winid_t win)
/* Only one keypress will be handled */
win->input_request_type = INPUT_REQUEST_NONE;
- g_signal_handler_block( win->widget, win->char_input_keypress_handler );
+ g_signal_handler_block(win->widget, win->char_input_keypress_handler);
return TRUE;
}
event->val1 = chars_written;
event->val2 = 0;
}
+
+/*** Internal function: cancels any pending input requests on the window and presents a warning if not INPUT_REQUEST_NONE ***/
+void
+cancel_old_input_request(winid_t win)
+{
+ switch(win->input_request_type) {
+ case INPUT_REQUEST_NONE:
+ break; /* All is well */
+ case INPUT_REQUEST_CHARACTER:
+ case INPUT_REQUEST_CHARACTER_UNICODE:
+ glk_cancel_char_event(win);
+ WARNING("Cancelling pending char event");
+ break;
+ case INPUT_REQUEST_LINE:
+ case INPUT_REQUEST_LINE_UNICODE:
+ glk_cancel_line_event(win, NULL);
+ WARNING("Cancelling pending line event");
+ break;
+ default:
+ WARNING("Could not cancel pending input request: unknown input request");
+ }
+}