Drop old mouse API and use the new one.
[midnight-commander.git] / lib / widget / mouse.c
blob6e63a876793d684c12c9451e38fa7ed62eab9996
1 /*
2 Widgets for the Midnight Commander
4 Copyright (C) 1994-2016
5 Free Software Foundation, Inc.
7 Authors:
8 Human beings.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 /** \file mouse.c
27 * \brief Header: High-level mouse API
30 #include <config.h>
32 #include "lib/global.h"
33 #include "lib/widget.h"
35 #include "lib/widget/mouse.h"
37 /*** global variables ****************************************************************************/
39 /*** file scope macro definitions ****************************************************************/
41 /*** file scope type declarations ****************************************************************/
43 /*** file scope variables ************************************************************************/
45 /* --------------------------------------------------------------------------------------------- */
46 /*** file scope functions ************************************************************************/
47 /* --------------------------------------------------------------------------------------------- */
49 /**
50 * Constructs a mouse event structure.
52 * It receives a Gpm_Event event and translates it into a higher level protocol.
54 * Tip: for details on the C mouse API, see MC's lib/tty/mouse.h,
55 * or GPM's excellent 'info' manual:
57 * http://www.fifi.org/cgi-bin/info2www?(gpm)Event+Types
59 static void
60 init_mouse_event (mouse_event_t * event, mouse_msg_t msg, const Gpm_Event * global_gpm,
61 const Widget * w)
63 event->msg = msg;
64 event->x = global_gpm->x - w->x - 1; /* '-1' because Gpm_Event is 1-based. */
65 event->y = global_gpm->y - w->y - 1;
66 event->count = global_gpm->type & (GPM_SINGLE | GPM_DOUBLE | GPM_TRIPLE);
67 event->buttons = global_gpm->buttons;
68 event->result.abort = FALSE;
69 event->result.repeat = FALSE;
72 /* --------------------------------------------------------------------------------------------- */
73 /*** public functions ****************************************************************************/
74 /* --------------------------------------------------------------------------------------------- */
76 /**
77 * Translate GPM event to high-level event,
79 * @param w Widget object
80 * @param event GPM event
81 * @param click whether mouse click was raised or not
83 * @return high level mouse event
85 mouse_event_t
86 mouse_translate_event (Widget * w, Gpm_Event * event, gboolean * click)
88 gboolean in_widget;
89 mouse_msg_t msg = MSG_MOUSE_NONE;
90 mouse_event_t local;
93 * Very special widgets may want to control area outside their bounds.
94 * For such widgets you will have to turn on the 'forced_capture' flag.
95 * You'll also need, in your mouse handler, to inform the system of
96 * events you want to pass on by setting 'event->result.abort' to TRUE.
98 in_widget = w->mouse.forced_capture || mouse_global_in_widget (event, w);
100 *click = FALSE;
102 if ((event->type & GPM_DOWN) != 0)
104 if (in_widget)
106 if ((event->buttons & GPM_B_UP) != 0)
107 msg = MSG_MOUSE_SCROLL_UP;
108 else if ((event->buttons & GPM_B_DOWN) != 0)
109 msg = MSG_MOUSE_SCROLL_DOWN;
110 else
112 /* Handle normal buttons: anything but the mouse wheel's.
114 * (Note that turning on capturing for the mouse wheel
115 * buttons doesn't make sense as they don't generate a
116 * mouse_up event, which means we'd never get uncaptured.)
118 w->mouse.capture = TRUE;
119 msg = MSG_MOUSE_DOWN;
121 w->mouse.last_buttons_down = event->buttons;
125 else if ((event->type & GPM_UP) != 0)
127 /* We trigger the mouse_up event even when !in_widget. That's
128 * because, for example, a paint application should stop drawing
129 * lines when the button is released even outside the canvas. */
130 if (w->mouse.capture)
132 w->mouse.capture = FALSE;
133 msg = MSG_MOUSE_UP;
135 if (in_widget)
136 *click = !w->mouse.was_drag;
139 * When using xterm, event->buttons reports the buttons' state
140 * after the event occurred (meaning that event->buttons is zero,
141 * because the mouse button is now released). When using GPM,
142 * however, that field reports the button(s) that was released.
144 * The following makes xterm behave effectively like GPM:
146 if (event->buttons == 0)
147 event->buttons = w->mouse.last_buttons_down;
150 else if ((event->type & GPM_DRAG) != 0)
152 if (w->mouse.capture)
153 msg = MSG_MOUSE_DRAG;
155 else if ((event->type & GPM_MOVE) != 0)
157 if (in_widget)
158 msg = MSG_MOUSE_MOVE;
161 if (msg != MSG_MOUSE_NONE)
162 /* Remember the current state for next event. */
163 w->mouse.was_drag = ((event->type & GPM_DRAG) != 0);
165 init_mouse_event (&local, msg, event, w);
167 return local;
170 /* --------------------------------------------------------------------------------------------- */
173 * Call widget mouse handler to process high-level mouse event.
175 * @param w Widget object
176 * @param high level mouse event
177 * @param click whether mouse click was raised or not
179 * @return result of mouse event handling
182 mouse_process_event (Widget * w, mouse_event_t * event, gboolean click)
184 int ret = MOU_UNHANDLED;
186 if (event->msg != MSG_MOUSE_NONE)
188 w->mouse_callback (w, event->msg, event);
189 if (click)
190 w->mouse_callback (w, MSG_MOUSE_CLICK, event);
192 if (!event->result.abort)
193 ret = event->result.repeat ? MOU_REPEAT : MOU_NORMAL;
196 return ret;
199 /* --------------------------------------------------------------------------------------------- */