1 /* mouse_button.c */
2 /* COPYRIGHT (C) 2000 THE VICTORIA UNIVERSITY OF MANCHESTER and John Levon
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by the Free
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307, USA.
16 */
17 /* For button presses and releases */
18 /*
19 * $Log: mouse_button.c,v $
20 * Revision 1.2 2000/12/06 20:56:02 moz
21 * GPL stuff.
22 *
23 * Revision 1.1.1.1 2000/08/21 01:05:31 moz
24 *
25 *
26 * Revision 1.1.1.1 2000/07/19 22:45:30 moz
27 * CVS Import
28 *
29 * Revision 1.11 2000/03/09 01:00:06 moz
30 * stk_display_menu() cleanup.
31 *
32 * Revision 1.10 2000/03/07 21:44:30 moz
33 * Compile fixes.
34 *
35 * Revision 1.9 2000/02/21 01:51:16 moz
36 * Don't allow edit menu when editing_object.
37 *
38 * Revision 1.8 2000/02/18 01:16:16 moz
39 * Compile fix.
40 *
41 * Revision 1.7 2000/01/31 01:05:34 moz
42 * Update mouse_x,mouse_y.
43 *
44 * Revision 1.6 2000/01/26 18:18:48 moz
45 * Added hook to unselect_polygon() for gc.
46 *
47 * Revision 1.5 1999/11/15 02:07:37 moz
48 * Name change.
49 *
50 * Revision 1.4 1999/05/22 23:39:18 moz
51 * Pedantic ANSI.
52 *
53 * Revision 1.3 1999/05/19 17:08:52 moz
54 * 1.0 Checkin.
55 *
56 * Revision 1.2 1999/04/27 16:55:47 moz
57 * Enable/disable flip object as necessary.
58 *
59 * Revision 1.1 1999/03/30 00:05:28 moz
60 * Initial revision
61 *
62 */
63
64 #include "include/figurine.h"
65 #include "include/extern.h"
66
67 BEvent bev;
68 Time last_press[3] = { 0, 0, 0 };
69 extern int mouse_x;
70 extern int mouse_y;
71 void unselect_polygon(void);
72
73
74 /* Receivers of a bev must act as appropriate :
75
76 If they receive a HELD, act as if the mouse was
77 being dragged with that button.
78
79 If they receive a CLICKED, ignore the (always previously
80 set) HELD mode, and move to CLICKED actions
81
82 If they receive a RELEASED, end the HELD or CLICKED mode
83 as appropriate
84 */
85
86 void
handle_button_press(XEvent * report)87 handle_button_press(XEvent *report)
88 {
89 List l;
90 List l2;
91
92 l = where_in_list(wins,report->xbutton.window);
93
94 switch (l->type)
95 {
96 case RULER_X_WIN:
97 case RULER_Y_WIN:
98 WS(l)->grabbed = TRUE;
99 break;
100
101 case DRAW_WIN:
102 l2 = where_in_list(wins,WS(l)->parent);
103
104 if (report->xmotion.state & ControlMask)
105 state.control_down = TRUE;
106 else
107 state.control_down = FALSE;
108
109 if (report->xmotion.state & ShiftMask)
110 state.shift_down = TRUE;
111 else
112 state.shift_down = FALSE;
113
114 if (!state.editing_object)
115 state.rubberon = TRUE;
116
117 /* Here's why we immediately send a HELD: We can't query
118 server time on a motion event so we assume
119 HELD instead. If they subsequently receive a CLICKED
120 after a HELD, they then accept that. A RELEASED is sent
121 either way on releasing of the button.
122 See client restrictions above. */
123
124 bev.type = BUTTON_HELD;
125 bev.x = report->xbutton.x;
126 bev.y = report->xbutton.y;
127 bev.button = report->xbutton.button;
128 mouse_x = bev.x;
129 mouse_y = bev.y;
130
131 /* due to dumb way two-button mice represent a 2nd button Press
132 (Release 1, Press 2) we have to use a modifier for the other menu */
133 /* you also can't directly cancel whilst drawing a held line - our
134 Release 1 is difficult to catch as a special case. Swines. */
135 if (state.current_icon==POINTERICON && !state.editing_point && report->xbutton.button==Button3
136 && !state.editing_object && state.control_down && VIEW(l2)!=NULL)
137 {
138 Window w1; int x1,y1; int idum; uint indum;
139
140 /* open up edit menu */
141 if (VIEW(l2)->selected_object!=NULL)
142 {
143 stk_enable_menu_label(emw, 0);
144 stk_enable_menu_label(emw, 1);
145 stk_enable_menu_label(emw, 3);
146 stk_enable_menu_label(emw, 5);
147 stk_enable_menu_label(emw, 6);
148 if (VIEW(l2)->selected_object->ob->type!=ELLIPSE &&
149 VIEW(l2)->selected_object->ob->type!=TEXT)
150 {
151 stk_enable_menu_label(emw,7);
152 stk_enable_menu_label(emw,8);
153 }
154 else
155 {
156 stk_disable_menu_label(emw,7);
157 stk_disable_menu_label(emw,8);
158 };
159 }
160 else
161 {
162 stk_disable_menu_label(emw, 0);
163 stk_disable_menu_label(emw, 1);
164 stk_disable_menu_label(emw, 3);
165 stk_disable_menu_label(emw, 5);
166 stk_disable_menu_label(emw, 6);
167 stk_disable_menu_label(emw, 7);
168 stk_disable_menu_label(emw, 8);
169 };
170
171 XQueryPointer(display,RootWindow(display,screen),&w1,&w1,&x1,&y1,&idum, &idum, &indum);
172 XUngrabPointer(display,CurrentTime);
173
174 stk_display_menu(VIEW(l2), emw, x1,y1, Button3);
175
176 }
177 else if (!state.editing_point && !state.editing_object && !state.busy_drawing && report->xbutton.button==Button3)
178 {
179 /* if you add something here, it probably needs to be in really_close_view() as well */
180 if (state.editing_text)
181 unselect_text(VIEW(l2));
182
183 if (state.compound_selected)
184 unselect_compound(VIEW(l2));
185
186 if (state.current_icon==ARCICON)
187 unselect_arc(VIEW(l2));
188
189 if (state.current_icon==POLYGONICON)
190 unselect_polygon();
191
192 XUngrabPointer(display,CurrentTime);
193 stk_unselect_icon((signed)state.current_icon,float_menu);
194 stk_display_icon_menu(float_menu, RULER_PIXEL_SIZE + report->xbutton.x + VIEW(l2)->window.x - 30,
195 RULER_PIXEL_SIZE + report->xbutton.y + VIEW(l2)->window.y - 30, FALSE, Button1);
196 XFlush(display);
197 }
198 else
199 {
200 /* otherwise it's a normal button event, pass it downwards */
201 switch (state.current_icon)
202 {
203 case ARCICON:
204 arc_button(&bev, VIEW(l2));
205 break;
206
207 case SPLINEICON:
208 spline_button(&bev, VIEW(l2));
209 break;
210
211 case POLYLINEICON:
212 polyline_button(&bev,VIEW(l2));
213 break;
214
215 case ELLIPSEICON:
216 case BOXELLIPSEICON:
217 ellipse_button(&bev,VIEW(l2));
218 break;
219
220 case ARCELLIPSEICON:
221 arcellipse_button(&bev,VIEW(l2));
222 break;
223
224 case TEXTICON:
225 case NODEICON:
226 text_button(&bev,VIEW(l2));
227 break;
228
229 case RECTANGLEICON:
230 rectangle_button(&bev, VIEW(l2));
231 break;
232
233 case POLYGONICON:
234 polygon_button(&bev, VIEW(l2));
235 break;
236
237 case POINTERICON:
238 edit_button(&bev, VIEW(l2));
239 break;
240
241 default:
242 break;
243 };
244 };
245
246 switch (report->xbutton.button)
247 {
248 case Button1:
249 last_press[0] = report->xbutton.time;
250 break;
251
252 case Button2:
253 last_press[1] = report->xbutton.time;
254 break;
255
256 case Button3:
257 last_press[2] = report->xbutton.time;
258 break;
259 };
260 break;
261
262 };
263
264 }
265
266 void
handle_button_release(XEvent * report)267 handle_button_release(XEvent *report)
268 {
269 Boolean clicked=0;
270 List l;
271 List l2;
272
273
274 l = where_in_list(wins,report->xbutton.window);
275
276 switch (l->type)
277 {
278 case RULER_X_WIN:
279 case RULER_Y_WIN:
280 WS(l)->grabbed = FALSE;
281 break;
282
283 case DRAW_WIN:
284 l2 = where_in_list(wins,WS(l)->parent);
285
286 switch (report->xbutton.button)
287 {
288 case Button1:
289 clicked = (report->xbutton.time - last_press[0]) < RELEASE_DEFAULTS_LATENCY;
290 last_press[0] = 0;
291 break;
292
293 case Button2:
294 clicked = (report->xbutton.time - last_press[1]) < RELEASE_DEFAULTS_LATENCY;
295 last_press[1] = 0;
296 break;
297
298 case Button3:
299 clicked = (report->xbutton.time - last_press[2]) < RELEASE_DEFAULTS_LATENCY;
300 last_press[2] = 0;
301 break;
302 }
303
304 if (clicked)
305 bev.type = BUTTON_CLICKED;
306 else
307 bev.type = BUTTON_RELEASED;
308
309 bev.x = report->xbutton.x;
310 bev.y = report->xbutton.y;
311 bev.button = report->xbutton.button;
312
313 if (state.editing_text || state.current_icon==TEXTICON || state.current_icon==NODEICON)
314 text_button(&bev,VIEW(l2));
315 else if (state.current_icon==COMPOUNDICON)
316 compound_button(&bev,VIEW(l2));
317 else if (state.busy_drawing)
318 {
319 switch (state.current_icon)
320 {
321 case ARCICON:
322 arc_button(&bev, VIEW(l2));
323 break;
324
325 case SPLINEICON:
326 spline_button(&bev, VIEW(l2));
327 break;
328
329 case POLYLINEICON:
330 polyline_button(&bev,VIEW(l2));
331 break;
332
333 case ELLIPSEICON:
334 case BOXELLIPSEICON:
335 ellipse_button(&bev,VIEW(l2));
336 break;
337
338 case ARCELLIPSEICON:
339 arcellipse_button(&bev,VIEW(l2));
340 break;
341
342 case RECTANGLEICON:
343 rectangle_button(&bev, VIEW(l2));
344 break;
345
346 case POLYGONICON:
347 polygon_button(&bev, VIEW(l2));
348 break;
349 default:
350 v_error(state.current_icon);
351 break;
352 };
353
354 }
355 else /* we're not currently drawing */
356 {
357 if (state.current_icon==POINTERICON)
358 edit_button(&bev,VIEW(l2));
359 };
360
361 break;
362
363 }; /* end switch */
364
365 }
366