2015-11-26 01:28:08 +03:00
|
|
|
/*
|
|
|
|
Widgets for the Midnight Commander
|
|
|
|
|
2023-01-03 11:30:57 +03:00
|
|
|
Copyright (C) 2016-2023
|
2015-11-26 01:28:08 +03:00
|
|
|
Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Authors:
|
|
|
|
Human beings.
|
|
|
|
|
|
|
|
This file is part of the Midnight Commander.
|
|
|
|
|
|
|
|
The Midnight Commander is free software: you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation, either version 3 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
The Midnight Commander is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file mouse.c
|
|
|
|
* \brief Header: High-level mouse API
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "lib/global.h"
|
|
|
|
#include "lib/widget.h"
|
|
|
|
|
2016-02-02 14:33:48 +03:00
|
|
|
#include "lib/widget/mouse.h"
|
|
|
|
|
2015-11-26 01:28:08 +03:00
|
|
|
/*** global variables ****************************************************************************/
|
|
|
|
|
|
|
|
/*** file scope macro definitions ****************************************************************/
|
|
|
|
|
|
|
|
/*** file scope type declarations ****************************************************************/
|
|
|
|
|
Update template for .c files.
Add section for forward declarations of local functions. This section is
located before file scope variables because functions can be used in
strucutres (see find.c for example):
/*** forward declarations (file scope functions) *************************************************/
/* button callbacks */
static int start_stop (WButton * button, int action);
static int find_do_view_file (WButton * button, int action);
static int find_do_edit_file (WButton * button, int action);
/*** file scope variables ************************************************************************/
static struct
{
...
bcback_fn callback;
} fbuts[] =
{
...
{ B_STOP, NORMAL_BUTTON, N_("S&uspend"), 0, 0, NULL, start_stop },
...
{ B_VIEW, NORMAL_BUTTON, N_("&View - F3"), 0, 0, NULL, find_do_view_file },
{ B_VIEW, NORMAL_BUTTON, N_("&Edit - F4"), 0, 0, NULL, find_do_edit_file }
};
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2023-02-24 09:27:11 +03:00
|
|
|
/*** forward declarations (file scope functions) *************************************************/
|
|
|
|
|
2015-11-26 01:28:08 +03:00
|
|
|
/*** file scope variables ************************************************************************/
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*** file scope functions ************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
2016-03-06 09:44:16 +03:00
|
|
|
* Constructs a mouse event structure.
|
|
|
|
*
|
|
|
|
* It receives a Gpm_Event event and translates it into a higher level protocol.
|
|
|
|
*
|
|
|
|
* Tip: for details on the C mouse API, see MC's lib/tty/mouse.h,
|
|
|
|
* or GPM's excellent 'info' manual:
|
|
|
|
*
|
|
|
|
* http://www.fifi.org/cgi-bin/info2www?(gpm)Event+Types
|
2015-11-26 01:28:08 +03:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
init_mouse_event (mouse_event_t * event, mouse_msg_t msg, const Gpm_Event * global_gpm,
|
|
|
|
const Widget * w)
|
|
|
|
{
|
|
|
|
event->msg = msg;
|
2022-05-01 10:43:33 +03:00
|
|
|
event->x = global_gpm->x - w->rect.x - 1; /* '-1' because Gpm_Event is 1-based. */
|
|
|
|
event->y = global_gpm->y - w->rect.y - 1;
|
2015-11-26 01:28:08 +03:00
|
|
|
event->count = global_gpm->type & (GPM_SINGLE | GPM_DOUBLE | GPM_TRIPLE);
|
|
|
|
event->buttons = global_gpm->buttons;
|
|
|
|
event->result.abort = FALSE;
|
|
|
|
event->result.repeat = FALSE;
|
|
|
|
}
|
|
|
|
|
2016-02-02 14:33:48 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Translate GPM event to high-level event,
|
|
|
|
*
|
|
|
|
* @param w Widget object
|
|
|
|
* @param event GPM event
|
|
|
|
*
|
|
|
|
* @return high level mouse event
|
|
|
|
*/
|
2016-11-15 09:33:34 +03:00
|
|
|
static mouse_event_t
|
2016-03-23 19:17:05 +03:00
|
|
|
mouse_translate_event (Widget * w, Gpm_Event * event)
|
2016-02-02 14:33:48 +03:00
|
|
|
{
|
2015-11-26 01:28:08 +03:00
|
|
|
gboolean in_widget;
|
|
|
|
mouse_msg_t msg = MSG_MOUSE_NONE;
|
2016-02-02 14:33:48 +03:00
|
|
|
mouse_event_t local;
|
2015-11-26 01:28:08 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Very special widgets may want to control area outside their bounds.
|
|
|
|
* For such widgets you will have to turn on the 'forced_capture' flag.
|
|
|
|
* You'll also need, in your mouse handler, to inform the system of
|
|
|
|
* events you want to pass on by setting 'event->result.abort' to TRUE.
|
|
|
|
*/
|
2016-03-06 09:44:16 +03:00
|
|
|
in_widget = w->mouse.forced_capture || mouse_global_in_widget (event, w);
|
2015-11-26 01:28:08 +03:00
|
|
|
|
|
|
|
if ((event->type & GPM_DOWN) != 0)
|
|
|
|
{
|
|
|
|
if (in_widget)
|
|
|
|
{
|
|
|
|
if ((event->buttons & GPM_B_UP) != 0)
|
|
|
|
msg = MSG_MOUSE_SCROLL_UP;
|
|
|
|
else if ((event->buttons & GPM_B_DOWN) != 0)
|
|
|
|
msg = MSG_MOUSE_SCROLL_DOWN;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Handle normal buttons: anything but the mouse wheel's.
|
|
|
|
*
|
|
|
|
* (Note that turning on capturing for the mouse wheel
|
|
|
|
* buttons doesn't make sense as they don't generate a
|
|
|
|
* mouse_up event, which means we'd never get uncaptured.)
|
|
|
|
*/
|
2016-03-06 09:44:16 +03:00
|
|
|
w->mouse.capture = TRUE;
|
2015-11-26 01:28:08 +03:00
|
|
|
msg = MSG_MOUSE_DOWN;
|
|
|
|
|
2016-03-06 09:44:16 +03:00
|
|
|
w->mouse.last_buttons_down = event->buttons;
|
2015-11-26 01:28:08 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((event->type & GPM_UP) != 0)
|
|
|
|
{
|
|
|
|
/* We trigger the mouse_up event even when !in_widget. That's
|
|
|
|
* because, for example, a paint application should stop drawing
|
|
|
|
* lines when the button is released even outside the canvas. */
|
2016-03-06 09:44:16 +03:00
|
|
|
if (w->mouse.capture)
|
2015-11-26 01:28:08 +03:00
|
|
|
{
|
2016-03-06 09:44:16 +03:00
|
|
|
w->mouse.capture = FALSE;
|
2015-11-26 01:28:08 +03:00
|
|
|
msg = MSG_MOUSE_UP;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When using xterm, event->buttons reports the buttons' state
|
|
|
|
* after the event occurred (meaning that event->buttons is zero,
|
|
|
|
* because the mouse button is now released). When using GPM,
|
|
|
|
* however, that field reports the button(s) that was released.
|
|
|
|
*
|
|
|
|
* The following makes xterm behave effectively like GPM:
|
|
|
|
*/
|
|
|
|
if (event->buttons == 0)
|
2016-03-06 09:44:16 +03:00
|
|
|
event->buttons = w->mouse.last_buttons_down;
|
2015-11-26 01:28:08 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((event->type & GPM_DRAG) != 0)
|
|
|
|
{
|
2016-03-06 09:44:16 +03:00
|
|
|
if (w->mouse.capture)
|
2015-11-26 01:28:08 +03:00
|
|
|
msg = MSG_MOUSE_DRAG;
|
|
|
|
}
|
|
|
|
else if ((event->type & GPM_MOVE) != 0)
|
|
|
|
{
|
|
|
|
if (in_widget)
|
|
|
|
msg = MSG_MOUSE_MOVE;
|
|
|
|
}
|
|
|
|
|
2016-02-02 14:33:48 +03:00
|
|
|
init_mouse_event (&local, msg, event, w);
|
2015-11-26 01:28:08 +03:00
|
|
|
|
2016-02-02 14:33:48 +03:00
|
|
|
return local;
|
2015-11-26 01:28:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
2016-02-02 14:33:48 +03:00
|
|
|
* Call widget mouse handler to process high-level mouse event.
|
2015-11-26 01:28:08 +03:00
|
|
|
*
|
2016-03-23 19:17:05 +03:00
|
|
|
* Besides sending to the widget the event itself, this function may also
|
|
|
|
* send one or more pseudo events. Currently, MSG_MOUSE_CLICK is the only
|
|
|
|
* pseudo event in existence but in the future (e.g., with the introduction
|
|
|
|
* of a drag-drop API) there may be more.
|
|
|
|
*
|
2016-02-02 14:33:48 +03:00
|
|
|
* @param w Widget object
|
2016-03-23 19:17:05 +03:00
|
|
|
* @param event high level mouse event
|
2016-02-02 14:33:48 +03:00
|
|
|
*
|
|
|
|
* @return result of mouse event handling
|
2015-11-26 01:28:08 +03:00
|
|
|
*/
|
2016-11-15 09:33:34 +03:00
|
|
|
static int
|
2016-03-23 19:17:05 +03:00
|
|
|
mouse_process_event (Widget * w, mouse_event_t * event)
|
2015-11-26 01:28:08 +03:00
|
|
|
{
|
2016-02-02 14:33:48 +03:00
|
|
|
int ret = MOU_UNHANDLED;
|
|
|
|
|
|
|
|
if (event->msg != MSG_MOUSE_NONE)
|
|
|
|
{
|
2016-03-06 09:44:16 +03:00
|
|
|
w->mouse_callback (w, event->msg, event);
|
2016-03-23 19:17:05 +03:00
|
|
|
|
2017-01-25 19:36:16 +03:00
|
|
|
/* If a widget aborts a MSG_MOUSE_DOWN, we uncapture it so it
|
|
|
|
* doesn't steal events from other widgets. */
|
|
|
|
if (event->msg == MSG_MOUSE_DOWN && event->result.abort)
|
|
|
|
w->mouse.capture = FALSE;
|
|
|
|
|
2016-03-23 19:17:05 +03:00
|
|
|
/* Upon releasing the mouse button: if the mouse hasn't been dragged
|
|
|
|
* since the MSG_MOUSE_DOWN, we also trigger a click. */
|
|
|
|
if (event->msg == MSG_MOUSE_UP && w->mouse.last_msg == MSG_MOUSE_DOWN)
|
2016-03-06 09:44:16 +03:00
|
|
|
w->mouse_callback (w, MSG_MOUSE_CLICK, event);
|
2016-02-02 14:33:48 +03:00
|
|
|
|
2016-03-23 19:17:05 +03:00
|
|
|
/* Record the current event type for the benefit of the next event. */
|
|
|
|
w->mouse.last_msg = event->msg;
|
|
|
|
|
2016-02-02 14:33:48 +03:00
|
|
|
if (!event->result.abort)
|
|
|
|
ret = event->result.repeat ? MOU_REPEAT : MOU_NORMAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2015-11-26 01:28:08 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 09:33:34 +03:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*** public functions ****************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Translate GPM event to high-level event and process it
|
|
|
|
*
|
|
|
|
* @param w Widget object
|
|
|
|
* @param event GPM event
|
|
|
|
*
|
|
|
|
* @return result of mouse event handling
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
mouse_handle_event (Widget * w, Gpm_Event * event)
|
|
|
|
{
|
|
|
|
mouse_event_t me;
|
|
|
|
|
|
|
|
me = mouse_translate_event (w, event);
|
|
|
|
|
|
|
|
return mouse_process_event (w, &me);
|
|
|
|
}
|
|
|
|
|
2015-11-26 01:28:08 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|