~ubuntu-branches/ubuntu/breezy/gnubik/breezy

« back to all changes in this revision

Viewing changes to src/select-gtk.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2004-09-21 13:48:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040921134826-p3sk7d3qzsaotn2s
Tags: upstream-2.2
ImportĀ upstreamĀ versionĀ 2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    A system to permit user selection of a block and rotation axis
 
3
    of a magic cube.
 
4
    Copyright (C) 1998, 2003  John Darrington
 
5
 
 
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.
 
10
 
 
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.
 
15
 
 
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
 
19
*/
 
20
static const char RCSID[]="$Id: select-gtk.c,v 1.5 2003/10/26 04:32:51 jmd Exp $";
 
21
 
 
22
 
 
23
/* This library provides  a means of picking a block using the mouse cursor.
 
24
 
 
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. 
 
30
 
 
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.
 
33
*/
 
34
 
 
35
#include "select.h"
 
36
#include <float.h>
 
37
#include <stdio.h>
 
38
#include "gnubik.h"
 
39
#include "ui.h"
 
40
 
 
41
#include <gtk/gtk.h>
 
42
 
 
43
 
 
44
static int idle_threshold;
 
45
static gboolean motion= FALSE;
 
46
static gboolean Stop_Detected = FALSE;
 
47
 
 
48
extern int mouse_x, mouse_y;
 
49
extern double granularity;
 
50
extern void (*action)(void);
 
51
 
 
52
 
 
53
 
 
54
static gboolean detect_motion (GtkWidget *w, 
 
55
                               GdkEventMotion *event, gpointer user_data);
 
56
 
 
57
static gboolean UnsetMotion(gpointer data);
 
58
 
 
59
 
 
60
static gboolean enableDisableSelection(GtkWidget *w, 
 
61
                       GdkEventCrossing *event, gpointer data);
 
62
 
 
63
extern GtkWidget *glxarea;
 
64
extern GtkWidget *toplevel;
 
65
 
 
66
 
 
67
static gboolean timerActive;
 
68
 
 
69
static guint timer;
 
70
 
 
71
/* is the selection mechanism necessary ? */
 
72
static gboolean needSelection;
 
73
 
 
74
 
 
75
 
 
76
 
 
77
 
 
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. */
 
82
void
 
83
initSelection(int holdoff, double precision, void (*do_this)(void) )
 
84
{
 
85
 
 
86
 
 
87
  needSelection = FALSE;
 
88
  idle_threshold = holdoff;
 
89
  granularity = precision ;
 
90
 
 
91
  g_signal_connect (GTK_OBJECT(glxarea),"motion_notify_event",
 
92
                      GTK_SIGNAL_FUNC(detect_motion),0);
 
93
 
 
94
 
 
95
 
 
96
  action = do_this;
 
97
 
 
98
 
 
99
  timer = gtk_timeout_add(idle_threshold,UnsetMotion,0);
 
100
 
 
101
  timerActive=TRUE;
 
102
 
 
103
  /* Add a handler to for all those occasions when we don't need the
 
104
     selection mechanism going */
 
105
 
 
106
  g_signal_connect (GTK_OBJECT(glxarea),"enter-notify-event",
 
107
                      GTK_SIGNAL_FUNC(enableDisableSelection),0);
 
108
 
 
109
  g_signal_connect (GTK_OBJECT(glxarea),"leave-notify-event",
 
110
                      GTK_SIGNAL_FUNC(enableDisableSelection),0);
 
111
                      
 
112
 
 
113
 
 
114
 
 
115
  g_signal_connect (GTK_OBJECT(glxarea),"visibility-notify-event",
 
116
                      GTK_SIGNAL_FUNC(enableDisableSelection),0);
 
117
 
 
118
 
 
119
 
 
120
 
 
121
  g_signal_connect (GTK_OBJECT(glxarea),"unmap-event",
 
122
                      GTK_SIGNAL_FUNC(enableDisableSelection),0);
 
123
 
 
124
 
 
125
 
 
126
 
 
127
 
 
128
}
 
129
 
 
130
 
 
131
void 
 
132
disableSelection(void)
 
133
{
 
134
 
 
135
    gtk_timeout_remove(timer);
 
136
    timerActive=FALSE;
 
137
}
 
138
 
 
139
void 
 
140
enableSelection(void)
 
141
{
 
142
    if ( !timerActive) { 
 
143
      timer = gtk_timeout_add(idle_threshold,UnsetMotion,0);
 
144
      timerActive=TRUE;
 
145
    }
 
146
 
 
147
    needSelection = TRUE ;
 
148
}
 
149
 
 
150
 
 
151
/* When the window is not mapped, kill the selection mechanism.  It wastes
 
152
processor time */
 
153
static gboolean 
 
154
enableDisableSelection(GtkWidget *w, 
 
155
                       GdkEventCrossing *event, gpointer data)
 
156
{
 
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;
 
162
 
 
163
 
 
164
  switch (event->type) {
 
165
 
 
166
  case GDK_ENTER_NOTIFY:
 
167
    entered++;
 
168
    needSelection = FALSE ;
 
169
    if ( !timerActive) { 
 
170
      timer = gtk_timeout_add(idle_threshold,UnsetMotion,0);
 
171
      timerActive=TRUE;
 
172
    }
 
173
 
 
174
    break;
 
175
  case GDK_LEAVE_NOTIFY:
 
176
    updateSelection();
 
177
    entered--;
 
178
    if ( entered > 0 ) break ;
 
179
 
 
180
    needSelection = TRUE ;
 
181
    gtk_timeout_remove(timer);
 
182
    timerActive=FALSE;
 
183
 
 
184
    break;
 
185
 
 
186
#if 0 
 
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);
 
193
      timerActive=FALSE;
 
194
    }
 
195
    else { 
 
196
      needSelection = FALSE ;
 
197
      if ( !timerActive) { 
 
198
        timer = gtk_timeout_add(idle_threshold,UnsetMotion,0);
 
199
        timerActive=TRUE;
 
200
      }
 
201
      timerActive=TRUE;
 
202
 
 
203
    }
 
204
    break;
 
205
#endif
 
206
 
 
207
  default:
 
208
    break;
 
209
  }
 
210
 
 
211
  return FALSE;
 
212
}
 
213
 
 
214
 
 
215
 
 
216
 
 
217
/* This callback occurs whenever the mouse is moving */
 
218
static gboolean
 
219
detect_motion (GtkWidget *w, GdkEventMotion *event, gpointer user_data)
 
220
{
 
221
 
 
222
  if ( event->type != GDK_MOTION_NOTIFY)
 
223
    return FALSE;
 
224
 
 
225
  mouse_x = event->x;
 
226
  mouse_y = event->y;
 
227
 
 
228
  motion = TRUE;
 
229
  Stop_Detected = FALSE;
 
230
 
 
231
  return FALSE;
 
232
}
 
233
 
 
234
 
 
235
 
 
236
 
 
237
 
 
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. 
 
242
*/
 
243
gboolean
 
244
UnsetMotion(gpointer data)
 
245
{
 
246
 
 
247
  if ( motion == FALSE ) { /* if not moved since last time */
 
248
 
 
249
    if ( ! Stop_Detected ) {
 
250
      /* in here, things happen upon the mouse stopping */
 
251
      Stop_Detected = TRUE;
 
252
      updateSelection();
 
253
    }
 
254
  }
 
255
 
 
256
  motion = FALSE ;
 
257
        
 
258
  return TRUE;
 
259
 
 
260
}  /* end UnsetMotion */
 
261
 
 
262
 
 
263
 
 
264
int
 
265
get_widget_height(GtkWidget *w)
 
266
{
 
267
 
 
268
  return w->allocation.height;
 
269
 
 
270
}
 
271
 
 
272