1 #define __SP_INPUT_C__
3 /*
4 * Extended input devices dialog
5 *
6 * Authors:
7 * Nicklas Lindgren <nili@lysator.liu.se>
8 *
9 * Copyright (C) 2005 Authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
17 #include <gtk/gtk.h>
19 #include "../inkscape.h"
20 #include "../macros.h"
21 #include "../verbs.h"
22 #include "../interface.h"
23 #include "../xml/repr.h"
25 #include "dialog-events.h"
26 #include "../prefs-utils.h"
29 static GtkWidget *dlg = NULL;
30 static win_data wd;
32 // impossible original values to make sure they are read from prefs
33 static gint x = -1000, y = -1000, w = 0, h = 0;
34 static gchar *prefs_path = "dialogs.input";
36 static void
37 sp_input_dialog_destroy (GtkObject *object, gpointer data)
38 {
39 sp_signal_disconnect_by_data (INKSCAPE, dlg);
40 wd.win = dlg = NULL;
41 wd.stop = 0;
42 }
44 static gboolean
45 sp_input_dialog_delete (GtkObject *object, GdkEvent *event, gpointer data)
46 {
47 gtk_window_get_position ((GtkWindow *) dlg, &x, &y);
48 gtk_window_get_size ((GtkWindow *) dlg, &w, &h);
50 prefs_set_int_attribute (prefs_path, "x", x);
51 prefs_set_int_attribute (prefs_path, "y", y);
52 prefs_set_int_attribute (prefs_path, "w", w);
53 prefs_set_int_attribute (prefs_path, "h", h);
55 return FALSE; // which means, go ahead and destroy it
57 }
59 static gchar *axis_use_strings[GDK_AXIS_LAST] = {
60 "ignore", "x", "y", "pressure", "xtilt", "ytilt", "wheel"
61 };
63 void
64 sp_input_load_from_preferences (void)
65 {
66 Inkscape::XML::Node *devices = inkscape_get_repr(INKSCAPE, "devices");
67 if (devices == NULL)
68 return;
70 Inkscape::XML::Node *repr;
71 GList *list_ptr;
73 for (list_ptr = gdk_devices_list(); list_ptr != NULL; list_ptr = list_ptr->next) {
74 GdkDevice *device = static_cast<GdkDevice *>(list_ptr->data);
75 repr = sp_repr_lookup_child(devices, "id", device->name);
76 if (repr != NULL) {
77 GdkInputMode mode;
78 const gchar *attribute = repr->attribute("mode");
80 if (attribute == NULL)
81 mode = GDK_MODE_DISABLED;
82 else if (!strcmp(attribute, "screen"))
83 mode = GDK_MODE_SCREEN;
84 else if (!strcmp(attribute, "window"))
85 mode = GDK_MODE_WINDOW;
86 else
87 mode = GDK_MODE_DISABLED;
89 if (device->mode != mode) {
90 gdk_device_set_mode(device, mode);
91 }
93 const gchar *temp_ptr;
94 std::string::size_type pos0;
95 std::string::size_type pos1;
96 gint i;
97 gint j;
99 GdkAxisUse axis_use;
101 temp_ptr = repr->attribute("axes");
102 if (temp_ptr != NULL) {
103 const std::string temp_str = temp_ptr;
104 pos0 = pos1 = 0;
105 for (i=0; i < device->num_axes; i++) {
106 pos1 = temp_str.find(";", pos0);
107 if (pos1 == std::string::npos)
108 break; // Too few axis specifications
110 axis_use = GDK_AXIS_IGNORE;
111 for (j=0; j < GDK_AXIS_LAST; j++)
112 if (!strcmp(temp_str.substr(pos0, pos1-pos0).c_str(), axis_use_strings[j])) {
113 axis_use = static_cast<GdkAxisUse>(j);
114 break;
115 }
116 gdk_device_set_axis_use(device, i, axis_use);
117 pos0 = pos1 + 1;
118 }
119 }
121 guint keyval;
122 GdkModifierType modifier;
124 temp_ptr = repr->attribute("keys");
125 if (temp_ptr != NULL) {
126 const std::string temp_str = temp_ptr;
127 pos0 = pos1 = 0;
128 for (i=0; i < device->num_keys; i++) {
129 pos1 = temp_str.find(";", pos0);
130 if (pos1 == std::string::npos)
131 break; // Too few key specifications
133 gtk_accelerator_parse(temp_str.substr(pos0, pos1-pos0).c_str(), &keyval, &modifier);
134 gdk_device_set_key(device, i, keyval, modifier);
135 pos0 = pos1 + 1;
136 }
137 }
138 }
139 }
140 }
142 void
143 sp_input_save_to_preferences (void)
144 {
145 Inkscape::XML::Node *devices = inkscape_get_repr(INKSCAPE, "devices");
146 if (devices == NULL)
147 // TODO: find a clean way to add a node to the preferences root, or
148 // give an error message
149 return;
151 Inkscape::XML::Node *repr;
152 GList *list_ptr;
154 for (list_ptr = gdk_devices_list(); list_ptr != NULL; list_ptr = list_ptr->next) {
155 gint i;
156 std::string temp_attribute;
157 GdkDevice *device = static_cast<GdkDevice *>(list_ptr->data);
159 repr = sp_repr_lookup_child(devices, "id", device->name);
160 if (repr == NULL) {
161 repr = sp_repr_new("group");
162 repr->setAttribute("id", device->name);
163 devices->appendChild(repr);
164 Inkscape::GC::release(repr);
165 }
166 switch (device->mode) {
167 default:
168 case GDK_MODE_DISABLED: {
169 repr->setAttribute("mode", "disabled");
170 break;
171 }
172 case GDK_MODE_SCREEN: {
173 repr->setAttribute("mode", "screen");
174 break;
175 }
176 case GDK_MODE_WINDOW: {
177 repr->setAttribute("mode", "window");
178 break;
179 }
180 }
182 temp_attribute = "";
183 for (i=0; i < device->num_axes; i++) {
184 temp_attribute += axis_use_strings[device->axes[i].use];
185 temp_attribute += ";";
186 }
187 repr->setAttribute("axes", temp_attribute.c_str());
189 temp_attribute = "";
190 for (i=0; i < device->num_keys; i++) {
191 temp_attribute += gtk_accelerator_name(device->keys[i].keyval, device->keys[i].modifiers);
192 temp_attribute += ";";
193 }
194 repr->setAttribute("keys", temp_attribute.c_str());
195 }
196 }
198 static void
199 sp_input_save_button (GtkObject *object, gpointer data)
200 {
201 sp_input_save_to_preferences();
202 }
204 /**
205 * \brief Dialog
206 *
207 */
208 void
209 sp_input_dialog (void)
210 {
211 if (dlg == NULL) {
213 gchar title[500];
214 sp_ui_dialog_title_string (Inkscape::Verb::get(SP_VERB_DIALOG_INPUT), title);
216 dlg = gtk_input_dialog_new();
218 if (x == -1000 || y == -1000) {
219 x = prefs_get_int_attribute (prefs_path, "x", 0);
220 y = prefs_get_int_attribute (prefs_path, "y", 0);
221 }
223 if (w ==0 || h == 0) {
224 w = prefs_get_int_attribute (prefs_path, "w", 0);
225 h = prefs_get_int_attribute (prefs_path, "h", 0);
226 }
228 if (x != 0 || y != 0) {
229 gtk_window_move ((GtkWindow *) dlg, x, y);
230 } else {
231 gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
232 }
234 if (w && h) {
235 gtk_window_resize ((GtkWindow *) dlg, w, h);
236 }
238 sp_transientize (dlg);
239 wd.win = dlg;
240 wd.stop = 0;
242 g_signal_connect ( G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (sp_transientize_callback), &wd);
243 gtk_signal_connect ( GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC (sp_dialog_event_handler), dlg);
244 gtk_signal_connect ( GTK_OBJECT (dlg), "destroy", G_CALLBACK (sp_input_dialog_destroy), dlg);
245 gtk_signal_connect ( GTK_OBJECT (dlg), "delete_event", G_CALLBACK (sp_input_dialog_delete), dlg);
246 g_signal_connect ( G_OBJECT (INKSCAPE), "shut_down", G_CALLBACK (sp_input_dialog_delete), dlg);
247 g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_hide", G_CALLBACK (sp_dialog_hide), dlg);
248 g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_unhide", G_CALLBACK (sp_dialog_unhide), dlg);
250 // Dialog-specific stuff
251 gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(dlg)->close_button),
252 "clicked",
253 (GtkSignalFunc)gtk_widget_destroy,
254 GTK_OBJECT(dlg));
255 gtk_signal_connect (GTK_OBJECT(GTK_INPUT_DIALOG(dlg)->save_button),
256 "clicked",
257 (GtkSignalFunc)sp_input_save_button, NULL);
258 }
260 gtk_window_present ((GtkWindow *) dlg);
261 }
264 /*
265 Local Variables:
266 mode:c++
267 c-file-style:"stroustrup"
268 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
269 indent-tabs-mode:nil
270 fill-column:99
271 End:
272 */
273 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :