Compare commits
1 commit
master
...
keybroadca
Author | SHA1 | Date | |
---|---|---|---|
|
32daef9154 |
9 changed files with 522 additions and 19 deletions
8
include/core/keybroadcast.hpp
Normal file
8
include/core/keybroadcast.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef _keybroadcast__hpp__included__
|
||||
#define _keybroadcast__hpp__included__
|
||||
|
||||
void keybroadcast_notify_foreground(bool fg);
|
||||
void keybroadcast_set_master(uint16_t port);
|
||||
void keybroadcast_set_slave(uint16_t port);
|
||||
|
||||
#endif
|
|
@ -303,6 +303,11 @@ struct platform
|
|||
* Parameter sync: If true, execute function call synchronously, else asynchronously.
|
||||
*/
|
||||
static void queue(void (*f)(void* arg), void* arg, bool sync) throw(std::bad_alloc);
|
||||
/**
|
||||
* Set handle to mirror all non-exclusive key events to.
|
||||
*/
|
||||
static void set_mirror_fn(std::function<void(keyboard::modifier_set& mods, keyboard::key& key,
|
||||
keyboard::event& event)> fn);
|
||||
/**
|
||||
* Run all queues.
|
||||
*/
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
void load(const JSON::node& state);
|
||||
JSON::node save();
|
||||
std::string get_summary();
|
||||
void master_enable(bool state);
|
||||
private:
|
||||
struct axis_info
|
||||
{
|
||||
|
@ -109,6 +110,7 @@ private:
|
|||
unsigned next_hat;
|
||||
unsigned jid;
|
||||
mutex_class mutex;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
class set
|
||||
|
@ -127,6 +129,7 @@ public:
|
|||
void set_axismode_cb(std::function<void(unsigned jnum, unsigned num, int mode, double tolerance)> fn);
|
||||
void set_newitem_cb(std::function<void(unsigned jnum, unsigned num, int type)> fn);
|
||||
std::string get_summary();
|
||||
void master_enable(bool state);
|
||||
private:
|
||||
set(const set&);
|
||||
set& operator=(const set&);
|
||||
|
@ -137,6 +140,7 @@ private:
|
|||
std::function<void(unsigned jnum, unsigned num, int type)> newitem_fn;
|
||||
std::vector<pad*> _gamepads;
|
||||
mutex_class mutex;
|
||||
bool enabled;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -245,6 +245,10 @@ public:
|
|||
* Stringify.
|
||||
*/
|
||||
operator std::string() const throw(std::bad_alloc);
|
||||
/**
|
||||
* Get internal set.
|
||||
*/
|
||||
std::set<modifier*> get_set() const throw(std::bad_alloc) { return set; }
|
||||
/**
|
||||
* Equality check.
|
||||
*
|
||||
|
@ -330,16 +334,22 @@ public:
|
|||
*
|
||||
* Parameter _chngmask: The change mask.
|
||||
* Parameter _type: Type of the event.
|
||||
* Parameter _raw: The raw event value.
|
||||
*/
|
||||
event(uint32_t _chngmask, keytype _type) throw()
|
||||
event(uint32_t _chngmask, keytype _type, int32_t _raw) throw()
|
||||
{
|
||||
chngmask = _chngmask;
|
||||
type = _type;
|
||||
raw = _raw;
|
||||
}
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~event() throw();
|
||||
/**
|
||||
* Get original raw state reported.
|
||||
*/
|
||||
int32_t get_raw() const throw() { return raw; }
|
||||
/**
|
||||
* Get analog state. The format is dependent on key type.
|
||||
*/
|
||||
|
@ -357,6 +367,7 @@ public:
|
|||
private:
|
||||
uint32_t chngmask;
|
||||
keytype type;
|
||||
int32_t raw;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -369,8 +380,9 @@ public:
|
|||
* Construct a new key event.
|
||||
*
|
||||
* Parameter chngmask: The change mask.
|
||||
* Parameter _raw: The raw event value.
|
||||
*/
|
||||
event_key(uint32_t chngmask);
|
||||
event_key(uint32_t chngmask, int32_t _raw);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
|
@ -397,8 +409,9 @@ public:
|
|||
* Parameter state: The analog state.
|
||||
* Parameter chngmask: The change mask.
|
||||
* Parameter cal: The calibration structure.
|
||||
* Parameter _raw: The raw event value.
|
||||
*/
|
||||
event_axis(int32_t state, uint32_t chngmask);
|
||||
event_axis(int32_t state, uint32_t chngmask, int32_t _raw);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
|
@ -424,8 +437,9 @@ public:
|
|||
* Construct a new hat event.
|
||||
*
|
||||
* Parameter chngmask: The change mask to use.
|
||||
* Parameter _raw: The raw event value.
|
||||
*/
|
||||
event_hat(uint32_t chngmask);
|
||||
event_hat(uint32_t chngmask, int32_t _raw);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
|
@ -449,8 +463,9 @@ public:
|
|||
*
|
||||
* Parameter state: The game-relative position to use.
|
||||
* Parameter cal: The calibration structure.
|
||||
* Parameter _raw: The raw event value.
|
||||
*/
|
||||
event_mouse(int32_t state, const mouse_calibration& cal);
|
||||
event_mouse(int32_t state, const mouse_calibration& cal, int32_t _raw);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
|
|
393
src/core/keybroadcast.cpp
Normal file
393
src/core/keybroadcast.cpp
Normal file
|
@ -0,0 +1,393 @@
|
|||
#include "core/window.hpp"
|
||||
#include "core/keybroadcast.hpp"
|
||||
#include "core/keymapper.hpp"
|
||||
#include "library/string.hpp"
|
||||
#include "library/minmax.hpp"
|
||||
#include <sstream>
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
//Why the fuck does windows have nonstandard socket API???
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
struct sockaddr_un { int sun_family; char sun_path[108]; };
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
typedef SOCKET sock_handle_t;
|
||||
sock_handle_t invalid_socket = INVALID_SOCKET;
|
||||
#else
|
||||
typedef int sock_handle_t;
|
||||
sock_handle_t invalid_socket = -1;
|
||||
#endif
|
||||
|
||||
class k_link
|
||||
{
|
||||
public:
|
||||
k_link(sock_handle_t handle)
|
||||
{
|
||||
link_handle = handle;
|
||||
dead_flag = true;
|
||||
}
|
||||
~k_link()
|
||||
{
|
||||
low_close();
|
||||
}
|
||||
//Returns true if link has something to transmit, else false.
|
||||
bool can_tx()
|
||||
{
|
||||
umutex_class h(lock);
|
||||
return !msg_tx_queue.empty();
|
||||
}
|
||||
//Write some data to link. If can_tx() returned true, this will try to transmit something.
|
||||
void handle_tx()
|
||||
{
|
||||
umutex_class h(lock);
|
||||
if(dead_flag)
|
||||
return;
|
||||
if(msg_tx_queue.empty())
|
||||
return;
|
||||
const std::string& txmsg = msg_tx_queue.front();
|
||||
char buf[512];
|
||||
size_t totransmit = txmsg.length() - first_msg_tx_count;
|
||||
if(totransmit > sizeof(buf))
|
||||
totransmit = sizeof(buf);
|
||||
size_t tocopy = totransmit;
|
||||
if(totransmit < sizeof(buf))
|
||||
buf[totransmit++] = '\0';
|
||||
if(tocopy > 0)
|
||||
std::copy(txmsg.begin() + first_msg_tx_count, txmsg.begin() + first_msg_tx_count +
|
||||
tocopy, buf);
|
||||
//Actually try to transmit. If entiere message is transmitted, remove it.
|
||||
first_msg_tx_count += low_write(buf, totransmit);
|
||||
if(first_msg_tx_count >= txmsg.length() + 1)
|
||||
msg_tx_queue.pop_front();
|
||||
}
|
||||
//Read some data from link.
|
||||
void handle_rx()
|
||||
{
|
||||
umutex_class h(lock);
|
||||
if(dead_flag)
|
||||
return;
|
||||
char buf[512];
|
||||
size_t recvd = low_read(buf, sizeof(buf));
|
||||
size_t off = 0;
|
||||
for(unsigned i = 0; i < recvd; i++) {
|
||||
if(buf[i] == '\0') {
|
||||
//End of message.
|
||||
size_t off2 = partial_rx_msg.size();
|
||||
partial_rx_msg.resize(off2 + i - off);
|
||||
std::copy(buf + off, buf + i, partial_rx_msg.begin() + off2);
|
||||
msg_rx_queue.push_back(std::string(partial_rx_msg.begin(),
|
||||
partial_rx_msg.end()));
|
||||
off = i + 1;
|
||||
}
|
||||
}
|
||||
//Copy incomplete parts.
|
||||
size_t off2 = partial_rx_msg.size();
|
||||
partial_rx_msg.resize(off2 + recvd - off);
|
||||
std::copy(buf + off, buf + recvd, partial_rx_msg.begin() + off2);
|
||||
}
|
||||
//Returns true if there is a pending message.
|
||||
bool recv_ready()
|
||||
{
|
||||
umutex_class h(lock);
|
||||
return !msg_rx_queue.empty();
|
||||
}
|
||||
//Read a pending message.
|
||||
std::string recv()
|
||||
{
|
||||
umutex_class h(lock);
|
||||
if(msg_rx_queue.empty())
|
||||
return "";
|
||||
std::string msg = msg_rx_queue.front();
|
||||
msg_rx_queue.pop_front();
|
||||
return msg;
|
||||
}
|
||||
//Send a message to link.
|
||||
void send(const std::string& str)
|
||||
{
|
||||
umutex_class h(lock);
|
||||
msg_tx_queue.push_back(str);
|
||||
}
|
||||
//Is dead?
|
||||
bool dead()
|
||||
{
|
||||
return dead_flag;
|
||||
}
|
||||
//Get link handle.
|
||||
sock_handle_t handle()
|
||||
{
|
||||
return link_handle;
|
||||
}
|
||||
private:
|
||||
size_t low_read(char* buf, size_t maxread);
|
||||
size_t low_write(const char* buf, size_t maxwrite);
|
||||
void low_close();
|
||||
k_link(const k_link&);
|
||||
k_link& operator=(const k_link&);
|
||||
sock_handle_t link_handle;
|
||||
std::list<std::string> msg_rx_queue;
|
||||
std::list<std::string> msg_tx_queue;
|
||||
size_t first_msg_tx_count;
|
||||
std::vector<char> partial_rx_msg;
|
||||
bool dead_flag;
|
||||
mutex_class lock;
|
||||
};
|
||||
|
||||
k_link* client_link;
|
||||
mutex_class client_link_lock;
|
||||
cv_class client_link_change;
|
||||
bool client_link_exit;
|
||||
bool client_link_exited;
|
||||
|
||||
void slave_thread()
|
||||
{
|
||||
client_link_exited = false;
|
||||
while(!client_link_exit) {
|
||||
{
|
||||
umutex_class h(client_link_lock);
|
||||
if(!client_link);
|
||||
}
|
||||
}
|
||||
client_link_exited = true;
|
||||
}
|
||||
|
||||
class k_server
|
||||
{
|
||||
public:
|
||||
//Fill the sets with available socket handles.
|
||||
void poll_readyness(std::set<sock_handle_t>& rx, std::set<sock_handle_t>& tx)
|
||||
{
|
||||
for(auto i : links) {
|
||||
//Always ready for RX.
|
||||
rx.insert(i->handle());
|
||||
if(i->can_tx()) tx.insert(i->handle());
|
||||
}
|
||||
}
|
||||
//Given sockets with activity, do RX/TX cycle.
|
||||
void do_rx_tx(std::set<sock_handle_t>& rx, std::set<sock_handle_t>& tx)
|
||||
{
|
||||
//Read/write all available sockets.
|
||||
for(auto i : links) {
|
||||
if(rx.count(i->handle()))
|
||||
i->handle_rx();
|
||||
if(tx.count(i->handle()))
|
||||
i->handle_tx();
|
||||
}
|
||||
//Check for dead connections and close those.
|
||||
for(auto i = links.begin(); i != links.end();) {
|
||||
if((*i)->dead()) {
|
||||
delete *i;
|
||||
i = links.erase(i);
|
||||
} else
|
||||
i++;
|
||||
}
|
||||
redistribute_messages();
|
||||
}
|
||||
//Receive from all connections, broadcast the message.
|
||||
void redistribute_messages()
|
||||
{
|
||||
//Receive on all connections, send on all other connections.
|
||||
for(auto i : links) {
|
||||
//Loop over all received messages.
|
||||
while(i->recv_ready()) {
|
||||
std::string msg = i->recv();
|
||||
if(!msg.length()) continue; //Skip empty messages.
|
||||
//Send to all others.
|
||||
for(auto j : links) {
|
||||
if(i == j) continue; //Don't send back.
|
||||
j->send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Accept a new connection.
|
||||
void accept()
|
||||
{
|
||||
sock_handle_t h = low_accept();
|
||||
if(h == invalid_socket)
|
||||
return;
|
||||
links.push_back(new k_link(h));
|
||||
}
|
||||
//Main poll loop.
|
||||
void loop()
|
||||
{
|
||||
while(true) {
|
||||
fd_set rset;
|
||||
fd_set wset;
|
||||
sock_handle_t bound = 0;
|
||||
FD_ZERO(&rset);
|
||||
FD_ZERO(&wset);
|
||||
|
||||
std::set<sock_handle_t> rx;
|
||||
std::set<sock_handle_t> tx;
|
||||
rx.insert(server_handle);
|
||||
poll_readyness(rx, tx);
|
||||
for(auto i : rx) FD_SET(i, &rset);
|
||||
for(auto i : tx) FD_SET(i, &wset);
|
||||
if(!rx.empty()) bound = max(bound, *rx.rbegin() + 1);
|
||||
if(!tx.empty()) bound = max(bound, *tx.rbegin() + 1);
|
||||
int r = select(bound, &rset, &wset, NULL, NULL);
|
||||
for(auto i = rx.begin(); i != rx.end(); i++) {
|
||||
if(FD_ISSET(*i, &rset))
|
||||
i = rx.erase(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
for(auto i = tx.begin(); i != tx.end(); i++) {
|
||||
if(FD_ISSET(*i, &wset))
|
||||
i = tx.erase(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
do_rx_tx(rx, tx);
|
||||
if(FD_ISSET(server_handle, &rset))
|
||||
accept();
|
||||
}
|
||||
}
|
||||
//Thread function for the server.
|
||||
static int thread_main(void* x)
|
||||
{
|
||||
k_server* _x = reinterpret_cast<k_server*>(x);
|
||||
_x->loop();
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
sock_handle_t low_accept();
|
||||
std::list<k_link*> links;
|
||||
sock_handle_t server_handle;
|
||||
};
|
||||
|
||||
struct s_triple
|
||||
{
|
||||
s_triple();
|
||||
s_triple(const std::string& r);
|
||||
std::set<std::string> mods;
|
||||
std::string key;
|
||||
int32_t value;
|
||||
bool ok;
|
||||
operator std::string();
|
||||
};
|
||||
|
||||
s_triple::s_triple() {}
|
||||
s_triple::s_triple(const std::string& r)
|
||||
{
|
||||
ok = false;
|
||||
size_t count;
|
||||
size_t length;
|
||||
char tmp;
|
||||
std::vector<char> tmp3;
|
||||
//size:{length:string}...length:string value
|
||||
std::istringstream x(r);
|
||||
x >> count;
|
||||
if(!x) return; //Bad message.
|
||||
x >> tmp;
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
x >> length;
|
||||
x >> tmp;
|
||||
if(length > r.length())
|
||||
return; //Bad message.
|
||||
tmp3.resize(length);
|
||||
x.read(&tmp3[0], length);
|
||||
if(!x) return; //Bad message
|
||||
std::string tmp2(tmp3.begin(), tmp3.end());
|
||||
mods.insert(tmp2);
|
||||
}
|
||||
x >> length;
|
||||
x >> tmp;
|
||||
if(length > r.length())
|
||||
return; //Bad message.
|
||||
tmp3.resize(length);
|
||||
x.read(&tmp3[0], length);
|
||||
key = std::string(tmp3.begin(), tmp3.end());
|
||||
if(!x) return; //Bad message
|
||||
x >> value;
|
||||
if(x) ok = true;
|
||||
}
|
||||
|
||||
s_triple::operator std::string()
|
||||
{
|
||||
std::ostringstream x;
|
||||
x << mods.size() << ":";
|
||||
for(auto& i : mods)
|
||||
x << i.length() << ":" << i;
|
||||
x << key.length() << ":" << key;
|
||||
x << value;
|
||||
return x.str();
|
||||
}
|
||||
|
||||
void event_handler(keyboard::modifier_set& mods, keyboard::key& key, keyboard::event& event)
|
||||
{
|
||||
if(!client_link)
|
||||
return;
|
||||
|
||||
std::set<keyboard::modifier*> tmp = mods.get_set();
|
||||
std::string _key = key.get_name();
|
||||
int32_t value = event.get_raw();
|
||||
|
||||
std::set<std::string> _mods;
|
||||
for(auto i : tmp)
|
||||
_mods.insert(i->get_name());
|
||||
|
||||
s_triple s;
|
||||
s.mods = _mods;
|
||||
s.key = _key;
|
||||
s.value = value;
|
||||
std::string rep = s;
|
||||
client_link->send(rep);
|
||||
}
|
||||
|
||||
//Inject specified rep.
|
||||
void inject_event(const std::string& rep)
|
||||
{
|
||||
s_triple s(rep);
|
||||
if(!s.ok) {
|
||||
messages << "Warning: inject_event: Skipping malformed message." << std::endl;
|
||||
return;
|
||||
}
|
||||
keyboard::modifier_set _mods;
|
||||
for(auto& i : s.mods) {
|
||||
keyboard::modifier* m = lsnes_kbd.try_lookup_modifier(i);
|
||||
if(m)
|
||||
_mods.add(*m);
|
||||
else
|
||||
messages << "Warning: inject_event: Ignoring unknown modifier '" << i << "'"
|
||||
<< std::endl;
|
||||
}
|
||||
keyboard::key* _key = lsnes_kbd.try_lookup_key(s.key);
|
||||
if(!_key) {
|
||||
messages << "Warning: inject_event: Skipping unknown key '" << s.key << "'"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
platform::queue(keypress(_mods, *_key, s.value));
|
||||
}
|
||||
|
||||
int slave_thread(void* arg)
|
||||
{
|
||||
//TODO.
|
||||
}
|
||||
}
|
||||
|
||||
void keybroadcast_notify_foreground(bool fg)
|
||||
{
|
||||
if(client_link)
|
||||
lsnes_gamepads.master_enable(!fg);
|
||||
}
|
||||
|
||||
|
||||
void keybroadcast_set_master(uint16_t port)
|
||||
{
|
||||
//TODO.
|
||||
}
|
||||
|
||||
void keybroadcast_set_slave(uint16_t port)
|
||||
{
|
||||
//TODO.
|
||||
}
|
|
@ -135,6 +135,34 @@ namespace
|
|||
std::vector<char> stream;
|
||||
};
|
||||
|
||||
class keyboard_monitor : public keyboard::event_listener
|
||||
{
|
||||
public:
|
||||
keyboard_monitor() throw()
|
||||
{
|
||||
active = false;
|
||||
}
|
||||
~keyboard_monitor() throw() {}
|
||||
void on_key_event(keyboard::modifier_set& mods, keyboard::key& key, keyboard::event& event)
|
||||
{
|
||||
if(fn) fn(mods, key, event);
|
||||
}
|
||||
bool active;
|
||||
std::function<void(keyboard::modifier_set& mods, keyboard::key& key, keyboard::event& event)> fn;
|
||||
} keyboard_monitor_cb;
|
||||
|
||||
void monitor_all_keys()
|
||||
{
|
||||
for(auto i : lsnes_kbd.all_keys())
|
||||
i->add_listener(keyboard_monitor_cb, true);
|
||||
}
|
||||
|
||||
void unmonitor_all_keys()
|
||||
{
|
||||
for(auto i : lsnes_kbd.all_keys())
|
||||
i->remove_listener(keyboard_monitor_cb);
|
||||
}
|
||||
|
||||
class msgcallback : public messagebuffer::update_handler
|
||||
{
|
||||
public:
|
||||
|
@ -503,6 +531,24 @@ void platform::queue(void (*f)(void* arg), void* arg, bool sync) throw(std::bad_
|
|||
}
|
||||
}
|
||||
|
||||
void platform::set_mirror_fn(std::function<void(keyboard::modifier_set& mods, keyboard::key& key,
|
||||
keyboard::event& event)> fn)
|
||||
{
|
||||
if(fn) {
|
||||
keyboard_monitor_cb.fn = fn;
|
||||
if(!keyboard_monitor_cb.active)
|
||||
for(auto i : lsnes_kbd.all_keys())
|
||||
i->add_listener(keyboard_monitor_cb, true);
|
||||
keyboard_monitor_cb.active = true;
|
||||
} else {
|
||||
if(keyboard_monitor_cb.active)
|
||||
for(auto i : lsnes_kbd.all_keys())
|
||||
i->remove_listener(keyboard_monitor_cb);
|
||||
keyboard_monitor_cb.active = false;
|
||||
keyboard_monitor_cb.fn = fn;
|
||||
}
|
||||
}
|
||||
|
||||
void platform::run_queues() throw()
|
||||
{
|
||||
internal_run_queues(false);
|
||||
|
|
|
@ -226,6 +226,10 @@ unsigned pad::add_hat(uint64_t idx, uint64_t idy, int64_t mindev, const std::str
|
|||
void pad::report_axis(uint64_t id, int64_t val)
|
||||
{
|
||||
mutex.lock();
|
||||
if(!enabled) {
|
||||
mutex.unlock();
|
||||
return;
|
||||
}
|
||||
if(_axes.count(id)) {
|
||||
axis_info& i = _axes[id];
|
||||
int16_t val2 = map_value(val, i.minus, i.zero, i.plus, i.neutral, i.pressure);
|
||||
|
@ -258,6 +262,10 @@ void pad::report_axis(uint64_t id, int64_t val)
|
|||
void pad::report_button(uint64_t id, bool val)
|
||||
{
|
||||
mutex.lock();
|
||||
if(!enabled) {
|
||||
mutex.unlock();
|
||||
return;
|
||||
}
|
||||
if(!_buttons.count(id)) {
|
||||
mutex.unlock();
|
||||
return;
|
||||
|
@ -275,6 +283,10 @@ void pad::report_button(uint64_t id, bool val)
|
|||
void pad::report_hat(uint64_t id, int angle)
|
||||
{
|
||||
mutex.lock();
|
||||
if(!enabled) {
|
||||
mutex.unlock();
|
||||
return;
|
||||
}
|
||||
unsigned h = angle_to_bitmask(angle);
|
||||
if(!_hats.count(id)) {
|
||||
mutex.unlock();
|
||||
|
@ -623,8 +635,15 @@ std::string pad::get_summary()
|
|||
return x.str();
|
||||
}
|
||||
|
||||
void pad::master_enable(bool state)
|
||||
{
|
||||
umutex_class H(mutex);
|
||||
enabled = state;
|
||||
}
|
||||
|
||||
set::set()
|
||||
{
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
set::~set()
|
||||
|
@ -711,6 +730,7 @@ unsigned set::add(const std::string& name)
|
|||
gp->set_axismode_cb(amode_fn);
|
||||
gp->set_newitem_cb(newitem_fn);
|
||||
_gamepads.push_back(gp);
|
||||
gp->master_enable(enabled);
|
||||
return _gamepads.size() - 1;
|
||||
} catch(...) {
|
||||
delete gp;
|
||||
|
@ -765,4 +785,13 @@ std::string set::get_summary()
|
|||
x << i->get_summary();
|
||||
return x.str();
|
||||
}
|
||||
|
||||
void set::master_enable(bool state)
|
||||
{
|
||||
umutex_class h(mutex);
|
||||
enabled = state;
|
||||
for(auto i : _gamepads)
|
||||
i->master_enable(state);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -259,24 +259,24 @@ key::~key() throw()
|
|||
register_queue<keyboard, key>::do_unregister(kbd, name);
|
||||
}
|
||||
|
||||
event_key::event_key(uint32_t chngmask)
|
||||
: event(chngmask, keytype::KBD_KEYTYPE_KEY)
|
||||
event_key::event_key(uint32_t chngmask, int32_t _raw)
|
||||
: event(chngmask, keytype::KBD_KEYTYPE_KEY, _raw)
|
||||
{
|
||||
}
|
||||
|
||||
event_axis::event_axis(int32_t _state, uint32_t chngmask)
|
||||
: event(chngmask, keytype::KBD_KEYTYPE_AXIS)
|
||||
event_axis::event_axis(int32_t _state, uint32_t chngmask, int32_t _raw)
|
||||
: event(chngmask, keytype::KBD_KEYTYPE_AXIS, _raw)
|
||||
{
|
||||
state = _state;
|
||||
}
|
||||
|
||||
event_hat::event_hat(uint32_t chngmask)
|
||||
: event(chngmask, keytype::KBD_KEYTYPE_HAT)
|
||||
event_hat::event_hat(uint32_t chngmask, int32_t _raw)
|
||||
: event(chngmask, keytype::KBD_KEYTYPE_HAT, _raw)
|
||||
{
|
||||
}
|
||||
|
||||
event_mouse::event_mouse(int32_t _state, const mouse_calibration& _cal)
|
||||
: event(0, keytype::KBD_KEYTYPE_MOUSE)
|
||||
event_mouse::event_mouse(int32_t _state, const mouse_calibration& _cal, int32_t _raw)
|
||||
: event(0, keytype::KBD_KEYTYPE_MOUSE, _raw)
|
||||
{
|
||||
state = _state;
|
||||
cal = _cal;
|
||||
|
@ -397,7 +397,7 @@ void key_key::set_state(modifier_set mods, int32_t _state) throw()
|
|||
}
|
||||
mutex.unlock();
|
||||
if(edge) {
|
||||
event_key e(change);
|
||||
event_key e(change, _state);
|
||||
call_listeners(mods, e);
|
||||
}
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ void key_hat::set_state(modifier_set mods, int32_t _state) throw()
|
|||
}
|
||||
mutex.unlock();
|
||||
if(edge) {
|
||||
event_hat e(change);
|
||||
event_hat e(change, _state);
|
||||
call_listeners(mods, e);
|
||||
}
|
||||
}
|
||||
|
@ -534,7 +534,7 @@ void key_axis::set_state(modifier_set mods, int32_t _rawstate) throw()
|
|||
}
|
||||
mutex.unlock();
|
||||
if(edge) {
|
||||
event_axis e(state, change);
|
||||
event_axis e(state, change, _rawstate);
|
||||
call_listeners(mods, e);
|
||||
}
|
||||
}
|
||||
|
@ -589,7 +589,7 @@ void key_mouse::set_state(modifier_set mods, int32_t _rawstate) throw()
|
|||
}
|
||||
mutex.unlock();
|
||||
if(edge) {
|
||||
event_mouse e(state, _cal);
|
||||
event_mouse e(state, _cal, _rawstate);
|
||||
call_listeners(mods, e);
|
||||
}
|
||||
}
|
||||
|
@ -599,8 +599,9 @@ void key_mouse::set_calibration(mouse_calibration _cal) throw()
|
|||
mutex.lock();
|
||||
cal = _cal;
|
||||
int32_t state = cal.get_calibrated_value(rawstate);
|
||||
int32_t lraw = rawstate;
|
||||
mutex.unlock();
|
||||
event_mouse e(state, _cal);
|
||||
event_mouse e(state, _cal, lraw);
|
||||
modifier_set mods;
|
||||
call_listeners(mods, e);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "core/dispatch.hpp"
|
||||
#include "core/framebuffer.hpp"
|
||||
#include "core/framerate.hpp"
|
||||
#include "core/keybroadcast.hpp"
|
||||
#include "core/keymapper.hpp"
|
||||
#include "interface/romtype.hpp"
|
||||
#include "core/loadlib.hpp"
|
||||
|
@ -181,7 +182,7 @@ namespace
|
|||
{
|
||||
was_focused = (wxWindow::FindFocus() != NULL);
|
||||
was_enabled = platform::is_sound_enabled();
|
||||
Start(500);
|
||||
Start(100);
|
||||
}
|
||||
void Notify()
|
||||
{
|
||||
|
@ -196,6 +197,7 @@ namespace
|
|||
if(!background_audio)
|
||||
platform::sound_enable(false);
|
||||
}
|
||||
keybroadcast_notify_foreground(is_focused);
|
||||
was_focused = is_focused;
|
||||
}
|
||||
private:
|
||||
|
|
Loading…
Add table
Reference in a new issue