]> git.itanic.dy.fi Git - maemo-mapper/blob - src/input.c
Added ability to set "Toggle Tracking" as a hardware key.
[maemo-mapper] / src / input.c
1 /*
2  * Copyright (C) 2006, 2007 John Costigan.
3  *
4  * POI and GPS-Info code originally written by Cezary Jackiewicz.
5  *
6  * Default map data provided by http://www.openstreetmap.org/
7  *
8  * This file is part of Maemo Mapper.
9  *
10  * Maemo Mapper is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * Maemo Mapper is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Maemo Mapper.  If not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #    include "config.h"
26 #endif
27
28 #define _GNU_SOURCE
29
30 #include <math.h>
31 #include <gdk/gdkkeysyms.h>
32
33 #ifndef LEGACY
34 #    include <hildon/hildon-defines.h>
35 #    include <hildon/hildon-banner.h>
36 #else
37 #    include <hildon-widgets/hildon-defines.h>
38 #    include <hildon-widgets/hildon-banner.h>
39 #endif
40
41 #include "types.h"
42 #include "data.h"
43 #include "defines.h"
44
45 #include "display.h"
46 #include "gdk-pixbuf-rotate.h"
47 #include "gps.h"
48 #include "input.h"
49 #include "maps.h"
50 #include "path.h"
51 #include "poi.h"
52 #include "util.h"
53
54 static gint _key_zoom_is_down = FALSE;
55 static gint _key_zoom_new = -1;
56 static gint _key_zoom_timeout_sid = 0;
57 static gint _key_pan_is_down = FALSE;
58 static gfloat _key_pan_incr_devx = 0;
59 static gfloat _key_pan_incr_devy = 0;
60 static gint _key_pan_timeout_sid = 0;
61
62 static gboolean
63 key_pan_timeout(CustomAction action)
64 {
65     printf("%s()\n", __PRETTY_FUNCTION__);
66     if(_key_pan_is_down)
67     {
68         /* The pan key is still down.  Continue panning. */
69         _map_offset_devx += -_key_pan_incr_devx;
70         _map_offset_devy += -_key_pan_incr_devy;
71         MACRO_QUEUE_DRAW_AREA();
72         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
73         return TRUE;
74     }
75     else
76     {
77         gfloat panx_adj, pany_adj;
78         /* Time is up for further action - execute the pan. */
79         /* Adjust for rotate angle. */
80         gdk_pixbuf_rotate_vector(&panx_adj, &pany_adj, _map_reverse_matrix,
81                 _map_offset_devx, _map_offset_devy);
82         map_pan(-pixel2unit((gint)(panx_adj + 0.5f)),
83                     -pixel2unit((gint)(pany_adj + 0.5f)));
84         _key_pan_timeout_sid = 0;
85         vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
86         return FALSE;
87     }
88 }
89
90 static gboolean
91 key_zoom_timeout(CustomAction action)
92 {
93     printf("%s()\n", __PRETTY_FUNCTION__);
94     if(_key_zoom_is_down)
95     {
96         /* The zoom key is still down.  Continue zooming. */
97         if(action == CUSTOM_ACTION_ZOOM_IN)
98         {
99             /* We're currently zooming in (_zoom is decreasing). */
100             gint test = _key_zoom_new - _curr_repo->view_zoom_steps;
101             if(test >= 0)
102                 /* We can zoom some more.  Hurray! */
103                 _key_zoom_new = test;
104         }
105         else
106         {
107             /* We're currently zooming out (_zoom is increasing). */
108             gint test = _key_zoom_new + _curr_repo->view_zoom_steps;
109             if(test <= MAX_ZOOM)
110                 /* We can zoom some more.  Hurray! */
111                 _key_zoom_new = test;
112         }
113         /* Tell them where they're about to zoom. */
114         {
115             gchar buffer[32];
116             snprintf(buffer, sizeof(buffer),
117                     "%s %d", _("Zoom to Level"), _key_zoom_new);
118             MACRO_BANNER_SHOW_INFO(_window, buffer);
119         }
120         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
121         return TRUE;
122     }
123     else
124     {
125         /* Time is up for further action - execute. */
126         if(_key_zoom_new != _zoom)
127             map_set_zoom(_key_zoom_new);
128         _key_pan_timeout_sid = 0;
129         _key_zoom_new = -1;
130         vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
131         return FALSE;
132     }
133
134 }
135
136 static CustomKey
137 get_custom_key_from_keyval(gint keyval)
138 {
139     CustomKey custom_key;
140     printf("%s(%d)\n", __PRETTY_FUNCTION__, keyval);
141
142     switch(keyval)
143     {
144         case HILDON_HARDKEY_UP:
145             custom_key = CUSTOM_KEY_UP;
146             break;
147         case HILDON_HARDKEY_DOWN:
148             custom_key = CUSTOM_KEY_DOWN;
149             break;
150         case HILDON_HARDKEY_LEFT:
151             custom_key = CUSTOM_KEY_LEFT;
152             break;
153         case HILDON_HARDKEY_RIGHT:
154             custom_key = CUSTOM_KEY_RIGHT;
155             break;
156         case HILDON_HARDKEY_SELECT:
157             custom_key = CUSTOM_KEY_SELECT;
158             break;
159         case HILDON_HARDKEY_INCREASE:
160             custom_key = CUSTOM_KEY_INCREASE;
161             break;
162         case HILDON_HARDKEY_DECREASE:
163             custom_key = CUSTOM_KEY_DECREASE;
164             break;
165         case HILDON_HARDKEY_FULLSCREEN:
166             custom_key = CUSTOM_KEY_FULLSCREEN;
167             break;
168         case HILDON_HARDKEY_ESC:
169             custom_key = CUSTOM_KEY_ESC;
170             break;
171         default:
172             custom_key = -1;
173     }
174
175     vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, custom_key);
176     return custom_key;
177 }
178
179 gboolean
180 window_cb_key_press(GtkWidget* widget, GdkEventKey *event)
181 {
182     CustomKey custom_key;
183     printf("%s()\n", __PRETTY_FUNCTION__);
184
185     custom_key = get_custom_key_from_keyval(event->keyval);
186     if(custom_key == -1)
187         return FALSE; /* Not our event. */
188
189     switch(_action[custom_key])
190     {
191         case CUSTOM_ACTION_PAN_NORTH:
192         case CUSTOM_ACTION_PAN_SOUTH:
193         case CUSTOM_ACTION_PAN_EAST:
194         case CUSTOM_ACTION_PAN_WEST:
195         case CUSTOM_ACTION_PAN_UP:
196         case CUSTOM_ACTION_PAN_DOWN:
197         case CUSTOM_ACTION_PAN_LEFT:
198         case CUSTOM_ACTION_PAN_RIGHT:
199             if(!_key_pan_is_down)
200             {
201                 _key_pan_is_down = TRUE;
202                 if(_center_mode > 0)
203                     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
204                                 _menu_view_ac_none_item), FALSE);
205                 if(_key_pan_timeout_sid)
206                 {
207                     g_source_remove(_key_pan_timeout_sid);
208                     _key_pan_timeout_sid = 0;
209                 }
210                 /* Figure out new pan. */
211                 switch(_action[custom_key])
212                 {
213                     case CUSTOM_ACTION_PAN_UP:
214                     case CUSTOM_ACTION_PAN_NORTH:
215                         _key_pan_incr_devy = -PAN_PIXELS;
216                         break;
217                     case CUSTOM_ACTION_PAN_SOUTH:
218                     case CUSTOM_ACTION_PAN_DOWN:
219                         _key_pan_incr_devy = PAN_PIXELS;
220                         break;
221                     case CUSTOM_ACTION_PAN_EAST:
222                     case CUSTOM_ACTION_PAN_RIGHT:
223                         _key_pan_incr_devx = PAN_PIXELS;
224                         break;
225                     case CUSTOM_ACTION_PAN_WEST:
226                     case CUSTOM_ACTION_PAN_LEFT:
227                         _key_pan_incr_devx = -PAN_PIXELS;
228                         break;
229                     default:
230                         g_printerr("Invalid action in key_pan_timeout(): %d\n",
231                                 _action[custom_key]);
232                 }
233                 switch(_action[custom_key])
234                 {
235                     case CUSTOM_ACTION_PAN_NORTH:
236                     case CUSTOM_ACTION_PAN_SOUTH:
237                     case CUSTOM_ACTION_PAN_EAST:
238                     case CUSTOM_ACTION_PAN_WEST:
239                         /* Adjust for rotate angle. */
240                         gdk_pixbuf_rotate_vector(&_key_pan_incr_devx,
241                                 &_key_pan_incr_devy, _map_rotate_matrix,
242                                 _key_pan_incr_devx, _key_pan_incr_devy);
243                     default:
244                         ;
245                 }
246                 key_pan_timeout(_action[custom_key]);
247                 _key_pan_timeout_sid = g_timeout_add_full(G_PRIORITY_HIGH_IDLE,
248                         250, (GSourceFunc)key_pan_timeout,
249                         (gpointer)(_action[custom_key]), NULL);
250             }
251             break;
252
253         case CUSTOM_ACTION_RESET_VIEW_ANGLE:
254             map_rotate(-_next_map_rotate_angle);
255             break;
256
257         case CUSTOM_ACTION_ROTATE_CLOCKWISE:
258         {
259             map_rotate(-ROTATE_DEGREES);
260             break;
261         }
262
263         case CUSTOM_ACTION_ROTATE_COUNTERCLOCKWISE:
264         {
265             map_rotate(ROTATE_DEGREES);
266             break;
267         }
268
269         case CUSTOM_ACTION_TOGGLE_AUTOROTATE:
270             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
271                         _menu_view_rotate_auto_item), !_center_rotate);
272             break;
273
274         case CUSTOM_ACTION_TOGGLE_AUTOCENTER:
275             switch(_center_mode)
276             {
277                 case CENTER_LATLON:
278                 case CENTER_WAS_LEAD:
279                     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
280                                 _menu_view_ac_lead_item), TRUE);
281                     break;
282                 case CENTER_LEAD:
283                 case CENTER_WAS_LATLON:
284                     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
285                                 _menu_view_ac_latlon_item), TRUE);
286                     break;
287             }
288             break;
289
290         case CUSTOM_ACTION_ZOOM_IN:
291         case CUSTOM_ACTION_ZOOM_OUT:
292             if(!_key_zoom_is_down)
293             {
294                 _key_zoom_is_down = TRUE;
295                 if(_key_zoom_timeout_sid)
296                 {
297                     g_source_remove(_key_zoom_timeout_sid);
298                     _key_zoom_timeout_sid = 0;
299                 }
300                 if(_key_zoom_new == -1)
301                     _key_zoom_new = _next_zoom;
302                 _key_zoom_new = _key_zoom_new
303                     + (_action[custom_key] == CUSTOM_ACTION_ZOOM_IN
304                             ? -_curr_repo->view_zoom_steps
305                             : _curr_repo->view_zoom_steps);
306                 BOUND(_key_zoom_new, 0, MAX_ZOOM);
307                 {
308                     gchar buffer[80];
309                     snprintf(buffer, sizeof(buffer),"%s %d",
310                             _("Zoom to Level"), _key_zoom_new);
311                     MACRO_BANNER_SHOW_INFO(_window, buffer);
312                 }
313                 _key_zoom_timeout_sid =g_timeout_add_full(G_PRIORITY_HIGH_IDLE,
314                         500, (GSourceFunc)key_zoom_timeout,
315                         (gpointer)(_action[custom_key]), NULL);
316             }
317             break;
318
319         case CUSTOM_ACTION_TOGGLE_FULLSCREEN:
320             gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
321                         _menu_view_fullscreen_item), !_fullscreen);
322             break;
323
324         case CUSTOM_ACTION_TOGGLE_TRACKING:
325             gtk_check_menu_item_set_active(
326                     GTK_CHECK_MENU_ITEM(_menu_track_enable_tracking_item),
327                     !_enable_tracking);
328             break;
329
330         case CUSTOM_ACTION_TOGGLE_TRACKS:
331             switch(_show_paths)
332             {
333                 case 0:
334                     /* Nothing shown, nothing saved; just set both. */
335                     _show_paths = TRACKS_MASK | ROUTES_MASK;
336                     break;
337                 case TRACKS_MASK << 16:
338                 case ROUTES_MASK << 16:
339                 case (ROUTES_MASK | TRACKS_MASK) << 16:
340                     /* Something was saved and nothing changed since.
341                      * Restore saved. */
342                     _show_paths = _show_paths >> 16;
343                     break;
344                 default:
345                     /* There is no history, or they changed something
346                      * since the last historical change. Save and
347                      * clear. */
348                     _show_paths = _show_paths << 16;
349             }
350             gtk_check_menu_item_set_active(
351                     GTK_CHECK_MENU_ITEM(_menu_view_show_routes_item),
352                     _show_paths & ROUTES_MASK);
353
354             gtk_check_menu_item_set_active(
355                     GTK_CHECK_MENU_ITEM(_menu_view_show_tracks_item),
356                     _show_paths & TRACKS_MASK);
357
358         case CUSTOM_ACTION_TOGGLE_SCALE:
359             gtk_check_menu_item_set_active(
360                     GTK_CHECK_MENU_ITEM(_menu_view_show_scale_item),
361                     !_show_scale);
362             break;
363
364         case CUSTOM_ACTION_TOGGLE_POI:
365             gtk_check_menu_item_set_active(
366                     GTK_CHECK_MENU_ITEM(_menu_view_show_poi_item),
367                     !_show_poi);
368             break;
369         case CUSTOM_ACTION_CHANGE_REPO: {
370             GList *curr = g_list_find(_repo_list, _curr_repo);
371             if(!curr)
372                 break;
373
374             /* Loop until we reach a next-able repo, or until we get
375              * back to the current repo. */
376             while((curr = (curr->next ? curr->next : _repo_list))
377                     && !((RepoData*)curr->data)->nextable
378                     && curr->data != _curr_repo) { }
379
380             if(curr->data != _curr_repo)
381             {
382                 repo_set_curr(curr->data);
383                 gtk_check_menu_item_set_active(
384                         GTK_CHECK_MENU_ITEM(_curr_repo->menu_item),
385                         TRUE);
386             }
387             else
388             {
389                 popup_error(_window,
390                     _("There are no other next-able repositories."));
391             }
392             break;
393         }
394
395         case CUSTOM_ACTION_RESET_BLUETOOTH:
396             reset_bluetooth();
397             break;
398
399         case CUSTOM_ACTION_ROUTE_DISTNEXT:
400             route_show_distance_to_next();
401             break;
402
403         case CUSTOM_ACTION_ROUTE_DISTLAST:
404             route_show_distance_to_last();
405             break;
406
407         case CUSTOM_ACTION_TRACK_BREAK:
408             track_insert_break(TRUE);
409             break;
410
411         case CUSTOM_ACTION_TRACK_CLEAR:
412             track_clear();
413             break;
414
415         case CUSTOM_ACTION_TRACK_DISTLAST:
416             track_show_distance_from_last();
417             break;
418
419         case CUSTOM_ACTION_TRACK_DISTFIRST:
420             track_show_distance_from_first();
421             break;
422
423         case CUSTOM_ACTION_TOGGLE_GPS:
424             gtk_check_menu_item_set_active(
425                     GTK_CHECK_MENU_ITEM(_menu_gps_enable_item),
426                     !_enable_gps);
427             break;
428
429         case CUSTOM_ACTION_TOGGLE_GPSINFO:
430             gtk_check_menu_item_set_active(
431                     GTK_CHECK_MENU_ITEM(_menu_gps_show_info_item),
432                     !_gps_info);
433             break;
434
435         case CUSTOM_ACTION_TOGGLE_SPEEDLIMIT:
436             _speed_limit_on ^= 1;
437             break;
438
439         default:
440             vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
441             return FALSE;
442     }
443
444     return TRUE;
445     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
446 }
447
448 gboolean
449 window_cb_key_release(GtkWidget* widget, GdkEventKey *event)
450 {
451     CustomKey custom_key;
452     printf("%s()\n", __PRETTY_FUNCTION__);
453
454     custom_key = get_custom_key_from_keyval(event->keyval);
455     if(custom_key < 0)
456         return FALSE; /* Not our event. */
457
458     switch(_action[custom_key])
459     {
460         case CUSTOM_ACTION_ZOOM_IN:
461         case CUSTOM_ACTION_ZOOM_OUT:
462             if(_key_zoom_timeout_sid)
463             {
464                 g_source_remove(_key_zoom_timeout_sid);
465                 _key_zoom_timeout_sid = 0;
466                 _key_zoom_timeout_sid =g_timeout_add_full(G_PRIORITY_HIGH_IDLE,
467                         500, (GSourceFunc)key_zoom_timeout, NULL, NULL);
468             }
469             _key_zoom_is_down = FALSE;
470             return TRUE;
471
472         case CUSTOM_ACTION_PAN_NORTH:
473         case CUSTOM_ACTION_PAN_SOUTH:
474         case CUSTOM_ACTION_PAN_EAST:
475         case CUSTOM_ACTION_PAN_WEST:
476         case CUSTOM_ACTION_PAN_UP:
477         case CUSTOM_ACTION_PAN_DOWN:
478         case CUSTOM_ACTION_PAN_LEFT:
479         case CUSTOM_ACTION_PAN_RIGHT:
480             if(_key_pan_timeout_sid)
481             {
482                 g_source_remove(_key_pan_timeout_sid);
483                 _key_pan_timeout_sid = g_timeout_add_full(G_PRIORITY_HIGH_IDLE,
484                         500, (GSourceFunc)key_pan_timeout, NULL, NULL);
485             }
486             _key_pan_is_down = FALSE;
487             _key_pan_incr_devx = 0;
488             _key_pan_incr_devy = 0;
489             return TRUE;
490
491         default:
492             return FALSE;
493     }
494     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
495 }
496
497 gboolean
498 map_cb_motion_notify(GtkWidget *widget, GdkEventMotion *event)
499 {
500     gint x, y;
501     GdkModifierType state;
502     printf("%s()\n", __PRETTY_FUNCTION__);
503
504     if(!_mouse_is_down)
505         return FALSE;
506
507     if(event->is_hint)
508         gdk_window_get_pointer(event->window, &x, &y, &state);
509     else
510     {
511         x = event->x;
512         y = event->y;
513         state = event->state;
514     }
515
516     if(_mouse_is_dragging)
517     {
518         /* Already in the process of dragging.  Set the offset. */
519         _map_offset_devx = x - _cmenu_position_x;
520         _map_offset_devy = y - _cmenu_position_y;
521         MACRO_QUEUE_DRAW_AREA();
522     }
523     else
524     {
525         gint diffx = x - _cmenu_position_x - _map_offset_devx;
526         gint diffy = y - _cmenu_position_y - _map_offset_devy;
527         if(diffx * diffx + diffy + diffy > 100)
528         {
529             _mouse_is_dragging = TRUE;
530         }
531     }
532
533     /* Return FALSE to allow context menu to work. */
534     vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
535     return TRUE;
536 }
537
538 gboolean
539 map_cb_button_press(GtkWidget *widget, GdkEventButton *event)
540 {
541     printf("%s()\n", __PRETTY_FUNCTION__);
542
543     if(!_mouse_is_down)
544     {
545         _cmenu_position_x = event->x + 0.5 - _map_offset_devx;
546         _cmenu_position_y = event->y + 0.5 - _map_offset_devy;
547         g_mutex_lock(_mouse_mutex);
548         _mouse_is_down = TRUE;
549     }
550
551     /* Return FALSE to allow context menu to work. */
552     vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
553     return FALSE;
554 }
555
556 gboolean
557 map_cb_button_release(GtkWidget *widget, GdkEventButton *event)
558 {
559     printf("%s()\n", __PRETTY_FUNCTION__);
560
561     if(!_mouse_is_down)
562     {
563         /* We didn't know about it anyway.  Return FALSE. */
564         vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
565         return FALSE;
566     }
567
568     _mouse_is_down = FALSE;
569
570 #ifdef DEBUG
571     if(event->button != 1)
572     {   
573         screen2unit((gint)(event->x + 0.5), (gint)(event->y + 0.5),
574                 _pos.unitx, _pos.unity);
575         unit2latlon(_pos.unitx, _pos.unity, _gps.lat, _gps.lon);
576         /* Test unit-to-lat/lon conversion. */
577         latlon2unit(_gps.lat, _gps.lon, _pos.unitx, _pos.unity);
578         _gps.speed = ((gint)(_gps.speed + 5) % 60);
579         _gps.heading = ((gint)(_gps.heading + 5) % 360);
580         if(track_add(time(NULL), FALSE))
581         {
582             /* Move mark to new location. */
583             map_refresh_mark(FALSE);
584         }
585         else
586         {
587             map_move_mark();
588         }
589     }
590     else
591 #endif
592     if(_mouse_is_dragging)
593     {
594         Point clkpt;
595
596         _mouse_is_dragging = FALSE;
597
598         screen2unit(_view_halfwidth_pixels, _view_halfheight_pixels,
599                 clkpt.unitx, clkpt.unity);
600
601         if(_center_mode > 0)
602         {
603             gfloat matrix[4];
604             gint mvpt_unitx, mvpt_unity;
605             gfloat new_offset_unitx, new_offset_unity;
606             /* If auto-center is enabled (meaning that panning will cause the
607              * view the rotate according to the heading), rotate the new
608              * unitx/unity around the mvpt, by any changes in _gps.heading
609              * since the last time _map_rotate_angle was updated.  The end
610              * result is that the point the user is moving stays in the same
611              * relative point, even if the heading has since changed. */
612             gdk_pixbuf_rotate_matrix_fill_for_rotation(matrix,
613                     deg2rad(_gps.heading - _next_map_rotate_angle));
614             buf2unit(_cmenu_position_x, _cmenu_position_y,
615                     mvpt_unitx, mvpt_unity);
616             gdk_pixbuf_rotate_vector(&new_offset_unitx, &new_offset_unity,
617                     matrix,
618                     (gint)(clkpt.unitx - mvpt_unitx),
619                     (gint)(clkpt.unity -mvpt_unity));
620             clkpt.unitx = mvpt_unitx + new_offset_unitx;
621             clkpt.unity = mvpt_unity + new_offset_unity;
622         }
623
624         if(_center_mode > 0)
625             gtk_check_menu_item_set_active(
626                     GTK_CHECK_MENU_ITEM(_menu_view_ac_none_item), TRUE);
627
628         map_center_unit(clkpt);
629     }
630     else
631     {
632         gboolean selected_point = FALSE;
633         Point clkpt;
634         screen2unit(event->x, event->y, clkpt.unitx, clkpt.unity);
635
636         if(_show_poi && (_poi_zoom > _zoom))
637         {
638             PoiInfo poi;
639             selected_point = select_poi(
640                     clkpt.unitx, clkpt.unity, &poi, TRUE);
641             if(selected_point)
642             {
643                 gchar *banner;
644                 banner = g_strdup_printf("%s (%s)", poi.label, poi.clabel);
645                 MACRO_BANNER_SHOW_INFO(_window, banner);
646                 g_free(banner);
647                 g_free(poi.label);
648                 g_free(poi.desc);
649                 g_free(poi.clabel);
650             }
651         }
652         if(!selected_point && (_show_paths & ROUTES_MASK)
653                 && _route.whead <= _route.wtail)
654         {
655             WayPoint *way = find_nearest_waypoint(
656                     clkpt.unitx, clkpt.unity);
657             if(way)
658             {
659                 selected_point = TRUE;
660                 MACRO_BANNER_SHOW_INFO(_window, way->desc);
661             }
662         }
663         if(!selected_point)
664         {
665             if(_center_mode > 0)
666                 gtk_check_menu_item_set_active(
667                         GTK_CHECK_MENU_ITEM(_menu_view_ac_none_item), TRUE);
668             map_center_unit_full(clkpt, _next_zoom,
669                     _center_mode > 0 && _center_rotate
670                     ? _gps.heading : _next_map_rotate_angle);
671         }
672     }
673
674     g_mutex_unlock(_mouse_mutex);
675
676     /* Return FALSE to avoid context menu (if it hasn't popped up already). */
677     vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
678     return FALSE;
679 }
680
681 void
682 input_init()
683 {
684     printf("%s():\n", __PRETTY_FUNCTION__);
685
686     g_signal_connect(G_OBJECT(_window), "key_press_event",
687             G_CALLBACK(window_cb_key_press), NULL);
688
689     g_signal_connect(G_OBJECT(_window), "key_release_event",
690             G_CALLBACK(window_cb_key_release), NULL);
691
692     g_signal_connect(G_OBJECT(_map_widget), "motion_notify_event",
693             G_CALLBACK(map_cb_motion_notify), NULL);
694
695     g_signal_connect(G_OBJECT(_map_widget), "button_press_event",
696             G_CALLBACK(map_cb_button_press), NULL);
697
698     g_signal_connect(G_OBJECT(_map_widget), "button_release_event",
699             G_CALLBACK(map_cb_button_release), NULL);
700
701     gtk_widget_add_events(_map_widget,
702             GDK_EXPOSURE_MASK
703             | GDK_POINTER_MOTION_MASK
704             | GDK_POINTER_MOTION_HINT_MASK
705             | GDK_BUTTON_PRESS_MASK
706             | GDK_BUTTON_RELEASE_MASK);
707
708     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
709 }