1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /**
3  * @file
4  * Event handler for dialog windows.
5  */
6 /* Authors:
7  *   bulia byak <bulia@dr.com>
8  *   Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
9  *
10  * Copyright (C) 2003-2014 Authors
11  *
12  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
13  */
14 
15 #include <gtkmm/entry.h>
16 #include <gtkmm/window.h>
17 
18 #include "desktop.h"
19 #include "inkscape.h"
20 #include "enums.h"
21 #include "include/macros.h"
22 #include "ui/dialog-events.h"
23 #include "ui/tools/tool-base.h"
24 
25 
26 /**
27  * Remove focus from window to whoever it is transient for.
28  */
sp_dialog_defocus_cpp(Gtk::Window * win)29 void sp_dialog_defocus_cpp(Gtk::Window *win)
30 {
31     //find out the document window we're transient for
32     Gtk::Window *w = win->get_transient_for();
33 
34     //switch to it
35     if (w) {
36         w->present();
37     }
38 }
39 
40 void
sp_dialog_defocus(GtkWindow * win)41 sp_dialog_defocus (GtkWindow *win)
42 {
43     GtkWindow *w;
44     //find out the document window we're transient for
45     w = gtk_window_get_transient_for(GTK_WINDOW(win));
46     //switch to it
47 
48     if (w) {
49         gtk_window_present (w);
50     }
51 }
52 
53 
54 /**
55  * Callback to defocus a widget's parent dialog.
56  */
sp_dialog_defocus_callback_cpp(Gtk::Entry * e)57 void sp_dialog_defocus_callback_cpp(Gtk::Entry *e)
58 {
59     sp_dialog_defocus_cpp(dynamic_cast<Gtk::Window *>(e->get_toplevel()));
60 }
61 
62 void
sp_dialog_defocus_callback(GtkWindow *,gpointer data)63 sp_dialog_defocus_callback (GtkWindow * /*win*/, gpointer data)
64 {
65     sp_dialog_defocus( GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(data))) );
66 }
67 
68 
69 
70 void
sp_dialog_defocus_on_enter_cpp(Gtk::Entry * e)71 sp_dialog_defocus_on_enter_cpp (Gtk::Entry *e)
72 {
73     e->signal_activate().connect(sigc::bind(sigc::ptr_fun(&sp_dialog_defocus_callback_cpp), e));
74 }
75 
76 void
sp_dialog_defocus_on_enter(GtkWidget * w)77 sp_dialog_defocus_on_enter (GtkWidget *w)
78 {
79     g_signal_connect ( G_OBJECT (w), "activate",
80                        G_CALLBACK (sp_dialog_defocus_callback), w );
81 }
82 
83 
84 
85 gboolean
sp_dialog_event_handler(GtkWindow * win,GdkEvent * event,gpointer data)86 sp_dialog_event_handler (GtkWindow *win, GdkEvent *event, gpointer data)
87 {
88     gboolean ret = FALSE;
89 
90     switch (event->type) {
91 
92         case GDK_KEY_PRESS:
93 
94             switch (Inkscape::UI::Tools::get_latin_keyval (&event->key)) {
95                 case GDK_KEY_Escape:
96                     sp_dialog_defocus (win);
97                     ret = TRUE;
98                     break;
99                 case GDK_KEY_F4:
100                 case GDK_KEY_w:
101                 case GDK_KEY_W:
102                     // close dialog
103                     if (MOD__CTRL_ONLY(event)) {
104 
105                         /* this code sends a delete_event to the dialog,
106                          * instead of just destroying it, so that the
107                          * dialog can do some housekeeping, such as remember
108                          * its position.
109                          */
110                         GdkEventAny event;
111                         GtkWidget *widget = GTK_WIDGET(win);
112                         event.type = GDK_DELETE;
113                         event.window = gtk_widget_get_window (widget);
114                         event.send_event = TRUE;
115                         g_object_ref (G_OBJECT (event.window));
116                         gtk_main_do_event(reinterpret_cast<GdkEvent*>(&event));
117                         g_object_unref (G_OBJECT (event.window));
118 
119                         ret = TRUE;
120                     }
121                     break;
122                 default: // pass keypress to the canvas
123                     break;
124             }
125     default:
126         ;
127     }
128 
129     return ret;
130 
131 }
132 
133 
134 
135 /**
136  * Make the argument dialog transient to the currently active document
137  * window.
138  */
sp_transientize(GtkWidget * dialog)139 void sp_transientize(GtkWidget *dialog)
140 {
141     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
142 #ifndef _WIN32  // FIXME: Temporary Win32 special code to enable transient dialogs
143     // _set_skip_taskbar_hint makes transient dialogs NON-transient! When dialogs
144     // are made transient (_set_transient_for), they are already removed from
145     // the taskbar in Win32.
146     if (prefs->getBool( "/options/dialogsskiptaskbar/value")) {
147         gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
148     }
149 #endif
150 
151     gint transient_policy = prefs->getIntLimited("/options/transientpolicy/value", PREFS_DIALOGS_WINDOWS_NORMAL,
152                                                  PREFS_DIALOGS_WINDOWS_NONE, PREFS_DIALOGS_WINDOWS_AGGRESSIVE);
153 
154 #ifdef _WIN32 // Win32 special code to enable transient dialogs
155     transient_policy = PREFS_DIALOGS_WINDOWS_AGGRESSIVE;
156 #endif
157 
158     if (transient_policy) {
159 
160     // if there's an active document window, attach dialog to it as a transient:
161 
162         if ( SP_ACTIVE_DESKTOP )
163         {
164             SP_ACTIVE_DESKTOP->setWindowTransient (dialog, transient_policy);
165         }
166     }
167 } // end of sp_transientize()
168 
on_transientize(SPDesktop * desktop,win_data * wd)169 void on_transientize (SPDesktop *desktop, win_data *wd )
170 {
171     sp_transientize_callback (desktop, wd);
172 }
173 
174 void
sp_transientize_callback(SPDesktop * desktop,win_data * wd)175 sp_transientize_callback ( SPDesktop *desktop, win_data *wd )
176 {
177     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
178     gint transient_policy = prefs->getIntLimited("/options/transientpolicy/value", PREFS_DIALOGS_WINDOWS_NORMAL,
179                                                  PREFS_DIALOGS_WINDOWS_NONE, PREFS_DIALOGS_WINDOWS_AGGRESSIVE);
180 
181 #ifdef _WIN32 // Win32 special code to enable transient dialogs
182     transient_policy = PREFS_DIALOGS_WINDOWS_NORMAL;
183 #endif
184 
185     if (!transient_policy)
186         return;
187 
188     if (wd->win)
189     {
190         desktop->setWindowTransient (wd->win, transient_policy);
191     }
192 }
193 
on_dialog_hide(GtkWidget * w)194 void on_dialog_hide (GtkWidget *w)
195 {
196     if (w)
197         gtk_widget_hide (w);
198 }
199 
on_dialog_unhide(GtkWidget * w)200 void on_dialog_unhide (GtkWidget *w)
201 {
202     if (w)
203         gtk_widget_show (w);
204 }
205 
206 gboolean
sp_dialog_hide(GObject *,gpointer data)207 sp_dialog_hide(GObject * /*object*/, gpointer data)
208 {
209     GtkWidget *dlg = GTK_WIDGET(data);
210 
211     if (dlg)
212         gtk_widget_hide (dlg);
213 
214     return TRUE;
215 }
216 
217 
218 
219 gboolean
sp_dialog_unhide(GObject *,gpointer data)220 sp_dialog_unhide(GObject * /*object*/, gpointer data)
221 {
222     GtkWidget *dlg = GTK_WIDGET(data);
223 
224     if (dlg)
225         gtk_widget_show (dlg);
226 
227     return TRUE;
228 }
229 
230 
231 /*
232   Local Variables:
233   mode:c++
234   c-file-style:"stroustrup"
235   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
236   indent-tabs-mode:nil
237   fill-column:99
238   End:
239 */
240 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
241