2
A system to permit user selection of a block and rotation axis
4
Copyright (C) 1998, 2003 John Darrington
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20
static const char RCSID[]="$Id: select-gtk.c,v 1.5 2003/10/26 04:32:51 jmd Exp $";
23
/* This library provides a means of picking a block using the mouse cursor.
25
Two mutually co-operative mechanisms are used in this library. There is a
26
timer callback, which occurs at regular intervals. There is also the mouse
27
motion callback, which occurs whenever the mouse cursor is moving. If two
28
consecutive timer callbacks occur, without and intervening mouse motion callback,
29
then the cursor is assumed to be stationary.
31
If a stationary mouse is detected, the program goes on to determine which block
32
in the cube (if any) the cursor is located upon.
44
static int idle_threshold;
45
static gboolean motion= FALSE;
46
static gboolean Stop_Detected = FALSE;
48
extern int mouse_x, mouse_y;
49
extern double granularity;
50
extern void (*action)(void);
54
static gboolean detect_motion (GtkWidget *w,
55
GdkEventMotion *event, gpointer user_data);
57
static gboolean UnsetMotion(gpointer data);
60
static gboolean enableDisableSelection(GtkWidget *w,
61
GdkEventCrossing *event, gpointer data);
63
extern GtkWidget *glxarea;
64
extern GtkWidget *toplevel;
67
static gboolean timerActive;
71
/* is the selection mechanism necessary ? */
72
static gboolean needSelection;
78
/* Initialise the selection mechanism. Holdoff is the time for which
79
the mouse must stay still, for anything to happen. Precision is the
80
minimum distance it must have moved. Do_this is a pointer to a function
81
to be called when a new block is selected. */
83
initSelection(int holdoff, double precision, void (*do_this)(void) )
87
needSelection = FALSE;
88
idle_threshold = holdoff;
89
granularity = precision ;
91
g_signal_connect (GTK_OBJECT(glxarea),"motion_notify_event",
92
GTK_SIGNAL_FUNC(detect_motion),0);
99
timer = gtk_timeout_add(idle_threshold,UnsetMotion,0);
103
/* Add a handler to for all those occasions when we don't need the
104
selection mechanism going */
106
g_signal_connect (GTK_OBJECT(glxarea),"enter-notify-event",
107
GTK_SIGNAL_FUNC(enableDisableSelection),0);
109
g_signal_connect (GTK_OBJECT(glxarea),"leave-notify-event",
110
GTK_SIGNAL_FUNC(enableDisableSelection),0);
115
g_signal_connect (GTK_OBJECT(glxarea),"visibility-notify-event",
116
GTK_SIGNAL_FUNC(enableDisableSelection),0);
121
g_signal_connect (GTK_OBJECT(glxarea),"unmap-event",
122
GTK_SIGNAL_FUNC(enableDisableSelection),0);
132
disableSelection(void)
135
gtk_timeout_remove(timer);
140
enableSelection(void)
143
timer = gtk_timeout_add(idle_threshold,UnsetMotion,0);
147
needSelection = TRUE ;
151
/* When the window is not mapped, kill the selection mechanism. It wastes
154
enableDisableSelection(GtkWidget *w,
155
GdkEventCrossing *event, gpointer data)
157
/* This is a kludge to work around a rather horrible bug; for some
158
reason, some platforms emit a EnterNotify and LeaveNotify (in
159
that order) when animations occur. This workaround makes sure
160
that the window is not `entered twice' */
161
static int entered =0;
164
switch (event->type) {
166
case GDK_ENTER_NOTIFY:
168
needSelection = FALSE ;
170
timer = gtk_timeout_add(idle_threshold,UnsetMotion,0);
175
case GDK_LEAVE_NOTIFY:
178
if ( entered > 0 ) break ;
180
needSelection = TRUE ;
181
gtk_timeout_remove(timer);
187
case GDK_VISIBILITY_NOTIFY:
188
g_print("HELLOOOOOOOOOOOOO %d\n", event->state);
189
if (event->state == GDK_VISIBILITY_FULLY_OBSCURED ) {
190
g_print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n");
191
needSelection = TRUE ;
192
gtk_timeout_remove(timer);
196
needSelection = FALSE ;
198
timer = gtk_timeout_add(idle_threshold,UnsetMotion,0);
217
/* This callback occurs whenever the mouse is moving */
219
detect_motion (GtkWidget *w, GdkEventMotion *event, gpointer user_data)
222
if ( event->type != GDK_MOTION_NOTIFY)
229
Stop_Detected = FALSE;
238
/* This callback occurs at regular intervals. The period is determined by
239
idle_threshold. It checks to see if the mouse has moved, since the last
240
call of this function.
241
Post-condition: motion is FALSE.
244
UnsetMotion(gpointer data)
247
if ( motion == FALSE ) { /* if not moved since last time */
249
if ( ! Stop_Detected ) {
250
/* in here, things happen upon the mouse stopping */
251
Stop_Detected = TRUE;
260
} /* end UnsetMotion */
265
get_widget_height(GtkWidget *w)
268
return w->allocation.height;