1 /*
2 * gretl -- Gnu Regression, Econometrics and Time-series Library
3 * Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include <gtk/gtk.h>
21 #include "focus.h"
22
23 /* This module added 2021-06-17. The point of wrapping gtk_dialog_new()
24 and gtk_window_new() is to inject common code that supports a
25 record of the currently focused window. Then when functions such
26 as errbox, infobox and warnbox (or variants thereof) are called
27 we can arrange for the resulting message dialogs to be parented
28 by the window from which they were spawned. Hopefully this will
29 improve the placement of the transient windows.
30
31 The code that utilizes get_focus_window() is to be found in
32 dialogs.c, in the msgbox() function.
33 */
34
35 #define FOCUS_DEBUG 0
36
37 /* the window that currently has focus */
38 static GtkWidget *focus_window;
39
get_focus_window(void)40 GtkWidget *get_focus_window (void)
41 {
42 return focus_window;
43 }
44
45 /* callback for when a window receives focus */
46
focus_in_cb(GtkWidget * w,GdkEvent * event,gpointer p)47 static gboolean focus_in_cb (GtkWidget *w, GdkEvent *event,
48 gpointer p)
49 {
50 #if FOCUS_DEBUG
51 fprintf(stderr, "focus_in: %p\n", (void *) w);
52 #endif
53 focus_window = w;
54 return FALSE;
55 }
56
57 /* callback for when a window loses focus */
58
focus_out_cb(GtkWidget * w,GdkEvent * event,gpointer p)59 static gboolean focus_out_cb (GtkWidget *w, GdkEvent *event,
60 gpointer p)
61 {
62 #if FOCUS_DEBUG
63 fprintf(stderr, "focus_out: %p\n", (void *) w);
64 #endif
65 focus_window = NULL;
66 return FALSE;
67 }
68
69 /* callback for window destroyed */
70
destroy_cb(GtkWidget * w,gpointer p)71 static void destroy_cb (GtkWidget *w, gpointer p)
72 {
73 #if FOCUS_DEBUG
74 fprintf(stderr, "focus destroy: %p\n", (void *) w);
75 #endif
76 if (focus_window == w) {
77 focus_window = NULL;
78 }
79 }
80
real_gretl_gtk_object(int window)81 static GtkWidget *real_gretl_gtk_object (int window)
82 {
83 GtkWidget *ret;
84
85 if (window) {
86 ret = gtk_window_new(GTK_WINDOW_TOPLEVEL);
87 } else {
88 ret = gtk_dialog_new();
89 }
90
91 /* redundant? */
92 gtk_widget_add_events(ret, GDK_FOCUS_CHANGE_MASK);
93
94 /* attach our focus-related callbacks */
95 g_signal_connect(G_OBJECT(ret), "focus-in-event",
96 G_CALLBACK(focus_in_cb), NULL);
97 g_signal_connect(G_OBJECT(ret), "focus-out-event",
98 G_CALLBACK(focus_out_cb), NULL);
99 g_signal_connect(G_OBJECT(ret), "destroy",
100 G_CALLBACK(destroy_cb), NULL);
101
102 return ret;
103 }
104
105 /* wrapper for gtk_dialog_new() */
106
gretl_gtk_dialog(void)107 GtkWidget *gretl_gtk_dialog (void)
108 {
109 return real_gretl_gtk_object(0);
110 }
111
112 /* wrapper for gtk_window_new (toplevel) */
113
gretl_gtk_window(void)114 GtkWidget *gretl_gtk_window (void)
115 {
116 return real_gretl_gtk_object(1);
117 }
118