Make mouse be ordinary keys instead of being special

This commit is contained in:
Ilari Liusvaara 2012-01-17 23:48:13 +02:00
parent dfe264f629
commit 99d5ad2215
20 changed files with 263 additions and 130 deletions

View file

@ -351,6 +351,18 @@ struct porttype_info
* Parameter port: Port to set to.
*/
virtual void set_core_controller(unsigned port) const throw() = 0;
/**
* Does the controller have analog function?
*
* Parameter controller: Controller number.
*/
virtual bool is_analog(unsigned controller) const throw() = 0;
/**
* Does the controller have mouse-type function?
*
* Parameter controller: Controller number.
*/
virtual bool is_mouse(unsigned controller) const throw() = 0;
/**
* Port type value.
*/
@ -818,6 +830,26 @@ public:
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
return pinfo[port]->button_id(pcid % MAX_CONTROLLERS_PER_PORT, lbid);
}
/**
* Does the specified controller have analog function.
*
* Parameter pcid: Physical controller id.
*/
bool is_analog(unsigned pcid)
{
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
return pinfo[port]->is_analog(pcid % MAX_CONTROLLERS_PER_PORT);
}
/**
* Does the specified controller have mouse-type function.
*
* Parameter pcid: Physical controller id.
*/
bool is_mouse(unsigned pcid)
{
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
return pinfo[port]->is_mouse(pcid % MAX_CONTROLLERS_PER_PORT);
}
private:
size_t totalsize;
unsigned char memory[MAXIMUM_CONTROLLER_FRAME_SIZE];
@ -1136,6 +1168,14 @@ public:
* Returns: The physical button id, or -1 if no such button.
*/
int button_id(unsigned pcid, unsigned lbid) throw();
/**
* TODO: Document.
*/
bool is_analog(unsigned pcid) throw();
/**
* TODO: Document.
*/
bool is_mouse(unsigned pcid) throw();
private:
const porttype_info* porttypeinfo[MAX_PORTS];
porttype_t porttypes[MAX_PORTS];

View file

@ -111,23 +111,6 @@ public:
* Call all on_close() handlers.
*/
static void do_close() throw();
/**
* Click or release on window was receivied.
*
* The default handler does nothing.
*
* Parameter x: The x-coordinate of the click. May be negative or otherwise out of screen.
* Parameter y: The y-coordinate of the click. May be negative or otherwise out of screen.
* Parameter buttonmask: Bitfield giving current buttons held:
* Bit 0 => Left button is down/held.
* Bit 1 => Middle button is down/held.
* Bit 2 => Middle button is down/held.
*/
virtual void on_click(int32_t x, int32_t y, uint32_t buttonmask);
/**
* Call all on_click() handlers.
*/
static void do_click(int32_t x, int32_t y, uint32_t buttonmask) throw();
/**
* Sound mute/unmute status might have been changed.
*
@ -388,15 +371,6 @@ public:
* Get name of target.
*/
const std::string& get_name() throw();
/**
* Set window main screen compensation parameters. This is used for mouse click reporting.
*
* parameter xoffset: X coordinate of origin.
* parameter yoffset: Y coordinate of origin.
* parameter hscl: Horizontal scaling factor.
* parameter vscl: Vertical scaling factor.
*/
static void do_click_compensation(uint32_t xoffset, uint32_t yoffset, uint32_t hscl, uint32_t vscl);
/**
* Render buffer needs to be (possibly) resized, so that graphics plugin can update the mappings.
*

View file

@ -327,8 +327,12 @@ public:
* Set callback requests on/off
*/
void request_hook_callback(bool state);
/**
* Get status value.
*/
signed get_value();
private:
unsigned state;
signed state;
enum type ktype;
short last_rawval;
short cal_left;

View file

@ -534,13 +534,6 @@ struct platform
static void run_queues() throw();
};
/**
* Send a mouse click.
*
* Call from UI thread.
*/
void send_mouse_click(long x, long y, uint32_t buttons);
template<typename T>
void functor_call_helper(void* args)
{

View file

@ -51,6 +51,24 @@ namespace
controls.button(x, bid, newstate);
}
void send_analog(unsigned lcid, int32_t x, int32_t y)
{
int pcid = controls.lcid_to_pcid(lcid);
if(pcid < 0) {
messages << "Controller #" << (lcid + 1) << " not present" << std::endl;
return;
}
if(controls.is_analog(pcid) < 0) {
messages << "Controller #" << (lcid + 1) << " is not analog" << std::endl;
return;
}
auto g2 = get_framebuffer_size();
if(controls.is_mouse(pcid)) {
controls.analog(pcid, x - g2.first / 2, y - g2.second / 2);
} else
controls.analog(pcid, x / 2 , y / 2);
}
function_ptr_command<tokensplitter&> autofire("autofire", "Set autofire pattern",
"Syntax: autofire <buttons|->...\nSet autofire pattern\n",
[](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
@ -139,6 +157,32 @@ namespace
std::string button;
};
class analog_action : public command
{
public:
analog_action(const std::string& cmd, unsigned _controller)
throw(std::bad_alloc)
: command(cmd)
{
controller = _controller;
}
~analog_action() throw() {}
void invoke(const std::string& args) throw(std::bad_alloc, std::runtime_error)
{
if(args != "")
throw std::runtime_error("This command does not take parameters");
keygroup* mouse_x = keygroup::lookup_by_name("mouse_x");
keygroup* mouse_y = keygroup::lookup_by_name("mouse_y");
if(!mouse_x || !mouse_y) {
messages << "Controller analog function not available without mouse" << std::endl;
return;
}
send_analog(controller, mouse_x->get_value(), mouse_y->get_value());
}
private:
unsigned controller;
};
class button_action_helper
{
public:
@ -165,6 +209,11 @@ namespace
y = cstr + get_logical_button_name(i);
our_commands.insert(new button_action(x, j, k, y));
}
for(unsigned k = 0; k < 8; ++k) {
std::string x = "controllerXanalog";
x[10] = 49 + k;
our_commands.insert(new analog_action(x, k));
}
}
~button_action_helper()
{

View file

@ -106,5 +106,15 @@ namespace
return;
snes_set_controller_port_device(port != 0, SNES_DEVICE_JOYPAD);
}
bool is_analog(unsigned controller) const throw()
{
return false;
}
bool is_mouse(unsigned controller) const throw()
{
return false;
}
} gamepad;
}

View file

@ -113,5 +113,15 @@ namespace
return;
snes_set_controller_port_device(port != 0, SNES_DEVICE_JUSTIFIER);
}
bool is_analog(unsigned controller) const throw()
{
return (controller == 0);
}
bool is_mouse(unsigned controller) const throw()
{
return false;
}
} justifier;
}

View file

@ -127,5 +127,15 @@ namespace
return;
snes_set_controller_port_device(port != 0, SNES_DEVICE_JUSTIFIERS);
}
bool is_analog(unsigned controller) const throw()
{
return (controller < 2);
}
bool is_mouse(unsigned controller) const throw()
{
return false;
}
} justifiers;
}

View file

@ -113,5 +113,15 @@ namespace
return;
snes_set_controller_port_device(port != 0, SNES_DEVICE_MOUSE);
}
bool is_analog(unsigned controller) const throw()
{
return (controller == 0);
}
bool is_mouse(unsigned controller) const throw()
{
return (controller == 0);
}
} mouse;
}

View file

@ -120,5 +120,15 @@ namespace
return;
snes_set_controller_port_device(port != 0, SNES_DEVICE_MULTITAP);
}
bool is_analog(unsigned controller) const throw()
{
return false;
}
bool is_mouse(unsigned controller) const throw()
{
return false;
}
} multitap;
}

View file

@ -64,5 +64,15 @@ namespace
return;
snes_set_controller_port_device(port != 0, SNES_DEVICE_NONE);
}
bool is_analog(unsigned controller) const throw()
{
return false;
}
bool is_mouse(unsigned controller) const throw()
{
return false;
}
} none;
}

View file

@ -125,5 +125,15 @@ namespace
return;
snes_set_controller_port_device(port != 0, SNES_DEVICE_SUPER_SCOPE);
}
bool is_analog(unsigned controller) const throw()
{
return (controller == 0);
}
bool is_mouse(unsigned controller) const throw()
{
return false;
}
} superscope;
}

View file

@ -79,6 +79,16 @@ namespace
std::cerr << "Attempt to set core port type to INVALID port type" << std::endl;
exit(1);
}
bool is_analog(unsigned controller) const throw()
{
return false;
}
bool is_mouse(unsigned controller) const throw()
{
return false;
}
};
porttype_invalid& get_invalid_port_type()
@ -750,3 +760,13 @@ controller_frame controller_state::commit(controller_frame controls) throw()
_committed = controls;
return _committed;
}
bool controller_state::is_analog(unsigned pcid) throw()
{
return _input.is_analog(pcid);
}
bool controller_state::is_mouse(unsigned pcid) throw()
{
return _input.is_mouse(pcid);
}

View file

@ -146,22 +146,6 @@ void information_dispatch::do_close() throw()
}
}
void information_dispatch::on_click(int32_t x, int32_t y, uint32_t buttonmask)
{
//Do nothing.
}
void information_dispatch::do_click(int32_t x, int32_t y, uint32_t buttonmask) throw()
{
x = (x - vc_xoffset) / vc_hscl;
y = (y - vc_yoffset) / vc_vscl;
for(auto& i : dispatch()) {
START_EH_BLOCK
i->on_click(x, y, buttonmask);
END_EH_BLOCK(i, "on_click");
}
}
void information_dispatch::on_sound_unmute(bool unmuted)
{
//Do nothing.
@ -492,14 +476,6 @@ void information_dispatch::update_dumpers(bool nocalls) throw()
}
}
void information_dispatch::do_click_compensation(uint32_t xoffset, uint32_t yoffset, uint32_t hscl, uint32_t vscl)
{
vc_xoffset = xoffset;
vc_yoffset = yoffset;
vc_hscl = hscl;
vc_vscl = vscl;
}
void information_dispatch::on_set_screen(screen& scr)
{
//Do nothing.

View file

@ -210,6 +210,8 @@ void redraw_framebuffer()
void render_framebuffer()
{
static uint32_t val1, val2, val3, val4;
uint32_t nval1, nval2, nval3, nval4;
render_info& ri = get_read_buffer();
main_screen.reallocate(ri.fbuf.width * ri.hscl + ri.lgap + ri.rgap, ri.fbuf.height * ri.vscl + ri.tgap +
ri.bgap);
@ -218,7 +220,22 @@ void render_framebuffer()
ri.rq.run(main_screen);
information_dispatch::do_set_screen(main_screen);
//We would want divide by 2, but we'll do it ourselves in order to do mouse.
information_dispatch::do_click_compensation(ri.lgap, ri.tgap, 1, 1);
keygroup* mouse_x = keygroup::lookup_by_name("mouse_x");
keygroup* mouse_y = keygroup::lookup_by_name("mouse_y");
nval1 = ri.lgap;
nval2 = ri.tgap;
nval3 = ri.fbuf.width * ri.hscl + ri.rgap;
nval4 = ri.fbuf.height * ri.vscl + ri.bgap;
if(mouse_x && (nval1 != val1 || nval3 != val3))
mouse_x->change_calibration(-static_cast<short>(ri.lgap), ri.lgap, ri.fbuf.width * ri.hscl + ri.rgap,
0.5);
if(mouse_y && (nval2 != val2 || nval4 != val4))
mouse_y->change_calibration(-static_cast<short>(ri.tgap), ri.tgap, ri.fbuf.height * ri.vscl + ri.bgap,
0.5);
val1 = nval1;
val2 = nval2;
val3 = nval3;
val4 = nval4;
buffering.end_read();
}

View file

@ -417,13 +417,15 @@ void keygroup::set_position(short pos, const modifier_set& modifiers) throw()
if(requests_hook)
lua_callback_keyhook(keyname, get_parameters());
double x = compensate2(compensate(pos));
unsigned tmp;
signed tmp;
bool left, right, up, down;
bool oleft, oright, oup, odown;
switch(ktype) {
case KT_DISABLED:
case KT_MOUSE:
return;
case KT_MOUSE:
state = pos - cal_center;
break;
case KT_KEY:
case KT_PRESSURE_0M:
case KT_PRESSURE_0P:
@ -557,6 +559,10 @@ std::set<std::string> keygroup::get_keys() throw(std::bad_alloc)
return r;
}
signed keygroup::get_value()
{
return state;
}
namespace
{

View file

@ -669,26 +669,6 @@ namespace
}
on_quit_prompt = false;
}
void send_analog(unsigned acid, int32_t x, int32_t y)
{
auto g2 = get_framebuffer_size();
if(controls.acid_is_mouse(acid)) {
controls.analog(acid, x - g2.first / 2, y - g2.second / 2);
} else
controls.analog(acid, x / 2 , y / 2);
}
void on_click(int32_t x, int32_t y, uint32_t buttonmask) throw()
{
if(buttonmask & ~prev_mouse_mask & 1)
send_analog(0, x, y);
if(buttonmask & ~prev_mouse_mask & 2)
send_analog(1, x, y);
if(buttonmask & ~prev_mouse_mask & 4)
send_analog(2, x, y);
prev_mouse_mask = buttonmask;
}
} mywcb;
//If there is a pending load, perform it. Return 1 on successful load, 0 if nothing to load, -1 on load

