/*
 * Kmscon - Input Handling
 *
 * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@googlemail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * Input Devices
 * This input object can combine multiple linux input devices into a single
 * device and notifies the application about events. It has several different
 * keyboard backends so the full XKB feature set is available.
 */

#ifndef KMSCON_INPUT_H
#define KMSCON_INPUT_H

#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include "shl/eloop.h"

struct input;

/* keep in sync with shl_xkb_mods */
enum input_modifier {
	INPUT_SHIFT_MASK = (1 << 0),
	INPUT_LOCK_MASK = (1 << 1),
	INPUT_CONTROL_MASK = (1 << 2),
	INPUT_ALT_MASK = (1 << 3),
	INPUT_LOGO_MASK = (1 << 4),
};

/* keep in sync with TSM_VTE_INVALID */
#define INPUT_INVALID 0xffffffff

struct input_key_event {
	bool handled;	   /* user-controlled, default is false */
	uint16_t keycode;  /* linux keycode - KEY_* - linux/input.h */
	uint32_t ascii;	   /* ascii keysym for @keycode */
	unsigned int mods; /* active modifiers - input_modifier mask */

	unsigned int num_syms; /* number of keysyms */
	uint32_t *keysyms;     /* XKB-common keysym-array - XKB_KEY_* */
	uint32_t *codepoints;  /* ucs4 unicode value or INPUT_INVALID */
};

enum input_ev_type {
	POINTER_MOVED,
	POINTER_BUTTON,
	POINTER_WHEEL,
	POINTER_SYNC,
	POINTER_HIDE_TIMEOUT,
};

struct input_pointer_event {
	enum input_ev_type event;
	int32_t pointer_x;
	int32_t pointer_y;
	int32_t wheel;
	uint8_t button;
	bool pressed;
	bool double_click;
};

#define INPUT_HAS_MODS(_ev, _mods) (((_ev)->mods & (_mods)) == (_mods))

typedef void (*input_key_cb)(struct input *input, struct input_key_event *ev, void *data);

typedef void (*input_pointer_cb)(struct input *input, struct input_pointer_event *ev, void *data);

typedef int (*uterm_open_cb)(const char *node, int *fd_id, void *data);
typedef void (*uterm_close_cb)(int fd, int fd_id, void *data);

int input_new(struct input **out, struct ev_eloop *eloop);
int input_set_keymap(struct input *input, const char *model, const char *layout,
		     const char *variant, const char *options, const char *locale,
		     const char *keymap, const char *compose_file, size_t compose_file_len);
void input_set_conf(struct input *input, unsigned int repeat_delay, unsigned int repeat_rate,
		    bool mouse_enabled);
void input_ref(struct input *input);
void input_unref(struct input *input);

void *input_add_dev(struct input *input, const char *node);
void input_remove_dev(struct input *input, void *data);

int input_register_key_cb(struct input *input, input_key_cb cb, void *data);
void input_unregister_key_cb(struct input *input, input_key_cb cb, void *data);

int input_register_pointer_cb(struct input *input, input_pointer_cb cb, void *data);
void input_unregister_pointer_cb(struct input *input, input_pointer_cb cb, void *data);

void input_set_device_ops(struct input *input, uterm_open_cb open_cb, uterm_close_cb close_cb,
			  void *data);

void input_sleep(struct input *input);
void input_wake_up(struct input *input);
bool input_is_awake(struct input *input);
void input_set_pointer_max(struct input *input, unsigned int max_x, unsigned int max_y);

void input_set_leds(struct input *input, unsigned int scroll_lock, unsigned int num_lock,
		    unsigned int caps_lock);

#endif /* KMSCON_INPUT_H */
