@@ -35,6 +35,8 @@ typedef struct {
3535 GtkWidget * sun_label ;
3636 GtkWidget * web_view ;
3737 GtkWidget * overlay_vbox ;
38+ GtkWidget * loading_label ;
39+ gboolean web_loading ;
3840
3941 /* State */
4042 WeatherData weather ;
@@ -217,15 +219,40 @@ static gboolean on_weather_tick(gpointer data)
217219/* Web view / touch handling */
218220/* ------------------------------------------------------------------ */
219221
222+ static gboolean on_webview_timeout (gpointer data );
223+
224+ static void show_web_view (void )
225+ {
226+ gtk_widget_hide (app .loading_label );
227+ app .web_loading = FALSE;
228+ gtk_stack_set_visible_child_name (GTK_STACK (app .stack ), "web" );
229+
230+ if (app .webview_timeout )
231+ g_source_remove (app .webview_timeout );
232+ app .webview_timeout = g_timeout_add_seconds (30 , on_webview_timeout , NULL );
233+ }
234+
220235static gboolean on_webview_timeout (gpointer data )
221236{
222237 (void )data ;
223238
224239 gtk_stack_set_visible_child_name (GTK_STACK (app .stack ), "weather" );
240+ gtk_widget_hide (app .loading_label );
241+ app .web_loading = FALSE;
225242 app .webview_timeout = 0 ;
226243 return G_SOURCE_REMOVE ;
227244}
228245
246+ static void on_web_load_changed (WebKitWebView * web_view ,
247+ WebKitLoadEvent event , gpointer data )
248+ {
249+ (void )web_view ;
250+ (void )data ;
251+
252+ if (event == WEBKIT_LOAD_FINISHED && app .web_loading )
253+ show_web_view ();
254+ }
255+
229256static gboolean on_key_press (GtkWidget * widget , GdkEventKey * event ,
230257 gpointer data )
231258{
@@ -256,13 +283,18 @@ static void toggle_web_view(void)
256283 return ;
257284 }
258285
259- /* Switch to web view */
260- webkit_web_view_load_uri (WEBKIT_WEB_VIEW (app .web_view ), app .web_url );
261- gtk_stack_set_visible_child_name (GTK_STACK (app .stack ), "web" );
286+ if (app .web_loading ) {
287+ /* Already loading -- cancel */
288+ webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (app .web_view ));
289+ gtk_widget_hide (app .loading_label );
290+ app .web_loading = FALSE;
291+ return ;
292+ }
262293
263- if (app .webview_timeout )
264- g_source_remove (app .webview_timeout );
265- app .webview_timeout = g_timeout_add_seconds (30 , on_webview_timeout , NULL );
294+ /* Start loading, stay on weather view until page is ready */
295+ app .web_loading = TRUE;
296+ gtk_widget_show (app .loading_label );
297+ webkit_web_view_load_uri (WEBKIT_WEB_VIEW (app .web_view ), app .web_url );
266298}
267299
268300static gboolean on_button_press (GtkWidget * widget , GdkEventButton * event ,
@@ -338,17 +370,29 @@ static GtkWidget *create_weather_view(void)
338370 gtk_box_pack_start (GTK_BOX (vbox ), app .wind_label , FALSE, FALSE, 0 );
339371 gtk_box_pack_start (GTK_BOX (vbox ), app .sun_label , FALSE, FALSE, 10 );
340372
373+ /* Loading notification -- shown while web page loads */
374+ app .loading_label = gtk_label_new ("Loading \u2026" );
375+ gtk_widget_set_halign (app .loading_label , GTK_ALIGN_CENTER );
376+ gtk_widget_set_valign (app .loading_label , GTK_ALIGN_END );
377+ gtk_widget_set_margin_bottom (app .loading_label , 20 );
378+ gtk_style_context_add_class (gtk_widget_get_style_context (app .loading_label ),
379+ "overlay-small" );
380+ gtk_widget_set_no_show_all (app .loading_label , TRUE);
381+
341382 /* Overlay: drawing area + labels on top */
342383 GtkWidget * overlay = gtk_overlay_new ();
343384 gtk_container_add (GTK_CONTAINER (overlay ), app .drawing_area );
344385 gtk_overlay_add_overlay (GTK_OVERLAY (overlay ), vbox );
386+ gtk_overlay_add_overlay (GTK_OVERLAY (overlay ), app .loading_label );
345387
346388 return overlay ;
347389}
348390
349391static GtkWidget * create_web_view (void )
350392{
351393 app .web_view = webkit_web_view_new ();
394+ g_signal_connect (app .web_view , "load-changed" ,
395+ G_CALLBACK (on_web_load_changed ), NULL );
352396 return app .web_view ;
353397}
354398
0 commit comments