View file

@ -538,28 +538,6 @@ namespace
{
graphics_plugin::notify_status();
}
struct handle_mouse_request
{
long x;
long y;
uint32_t mask;
};
void _handle_mouse(void* args)
{
struct handle_mouse_request* x = reinterpret_cast<struct handle_mouse_request*>(args);
information_dispatch::do_click(x->x, x->y, x->mask);
}
}
void send_mouse_click(long x, long y, uint32_t buttons)
{
struct handle_mouse_request z;
z.x = x;
z.y = y;
z.mask = buttons;
platform::queue(_handle_mouse, &z, true);
}
mutex& platform::msgbuf_lock() throw()

View file

@ -288,6 +288,12 @@ namespace
{
platform::queue(emu_handle_quit_signal, NULL, false);
}
keygroup mouse_x("mouse_x", keygroup::KT_MOUSE);
keygroup mouse_y("mouse_y", keygroup::KT_MOUSE);
keygroup mouse_l("mouse_left", keygroup::KT_KEY);
keygroup mouse_m("mouse_center", keygroup::KT_KEY);
keygroup mouse_r("mouse_right", keygroup::KT_KEY);
}
void notify_emulator_exit()
@ -339,34 +345,40 @@ void ui_loop()
ui_panic();
while(true);
}
if(e.type == SDL_MOUSEBUTTONDOWN) {
int i;
switch(e.button.button) {
case SDL_BUTTON_LEFT:
mouse_state |= 1;
break;
case SDL_BUTTON_MIDDLE:
mouse_state |= 2;
break;
case SDL_BUTTON_RIGHT:
mouse_state |= 4;
break;
};
send_mouse_click(e.button.x, e.button.y, mouse_state);
if(e.type == SDL_MOUSEMOTION && special_mode == SPECIALMODE_NORMAL) {
platform::queue(keypress(modifier_set(), mouse_x, e.motion.x - 6));
platform::queue(keypress(modifier_set(), mouse_y, e.motion.y - 6));
}
if(e.type == SDL_MOUSEBUTTONUP) {
if(e.type == SDL_MOUSEBUTTONDOWN && special_mode == SPECIALMODE_NORMAL) {
int i;
platform::queue(keypress(modifier_set(), mouse_x, e.button.x - 6));
platform::queue(keypress(modifier_set(), mouse_y, e.button.y - 6));
switch(e.button.button) {
case SDL_BUTTON_LEFT:
mouse_state &= ~1;
platform::queue(keypress(modifier_set(), mouse_l, 1));
break;
case SDL_BUTTON_MIDDLE:
mouse_state &= ~2;
platform::queue(keypress(modifier_set(), mouse_m, 1));
break;
case SDL_BUTTON_RIGHT:
mouse_state &= ~4;
platform::queue(keypress(modifier_set(), mouse_r, 1));
break;
};
}
if(e.type == SDL_MOUSEBUTTONUP && special_mode == SPECIALMODE_NORMAL) {
platform::queue(keypress(modifier_set(), mouse_x, e.button.x - 6));
platform::queue(keypress(modifier_set(), mouse_y, e.button.y - 6));
switch(e.button.button) {
case SDL_BUTTON_LEFT:
platform::queue(keypress(modifier_set(), mouse_l, 0));
break;
case SDL_BUTTON_MIDDLE:
platform::queue(keypress(modifier_set(), mouse_m, 0));
break;
case SDL_BUTTON_RIGHT:
platform::queue(keypress(modifier_set(), mouse_r, 0));
break;
};
send_mouse_click(e.button.x, e.button.y, mouse_state);
}
//Handle entering identify mode.
if(identify_requested) {

View file

@ -118,22 +118,33 @@ namespace
emulation_thread->join();
}
keygroup mouse_x("mouse_x", keygroup::KT_MOUSE);
keygroup mouse_y("mouse_y", keygroup::KT_MOUSE);
keygroup mouse_l("mouse_left", keygroup::KT_KEY);
keygroup mouse_m("mouse_center", keygroup::KT_KEY);
keygroup mouse_r("mouse_right", keygroup::KT_KEY);
keygroup mouse_i("mouse_inwindow", keygroup::KT_KEY);
void handle_wx_mouse(wxMouseEvent& e)
{
static uint32_t mask = 0;
platform::queue(keypress(modifier_set(), mouse_x, e.GetX()));
platform::queue(keypress(modifier_set(), mouse_y, e.GetY()));
if(e.Entering())
platform::queue(keypress(modifier_set(), mouse_i, 1));
if(e.Leaving())
platform::queue(keypress(modifier_set(), mouse_i, 0));
if(e.LeftDown())
mask |= 1;
platform::queue(keypress(modifier_set(), mouse_l, 1));
if(e.LeftUp())
mask &= ~1;
platform::queue(keypress(modifier_set(), mouse_l, 0));
if(e.MiddleDown())
mask |= 2;
platform::queue(keypress(modifier_set(), mouse_m, 1));
if(e.MiddleUp())
mask &= ~2;
platform::queue(keypress(modifier_set(), mouse_m, 0));
if(e.RightDown())
mask |= 4;
platform::queue(keypress(modifier_set(), mouse_r, 1));
if(e.RightUp())
mask &= ~4;
send_mouse_click(e.GetX(), e.GetY(), mask);
platform::queue(keypress(modifier_set(), mouse_r, 0));
}
bool is_readonly_mode()
@ -619,6 +630,9 @@ wxwin_mainwindow::panel::panel(wxWindow* win)
this->Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(panel::on_mouse), NULL, this);
this->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(panel::on_mouse), NULL, this);
this->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(panel::on_mouse), NULL, this);
this->Connect(wxEVT_MOTION, wxMouseEventHandler(panel::on_mouse), NULL, this);
this->Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(panel::on_mouse), NULL, this);
this->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(panel::on_mouse), NULL, this);
SetMinSize(wxSize(512, 448));
}