Don't close the window when the user refused to quit.
[gliv.git] / src / cursors.c
blobc99952ead579cc66401b7b0d4097f1871ac8c65a
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /*****************************
22 * Change or hide the cursor *
23 *****************************/
25 #include "gliv.h"
26 #include "cursors.h"
27 #include "options.h"
28 #include "all_cursors.h"
30 extern rt_struct *rt;
31 extern options_struct *options;
32 extern GtkWidget *gl_widget;
34 #define NB_CURSORS 6
36 /* Must be kept in sync with init_cursors(). */
37 typedef enum {
38 CURSOR_DEFAULT = 0,
39 CURSOR_MOVE,
40 CURSOR_ROTATE,
41 CURSOR_ZOOM,
42 CURSOR_ZOOM_ROTATE,
43 CURSOR_RECT_ZOOM
44 } cursor_type;
46 static cursor_type current_type = CURSOR_DEFAULT;
47 static GdkCursor **cursors = NULL;
48 static gboolean hide_cursor_enabled = TRUE;
50 typedef struct {
51 gint width;
52 gint height;
53 gint x_hot;
54 gint y_hot;
55 guchar *bits;
56 } xbm_data;
58 #define MAKE_CURSOR(name) \
59 do { \
60 source = gdk_bitmap_create_from_data(NULL, cursor_##name##_bits, \
61 cursor_##name##_width, \
62 cursor_##name##_height); \
64 mask = gdk_bitmap_create_from_data(NULL, cursor_##name##_mask_bits, \
65 cursor_##name##_mask_width, \
66 cursor_##name##_mask_height); \
68 *fill = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg, \
69 cursor_##name##_x_hot, \
70 cursor_##name##_y_hot); \
71 gdk_pixmap_unref(source); \
72 gdk_pixmap_unref(mask); \
73 fill++; \
74 } while (0)
76 static void init_cursors(void)
78 GdkPixmap *source, *mask;
79 GdkColor fg = { 0, 0, 0, 0 }; /* Black */
80 GdkColor bg = { 65535, 65535, 65535, 65535 }; /* White */
81 GdkCursor **fill;
83 cursors = fill = g_new(GdkCursor *, NB_CURSORS);
85 *fill++ = NULL;
86 MAKE_CURSOR(move);
87 MAKE_CURSOR(rotate);
88 MAKE_CURSOR(zoom);
89 MAKE_CURSOR(zoom_rotate);
90 MAKE_CURSOR(rect_zoom);
93 /* Called by the timer or the menu. */
94 void hide_cursor(void)
96 static GdkCursor *hidden_cursor = NULL;
98 if (hidden_cursor == NULL) {
99 /* First time. */
100 GdkPixmap *pmap;
101 GdkColor *col;
102 gchar *data;
104 data = g_new0(gchar, 1);
105 col = g_new0(GdkColor, 1);
106 pmap = gdk_bitmap_create_from_data(NULL, data, 1, 1);
107 hidden_cursor = gdk_cursor_new_from_pixmap(pmap, pmap, col, col, 0, 0);
109 g_free(data);
110 g_free(col);
111 g_object_unref(pmap);
113 gtk_widget_add_events(gl_widget, GDK_POINTER_MOTION_MASK);
116 gdk_window_set_cursor(gl_widget->window, hidden_cursor);
117 rt->cursor_hidden = TRUE;
120 void show_cursor(void)
122 if (cursors == NULL)
123 init_cursors();
125 rt->cursor_hidden = FALSE;
126 gdk_window_set_cursor(gl_widget->window, cursors[current_type]);
127 schedule_hide_cursor();
130 /* Set the appropriate cursor for the current situation. */
131 void set_correct_cursor(void)
133 GdkModifierType state;
134 cursor_type new_cursor;
136 if (cursors == NULL)
137 init_cursors();
139 gdk_display_get_pointer(gdk_display_get_default(), NULL, NULL, NULL,
140 &state);
142 if (state & GDK_BUTTON3_MASK && (state & GDK_BUTTON1_MASK) == 0)
143 new_cursor = CURSOR_RECT_ZOOM;
145 else if (state & GDK_SHIFT_MASK) {
146 if (state & GDK_CONTROL_MASK)
147 new_cursor = CURSOR_ZOOM_ROTATE;
148 else
149 new_cursor = CURSOR_ZOOM;
151 } else if (state & GDK_CONTROL_MASK)
152 new_cursor = CURSOR_ROTATE;
154 else if (state & GDK_BUTTON1_MASK)
155 new_cursor = CURSOR_MOVE;
157 else
158 new_cursor = CURSOR_DEFAULT;
160 if (new_cursor != current_type) {
161 current_type = new_cursor;
162 if (rt->cursor_hidden == FALSE)
163 gdk_window_set_cursor(gl_widget->window, cursors[current_type]);
168 * Used to prevent the cursor from being toggled automatically,
169 * this is useful when displaying dialogs.
171 void set_hide_cursor_enabled(gboolean enabled)
173 if (enabled == hide_cursor_enabled)
174 /* Already done. */
175 return;
177 hide_cursor_enabled = enabled;
178 if (hide_cursor_enabled == FALSE && rt->cursor_hidden)
179 show_cursor();
181 schedule_hide_cursor();
184 void schedule_hide_cursor(void)
186 static guint id = 0;
188 if (id != 0)
189 /* Remove previous schedule. */
190 g_source_remove(id);
192 if (options->delay == 0 || hide_cursor_enabled == FALSE)
193 id = 0;
194 else
195 id = g_timeout_add(options->delay, (GSourceFunc) hide_cursor, NULL);