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