2 Widgets for the Midnight Commander
4 Copyright (C) 1994-2016
5 Free Software Foundation, Inc.
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/>.
27 * \brief Header: High-level mouse API
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 /* --------------------------------------------------------------------------------------------- */
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
60 init_mouse_event (mouse_event_t
* event
, mouse_msg_t msg
, const Gpm_Event
* global_gpm
,
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 /* --------------------------------------------------------------------------------------------- */
77 * Translate GPM event to high-level event,
79 * @param w Widget object
80 * @param event GPM event
82 * @return high level mouse event
85 mouse_translate_event (Widget
* w
, Gpm_Event
* event
)
88 mouse_msg_t msg
= MSG_MOUSE_NONE
;
92 * Very special widgets may want to control area outside their bounds.
93 * For such widgets you will have to turn on the 'forced_capture' flag.
94 * You'll also need, in your mouse handler, to inform the system of
95 * events you want to pass on by setting 'event->result.abort' to TRUE.
97 in_widget
= w
->mouse
.forced_capture
|| mouse_global_in_widget (event
, w
);
99 if ((event
->type
& GPM_DOWN
) != 0)
103 if ((event
->buttons
& GPM_B_UP
) != 0)
104 msg
= MSG_MOUSE_SCROLL_UP
;
105 else if ((event
->buttons
& GPM_B_DOWN
) != 0)
106 msg
= MSG_MOUSE_SCROLL_DOWN
;
109 /* Handle normal buttons: anything but the mouse wheel's.
111 * (Note that turning on capturing for the mouse wheel
112 * buttons doesn't make sense as they don't generate a
113 * mouse_up event, which means we'd never get uncaptured.)
115 w
->mouse
.capture
= TRUE
;
116 msg
= MSG_MOUSE_DOWN
;
118 w
->mouse
.last_buttons_down
= event
->buttons
;
122 else if ((event
->type
& GPM_UP
) != 0)
124 /* We trigger the mouse_up event even when !in_widget. That's
125 * because, for example, a paint application should stop drawing
126 * lines when the button is released even outside the canvas. */
127 if (w
->mouse
.capture
)
129 w
->mouse
.capture
= FALSE
;
133 * When using xterm, event->buttons reports the buttons' state
134 * after the event occurred (meaning that event->buttons is zero,
135 * because the mouse button is now released). When using GPM,
136 * however, that field reports the button(s) that was released.
138 * The following makes xterm behave effectively like GPM:
140 if (event
->buttons
== 0)
141 event
->buttons
= w
->mouse
.last_buttons_down
;
144 else if ((event
->type
& GPM_DRAG
) != 0)
146 if (w
->mouse
.capture
)
147 msg
= MSG_MOUSE_DRAG
;
149 else if ((event
->type
& GPM_MOVE
) != 0)
152 msg
= MSG_MOUSE_MOVE
;
155 init_mouse_event (&local
, msg
, event
, w
);
160 /* --------------------------------------------------------------------------------------------- */
163 * Call widget mouse handler to process high-level mouse event.
165 * Besides sending to the widget the event itself, this function may also
166 * send one or more pseudo events. Currently, MSG_MOUSE_CLICK is the only
167 * pseudo event in existence but in the future (e.g., with the introduction
168 * of a drag-drop API) there may be more.
170 * @param w Widget object
171 * @param event high level mouse event
173 * @return result of mouse event handling
176 mouse_process_event (Widget
* w
, mouse_event_t
* event
)
178 int ret
= MOU_UNHANDLED
;
180 if (event
->msg
!= MSG_MOUSE_NONE
)
182 w
->mouse_callback (w
, event
->msg
, event
);
184 /* Upon releasing the mouse button: if the mouse hasn't been dragged
185 * since the MSG_MOUSE_DOWN, we also trigger a click. */
186 if (event
->msg
== MSG_MOUSE_UP
&& w
->mouse
.last_msg
== MSG_MOUSE_DOWN
)
187 w
->mouse_callback (w
, MSG_MOUSE_CLICK
, event
);
189 /* Record the current event type for the benefit of the next event. */
190 w
->mouse
.last_msg
= event
->msg
;
192 if (!event
->result
.abort
)
193 ret
= event
->result
.repeat
? MOU_REPEAT
: MOU_NORMAL
;
199 /* --------------------------------------------------------------------------------------------- */