mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-15 22:05:24 -05:00
As long as the mouse button was *pressed* while the pointer was inside the grid, we want to keep reporting motion events until the button is released. Even when the pointer moves outside the grid (but in this case, the reported coordinates are bounded by the grid size). This patch also tries to improve multi-button handling (i.e. multiple buttons pressed at the same time), and the events we report to the client for these, in the following ways: * Motion events now report the *initial* button. That is, if you start a drag operation with the LEFT button, then press RIGHT (before releasing LEFT), keep reporting LEFT in the motion events. * Mouse release events are reported for *any* button, as long as the pointer is *inside* the grid, *or*, the button released was the button used to start a drag operation. The last point is important; if we have reported a button press followed by motion events (i.e. a drag operation), we need to report the button release, *even* if the pointer is outside the grid. Note that the client may receive unbalanced button press/release events in the following ways if the user pressed one, and then a second button *inside* the grid, then releases the *first* button (possibly outside the grid), and finally releases the *second* button *outside* the grid. In this case, both buttons will report press events. The first button will report a release event since it is the initial button in the drag operation. However, we don’t track the fact that the second button is being pressed, and thus if it is released outside the grid, it wont generate a release event.
439 lines
10 KiB
C
439 lines
10 KiB
C
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <wayland-client.h>
|
|
#include <xkbcommon/xkbcommon.h>
|
|
|
|
#include <primary-selection-unstable-v1.h>
|
|
#include <presentation-time.h>
|
|
|
|
#include <tllist.h>
|
|
|
|
#include "fdm.h"
|
|
|
|
/* Forward declarations */
|
|
struct terminal;
|
|
|
|
typedef tll(xkb_keycode_t) xkb_keycode_list_t;
|
|
|
|
struct key_binding {
|
|
xkb_mod_mask_t mods;
|
|
xkb_keysym_t sym;
|
|
xkb_keycode_list_t key_codes;
|
|
};
|
|
typedef tll(struct key_binding) key_binding_list_t;
|
|
|
|
enum bind_action_normal {
|
|
BIND_ACTION_NONE,
|
|
BIND_ACTION_SCROLLBACK_UP_PAGE,
|
|
BIND_ACTION_SCROLLBACK_UP_HALF_PAGE,
|
|
BIND_ACTION_SCROLLBACK_UP_LINE,
|
|
BIND_ACTION_SCROLLBACK_DOWN_PAGE,
|
|
BIND_ACTION_SCROLLBACK_DOWN_HALF_PAGE,
|
|
BIND_ACTION_SCROLLBACK_DOWN_LINE,
|
|
BIND_ACTION_CLIPBOARD_COPY,
|
|
BIND_ACTION_CLIPBOARD_PASTE,
|
|
BIND_ACTION_PRIMARY_PASTE,
|
|
BIND_ACTION_SEARCH_START,
|
|
BIND_ACTION_FONT_SIZE_UP,
|
|
BIND_ACTION_FONT_SIZE_DOWN,
|
|
BIND_ACTION_FONT_SIZE_RESET,
|
|
BIND_ACTION_SPAWN_TERMINAL,
|
|
BIND_ACTION_MINIMIZE,
|
|
BIND_ACTION_MAXIMIZE,
|
|
BIND_ACTION_FULLSCREEN,
|
|
BIND_ACTION_PIPE_SCROLLBACK,
|
|
BIND_ACTION_PIPE_VIEW,
|
|
BIND_ACTION_PIPE_SELECTED,
|
|
|
|
/* Mouse specific actions - i.e. they require a mouse coordinate */
|
|
BIND_ACTION_SELECT_BEGIN,
|
|
BIND_ACTION_SELECT_BEGIN_BLOCK,
|
|
BIND_ACTION_SELECT_EXTEND,
|
|
BIND_ACTION_SELECT_WORD,
|
|
BIND_ACTION_SELECT_WORD_WS,
|
|
BIND_ACTION_SELECT_ROW,
|
|
|
|
BIND_ACTION_KEY_COUNT = BIND_ACTION_PIPE_SELECTED + 1,
|
|
BIND_ACTION_COUNT = BIND_ACTION_SELECT_ROW + 1,
|
|
};
|
|
|
|
struct key_binding_normal {
|
|
struct key_binding bind;
|
|
enum bind_action_normal action;
|
|
char **pipe_argv;
|
|
};
|
|
|
|
struct mouse_binding {
|
|
enum bind_action_normal action;
|
|
xkb_mod_mask_t mods;
|
|
uint32_t button;
|
|
int count;
|
|
char **pipe_argv;
|
|
};
|
|
typedef tll(struct mouse_binding) mouse_binding_list_t;
|
|
|
|
enum bind_action_search {
|
|
BIND_ACTION_SEARCH_NONE,
|
|
BIND_ACTION_SEARCH_CANCEL,
|
|
BIND_ACTION_SEARCH_COMMIT,
|
|
BIND_ACTION_SEARCH_FIND_PREV,
|
|
BIND_ACTION_SEARCH_FIND_NEXT,
|
|
BIND_ACTION_SEARCH_EDIT_LEFT,
|
|
BIND_ACTION_SEARCH_EDIT_LEFT_WORD,
|
|
BIND_ACTION_SEARCH_EDIT_RIGHT,
|
|
BIND_ACTION_SEARCH_EDIT_RIGHT_WORD,
|
|
BIND_ACTION_SEARCH_EDIT_HOME,
|
|
BIND_ACTION_SEARCH_EDIT_END,
|
|
BIND_ACTION_SEARCH_DELETE_PREV,
|
|
BIND_ACTION_SEARCH_DELETE_PREV_WORD,
|
|
BIND_ACTION_SEARCH_DELETE_NEXT,
|
|
BIND_ACTION_SEARCH_DELETE_NEXT_WORD,
|
|
BIND_ACTION_SEARCH_EXTEND_WORD,
|
|
BIND_ACTION_SEARCH_EXTEND_WORD_WS,
|
|
BIND_ACTION_SEARCH_CLIPBOARD_PASTE,
|
|
BIND_ACTION_SEARCH_PRIMARY_PASTE,
|
|
BIND_ACTION_SEARCH_COUNT,
|
|
};
|
|
|
|
struct key_binding_search {
|
|
struct key_binding bind;
|
|
enum bind_action_search action;
|
|
};
|
|
|
|
/* Mime-types we support when dealing with data offers (e.g. copy-paste, or DnD) */
|
|
enum data_offer_mime_type {
|
|
DATA_OFFER_MIME_UNSET,
|
|
DATA_OFFER_MIME_TEXT_PLAIN,
|
|
DATA_OFFER_MIME_TEXT_UTF8,
|
|
DATA_OFFER_MIME_URI_LIST,
|
|
};
|
|
|
|
struct wl_window;
|
|
struct wl_clipboard {
|
|
struct wl_window *window; /* For DnD */
|
|
struct wl_data_source *data_source;
|
|
struct wl_data_offer *data_offer;
|
|
enum data_offer_mime_type mime_type;
|
|
char *text;
|
|
uint32_t serial;
|
|
};
|
|
|
|
struct wl_primary {
|
|
struct zwp_primary_selection_source_v1 *data_source;
|
|
struct zwp_primary_selection_offer_v1 *data_offer;
|
|
enum data_offer_mime_type mime_type;
|
|
char *text;
|
|
uint32_t serial;
|
|
};
|
|
|
|
struct seat {
|
|
struct wayland *wayl;
|
|
struct wl_seat *wl_seat;
|
|
uint32_t wl_name;
|
|
char *name;
|
|
|
|
/* Focused terminals */
|
|
struct terminal *kbd_focus;
|
|
struct terminal *mouse_focus;
|
|
|
|
/* Keyboard state */
|
|
struct wl_keyboard *wl_keyboard;
|
|
struct {
|
|
uint32_t serial;
|
|
|
|
struct xkb_context *xkb;
|
|
struct xkb_keymap *xkb_keymap;
|
|
struct xkb_state *xkb_state;
|
|
struct xkb_compose_table *xkb_compose_table;
|
|
struct xkb_compose_state *xkb_compose_state;
|
|
struct {
|
|
int fd;
|
|
|
|
bool dont_re_repeat;
|
|
int32_t delay;
|
|
int32_t rate;
|
|
uint32_t key;
|
|
} repeat;
|
|
|
|
xkb_mod_index_t mod_shift;
|
|
xkb_mod_index_t mod_alt;
|
|
xkb_mod_index_t mod_ctrl;
|
|
xkb_mod_index_t mod_meta;
|
|
|
|
xkb_keycode_t key_arrow_up;
|
|
xkb_keycode_t key_arrow_down;
|
|
|
|
/* Enabled modifiers */
|
|
bool shift;
|
|
bool alt;
|
|
bool ctrl;
|
|
bool meta;
|
|
|
|
struct {
|
|
tll(struct key_binding_normal) key;
|
|
tll(struct key_binding_search) search;
|
|
} bindings;
|
|
} kbd;
|
|
|
|
/* Pointer state */
|
|
struct wl_pointer *wl_pointer;
|
|
struct {
|
|
uint32_t serial;
|
|
|
|
struct wl_surface *surface;
|
|
struct wl_cursor_theme *theme;
|
|
struct wl_cursor *cursor;
|
|
int scale;
|
|
bool hidden;
|
|
|
|
const char *xcursor;
|
|
struct wl_callback *xcursor_callback;
|
|
bool xcursor_pending;
|
|
} pointer;
|
|
|
|
struct {
|
|
int x;
|
|
int y;
|
|
int col;
|
|
int row;
|
|
int button;
|
|
|
|
/*
|
|
* Button to send in motion events to the client. This is
|
|
* always the *first* button pressed on the grid. If multiple
|
|
* buttons are pressed, the first button is still the one used
|
|
* in motion events.
|
|
*
|
|
* A non-zero value of this *also* indicates that the client
|
|
* should receive events even if the pointer is outside the
|
|
* grid.
|
|
*/
|
|
int button_for_motion_events;
|
|
bool consumed; /* True if a button press was consumed - i.e. if a binding claimed it */
|
|
|
|
int count;
|
|
int last_button;
|
|
struct timeval last_time;
|
|
|
|
/* We used a discrete axis event in the current pointer frame */
|
|
double axis_aggregated;
|
|
bool have_discrete;
|
|
|
|
mouse_binding_list_t bindings;
|
|
} mouse;
|
|
|
|
/* Clipboard */
|
|
struct wl_data_device *data_device;
|
|
struct zwp_primary_selection_device_v1 *primary_selection_device;
|
|
|
|
struct wl_clipboard clipboard;
|
|
struct wl_primary primary;
|
|
|
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
|
/* Input Method Editor */
|
|
struct zwp_text_input_v3 *wl_text_input;
|
|
struct {
|
|
struct {
|
|
struct {
|
|
char *text;
|
|
int32_t cursor_begin;
|
|
int32_t cursor_end;
|
|
} pending;
|
|
} preedit;
|
|
|
|
struct {
|
|
struct {
|
|
char *text;
|
|
} pending;
|
|
} commit;
|
|
|
|
struct {
|
|
struct {
|
|
uint32_t before_length;
|
|
uint32_t after_length;
|
|
} pending;
|
|
} surrounding;
|
|
|
|
uint32_t serial;
|
|
} ime;
|
|
#endif
|
|
};
|
|
|
|
enum csd_surface {
|
|
CSD_SURF_TITLE,
|
|
CSD_SURF_LEFT,
|
|
CSD_SURF_RIGHT,
|
|
CSD_SURF_TOP,
|
|
CSD_SURF_BOTTOM,
|
|
CSD_SURF_MINIMIZE,
|
|
CSD_SURF_MAXIMIZE,
|
|
CSD_SURF_CLOSE,
|
|
CSD_SURF_COUNT,
|
|
};
|
|
|
|
struct monitor {
|
|
struct wayland *wayl;
|
|
struct wl_output *output;
|
|
struct zxdg_output_v1 *xdg;
|
|
uint32_t wl_name;
|
|
|
|
int x;
|
|
int y;
|
|
|
|
struct {
|
|
/* Physical size, in mm */
|
|
struct {
|
|
int width;
|
|
int height;
|
|
} mm;
|
|
|
|
/* Physical size, in pixels */
|
|
struct {
|
|
int width;
|
|
int height;
|
|
} px_real;
|
|
|
|
/* Scaled size, in pixels */
|
|
struct {
|
|
int width;
|
|
int height;
|
|
} px_scaled;
|
|
} dim;
|
|
|
|
struct {
|
|
/* PPI, based on physical size */
|
|
struct {
|
|
int x;
|
|
int y;
|
|
} real;
|
|
|
|
/* PPI, logical, based on scaled size */
|
|
struct {
|
|
int x;
|
|
int y;
|
|
} scaled;
|
|
} ppi;
|
|
|
|
float dpi;
|
|
|
|
int scale;
|
|
float refresh;
|
|
enum wl_output_subpixel subpixel;
|
|
|
|
/* From wl_output */
|
|
char *make;
|
|
char *model;
|
|
|
|
/* From xdg_output */
|
|
char *name;
|
|
char *description;
|
|
|
|
float inch; /* e.g. 24" */
|
|
|
|
bool use_output_release;
|
|
};
|
|
|
|
struct wayland;
|
|
struct wl_window {
|
|
struct terminal *term;
|
|
struct wl_surface *surface;
|
|
struct xdg_surface *xdg_surface;
|
|
struct xdg_toplevel *xdg_toplevel;
|
|
|
|
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
|
|
|
enum {CSD_UNKNOWN, CSD_NO, CSD_YES } use_csd;
|
|
|
|
struct {
|
|
struct wl_surface *surface[CSD_SURF_COUNT];
|
|
struct wl_subsurface *sub_surface[CSD_SURF_COUNT];
|
|
int move_timeout_fd;
|
|
uint32_t serial;
|
|
} csd;
|
|
|
|
/* Scrollback search */
|
|
struct wl_surface *search_surface;
|
|
struct wl_subsurface *search_sub_surface;
|
|
|
|
struct wl_surface *scrollback_indicator_surface;
|
|
struct wl_subsurface *scrollback_indicator_sub_surface;
|
|
|
|
struct wl_surface *render_timer_surface;
|
|
struct wl_subsurface *render_timer_sub_surface;
|
|
|
|
struct wl_callback *frame_callback;
|
|
|
|
tll(const struct monitor *) on_outputs; /* Outputs we're mapped on */
|
|
|
|
bool is_configured;
|
|
bool is_fullscreen;
|
|
bool is_maximized;
|
|
bool is_tiled_top;
|
|
bool is_tiled_bottom;
|
|
bool is_tiled_left;
|
|
bool is_tiled_right;
|
|
bool is_tiled; /* At least one of is_tiled_{top,bottom,left,right} is true */
|
|
struct {
|
|
bool is_activated;
|
|
bool is_fullscreen;
|
|
bool is_maximized;
|
|
bool is_tiled_top;
|
|
bool is_tiled_bottom;
|
|
bool is_tiled_left;
|
|
bool is_tiled_right;
|
|
int width;
|
|
int height;
|
|
} configure;
|
|
};
|
|
|
|
struct config;
|
|
struct terminal;
|
|
struct wayland {
|
|
const struct config *conf;
|
|
struct fdm *fdm;
|
|
|
|
int fd;
|
|
|
|
struct wl_display *display;
|
|
struct wl_registry *registry;
|
|
struct wl_compositor *compositor;
|
|
struct wl_subcompositor *sub_compositor;
|
|
struct wl_shm *shm;
|
|
|
|
struct zxdg_output_manager_v1 *xdg_output_manager;
|
|
|
|
struct xdg_wm_base *shell;
|
|
struct zxdg_decoration_manager_v1 *xdg_decoration_manager;
|
|
|
|
struct wl_data_device_manager *data_device_manager;
|
|
struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager;
|
|
|
|
struct wp_presentation *presentation;
|
|
uint32_t presentation_clock_id;
|
|
|
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
|
struct zwp_text_input_manager_v3 *text_input_manager;
|
|
#endif
|
|
|
|
bool have_argb8888;
|
|
tll(struct monitor) monitors; /* All available outputs */
|
|
tll(struct seat) seats;
|
|
|
|
tll(struct terminal *) terms;
|
|
};
|
|
|
|
struct wayland *wayl_init(const struct config *conf, struct fdm *fdm);
|
|
void wayl_destroy(struct wayland *wayl);
|
|
|
|
void wayl_flush(struct wayland *wayl);
|
|
void wayl_roundtrip(struct wayland *wayl);
|
|
|
|
struct wl_window *wayl_win_init(struct terminal *term);
|
|
void wayl_win_destroy(struct wl_window *win);
|
|
|
|
bool wayl_reload_xcursor_theme(struct seat *seat, int new_scale);
|