Generalised input framework for raw mice, gamepads, trackers (incl. HMDs like Oculus Rift)

This commit is contained in:
rdb 2015-12-11 15:26:40 +01:00
parent 6480e82e3b
commit bd0683d101
64 changed files with 2969 additions and 1618 deletions

View File

@ -3641,6 +3641,21 @@ if (not RUNTIME):
TargetAdd('libp3dgraph.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dgraph', 'SRCDIR:panda/src/dgraph'])
TargetAdd('libp3dgraph_igate.obj', input='libp3dgraph.in', opts=["DEPENDENCYONLY"])
#
# DIRECTORY: panda/src/device/
#
if (not RUNTIME):
OPTS=['DIR:panda/src/device', 'BUILDING:PANDA']
TargetAdd('p3device_composite1.obj', opts=OPTS, input='p3device_composite1.cxx')
TargetAdd('p3device_composite2.obj', opts=OPTS, input='p3device_composite2.cxx')
OPTS=['DIR:panda/src/device']
IGATEFILES=GetDirectoryContents('panda/src/device', ["*.h", "*_composite*.cxx"])
TargetAdd('libp3device.in', opts=OPTS, input=IGATEFILES)
TargetAdd('libp3device.in', opts=['IMOD:panda3d.core', 'ILIB:libp3device', 'SRCDIR:panda/src/device'])
TargetAdd('libp3device_igate.obj', input='libp3device.in', opts=["DEPENDENCYONLY"])
#
# DIRECTORY: panda/src/display/
#
@ -3665,21 +3680,6 @@ if (not RUNTIME):
TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
#
# DIRECTORY: panda/src/device/
#
if (not RUNTIME):
OPTS=['DIR:panda/src/device', 'BUILDING:PANDA']
TargetAdd('p3device_composite1.obj', opts=OPTS, input='p3device_composite1.cxx')
TargetAdd('p3device_composite2.obj', opts=OPTS, input='p3device_composite2.cxx')
OPTS=['DIR:panda/src/device']
IGATEFILES=GetDirectoryContents('panda/src/device', ["*.h", "*_composite*.cxx"])
TargetAdd('libp3device.in', opts=OPTS, input=IGATEFILES)
TargetAdd('libp3device.in', opts=['IMOD:panda3d.core', 'ILIB:libp3device', 'SRCDIR:panda/src/device'])
TargetAdd('libp3device_igate.obj', input='libp3device.in', opts=["DEPENDENCYONLY"])
#
# DIRECTORY: panda/src/pnmtext/
#

View File

@ -44,10 +44,7 @@ is_valid() const {
////////////////////////////////////////////////////////////////////
INLINE int AnalogNode::
get_num_controls() const {
_analog->acquire();
int result = _analog->get_num_controls();
_analog->unlock();
return result;
return _analog->get_num_controls();
}
////////////////////////////////////////////////////////////////////
@ -60,10 +57,7 @@ get_num_controls() const {
////////////////////////////////////////////////////////////////////
INLINE double AnalogNode::
get_control_state(int index) const {
_analog->acquire();
double result = _analog->get_control_state(index);
_analog->unlock();
return result;
return _analog->get_control_state(index);
}
////////////////////////////////////////////////////////////////////
@ -75,10 +69,7 @@ get_control_state(int index) const {
////////////////////////////////////////////////////////////////////
INLINE bool AnalogNode::
is_control_known(int index) const {
_analog->acquire();
bool result = _analog->is_control_known(index);
_analog->unlock();
return result;
return _analog->is_control_known(index);
}
////////////////////////////////////////////////////////////////////

View File

@ -30,7 +30,7 @@ AnalogNode(ClientBase *client, const string &device_name) :
DataNode(device_name)
{
_xy_output = define_output("xy", EventStoreVec2::get_class_type());
_xy = new EventStoreVec2(LPoint2(0.0f, 0.0f));
_xy = new EventStoreVec2(LPoint2(0));
nassertv(client != (ClientBase *)NULL);
PT(ClientDevice) device =
@ -49,7 +49,23 @@ AnalogNode(ClientBase *client, const string &device_name) :
return;
}
_analog = DCAST(ClientAnalogDevice, device);
_analog = device;
}
////////////////////////////////////////////////////////////////////
// Function: AnalogNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
AnalogNode::
AnalogNode(InputDevice *device) :
DataNode(device->get_name()),
_analog(device)
{
_xy_output = define_output("xy", EventStoreVec2::get_class_type());
_xy = new EventStoreVec2(LPoint2(0));
nassertv(device != (InputDevice *)NULL);
}
////////////////////////////////////////////////////////////////////
@ -74,9 +90,7 @@ write(ostream &out, int indent_level) const {
DataNode::write(out, indent_level);
if (_analog != (ClientAnalogDevice *)NULL) {
_analog->acquire();
_analog->write_controls(out, indent_level + 2);
_analog->unlock();
}
}
@ -100,8 +114,6 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
_analog->poll();
LPoint2 out(0.0f, 0.0f);
_analog->acquire();
for (int i = 0; i < max_outputs; i++) {
if (_outputs[i]._index >= 0 &&
_analog->is_control_known(_outputs[i]._index)) {
@ -112,7 +124,6 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
}
}
}
_analog->unlock();
_xy->set_value(out);
output.set_data(_xy_output, EventParameter(_xy));
}

View File

@ -45,6 +45,7 @@
class EXPCL_PANDA_DEVICE AnalogNode : public DataNode {
PUBLISHED:
AnalogNode(ClientBase *client, const string &device_name);
AnalogNode(InputDevice *device);
virtual ~AnalogNode();
INLINE bool is_valid() const;
@ -73,7 +74,7 @@ private:
enum { max_outputs = 2 };
OutputData _outputs[max_outputs];
PT(ClientAnalogDevice) _analog;
PT(InputDevice) _analog;
protected:
// Inherited from DataNode

View File

@ -21,7 +21,7 @@
////////////////////////////////////////////////////////////////////
INLINE bool ButtonNode::
is_valid() const {
return (_button != (ClientButtonDevice *)NULL) && _button->is_connected();
return (_device != (ClientButtonDevice *)NULL) && _device->is_connected();
}
////////////////////////////////////////////////////////////////////
@ -36,10 +36,7 @@ is_valid() const {
////////////////////////////////////////////////////////////////////
INLINE int ButtonNode::
get_num_buttons() const {
_button->acquire();
int result = _button->get_num_buttons();
_button->unlock();
return result;
return _device->get_num_buttons();
}
////////////////////////////////////////////////////////////////////
@ -58,9 +55,7 @@ get_num_buttons() const {
////////////////////////////////////////////////////////////////////
INLINE void ButtonNode::
set_button_map(int index, ButtonHandle button) {
_button->acquire();
_button->set_button_map(index, button);
_button->unlock();
_device->set_button_map(index, button);
}
////////////////////////////////////////////////////////////////////
@ -73,10 +68,7 @@ set_button_map(int index, ButtonHandle button) {
////////////////////////////////////////////////////////////////////
INLINE ButtonHandle ButtonNode::
get_button_map(int index) const {
_button->acquire();
ButtonHandle result = _button->get_button_map(index);
_button->unlock();
return result;
return _device->get_button_map(index);
}
////////////////////////////////////////////////////////////////////
@ -88,10 +80,7 @@ get_button_map(int index) const {
////////////////////////////////////////////////////////////////////
INLINE bool ButtonNode::
get_button_state(int index) const {
_button->acquire();
bool result = _button->get_button_state(index);
_button->unlock();
return result;
return _device->get_button_state(index);
}
////////////////////////////////////////////////////////////////////
@ -103,8 +92,5 @@ get_button_state(int index) const {
////////////////////////////////////////////////////////////////////
INLINE bool ButtonNode::
is_button_known(int index) const {
_button->acquire();
bool result = _button->is_button_known(index);
_button->unlock();
return result;
return _device->is_button_known(index);
}

View File

@ -30,7 +30,6 @@ ButtonNode(ClientBase *client, const string &device_name) :
DataNode(device_name)
{
_button_events_output = define_output("button_events", ButtonEventList::get_class_type());
_button_events = new ButtonEventList;
nassertv(client != (ClientBase *)NULL);
PT(ClientDevice) device =
@ -49,7 +48,21 @@ ButtonNode(ClientBase *client, const string &device_name) :
return;
}
_button = DCAST(ClientButtonDevice, device);
_device = device;
}
////////////////////////////////////////////////////////////////////
// Function: ButtonNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
ButtonNode::
ButtonNode(InputDevice *device) :
DataNode(device->get_name()),
_device(device)
{
_button_events_output = define_output("button_events", ButtonEventList::get_class_type());
_device = device;
}
////////////////////////////////////////////////////////////////////
@ -59,7 +72,7 @@ ButtonNode(ClientBase *client, const string &device_name) :
////////////////////////////////////////////////////////////////////
ButtonNode::
~ButtonNode() {
// When the _button pointer destructs, the ClientButtonDevice
// When the _device pointer destructs, the ClientButtonDevice
// disconnects itself from the ClientBase, and everything that needs
// to get turned off does. Magic.
}
@ -73,11 +86,9 @@ void ButtonNode::
output(ostream &out) const {
DataNode::output(out);
if (_button != (ClientButtonDevice *)NULL) {
if (_device != (InputDevice *)NULL) {
out << " (";
_button->acquire();
_button->output_buttons(out);
_button->unlock();
_device->output_buttons(out);
out << ")";
}
}
@ -91,10 +102,8 @@ void ButtonNode::
write(ostream &out, int indent_level) const {
DataNode::write(out, indent_level);
if (_button != (ClientButtonDevice *)NULL) {
_button->acquire();
_button->write_buttons(out, indent_level + 2);
_button->unlock();
if (_device != (InputDevice *)NULL) {
_device->write_buttons(out, indent_level + 2);
}
}
@ -115,14 +124,7 @@ void ButtonNode::
do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
DataNodeTransmit &output) {
if (is_valid()) {
_button->poll();
_button->acquire();
(*_button_events) = (*_button->get_button_events());
_button->get_button_events()->clear();
_button->unlock();
output.set_data(_button_events_output, EventParameter(_button_events));
PT(ButtonEventList) bel = _device->get_button_events();
output.set_data(_button_events_output, EventParameter(bel));
}
}

View File

@ -20,8 +20,6 @@
#include "clientBase.h"
#include "clientButtonDevice.h"
#include "dataNode.h"
#include "buttonEventList.h"
////////////////////////////////////////////////////////////////////
// Class : ButtonNode
@ -41,6 +39,7 @@
class EXPCL_PANDA_DEVICE ButtonNode : public DataNode {
PUBLISHED:
ButtonNode(ClientBase *client, const string &device_name);
ButtonNode(InputDevice *device);
virtual ~ButtonNode();
INLINE bool is_valid() const;
@ -58,7 +57,7 @@ public:
virtual void write(ostream &out, int indent_level = 0) const;
private:
PT(ClientButtonDevice) _button;
PT(InputDevice) _device;
protected:
// Inherited from DataNode
@ -69,7 +68,6 @@ protected:
private:
// outputs
int _button_events_output;
PT(ButtonEventList) _button_events;
public:
static TypeHandle get_class_type() {

View File

@ -13,18 +13,6 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::AnalogState::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ClientAnalogDevice::AnalogState::
AnalogState() :
_state(0.0),
_known(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::Constructor
// Access: Protected
@ -35,65 +23,3 @@ ClientAnalogDevice(ClientBase *client, const string &device_name):
ClientDevice(client, get_class_type(), device_name)
{
}
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::get_num_controls
// Access: Public
// Description: Returns the number of analog controls known to the
// ClientAnalogDevice. This number may change as
// more controls are discovered.
////////////////////////////////////////////////////////////////////
INLINE int ClientAnalogDevice::
get_num_controls() const {
return _controls.size();
}
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::set_control_state
// Access: Public
// Description: Sets the state of the indicated analog index. The
// caller should ensure that acquire() is in effect while
// this call is made. This should be a number in the
// range -1.0 to 1.0, representing the current position
// of the control within its total range of movement.
////////////////////////////////////////////////////////////////////
INLINE void ClientAnalogDevice::
set_control_state(int index, double state) {
ensure_control_index(index);
nassertv(index >= 0 && index < (int)_controls.size());
_controls[index]._state = state;
_controls[index]._known = true;
}
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::get_control_state
// Access: Public
// Description: Returns the current position of indicated analog
// control (identified by its index number), or 0.0 if
// the control is unknown. The normal range of a single
// control is -1.0 to 1.0.
////////////////////////////////////////////////////////////////////
INLINE double ClientAnalogDevice::
get_control_state(int index) const {
if (index >= 0 && index < (int)_controls.size()) {
return _controls[index]._state;
} else {
return 0.0;
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::is_control_known
// Access: Public
// Description: Returns true if the state of the indicated analog
// control is known, or false if we have never heard
// anything about this particular control.
////////////////////////////////////////////////////////////////////
INLINE bool ClientAnalogDevice::
is_control_known(int index) const {
if (index >= 0 && index < (int)_controls.size()) {
return _controls[index]._known;
} else {
return false;
}
}

View File

@ -19,25 +19,6 @@
TypeHandle ClientAnalogDevice::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::ensure_control_index
// Access: Private
// Description: Guarantees that there is a slot in the array for the
// indicated index number, by filling the array up to
// that index if necessary.
////////////////////////////////////////////////////////////////////
void ClientAnalogDevice::
ensure_control_index(int index) {
nassertv(index >= 0);
_controls.reserve(index + 1);
while ((int)_controls.size() <= index) {
_controls.push_back(AnalogState());
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::write
// Access: Public, Virtual
@ -45,32 +26,6 @@ ensure_control_index(int index) {
////////////////////////////////////////////////////////////////////
void ClientAnalogDevice::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << get_type() << " " << get_device_name() << ":\n";
indent(out, indent_level) << get_type() << " " << get_name() << ":\n";
write_controls(out, indent_level + 2);
}
////////////////////////////////////////////////////////////////////
// Function: ClientAnalogDevice::write_analogs
// Access: Public
// Description: Writes a multi-line description of the current analog
// control states.
////////////////////////////////////////////////////////////////////
void ClientAnalogDevice::
write_controls(ostream &out, int indent_level) const {
bool any_controls = false;
Controls::const_iterator ai;
for (ai = _controls.begin(); ai != _controls.end(); ++ai) {
const AnalogState &state = (*ai);
if (state._known) {
any_controls = true;
indent(out, indent_level)
<< (int)(ai - _controls.begin()) << ". " << state._state << "\n";
}
}
if (!any_controls) {
indent(out, indent_level)
<< "(no known analog controls)\n";
}
}

View File

@ -36,30 +36,7 @@ protected:
INLINE ClientAnalogDevice(ClientBase *client, const string &device_name);
public:
INLINE int get_num_controls() const;
INLINE void set_control_state(int index, double state);
INLINE double get_control_state(int index) const;
INLINE bool is_control_known(int index) const;
virtual void write(ostream &out, int indent_level = 0) const;
void write_controls(ostream &out, int indent_level) const;
private:
void ensure_control_index(int index);
protected:
class AnalogState {
public:
INLINE AnalogState();
double _state;
bool _known;
};
typedef pvector<AnalogState> Controls;
Controls _controls;
public:
static TypeHandle get_class_type() {

View File

@ -144,7 +144,6 @@ get_device(TypeHandle device_type, const string &device_name) {
if (device != (ClientDevice *)NULL) {
dbn.insert(DevicesByName::value_type(device_name, device));
device->_is_connected = true;
}
return device;

View File

@ -12,113 +12,3 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::ButtonState::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ClientButtonDevice::ButtonState::
ButtonState() :
_handle(ButtonHandle::none()),
_state(S_unknown)
{
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::get_num_buttons
// Access: Public
// Description: Returns the number of buttons known to the
// ClientButtonDevice. This includes those buttons
// whose state has been seen, as well as buttons that
// have been associated with a ButtonHandle even if
// their state is unknown. This number may change as
// more buttons are discovered.
////////////////////////////////////////////////////////////////////
INLINE int ClientButtonDevice::
get_num_buttons() const {
return _buttons.size();
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::set_button_map
// Access: Public
// Description: Associates the indicated ButtonHandle with the button
// of the indicated index number. When the given button
// index changes state, a corresponding ButtonEvent will
// be generated with the given ButtonHandle. Pass
// ButtonHandle::none() to turn off any association.
//
// It is not necessary to call this if you simply want
// to query the state of the various buttons by index
// number; this is only necessary in order to generate
// ButtonEvents when the buttons change state.
////////////////////////////////////////////////////////////////////
INLINE void ClientButtonDevice::
set_button_map(int index, ButtonHandle button) {
ensure_button_index(index);
nassertv(index >= 0 && index < (int)_buttons.size());
_buttons[index]._handle = button;
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::get_button_map
// Access: Public
// Description: Returns the ButtonHandle that was previously
// associated with the given index number by
// a call to set_button_map(), or ButtonHandle::none()
// if no button was associated.
////////////////////////////////////////////////////////////////////
INLINE ButtonHandle ClientButtonDevice::
get_button_map(int index) const {
if (index >= 0 && index < (int)_buttons.size()) {
return _buttons[index]._handle;
} else {
return ButtonHandle::none();
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::get_button_state
// Access: Public
// Description: Returns true if the indicated button (identified by
// its index number) is currently known to be down, or
// false if it is up or unknown.
////////////////////////////////////////////////////////////////////
INLINE bool ClientButtonDevice::
get_button_state(int index) const {
if (index >= 0 && index < (int)_buttons.size()) {
return (_buttons[index]._state == S_down);
} else {
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::is_button_known
// Access: Public
// Description: Returns true if the state of the indicated button is
// known, or false if we have never heard anything about
// this particular button.
////////////////////////////////////////////////////////////////////
INLINE bool ClientButtonDevice::
is_button_known(int index) const {
if (index >= 0 && index < (int)_buttons.size()) {
return _buttons[index]._state != S_unknown;
} else {
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::get_button_events
// Access: Public
// Description: Returns the list of recently-generated ButtonEvents.
// This must be periodically cleared, or the buttons
// will accumulate.
////////////////////////////////////////////////////////////////////
INLINE ButtonEventList *ClientButtonDevice::
get_button_events() const {
return _button_events;
}

View File

@ -28,47 +28,6 @@ ClientButtonDevice::
ClientButtonDevice(ClientBase *client, const string &device_name):
ClientDevice(client, get_class_type(), device_name)
{
_button_events = new ButtonEventList();
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::set_button_state
// Access: Public
// Description: Sets the state of the indicated button index, where
// true indicates down, and false indicates up. This
// may generate a ButtonEvent if the button has an
// associated ButtonHandle. The caller should ensure
// that acquire() is in effect while this call is made.
////////////////////////////////////////////////////////////////////
void ClientButtonDevice::
set_button_state(int index, bool down) {
ensure_button_index(index);
nassertv(index >= 0 && index < (int)_buttons.size());
_buttons[index]._state = down ? S_down : S_up;
ButtonHandle handle = _buttons[index]._handle;
if (handle != ButtonHandle::none()) {
_button_events->add_event(ButtonEvent(handle, down ? ButtonEvent::T_down : ButtonEvent::T_up));
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::ensure_button_index
// Access: Private
// Description: Guarantees that there is a slot in the array for the
// indicated index number, by filling the array up to
// that index if necessary.
////////////////////////////////////////////////////////////////////
void ClientButtonDevice::
ensure_button_index(int index) {
nassertv(index >= 0);
_buttons.reserve(index + 1);
while ((int)_buttons.size() <= index) {
_buttons.push_back(ButtonState());
}
}
////////////////////////////////////////////////////////////////////
@ -78,7 +37,7 @@ ensure_button_index(int index) {
////////////////////////////////////////////////////////////////////
void ClientButtonDevice::
output(ostream &out) const {
out << get_type() << " " << get_device_name() << " (";
out << get_type() << " " << get_name() << " (";
output_buttons(out);
out << ")";
}
@ -90,74 +49,6 @@ output(ostream &out) const {
////////////////////////////////////////////////////////////////////
void ClientButtonDevice::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << get_type() << " " << get_device_name() << ":\n";
indent(out, indent_level) << get_type() << " " << get_name() << ":\n";
write_buttons(out, indent_level + 2);
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::output_buttons
// Access: Public
// Description: Writes a one-line string of all of the current button
// states.
////////////////////////////////////////////////////////////////////
void ClientButtonDevice::
output_buttons(ostream &out) const {
bool any_buttons = false;
Buttons::const_iterator bi;
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
const ButtonState &state = (*bi);
if (state._state != S_unknown) {
if (any_buttons) {
out << ", ";
}
any_buttons = true;
out << (int)(bi - _buttons.begin()) << "=";
if (state._state == S_up) {
out << "up";
} else {
out << "down";
}
}
}
if (!any_buttons) {
out << "no known buttons";
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientButtonDevice::write_buttons
// Access: Public
// Description: Writes a multi-line description of the current button
// states.
////////////////////////////////////////////////////////////////////
void ClientButtonDevice::
write_buttons(ostream &out, int indent_level) const {
bool any_buttons = false;
Buttons::const_iterator bi;
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
const ButtonState &state = (*bi);
if (state._state != S_unknown) {
any_buttons = true;
indent(out, indent_level)
<< (int)(bi - _buttons.begin()) << ". ";
if (state._handle != ButtonHandle::none()) {
out << "(" << state._handle << ") ";
}
if (state._state == S_up) {
out << "up";
} else {
out << "down";
}
out << "\n";
}
}
if (!any_buttons) {
indent(out, indent_level)
<< "(no known buttons)\n";
}
}

View File

@ -39,46 +39,9 @@ protected:
ClientButtonDevice(ClientBase *client, const string &device_name);
public:
INLINE int get_num_buttons() const;
INLINE void set_button_map(int index, ButtonHandle button);
INLINE ButtonHandle get_button_map(int index) const;
void set_button_state(int index, bool down);
INLINE bool get_button_state(int index) const;
INLINE bool is_button_known(int index) const;
INLINE ButtonEventList *get_button_events() const;
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;
void output_buttons(ostream &out) const;
void write_buttons(ostream &out, int indent_level) const;
private:
void ensure_button_index(int index);
protected:
enum State {
S_unknown,
S_up,
S_down
};
class ButtonState {
public:
INLINE ButtonState();
ButtonHandle _handle;
State _state;
};
typedef pvector<ButtonState> Buttons;
Buttons _buttons;
PT(ButtonEventList) _button_events;
public:
static TypeHandle get_class_type() {
return _type_handle;
@ -95,7 +58,6 @@ public:
private:
static TypeHandle _type_handle;
friend class ButtonState;
};
#include "clientButtonDevice.I"

View File

@ -24,17 +24,6 @@ get_client() const {
return _client;
}
////////////////////////////////////////////////////////////////////
// Function: ClientDevice::is_connected
// Access: Public
// Description: Returns true if the device is still connected to its
// ClientBase, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool ClientDevice::
is_connected() const {
return _is_connected;
}
////////////////////////////////////////////////////////////////////
// Function: ClientDevice::get_device_type
// Access: Public
@ -50,45 +39,3 @@ INLINE TypeHandle ClientDevice::
get_device_type() const {
return _device_type;
}
////////////////////////////////////////////////////////////////////
// Function: ClientDevice::get_device_name
// Access: Public
// Description: Returns the device name reported to the ClientBase.
// This has some implementation-defined meaning to
// identify particular devices.
////////////////////////////////////////////////////////////////////
INLINE const string &ClientDevice::
get_device_name() const {
return _device_name;
}
////////////////////////////////////////////////////////////////////
// Function: ClientDevice::acquire
// Access: Public
// Description: Grabs the mutex associated with this particular
// device. The device will not update asynchronously
// while the mutex is held, allowing the user to copy
// the data out without fear of getting a partial update
// during the copy.
////////////////////////////////////////////////////////////////////
INLINE void ClientDevice::
acquire() {
#ifdef OLD_HAVE_IPC
_lock.acquire();
#endif
}
////////////////////////////////////////////////////////////////////
// Function: ClientDevice::unlock
// Access: Public
// Description: Releases the mutex associated with this particular
// device. This should be called after all the data has
// been successfully copied out. See acquire().
////////////////////////////////////////////////////////////////////
INLINE void ClientDevice::
unlock() {
#ifdef OLD_HAVE_IPC
_lock.unlock();
#endif
}

View File

@ -27,15 +27,14 @@ TypeHandle ClientDevice::_type_handle;
////////////////////////////////////////////////////////////////////
ClientDevice::
ClientDevice(ClientBase *client, TypeHandle device_type,
const string &device_name) :
const string &device_name, int device_flags) :
InputDevice(device_name, DC_unknown, device_flags),
_client(client),
_device_type(device_type),
_device_name(device_name)
_device_type(device_type)
{
// We have to explicitly ref the client pointer, since we can't use
// a PT(ClientBase) for circular include reasons.
_client->ref();
_is_connected = false;
}
////////////////////////////////////////////////////////////////////
@ -49,7 +48,7 @@ ClientDevice(ClientBase *client, TypeHandle device_type,
////////////////////////////////////////////////////////////////////
ClientDevice::
~ClientDevice() {
nassertv(!_is_connected);
nassertv(!is_connected());
// And now we explicitly unref the client pointer.
unref_delete(_client);
@ -72,19 +71,17 @@ ClientDevice::
////////////////////////////////////////////////////////////////////
void ClientDevice::
disconnect() {
if (_is_connected) {
acquire();
if (is_connected()) {
bool disconnected =
_client->disconnect_device(_device_type, _device_name, this);
_is_connected = false;
unlock();
_client->disconnect_device(_device_type, get_name(), this);
set_connected(false);
nassertv(disconnected);
}
}
////////////////////////////////////////////////////////////////////
// Function: ClientDevice::poll
// Access: Public
// Function: ClientDevice::do_poll
// Access: Public, Virtual, Final
// Description: Causes the connected ClientBase to poll all of its
// clients, if necessary. This will be a no-op if the
// client is running in forked mode, or if it has
@ -94,7 +91,7 @@ disconnect() {
// data in this ClientDevice to ensure that it is fresh.
////////////////////////////////////////////////////////////////////
void ClientDevice::
poll() {
do_poll() {
_client->poll();
}
@ -105,7 +102,7 @@ poll() {
////////////////////////////////////////////////////////////////////
void ClientDevice::
output(ostream &out) const {
out << get_type() << " " << get_device_name();
out << get_type() << " " << get_name();
}
////////////////////////////////////////////////////////////////////

View File

@ -16,12 +16,7 @@
#define CLIENTDEVICE_H
#include "pandabase.h"
#include "typedReferenceCount.h"
#ifdef OLD_HAVE_IPC
#include <ipc_mutex.h>
#endif
#include "inputDevice.h"
class ClientBase;
@ -32,24 +27,20 @@ class ClientBase;
// This is an abstract interface; the actual
// implementations are in ClientTrackerDevice, etc.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DEVICE ClientDevice : public TypedReferenceCount {
class EXPCL_PANDA_DEVICE ClientDevice : public InputDevice {
protected:
ClientDevice(ClientBase *client, TypeHandle device_type,
const string &device_name);
const string &device_name, int device_flags=0);
public:
virtual ~ClientDevice();
INLINE ClientBase *get_client() const;
INLINE TypeHandle get_device_type() const;
INLINE const string &get_device_name() const;
INLINE bool is_connected() const;
void disconnect();
void poll();
INLINE void acquire();
INLINE void unlock();
virtual void do_poll() FINAL;
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level = 0) const;
@ -57,21 +48,15 @@ public:
private:
ClientBase *_client;
TypeHandle _device_type;
string _device_name;
bool _is_connected;
#ifdef OLD_HAVE_IPC
mutex _lock;
#endif
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedReferenceCount::init_type();
InputDevice::init_type();
register_type(_type_handle, "ClientDevice",
TypedReferenceCount::get_class_type());
InputDevice::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -20,18 +20,6 @@
////////////////////////////////////////////////////////////////////
INLINE ClientTrackerDevice::
ClientTrackerDevice(ClientBase *client, const string &device_name):
ClientDevice(client, get_class_type(), device_name)
ClientDevice(client, get_class_type(), device_name, IDF_has_tracker)
{
}
////////////////////////////////////////////////////////////////////
// Function: ClientTrackerDevice::get_data
// Access: Public
// Description: Returns the TrackerData that this device is
// reporting.
////////////////////////////////////////////////////////////////////
INLINE const TrackerData &ClientTrackerDevice::
get_data() const {
return _data;
}

View File

@ -30,12 +30,6 @@ class EXPCL_PANDA_DEVICE ClientTrackerDevice : public ClientDevice {
protected:
INLINE ClientTrackerDevice(ClientBase *client, const string &device_name);
public:
INLINE const TrackerData &get_data() const;
protected:
TrackerData _data;
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -23,7 +23,9 @@
#include "clientDialDevice.h"
#include "clientTrackerDevice.h"
#include "dialNode.h"
#include "mouseAndKeyboard.h"
#include "evdevInputDevice.h"
#include "inputDevice.h"
#include "linuxJoystickDevice.h"
#include "trackerNode.h"
#include "virtualMouse.h"
@ -64,7 +66,12 @@ init_libdevice() {
ClientDialDevice::init_type();
ClientTrackerDevice::init_type();
DialNode::init_type();
MouseAndKeyboard::init_type();
InputDevice::init_type();
TrackerNode::init_type();
VirtualMouse::init_type();
#ifdef PHAVE_LINUX_INPUT_H
EvdevInputDevice::init_type();
LinuxJoystickDevice::init_type();
#endif
}

View File

@ -33,10 +33,7 @@ is_valid() const {
////////////////////////////////////////////////////////////////////
INLINE int DialNode::
get_num_dials() const {
_dial->acquire();
int result = _dial->get_num_dials();
_dial->unlock();
return result;
return _dial->get_num_dials();
}
////////////////////////////////////////////////////////////////////
@ -49,10 +46,7 @@ get_num_dials() const {
////////////////////////////////////////////////////////////////////
INLINE double DialNode::
read_dial(int index) {
_dial->acquire();
double result = _dial->read_dial(index);
_dial->unlock();
return result;
return _dial->read_dial(index);
}
////////////////////////////////////////////////////////////////////
@ -64,8 +58,5 @@ read_dial(int index) {
////////////////////////////////////////////////////////////////////
INLINE bool DialNode::
is_dial_known(int index) const {
_dial->acquire();
bool result = _dial->is_dial_known(index);
_dial->unlock();
return result;
return _dial->is_dial_known(index);
}

View File

@ -0,0 +1,14 @@
// Filename: evdevInputDevice.I
// Created by: rdb (24Aug15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,424 @@
// Filename: evdevInputDevice.cxx
// Created by: rdb (24Aug15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "evdevInputDevice.h"
#ifdef PHAVE_LINUX_INPUT_H
#include "gamepadButton.h"
#include "keyboardButton.h"
#include "mouseButton.h"
#include <fcntl.h>
#include <linux/input.h>
#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7)))
TypeHandle EvdevInputDevice::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: EvdevInputDevice::Constructor
// Access: Published
// Description: Creates a new device using the Linux joystick
// device using the given file descriptor. It will
// be closed when this object destructs.
////////////////////////////////////////////////////////////////////
EvdevInputDevice::
EvdevInputDevice(int fd) :
_fd(fd) {
init_device();
}
////////////////////////////////////////////////////////////////////
// Function: EvdevInputDevice::Constructor
// Access: Published
// Description: Creates a new device using the Linux joystick
// device using the given device filename.
////////////////////////////////////////////////////////////////////
EvdevInputDevice::
EvdevInputDevice(const string &fn) {
_fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK);
if (_fd >= 0) {
init_device();
} else {
_is_connected = false;
device_cat.error()
<< "Opening raw input device: " << strerror(errno) << " " << fn << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: EvdevInputDevice::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
EvdevInputDevice::
~EvdevInputDevice() {
if (_fd != -1) {
close(_fd);
_fd = -1;
}
}
////////////////////////////////////////////////////////////////////
// Function: EvdevInputDevice::do_poll
// Access: Private, Virtual
// Description: Polls the input device for new activity, to ensure
// it contains the latest events. This will only have
// any effect for some types of input devices; others
// may be updated automatically, and this method will
// be a no-op.
////////////////////////////////////////////////////////////////////
void EvdevInputDevice::
do_poll() {
if (_fd != -1) {
while (process_events()) {}
}
}
////////////////////////////////////////////////////////////////////
// Function: EvdevInputDevice::init_device
// Access: Private
// Description: Reads basic properties from the device.
////////////////////////////////////////////////////////////////////
bool EvdevInputDevice::
init_device() {
uint8_t evtypes[EV_MAX/8 + 1];
char name[256];
char uniq[256];
if (ioctl(_fd, EVIOCGNAME(sizeof(name)), name) < 0 ||
ioctl(_fd, EVIOCGPHYS(sizeof(uniq)), uniq) < 0 ||
ioctl(_fd, EVIOCGBIT(0, EV_MAX), &evtypes) < 0) {
close(_fd);
_fd = -1;
_is_connected = false;
device_cat.error() << "Opening raw input device: ioctl failed\n";
return false;
}
for (char *p=name; *p; p++) {
if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) {
*p = '_';
}
}
for (char *p=uniq; *p; p++) {
if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) {
*p = '_';
}
}
_name = ((string)name) + "." + uniq;
if (test_bit(EV_REL, evtypes)) {
_flags |= IDF_has_pointer;
}
if (test_bit(EV_FF, evtypes)) {
_flags |= IDF_has_vibration;
}
_is_connected = true;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EvdevInputDevice::process_events
// Access: Private
// Description: Reads a number of events from the device.
////////////////////////////////////////////////////////////////////
bool EvdevInputDevice::
process_events() {
// Read 8 events at a time.
struct input_event events[8];
int n_read = read(_fd, events, sizeof(events));
if (n_read < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// No data available for now.
} else if (errno == ENODEV || errno == EINVAL) {
// The device ceased to exist, so we better close it.
close(_fd);
_fd = -1;
_is_connected = false;
errno = 0;
} else {
device_cat.error() << "read: " << strerror(errno) << "\n";
}
return false;
}
if (n_read == 0) {
return false;
}
n_read /= sizeof(struct input_event);
int x = _pointer_data.get_x();
int y = _pointer_data.get_y();
double time = ClockObject::get_global_clock()->get_frame_time();
ButtonHandle button;
for (int i = 0; i < n_read; ++i) {
switch (events[i].type) {
case EV_SYN:
break;
case EV_REL:
if (events[i].code == REL_X) x += events[i].value;
if (events[i].code == REL_Y) y += events[i].value;
break;
case EV_ABS:
if (events[i].code == ABS_X) x = events[i].value;
if (events[i].code == ABS_Y) y = events[i].value;
break;
case EV_KEY:
button = map_button(events[i].code);
_button_events->add_event(ButtonEvent(button, events[i].value ? ButtonEvent::T_down : ButtonEvent::T_up, time));
break;
default:
//cerr << "event " << events[i].type << " - " << events[i].code << " - " << events[i].value << "\n";
break;
}
}
set_pointer(true, x, y, time);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EvdevInputDevice::map_button
// Access: Public, Static
// Description: Maps an evdev code to a ButtonHandle.
////////////////////////////////////////////////////////////////////
ButtonHandle EvdevInputDevice::
map_button(int code) {
if (code >= 0 && code < 0x80) {
// See linux/input.h for the source of this mapping.
static const ButtonHandle keyboard_map[] = {
ButtonHandle::none(),
KeyboardButton::escape(),
KeyboardButton::ascii_key('1'),
KeyboardButton::ascii_key('2'),
KeyboardButton::ascii_key('3'),
KeyboardButton::ascii_key('4'),
KeyboardButton::ascii_key('5'),
KeyboardButton::ascii_key('6'),
KeyboardButton::ascii_key('7'),
KeyboardButton::ascii_key('8'),
KeyboardButton::ascii_key('9'),
KeyboardButton::ascii_key('0'),
KeyboardButton::ascii_key('-'),
KeyboardButton::ascii_key('='),
KeyboardButton::backspace(),
KeyboardButton::tab(),
KeyboardButton::ascii_key('q'),
KeyboardButton::ascii_key('w'),
KeyboardButton::ascii_key('e'),
KeyboardButton::ascii_key('r'),
KeyboardButton::ascii_key('t'),
KeyboardButton::ascii_key('y'),
KeyboardButton::ascii_key('u'),
KeyboardButton::ascii_key('i'),
KeyboardButton::ascii_key('o'),
KeyboardButton::ascii_key('p'),
KeyboardButton::ascii_key('['),
KeyboardButton::ascii_key(']'),
KeyboardButton::enter(),
KeyboardButton::lcontrol(),
KeyboardButton::ascii_key('a'),
KeyboardButton::ascii_key('s'),
KeyboardButton::ascii_key('d'),
KeyboardButton::ascii_key('f'),
KeyboardButton::ascii_key('g'),
KeyboardButton::ascii_key('h'),
KeyboardButton::ascii_key('j'),
KeyboardButton::ascii_key('k'),
KeyboardButton::ascii_key('l'),
KeyboardButton::ascii_key(';'),
KeyboardButton::ascii_key('\''),
KeyboardButton::ascii_key('`'),
KeyboardButton::lshift(),
KeyboardButton::ascii_key('\\'),
KeyboardButton::ascii_key('z'),
KeyboardButton::ascii_key('x'),
KeyboardButton::ascii_key('c'),
KeyboardButton::ascii_key('v'),
KeyboardButton::ascii_key('b'),
KeyboardButton::ascii_key('n'),
KeyboardButton::ascii_key('m'),
KeyboardButton::ascii_key(','),
KeyboardButton::ascii_key('.'),
KeyboardButton::ascii_key('/'),
KeyboardButton::rshift(),
KeyboardButton::ascii_key('*'),
KeyboardButton::lalt(),
KeyboardButton::space(),
KeyboardButton::caps_lock(),
KeyboardButton::f1(),
KeyboardButton::f2(),
KeyboardButton::f3(),
KeyboardButton::f4(),
KeyboardButton::f5(),
KeyboardButton::f6(),
KeyboardButton::f7(),
KeyboardButton::f8(),
KeyboardButton::f9(),
KeyboardButton::f10(),
KeyboardButton::num_lock(),
KeyboardButton::scroll_lock(),
KeyboardButton::ascii_key('7'),
KeyboardButton::ascii_key('8'),
KeyboardButton::ascii_key('9'),
KeyboardButton::ascii_key('-'),
KeyboardButton::ascii_key('4'),
KeyboardButton::ascii_key('5'),
KeyboardButton::ascii_key('6'),
KeyboardButton::ascii_key('+'),
KeyboardButton::ascii_key('1'),
KeyboardButton::ascii_key('2'),
KeyboardButton::ascii_key('3'),
KeyboardButton::ascii_key('0'),
KeyboardButton::ascii_key('.'),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
KeyboardButton::f11(),
KeyboardButton::f12(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
KeyboardButton::enter(),
KeyboardButton::rcontrol(),
KeyboardButton::ascii_key('/'),
KeyboardButton::print_screen(),
KeyboardButton::ralt(),
ButtonHandle::none(),
KeyboardButton::home(),
KeyboardButton::up(),
KeyboardButton::page_up(),
KeyboardButton::left(),
KeyboardButton::right(),
KeyboardButton::end(),
KeyboardButton::down(),
KeyboardButton::page_down(),
KeyboardButton::insert(),
KeyboardButton::del(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
KeyboardButton::pause(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
ButtonHandle::none(),
KeyboardButton::lmeta(),
KeyboardButton::rmeta(),
KeyboardButton::menu(),
};
return keyboard_map[code];
} else if (code < 0x100) {
return ButtonHandle::none();
} else if ((code & 0xfff0) == BTN_MOUSE) {
// The number for these is reversed in Panda.
if (code == BTN_RIGHT) {
return MouseButton::three();
} else if (code == BTN_MIDDLE) {
return MouseButton::two();
} else {
return MouseButton::button(code - BTN_MOUSE);
}
}
switch (code) {
case BTN_A:
return GamepadButton::action_a();
case BTN_B:
return GamepadButton::action_b();
case BTN_C:
return GamepadButton::action_c();
case BTN_X:
return GamepadButton::action_x();
case BTN_Y:
return GamepadButton::action_y();
case BTN_Z:
return GamepadButton::action_z();
case BTN_TL:
return GamepadButton::lshoulder();
case BTN_TR:
return GamepadButton::rshoulder();
case BTN_TL2:
return GamepadButton::ltrigger();
case BTN_TR2:
return GamepadButton::rtrigger();
case BTN_SELECT:
return GamepadButton::back();
case BTN_START:
return GamepadButton::start();
case BTN_MODE:
return GamepadButton::guide();
case BTN_THUMBL:
return GamepadButton::lstick();
case BTN_THUMBR:
return GamepadButton::rstick();
case BTN_TRIGGER_HAPPY1:
return GamepadButton::dpad_left();
case BTN_TRIGGER_HAPPY2:
return GamepadButton::dpad_right();
case BTN_TRIGGER_HAPPY3:
return GamepadButton::dpad_up();
case BTN_TRIGGER_HAPPY4:
return GamepadButton::dpad_down();
default:
return ButtonHandle::none();
}
}
#endif

View File

@ -0,0 +1,63 @@
// Filename: evdevInputDevice.h
// Created by: rdb (24Aug15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef EVDEVINPUTDEVICE_H
#define EVDEVINPUTDEVICE_H
#include "inputDevice.h"
#ifdef PHAVE_LINUX_INPUT_H
////////////////////////////////////////////////////////////////////
// Class : EvdevInputDevice
// Description : This is a type of device that uses the Linux
// /dev/input/event# API to read data from a raw mouse.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DEVICE EvdevInputDevice : public InputDevice {
PUBLISHED:
EvdevInputDevice(int fd);
EvdevInputDevice(const string &device);
virtual ~EvdevInputDevice();
private:
virtual void do_poll();
bool init_device();
bool process_events();
private:
int _fd;
public:
static ButtonHandle map_button(int code);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
InputDevice::init_type();
register_type(_type_handle, "EvdevInputDevice",
InputDevice::get_class_type());
}
private:
static TypeHandle _type_handle;
};
#include "evdevInputDevice.I"
#endif // PHAVE_LINUX_INPUT_H
#endif // EVDEVINPUTDEVICE_H

View File

@ -0,0 +1,445 @@
// Filename: inputDevice.I
// Created by: drose (24May00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: InputDevice::Default Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE InputDevice::
InputDevice() :
_flags(0),
_device_class(DC_unknown),
_is_connected(false),
_event_sequence(0),
_enable_pointer_events(false),
_battery_level(-1),
_max_battery_level(-1)
{
_button_events = new ButtonEventList;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_name
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE string InputDevice::
get_name() const {
LightMutexHolder holder(_lock);
return _name;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::is_connected
// Access: Public
// Description: Returns true if the device is still connected and
// able to receive data, false otherwise. May return
// false positives.
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
is_connected() const {
LightMutexHolder holder(_lock);
return _is_connected;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_device_class
// Access: Public
// Description: Returns an identification of the general type of
// device. If this could not be determined, returns
// DC_unknown.
////////////////////////////////////////////////////////////////////
INLINE InputDevice::DeviceClass InputDevice::
get_device_class() const {
LightMutexHolder holder(_lock);
return _device_class;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::has_pointer
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
has_pointer() const {
LightMutexHolder holder(_lock);
return ((_flags & IDF_has_pointer) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::has_keyboard
// Access: Public
// Description: Returns true if the device has a physical keyboard
// designed for text entry.
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
has_keyboard() const {
LightMutexHolder holder(_lock);
return ((_flags & IDF_has_keyboard) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::has_tracker
// Access: Public
// Description: Returns true if the device features a tracker that
// can track position and/or orientation in 3D space.
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
has_tracker() const {
LightMutexHolder holder(_lock);
return ((_flags & IDF_has_tracker) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::has_battery
// Access: Public
// Description: Returns true if the device may be able to provide
// information about its battery life.
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
has_battery() const {
LightMutexHolder holder(_lock);
return ((_flags & IDF_has_battery) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::has_axis
// Access: Public
// Description: Returns true if the device has the given axis.
////////////////////////////////////////////////////////////////////
/*
INLINE bool InputDevice::
has_axis(Axis axis) const {
LightMutexHolder holder(_lock);
return ((_has_axes & (1 << axis)) != 0);
}*/
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_pointer
// Access: Public
// Description: Returns the PointerData associated with the input
// device's pointer. This only makes sense if
// has_pointer() also returns true.
////////////////////////////////////////////////////////////////////
INLINE PointerData InputDevice::
get_pointer() const {
LightMutexHolder holder(_lock);
return _pointer_data;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_tracker
// Access: Public
// Description: Returns the TrackerData associated with the input
// device's tracker. This only makes sense if
// has_tracker() also returns true.
////////////////////////////////////////////////////////////////////
INLINE TrackerData InputDevice::
get_tracker() const {
LightMutexHolder holder(_lock);
return _tracker_data;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_battery_level
// Access: Public
// Description: Returns a rough indication of the battery level,
// ranging from 0 (completely empty battery) to the
// number reported by get_max_battery_level(), which
// represents a full battery.
// If this information is not known, returns -1.
////////////////////////////////////////////////////////////////////
INLINE short InputDevice::
get_battery_level() const {
LightMutexHolder holder(_lock);
return _battery_level;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_max_battery_level
// Access: Public
// Description: Returns the maximum value that may be reported by
// get_battery_level(), representing a full battery.
// Returns -1 if no battery information is known.
////////////////////////////////////////////////////////////////////
INLINE short InputDevice::
get_max_battery_level() const {
LightMutexHolder holder(_lock);
return _max_battery_level;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_num_buttons
// Access: Public
// Description: Returns the number of buttons known to the
// ClientButtonDevice. This includes those buttons
// whose state has been seen, as well as buttons that
// have been associated with a ButtonHandle even if
// their state is unknown. This number may change as
// more buttons are discovered.
////////////////////////////////////////////////////////////////////
INLINE int InputDevice::
get_num_buttons() const {
LightMutexHolder holder(_lock);
return _buttons.size();
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::set_button_map
// Access: Public
// Description: Associates the indicated ButtonHandle with the button
// of the indicated index number. When the given button
// index changes state, a corresponding ButtonEvent will
// be generated with the given ButtonHandle. Pass
// ButtonHandle::none() to turn off any association.
//
// It is not necessary to call this if you simply want
// to query the state of the various buttons by index
// number; this is only necessary in order to generate
// ButtonEvents when the buttons change state.
////////////////////////////////////////////////////////////////////
INLINE void InputDevice::
set_button_map(int index, ButtonHandle button) {
LightMutexHolder holder(_lock);
nassertv(index >= 0);
if (index >= (int)_buttons.size()) {
_buttons.resize(index + 1, ButtonState());
}
_buttons[index]._handle = button;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_button_map
// Access: Public
// Description: Returns the ButtonHandle that was previously
// associated with the given index number by
// a call to set_button_map(), or ButtonHandle::none()
// if no button was associated.
////////////////////////////////////////////////////////////////////
INLINE ButtonHandle InputDevice::
get_button_map(int index) const {
if (index >= 0 && index < (int)_buttons.size()) {
return _buttons[index]._handle;
} else {
return ButtonHandle::none();
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_button_state
// Access: Public
// Description: Returns true if the indicated button (identified by
// its index number) is currently known to be down, or
// false if it is up or unknown.
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
get_button_state(int index) const {
if (index >= 0 && index < (int)_buttons.size()) {
return (_buttons[index]._state == S_down);
} else {
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::is_button_known
// Access: Public
// Description: Returns true if the state of the indicated button is
// known, or false if we have never heard anything about
// this particular button.
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
is_button_known(int index) const {
if (index >= 0 && index < (int)_buttons.size()) {
return _buttons[index]._state != S_unknown;
} else {
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_num_controls
// Access: Public
// Description: Returns the number of analog controls known to the
// InputDevice. This number may change as
// more controls are discovered.
////////////////////////////////////////////////////////////////////
INLINE int InputDevice::
get_num_controls() const {
return _controls.size();
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::set_control_map
// Access: Public
// Description: Associates the indicated ControlAxis with the
// control of the indicated index number. Pass
// C_none to turn off any association.
//
// It is not necessary to call this if you simply want
// to query the state of the various controls by index
// number.
////////////////////////////////////////////////////////////////////
INLINE void InputDevice::
set_control_map(int index, ControlAxis axis) {
LightMutexHolder holder(_lock);
nassertv(index >= 0);
if (index >= (int)_controls.size()) {
_controls.resize(index + 1, AnalogState());
}
_controls[index]._axis = axis;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_control_map
// Access: Public
// Description: Returns the ControlAxis that was previously
// associated with the given index number by
// a call to set_control_map(), or C_none
// if no control was associated.
////////////////////////////////////////////////////////////////////
INLINE InputDevice::ControlAxis InputDevice::
get_control_map(int index) const {
if (index >= 0 && index < (int)_controls.size()) {
return _controls[index]._axis;
} else {
return C_none;
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_control_state
// Access: Public
// Description: Returns the current position of indicated analog
// control (identified by its index number), or 0.0 if
// the control is unknown. The normal range of a single
// control is -1.0 to 1.0.
////////////////////////////////////////////////////////////////////
INLINE double InputDevice::
get_control_state(int index) const {
if (index >= 0 && index < (int)_controls.size()) {
return _controls[index]._state;
} else {
return 0.0;
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::is_control_known
// Access: Public
// Description: Returns true if the state of the indicated analog
// control is known, or false if we have never heard
// anything about this particular control.
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
is_control_known(int index) const {
if (index >= 0 && index < (int)_controls.size()) {
return _controls[index]._known;
} else {
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::enable_pointer_events
// Access: Public
// Description: Enables the generation of mouse-movement events.
////////////////////////////////////////////////////////////////////
INLINE void InputDevice::
enable_pointer_events() {
LightMutexHolder holder(_lock);
_enable_pointer_events = true;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::disable_pointer_events
// Access: Public
// Description: Disables the generation of mouse-movement events.
////////////////////////////////////////////////////////////////////
INLINE void InputDevice::
disable_pointer_events() {
LightMutexHolder holder(_lock);
_enable_pointer_events = false;
_pointer_events.clear();
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::set_connected
// Access: Protected
// Description: Called to indicate that the device has been
// disconnected or connected from its host.
////////////////////////////////////////////////////////////////////
INLINE void InputDevice::
set_connected(bool connected) {
LightMutexHolder holder(_lock);
_is_connected = connected;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::operator ==
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
operator == (const InputDevice &) const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::operator !=
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
operator != (const InputDevice &) const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::operator <
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool InputDevice::
operator < (const InputDevice &) const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::ButtonState::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE InputDevice::ButtonState::
ButtonState() :
_handle(ButtonHandle::none()),
_state(S_unknown)
{
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::AnalogState::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE InputDevice::AnalogState::
AnalogState() :
_axis(C_none),
_state(0.0),
_known(false)
{
}

View File

@ -0,0 +1,517 @@
// Filename: inputDevice.cxx
// Created by: drose (24May00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "inputDevice.h"
TypeHandle InputDevice::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: InputDevice::Constructor
// Access: Private
// Description: Defines a new InputDevice for the window. Most
// windows will have exactly one InputDevice: a
// keyboard/mouse pair. Some may also add joystick
// data, or additional mice or something.
//
// This private constructor is only used internally by
// the named constructors, below.
////////////////////////////////////////////////////////////////////
InputDevice::
InputDevice(const string &name, DeviceClass dev_class, int flags) :
_name(name),
_flags(flags),
_device_class(dev_class),
_is_connected(true),
_event_sequence(0),
_enable_pointer_events(false),
_battery_level(-1),
_max_battery_level(-1)
{
_button_events = new ButtonEventList;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
InputDevice::
InputDevice(const InputDevice &copy) {
*this = copy;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void InputDevice::
operator = (const InputDevice &copy) {
LightMutexHolder holder(_lock);
LightMutexHolder holder1(copy._lock);
_name = copy._name;
_flags = copy._flags;
_is_connected = copy._is_connected;
_event_sequence = copy._event_sequence;
_enable_pointer_events = copy._enable_pointer_events;
_pointer_data = copy._pointer_data;
_button_events = copy._button_events;
_pointer_events = copy._pointer_events;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
InputDevice::
~InputDevice() {
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::poll
// Access: Public, Virtual
// Description: Polls the input device for new activity, to ensure
// it contains the latest events. This will only have
// any effect for some types of input devices; others
// may be updated automatically, and this method will
// be a no-op.
////////////////////////////////////////////////////////////////////
void InputDevice::
poll() {
LightMutexHolder holder(_lock);
do_poll();
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::has_button_event
// Access: Public
// Description: Returns true if this device has a pending button
// event (a mouse button or keyboard button down/up),
// false otherwise. If this returns true, the
// particular event may be extracted via
// get_button_event().
////////////////////////////////////////////////////////////////////
bool InputDevice::
has_button_event() const {
LightMutexHolder holder(_lock);
return !_button_events.is_null() && _button_events->get_num_events() > 0;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_button_events
// Access: Public
// Description: Returns the list of recently-generated ButtonEvents.
// The list is also cleared.
////////////////////////////////////////////////////////////////////
PT(ButtonEventList) InputDevice::
get_button_events() {
LightMutexHolder holder(_lock);
PT(ButtonEventList) result = new ButtonEventList;
swap(_button_events, result);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::has_pointer_event
// Access: Public
// Description: Returns true if this device has a pending pointer
// event (a mouse movement), or false otherwise. If
// this returns true, the particular event may be
// extracted via get_pointer_event().
////////////////////////////////////////////////////////////////////
bool InputDevice::
has_pointer_event() const {
LightMutexHolder holder(_lock);
return (_pointer_events != 0);
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::get_pointer_events
// Access: Public
// Description: Returns a PointerEventList containing all the recent
// pointer events. Clears the list.
////////////////////////////////////////////////////////////////////
PT(PointerEventList) InputDevice::
get_pointer_events() {
LightMutexHolder holder(_lock);
PT(PointerEventList) result = _pointer_events;
_pointer_events.clear();
return result;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::set_pointer
// Access: Protected
// Description: Records that a mouse movement has taken place.
////////////////////////////////////////////////////////////////////
void InputDevice::
set_pointer(bool inwin, double x, double y, double time) {
nassertv(_lock.debug_is_locked());
_pointer_data._in_window = inwin;
_pointer_data._xpos = x;
_pointer_data._ypos = y;
if (_enable_pointer_events) {
int seq = _event_sequence++;
if (_pointer_events.is_null()) {
_pointer_events = new PointerEventList();
}
_pointer_events->add_event(_pointer_data._in_window,
_pointer_data._xpos,
_pointer_data._ypos,
seq, time);
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::set_pointer_out_of_window
// Access: Protected
// Description: Records that the mouse pointer has left the window.
////////////////////////////////////////////////////////////////////
void InputDevice::
set_pointer_out_of_window(double time) {
nassertv(_lock.debug_is_locked());
_pointer_data._in_window = false;
if (_enable_pointer_events) {
int seq = _event_sequence++;
if (_pointer_events.is_null()) {
_pointer_events = new PointerEventList();
}
_pointer_events->add_event(_pointer_data._in_window,
_pointer_data._xpos,
_pointer_data._ypos,
seq, time);
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::set_button_state
// Access: Protected
// Description: Sets the state of the indicated button index, where
// true indicates down, and false indicates up. This
// may generate a ButtonEvent if the button has an
// associated ButtonHandle. The caller should ensure
// that acquire() is in effect while this call is made.
////////////////////////////////////////////////////////////////////
void InputDevice::
set_button_state(int index, bool down) {
nassertv(_lock.debug_is_locked());
nassertv(index >= 0);
if (index >= (int)_buttons.size()) {
_buttons.resize(index + 1, ButtonState());
}
_buttons[index]._state = down ? S_down : S_up;
ButtonHandle handle = _buttons[index]._handle;
if (handle != ButtonHandle::none()) {
_button_events->add_event(ButtonEvent(handle, down ? ButtonEvent::T_down : ButtonEvent::T_up));
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::set_control_state
// Access: Protected
// Description: Sets the state of the indicated analog index. The
// caller should ensure that acquire() is in effect while
// this call is made. This should be a number in the
// range -1.0 to 1.0, representing the current position
// of the control within its total range of movement.
////////////////////////////////////////////////////////////////////
void InputDevice::
set_control_state(int index, double state) {
nassertv(_lock.debug_is_locked());
nassertv(index >= 0);
if (index >= (int)_controls.size()) {
_controls.resize(index + 1, AnalogState());
}
_controls[index]._state = state;
_controls[index]._known = true;
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::set_tracker
// Access: Protected
// Description: Records that a tracker movement has taken place.
////////////////////////////////////////////////////////////////////
void InputDevice::
set_tracker(const LPoint3 &pos, const LOrientation &orient, double time) {
nassertv(_lock.debug_is_locked());
_tracker_data.set_pos(pos);
_tracker_data.set_orient(orient);
_tracker_data.set_time(time);
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::output
// Access: Public
// Description: Writes a one-line string describing the device.
////////////////////////////////////////////////////////////////////
void InputDevice::
output(ostream &out) const {
LightMutexHolder holder(_lock);
out << _name << " (";
if (!_is_connected) {
out << "dis";
}
out << "connected)";
if (_device_class != DC_unknown) {
out << ", " << _device_class;
}
if (_buttons.size() > 0) {
out << ", " << _buttons.size() << " buttons";
}
if (_controls.size() > 0) {
out << ", " << _controls.size() << " controls";
}
if (_flags & IDF_has_pointer) {
out << ", pointer";
}
if (_flags & IDF_has_keyboard) {
out << ", keyboard";
}
if (_flags & IDF_has_tracker) {
out << ", tracker";
}
if (_flags & IDF_has_vibration) {
out << ", vibration";
}
if (_flags & IDF_has_battery) {
out << ", battery";
if (_battery_level > 0 && _max_battery_level > 0) {
out << " [";
short i = 0;
for (; i < _battery_level - 1; ++i) {
out << '=';
}
out << '/';
for (; i < _max_battery_level; ++i) {
out << ' ';
}
out << ']';
}
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::output_buttons
// Access: Public
// Description: Writes a one-line string of all of the current button
// states.
////////////////////////////////////////////////////////////////////
void InputDevice::
output_buttons(ostream &out) const {
LightMutexHolder holder(_lock);
bool any_buttons = false;
Buttons::const_iterator bi;
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
const ButtonState &state = (*bi);
if (state._state != S_unknown) {
if (any_buttons) {
out << ", ";
}
any_buttons = true;
out << (int)(bi - _buttons.begin()) << "=";
if (state._state == S_up) {
out << "up";
} else {
out << "down";
}
}
}
if (!any_buttons) {
out << "no known buttons";
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::write_buttons
// Access: Public
// Description: Writes a multi-line description of the current button
// states.
////////////////////////////////////////////////////////////////////
void InputDevice::
write_buttons(ostream &out, int indent_level) const {
bool any_buttons = false;
Buttons::const_iterator bi;
for (bi = _buttons.begin(); bi != _buttons.end(); ++bi) {
const ButtonState &state = (*bi);
if (state._state != S_unknown) {
any_buttons = true;
indent(out, indent_level)
<< (int)(bi - _buttons.begin()) << ". ";
if (state._handle != ButtonHandle::none()) {
out << "(" << state._handle << ") ";
}
if (state._state == S_up) {
out << "up";
} else {
out << "down";
}
out << "\n";
}
}
if (!any_buttons) {
indent(out, indent_level)
<< "(no known buttons)\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::write_controls
// Access: Public
// Description: Writes a multi-line description of the current analog
// control states.
////////////////////////////////////////////////////////////////////
void InputDevice::
write_controls(ostream &out, int indent_level) const {
LightMutexHolder holder(_lock);
bool any_controls = false;
Controls::const_iterator ai;
for (ai = _controls.begin(); ai != _controls.end(); ++ai) {
const AnalogState &state = (*ai);
if (state._known) {
any_controls = true;
indent(out, indent_level)
<< (int)(ai - _controls.begin()) << ". " << state._state << "\n";
}
}
if (!any_controls) {
indent(out, indent_level)
<< "(no known analog controls)\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: InputDevice::do_poll
// Access: Protected, Virtual
// Description: Polls the input device for new activity, to ensure
// it contains the latest events. This will only have
// any effect for some types of input devices; others
// may be updated automatically, and this method will
// be a no-op.
////////////////////////////////////////////////////////////////////
void InputDevice::
do_poll() {
}
ostream &
operator << (ostream &out, InputDevice::DeviceClass dc) {
switch (dc) {
case InputDevice::DC_unknown:
out << "unknown";
break;
case InputDevice::DC_virtual:
out << "virtual";
break;
case InputDevice::DC_keyboard:
out << "keyboard";
break;
case InputDevice::DC_mouse:
out << "mouse";
break;
case InputDevice::DC_touch:
out << "touch";
break;
case InputDevice::DC_gamepad:
out << "gamepad";
break;
case InputDevice::DC_flight_stick:
out << "flight_stick";
break;
case InputDevice::DC_steering_wheel:
out << "steering_wheel";
break;
}
return out;
}
ostream &
operator << (ostream &out, InputDevice::ControlAxis axis) {
switch (axis) {
case InputDevice::C_none:
out << "none";
break;
case InputDevice::C_left_x:
out << "left_x";
break;
case InputDevice::C_left_y:
out << "left_y";
break;
case InputDevice::C_left_trigger:
out << "left_trigger";
break;
case InputDevice::C_right_x:
out << "right_x";
break;
case InputDevice::C_right_y:
out << "right_y";
break;
case InputDevice::C_right_trigger:
out << "right_trigger";
break;
case InputDevice::C_x:
out << "x";
break;
case InputDevice::C_y:
out << "y";
break;
case InputDevice::C_trigger:
out << "trigger";
break;
case InputDevice::C_throttle:
out << "throttle";
break;
}
return out;
}

View File

@ -0,0 +1,279 @@
// Filename: inputDevice.h
// Created by: drose (24May00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef INPUTDEVICE_H
#define INPUTDEVICE_H
#include "pandabase.h"
#include "buttonEvent.h"
#include "buttonEventList.h"
#include "pointerEvent.h"
#include "pointerEventList.h"
#include "mouseData.h"
#include "trackerData.h"
#include "clockObject.h"
#include "pdeque.h"
#include "pvector.h"
#include "lightMutex.h"
#include "lightMutexHolder.h"
typedef MouseData PointerData;
////////////////////////////////////////////////////////////////////
// Class : InputDevice
// Description : This is a structure representing a single input
// device. Input devices may have zero or more
// buttons, pointers, or controls associated with them,
// and optionally a tracker.
//
// These devices are brought under a common interface
// because there is such a large range of devices out
// there that may support any number of these types of
// controls, we couldn't even begin to cover them with
// type-specific subclasses.
//
// Use the various has_() and get_num_() methods to
// determine information about the device capabilities.
// For instance, has_keyboard() will give an indication
// that you can receive keystroke events from this
// device, and get_num_buttons() will tell you that
// the device may send button events.
//
// There is the DeviceType enumeration, however, which
// will (if known) contain identification about the
// general category of devices this fits in, such as
// keyboard, mouse, gamepad, or flight stick.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DEVICE InputDevice : public TypedReferenceCount {
PUBLISHED:
// This enum contains information that can be used to identify the
// type of input device.
enum DeviceClass {
DC_unknown,
// This means that the device doesn't correspond to a physical
// device, but rather to a dynamic source of input events.
DC_virtual,
// A physical, alphabetical keyboard.
DC_keyboard,
DC_mouse,
DC_touch,
// A gamepad with action buttons, a D-pad, and thumbsticks.
DC_gamepad,
DC_flight_stick,
DC_steering_wheel,
};
protected:
InputDevice(const string &name, DeviceClass dev_class, int flags);
public:
InputDevice();
InputDevice(const InputDevice &copy);
void operator = (const InputDevice &copy);
~InputDevice();
PUBLISHED:
enum ControlAxis {
C_none,
// Gamepad
C_left_x,
C_left_y,
C_left_trigger,
C_right_x,
C_right_y,
C_right_trigger,
// Flight stick
C_x,
C_y,
C_trigger,
C_throttle,
};
INLINE string get_name() const;
INLINE bool is_connected() const;
INLINE DeviceClass get_device_class() const;
// The human-readable name of this input device.
MAKE_PROPERTY(name, get_name);
// This is false if we know that the device is not currently connected.
// May report false positives if we can't know this with certainty.
MAKE_PROPERTY(connected, is_connected);
// This contains an identification of the general type of device. If
// this could not be determined, it is set to DC_unknown.
MAKE_PROPERTY(device_class, get_device_class);
INLINE bool has_pointer() const;
INLINE bool has_keyboard() const;
INLINE bool has_tracker() const;
INLINE bool has_battery() const;
INLINE PointerData get_pointer() const;
INLINE TrackerData get_tracker() const;
INLINE short get_battery_level() const;
INLINE short get_max_battery_level() const;
INLINE int get_num_buttons() const;
INLINE void set_button_map(int index, ButtonHandle button);
INLINE ButtonHandle get_button_map(int index) const;
INLINE bool get_button_state(int index) const;
INLINE bool is_button_known(int index) const;
INLINE int get_num_controls() const;
INLINE void set_control_map(int index, ControlAxis axis);
INLINE ControlAxis get_control_map(int index) const;
INLINE double get_control_state(int index) const;
INLINE bool is_control_known(int index) const;
INLINE void enable_pointer_events();
INLINE void disable_pointer_events();
void poll();
bool has_button_event() const;
PT(ButtonEventList) get_button_events();
bool has_pointer_event() const;
PT(PointerEventList) get_pointer_events();
virtual void output(ostream &out) const;
protected:
void set_pointer(bool inwin, double x, double y, double time);
void set_pointer_out_of_window(double time);
void set_button_state(int index, bool down);
void set_control_state(int index, double state);
void set_tracker(const LPoint3 &pos, const LOrientation &orient, double time);
virtual void do_poll();
public:
INLINE void set_connected(bool connected);
// We need these methods to make VC++ happy when we try to
// instantiate a pvector<InputDevice>. They don't do
// anything useful.
INLINE bool operator == (const InputDevice &other) const;
INLINE bool operator != (const InputDevice &other) const;
INLINE bool operator < (const InputDevice &other) const;
void output_buttons(ostream &out) const;
void write_buttons(ostream &out, int indent_level) const;
void write_controls(ostream &out, int indent_level) const;
protected:
enum InputDeviceFlags {
// The device provides absolute screen coordinates.
IDF_has_pointer = 0x01,
// The device has an interface for providing text input.
IDF_has_keyboard = 0x02,
// The device has a motion tracker, such as an HMD.
IDF_has_tracker = 0x04,
// The device can produce force feedback.
IDF_has_vibration = 0x08,
// The device provides information about battery life.
IDF_has_battery = 0x10,
};
protected:
typedef pdeque<ButtonEvent> ButtonEvents;
LightMutex _lock;
string _name;
DeviceClass _device_class;
int _flags;
int _event_sequence;
bool _is_connected;
bool _enable_pointer_events;
PointerData _pointer_data;
PT(ButtonEventList) _button_events;
PT(PointerEventList) _pointer_events;
public:
enum State {
S_unknown,
S_up,
S_down
};
class ButtonState {
public:
INLINE ButtonState();
ButtonHandle _handle;
State _state;
};
typedef pvector<ButtonState> Buttons;
Buttons _buttons;
class AnalogState {
public:
INLINE AnalogState();
ControlAxis _axis;
double _state;
bool _known;
};
typedef pvector<AnalogState> Controls;
Controls _controls;
short _battery_level;
short _max_battery_level;
TrackerData _tracker_data;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedReferenceCount::init_type();
register_type(_type_handle, "InputDevice",
TypedReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const InputDevice &device) {
device.output(out);
return out;
}
ostream &operator << (ostream &out, InputDevice::DeviceClass dc);
ostream &operator << (ostream &out, InputDevice::ControlAxis axis);
#include "inputDevice.I"
#endif

View File

@ -0,0 +1,27 @@
// Filename: inputDeviceManager.I
// Created by: rdb (09Dec15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: InputDeviceManager::get_global_ptr
// Access: Published, Static
// Description: Returns the singleton instance.
////////////////////////////////////////////////////////////////////
INLINE InputDeviceManager *InputDeviceManager::
get_global_ptr() {
if (_global_ptr == (InputDeviceManager *)NULL) {
_global_ptr = new InputDeviceManager;
}
return _global_ptr;
}

View File

@ -0,0 +1,240 @@
// Filename: inputDeviceManager.cxx
// Created by: rdb (09Dec15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "inputDeviceManager.h"
#include "linuxJoystickDevice.h"
#include "throw_event.h"
#ifdef PHAVE_LINUX_INPUT_H
#include <dirent.h>
#include <fcntl.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#endif
InputDeviceManager *InputDeviceManager::_global_ptr = NULL;
////////////////////////////////////////////////////////////////////
// Function: InputDeviceManager::Constructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
InputDeviceManager::
InputDeviceManager() : _inotify_fd(-1) {
#ifdef PHAVE_LINUX_INPUT_H
// Scan /dev/input for a list of input devices.
DIR *dir = opendir("/dev/input");
if (dir) {
dirent *entry = readdir(dir);
while (entry != NULL) {
if (entry->d_type == DT_CHR) {
string name(entry->d_name);
if (!consider_add_linux_device(name)) {
// We can't access it. That's pretty normal for most devices.
if (device_cat.is_debug()) {
device_cat.debug()
<< "Ignoring input device /dev/input/" << name << ": "
<< strerror(errno) << "\n";
}
errno = 0;
}
}
entry = readdir(dir);
}
closedir(dir);
} else {
device_cat.error()
<< "Error opening directory /dev/input: " << strerror(errno) << "\n";
return;
}
// Use inotify to watch /dev/input for hotplugging of devices.
_inotify_fd = inotify_init1(O_NONBLOCK);
if (_inotify_fd < 0) {
device_cat.error()
<< "Error initializing inotify: " << strerror(errno) << "\n";
} else if (inotify_add_watch(_inotify_fd, "/dev/input", IN_CREATE | IN_ATTRIB | IN_DELETE) < 0) {
device_cat.error()
<< "Error adding inotify watch on /dev/input: " << strerror(errno) << "\n";
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: InputDeviceManager::Destructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
InputDeviceManager::
~InputDeviceManager() {
#ifdef PHAVE_LINUX_INPUT_H
if (_inotify_fd >= 0) {
close(_inotify_fd);
_inotify_fd = -1;
}
#endif
}
#ifdef PHAVE_LINUX_INPUT_H
////////////////////////////////////////////////////////////////////
// Function: InputDeviceManager::consider_add_linux_device
// Access: Private
// Description: Checks whether the given device is accessible, and
// if so, adds it. Returns false on error.
////////////////////////////////////////////////////////////////////
bool InputDeviceManager::
consider_add_linux_device(const string &name) {
// Get the full path name first.
string path = "/dev/input/";
path += name;
if (access(path.c_str(), R_OK) < 0) {
return false;
}
if (_devices_by_path.count(name)) {
// We already have this device.
return true;
}
// Check if it's a joystick or game controller device.
if (name.size() > 2 && name[0] == 'j' && name[1] == 's' && isdigit(name[2])) {
PT(InputDevice) device = new LinuxJoystickDevice(path);
if (device_cat.is_info()) {
device_cat.info()
<< "Discovered input device " << *device << "\n";
}
_devices_by_path[name] = device;
_all_devices.push_back(MOVE(device));
return true;
}
return true;
}
#endif
////////////////////////////////////////////////////////////////////
// Function: InputDeviceManager::add_device
// Access: Public
// Description: Called when a new device has been discovered.
////////////////////////////////////////////////////////////////////
void InputDeviceManager::
add_device(InputDevice *device) {
{
LightMutexHolder holder(_lock);
_all_devices.push_back(device);
}
throw_event("device-added", device);
}
////////////////////////////////////////////////////////////////////
// Function: InputDeviceManager::remove_device
// Access: Public
// Description: Called when a device has been removed.
////////////////////////////////////////////////////////////////////
void InputDeviceManager::
remove_device(InputDevice *device) {
{
LightMutexHolder holder(_lock);
InputDevices::iterator it;
it = std::find(_all_devices.begin(), _all_devices.end(), device);
nassertv_always(it != _all_devices.end());
_all_devices.erase(it);
}
throw_event("device-removed", device);
}
////////////////////////////////////////////////////////////////////
// Function: InputDeviceManager::poll
// Access: Public
// Description: Polls the system to see if there are any new devices.
////////////////////////////////////////////////////////////////////
void InputDeviceManager::
poll() {
#ifdef PHAVE_LINUX_INPUT_H
// We use inotify to tell us whether a device was added, removed,
// or has changed permissions to allow us to access it.
unsigned int avail;
ioctl(_inotify_fd, FIONREAD, &avail);
if (avail == 0) {
return;
}
char buffer[avail];
int n_read = read(_inotify_fd, buffer, avail);
if (n_read < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// No data available for now.
} else {
device_cat.error() << "read: " << strerror(errno) << "\n";
}
return;
}
LightMutexHolder holder(_lock);
// Iterate over the events in the buffer.
char *ptr = buffer;
char *end = buffer + avail;
while (ptr < end) {
inotify_event *event = (inotify_event *)ptr;
string name(event->name);
if (event->mask & IN_DELETE) {
// The device was deleted. If we have it, remove it.
DevicesByPath::iterator it = _devices_by_path.find(name);
if (it != _devices_by_path.end()) {
PT(InputDevice) device = it->second;
device->set_connected(false);
InputDevices::iterator it2;
_devices_by_path.erase(it);
it2 = std::find(_all_devices.begin(), _all_devices.end(), device);
_all_devices.erase(it2);
if (device_cat.is_info()) {
device_cat.info()
<< "Removed input device " << *device << "\n";
}
throw_event("device-removed", device.p());
}
} else if (event->mask & (IN_CREATE | IN_ATTRIB)) {
// The device was created, or it was chmodded to be accessible.
DevicesByPath::iterator it = _devices_by_path.find(name);
if (it == _devices_by_path.end()) {
// We don't know about this device yet.
if (!consider_add_linux_device(name) && (event->mask & IN_CREATE) != 0) {
if (device_cat.is_debug()) {
device_cat.debug()
<< "Ignoring input device /dev/input/" << name << ": "
<< strerror(errno) << "\n";
}
}
errno = 0;
}
}
ptr += sizeof(inotify_event) + event->len;
}
#endif
}

View File

@ -0,0 +1,64 @@
// Filename: inputDeviceManager.h
// Created by: rdb (09Dec15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef INPUTDEVICEMANAGER_H
#define INPUTDEVICEMANAGER_H
#include "pandabase.h"
#include "lightMutex.h"
#include "inputDevice.h"
////////////////////////////////////////////////////////////////////
// Class : InputDeviceManager
// Description : This class keeps track of all the devices on a
// system, and sends out events when a device has been
// hot-plugged.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DEVICE InputDeviceManager {
private:
InputDeviceManager();
~InputDeviceManager();
#ifdef PHAVE_LINUX_INPUT_H
bool consider_add_linux_device(const string &name);
#endif
public:
void add_device(InputDevice *device);
void remove_device(InputDevice *device);
PUBLISHED:
void poll();
INLINE static InputDeviceManager *get_global_ptr();
private:
LightMutex _lock;
#ifdef PHAVE_LINUX_INPUT_H
int _inotify_fd;
typedef pmap<string, InputDevice*> DevicesByPath;
DevicesByPath _devices_by_path;
#endif
typedef pvector<PT(InputDevice)> InputDevices;
InputDevices _all_devices;
static InputDeviceManager *_global_ptr;
};
#include "inputDeviceManager.I"
#endif

View File

@ -0,0 +1,14 @@
// Filename: linuxJoystickDevice.I
// Created by: rdb (21Aug15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,313 @@
// Filename: linuxJoystickDevice.cxx
// Created by: rdb (21Aug15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "linuxJoystickDevice.h"
#ifdef PHAVE_LINUX_INPUT_H
#include "gamepadButton.h"
#include <fcntl.h>
#include <linux/joystick.h>
TypeHandle LinuxJoystickDevice::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: LinuxJoystickDevice::Constructor
// Access: Private
// Description: Creates a new device using the Linux joystick
// device using the given device filename.
////////////////////////////////////////////////////////////////////
LinuxJoystickDevice::
LinuxJoystickDevice(const string &device) :
_fd(-1),
_device(device)
{
LightMutexHolder holder(_lock);
if (!open_device()) {
device_cat.error()
<< "Could not open joystick device " << _device
<< ": " << strerror(errno) << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: LinuxJoystickDevice::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
LinuxJoystickDevice::
~LinuxJoystickDevice() {
if (_fd != -1) {
close(_fd);
_fd = -1;
}
}
////////////////////////////////////////////////////////////////////
// Function: LinuxJoystickDevice::do_poll
// Access: Private, Virtual
// Description: Polls the input device for new activity, to ensure
// it contains the latest events. This will only have
// any effect for some types of input devices; others
// may be updated automatically, and this method will
// be a no-op.
////////////////////////////////////////////////////////////////////
void LinuxJoystickDevice::
do_poll() {
if (_fd != -1) {
while (process_events()) {}
} else {
open_device();
}
}
////////////////////////////////////////////////////////////////////
// Function: LinuxJoystickDevice::open_device
// Access: Private
// Description: Opens or reopens the joystick device, and reads out
// the button and axis mappings.
// Assumes the lock has been held.
////////////////////////////////////////////////////////////////////
bool LinuxJoystickDevice::
open_device() {
nassertr(_lock.debug_is_locked(), false);
_fd = open(_device.c_str(), O_RDONLY | O_NONBLOCK);
if (_fd == -1) {
_is_connected = false;
return false;
}
// Read the name from the device.
char name[128];
name[0] = 0;
ioctl(_fd, JSIOCGNAME(sizeof(name)), name);
_name = name;
// Get the number of axes.
PN_uint8 num_axes = 0, num_buttons = 0;
ioctl(_fd, JSIOCGAXES, &num_axes);
ioctl(_fd, JSIOCGBUTTONS, &num_buttons);
_buttons.resize(num_buttons);
_controls.resize(num_axes);
if (num_buttons > 0) {
PN_uint16 btnmap[512];
ioctl(_fd, JSIOCGBTNMAP, btnmap);
for (char i = 0; i < num_buttons; ++i) {
ButtonHandle handle = ButtonHandle::none();
switch (btnmap[i]) {
case BTN_A:
handle = GamepadButton::action_a();
_device_class = DC_gamepad;
break;
case BTN_B:
handle = GamepadButton::action_b();
break;
case BTN_C:
handle = GamepadButton::action_c();
break;
case BTN_X:
handle = GamepadButton::action_x();
break;
case BTN_Y:
handle = GamepadButton::action_y();
break;
case BTN_Z:
handle = GamepadButton::action_z();
break;
case BTN_TL:
handle = GamepadButton::lshoulder();
break;
case BTN_TR:
handle = GamepadButton::rshoulder();
break;
case BTN_TL2:
handle = GamepadButton::ltrigger();
break;
case BTN_TR2:
handle = GamepadButton::rtrigger();
break;
case BTN_SELECT:
handle = GamepadButton::back();
break;
case BTN_START:
handle = GamepadButton::start();
break;
case BTN_MODE:
handle = GamepadButton::guide();
break;
case BTN_THUMBL:
handle = GamepadButton::lstick();
break;
case BTN_THUMBR:
handle = GamepadButton::rstick();
break;
case BTN_TRIGGER_HAPPY1:
handle = GamepadButton::dpad_left();
break;
case BTN_TRIGGER_HAPPY2:
handle = GamepadButton::dpad_right();
break;
case BTN_TRIGGER_HAPPY3:
handle = GamepadButton::dpad_up();
break;
case BTN_TRIGGER_HAPPY4:
handle = GamepadButton::dpad_down();
break;
default:
handle = ButtonHandle::none();
break;
}
_buttons[i]._handle = handle;
}
}
if (num_axes > 0) {
PN_uint8 axmap[512];
ioctl(_fd, JSIOCGAXMAP, axmap);
for (char i = 0; i < num_axes; ++i) {
ControlAxis axis = C_none;
switch (axmap[i]) {
case ABS_X:
if (_device_class == DC_gamepad) {
axis = C_left_x;
} else {
axis = C_x;
}
break;
case ABS_Y:
if (_device_class == DC_gamepad) {
axis = C_left_y;
} else {
axis = C_y;
}
break;
case ABS_Z:
if (_device_class == DC_gamepad) {
axis = C_left_trigger;
} else {
axis = C_trigger;
}
break;
case ABS_RX:
axis = C_right_x;
break;
case ABS_RY:
axis = C_right_y;
break;
case ABS_RZ:
axis = C_right_trigger;
break;
default:
axis = C_none;
break;
}
_controls[i]._axis = axis;
}
}
// Read the init events.
_is_connected = true;
while (process_events()) {};
return true;
}
////////////////////////////////////////////////////////////////////
// Function: LinuxJoystickDevice::process_events
// Access: Private
// Description: Reads a number of events from the joystick.
////////////////////////////////////////////////////////////////////
bool LinuxJoystickDevice::
process_events() {
// Read 8 events at a time.
struct js_event events[8];
int n_read = read(_fd, events, sizeof(events));
if (n_read < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// No data available for now.
} else if (errno == ENODEV) {
// The device ceased to exist, so we better close it.
close(_fd);
_fd = -1;
_is_connected = false;
errno = 0;
} else {
device_cat.error() << "read: " << strerror(errno) << "\n";
}
return false;
}
if (n_read == 0) {
return false;
}
n_read /= sizeof(struct js_event);
for (int i = 0; i < n_read; ++i) {
int index = events[i].number;
if (events[i].type & JS_EVENT_BUTTON) {
set_button_state(index, (events[i].value != 0));
} else if (events[i].type & JS_EVENT_AXIS) {
ControlAxis axis = _controls[index]._axis;
if (axis == C_left_trigger || axis == C_right_trigger || axis == C_trigger) {
// We'd like to use 0.0 to indicate the resting position.
set_control_state(index, (events[i].value + 32767) / 65534.0);
} else {
set_control_state(index, events[i].value / 32767.0);
}
}
}
return true;
}
#endif

View File

@ -0,0 +1,60 @@
// Filename: linuxJoystickDevice.h
// Created by: rdb (21Aug15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef LINUXJOYSTICKDEVICE_H
#define LINUXJOYSTICKDEVICE_H
#include "inputDevice.h"
#ifdef PHAVE_LINUX_INPUT_H
////////////////////////////////////////////////////////////////////
// Class : LinuxJoystickDevice
// Description : This is a type of device that uses the Linux
// /dev/input/js# API to read data from a game controller.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DEVICE LinuxJoystickDevice : public InputDevice {
PUBLISHED:
LinuxJoystickDevice(const string &device);
virtual ~LinuxJoystickDevice();
private:
virtual void do_poll();
bool open_device();
bool process_events();
private:
int _fd;
string _device;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
InputDevice::init_type();
register_type(_type_handle, "LinuxJoystickDevice",
InputDevice::get_class_type());
}
private:
static TypeHandle _type_handle;
};
#include "linuxJoystickDevice.I"
#endif // PHAVE_LINUX_INPUT_H
#endif // LINUXJOYSTICKDEVICE_H

View File

@ -5,4 +5,7 @@
#include "clientDevice.cxx"
#include "clientDialDevice.cxx"
#include "clientTrackerDevice.cxx"
#include "evdevInputDevice.cxx"
#include "inputDevice.cxx"
#include "inputDeviceManager.cxx"
#include "linuxJoystickDevice.cxx"

View File

@ -3,7 +3,6 @@
#include "analogNode.cxx"
#include "buttonNode.cxx"
#include "dialNode.cxx"
#include "mouseAndKeyboard.cxx"
#include "trackerData.cxx"
#include "trackerNode.cxx"
#include "virtualMouse.cxx"

View File

@ -20,10 +20,9 @@
////////////////////////////////////////////////////////////////////
INLINE bool TrackerNode::
is_valid() const {
return (_tracker != (ClientTrackerDevice *)NULL) && _tracker->is_connected();
return (!_tracker.is_null()/* && _tracker->is_connected()*/);
}
////////////////////////////////////////////////////////////////////
// Function: TrackerNode::get_pos
// Access: Public

View File

@ -51,7 +51,7 @@ TrackerNode(ClientBase *client, const string &device_name) :
return;
}
_tracker = DCAST(ClientTrackerDevice, device);
_tracker = device;
}
////////////////////////////////////////////////////////////////////
@ -60,18 +60,19 @@ TrackerNode(ClientBase *client, const string &device_name) :
// Description:
////////////////////////////////////////////////////////////////////
TrackerNode::
TrackerNode(ClientTrackerDevice *device) :
DataNode(device->get_device_name()),
TrackerNode(InputDevice *device) :
DataNode(device->get_name()),
_tracker(device)
{
_transform_output = define_output("transform", TransformState::get_class_type());
_transform = TransformState::make_identity();
nassertv(device != (ClientTrackerDevice *)NULL);
ClientBase *client = device->get_client();
nassertv(client != (ClientBase *)NULL);
set_tracker_coordinate_system(client->get_coordinate_system());
nassertv(device != (InputDevice *)NULL);
nassertv(device->has_tracker());
//TODO: get coordinate system from tracker object?
set_tracker_coordinate_system(CS_default);
set_graph_coordinate_system(CS_default);
}
@ -105,9 +106,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
DataNodeTransmit &output) {
if (is_valid()) {
_tracker->poll();
_tracker->acquire();
_data = _tracker->get_data();
_tracker->unlock();
_data = _tracker->get_tracker();
_data.get_orient().extract_to_matrix(_mat);
if (_tracker_cs != _graph_cs) {

View File

@ -19,7 +19,7 @@
#include "clientBase.h"
#include "trackerData.h"
#include "clientTrackerDevice.h"
#include "inputDevice.h"
#include "dataNode.h"
#include "luse.h"
#include "linmath_events.h"
@ -27,16 +27,16 @@
////////////////////////////////////////////////////////////////////
// Class : TrackerNode
// Description : This is the primary interface to a Tracker object
// associated with a ClientBase. It reads the position
// and orientation information from the tracker and
// makes it available as a transformation on the data
// graph.
// Description : This class reads the position and orientation
// information from a tracker device and makes it
// available as a transformation on the data graph.
// It is also the primary interface to a Tracker object
// associated with a ClientBase.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DEVICE TrackerNode : public DataNode {
PUBLISHED:
TrackerNode(ClientBase *client, const string &device_name);
TrackerNode(ClientTrackerDevice *device);
TrackerNode(InputDevice *device);
virtual ~TrackerNode();
INLINE bool is_valid() const;
@ -66,7 +66,7 @@ private:
CPT(TransformState) _transform;
private:
PT(ClientTrackerDevice) _tracker;
PT(InputDevice) _tracker;
TrackerData _data;
LMatrix4 _mat;
CoordinateSystem _tracker_cs, _graph_cs;

View File

@ -54,22 +54,6 @@ CallbackGraphicsWindow::
~CallbackGraphicsWindow() {
}
////////////////////////////////////////////////////////////////////
// Function: CallbackGraphicsWindow::get_input_device
// Access: Published
// Description: Returns a writable reference to the nth input device
// (mouse). This is intended to be used for the window
// implementation to record mouse and keyboard input
// information for the Panda system.
////////////////////////////////////////////////////////////////////
GraphicsWindowInputDevice &CallbackGraphicsWindow::
get_input_device(int device) {
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), _input_devices[0]);
return _input_devices[device];
}
////////////////////////////////////////////////////////////////////
// Function: CallbackGraphicsWindow::create_input_device
// Access: Published
@ -79,9 +63,7 @@ get_input_device(int device) {
////////////////////////////////////////////////////////////////////
int CallbackGraphicsWindow::
create_input_device(const string &name) {
GraphicsWindowInputDevice device =
GraphicsWindowInputDevice::pointer_and_keyboard(this, name);
return add_input_device(device);
return add_input_device(GraphicsWindowInputDevice::pointer_and_keyboard(this, name));
}
////////////////////////////////////////////////////////////////////

View File

@ -182,7 +182,6 @@ PUBLISHED:
INLINE void clear_render_callback();
INLINE CallbackObject *get_render_callback() const;
GraphicsWindowInputDevice &get_input_device(int device);
int create_input_device(const string &name);
public:

View File

@ -22,9 +22,11 @@
#include "graphicsPipe.h"
#include "graphicsOutput.h"
#include "graphicsBuffer.h"
#include "graphicsWindow.h"
#include "graphicsDevice.h"
#include "graphicsWindow.h"
#include "graphicsWindowInputDevice.h"
#include "graphicsWindowProcCallbackData.h"
#include "mouseAndKeyboard.h"
#include "nativeWindowHandle.h"
#include "parasiteBuffer.h"
#include "pandaSystem.h"
@ -501,7 +503,9 @@ init_libdisplay() {
GraphicsPipe::init_type();
GraphicsStateGuardian::init_type();
GraphicsWindow::init_type();
GraphicsWindowInputDevice::init_type();
GraphicsWindowProcCallbackData::init_type();
MouseAndKeyboard::init_type();
NativeWindowHandle::init_type();
ParasiteBuffer::init_type();
StandardMunger::init_type();

View File

@ -288,6 +288,20 @@ get_num_input_devices() const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::get_input_device
// Access: Published
// Description: Returns the nth input device associated with the
// window. Typically, a window will have exactly one
// input device: the keyboard/mouse pair.
////////////////////////////////////////////////////////////////////
InputDevice *GraphicsWindow::
get_input_device(int device) const {
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), NULL);
return _input_devices[device];
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::get_input_device_name
// Access: Published
@ -299,7 +313,7 @@ get_input_device_name(int device) const {
{
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), "");
result = _input_devices[device].get_name();
result = _input_devices[device]->get_name();
}
return result;
}
@ -317,7 +331,7 @@ has_pointer(int device) const {
{
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), false);
result = _input_devices[device].has_pointer();
result = _input_devices[device]->has_pointer();
}
return result;
}
@ -334,7 +348,7 @@ has_keyboard(int device) const {
{
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), false);
result = _input_devices[device].has_keyboard();
result = _input_devices[device]->has_keyboard();
}
return result;
}
@ -359,7 +373,7 @@ void GraphicsWindow::
enable_pointer_events(int device) {
LightMutexHolder holder(_input_lock);
nassertv(device >= 0 && device < (int)_input_devices.size());
_input_devices[device].enable_pointer_events();
_input_devices[device]->enable_pointer_events();
}
////////////////////////////////////////////////////////////////////
@ -371,7 +385,7 @@ void GraphicsWindow::
disable_pointer_events(int device) {
LightMutexHolder holder(_input_lock);
nassertv(device >= 0 && device < (int)_input_devices.size());
_input_devices[device].disable_pointer_events();
_input_devices[device]->disable_pointer_events();
}
////////////////////////////////////////////////////////////////////
@ -379,11 +393,11 @@ disable_pointer_events(int device) {
// Access: Published
// Description: See GraphicsWindowInputDevice::enable_pointer_mode
////////////////////////////////////////////////////////////////////
void GraphicsWindow::
/*void GraphicsWindow::
enable_pointer_mode(int device, double speed) {
LightMutexHolder holder(_input_lock);
nassertv(device >= 0 && device < (int)_input_devices.size());
_input_devices[device].enable_pointer_mode(speed);
_input_devices[device]->enable_pointer_mode(speed);
}
////////////////////////////////////////////////////////////////////
@ -395,8 +409,8 @@ void GraphicsWindow::
disable_pointer_mode(int device) {
LightMutexHolder holder(_input_lock);
nassertv(device >= 0 && device < (int)_input_devices.size());
_input_devices[device].disable_pointer_mode();
}
_input_devices[device]->disable_pointer_mode();
}*/
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::get_pointer
@ -412,7 +426,7 @@ get_pointer(int device) const {
{
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), MouseData());
result = _input_devices[device].get_pointer();
result = _input_devices[device]->get_pointer();
}
return result;
}
@ -443,81 +457,6 @@ close_ime() {
return;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::has_button_event
// Access: Public
// Description: Returns true if the indicated device has a pending
// button event (a mouse button or keyboard button
// down/up), false otherwise. If this returns true, the
// particular event may be extracted via
// get_button_event().
////////////////////////////////////////////////////////////////////
bool GraphicsWindow::
has_button_event(int device) const {
bool result;
{
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), false);
result = _input_devices[device].has_button_event();
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::get_button_event
// Access: Public
// Description: Assuming a previous call to has_button_event()
// returned true, this returns the pending button event.
////////////////////////////////////////////////////////////////////
ButtonEvent GraphicsWindow::
get_button_event(int device) {
ButtonEvent result;
{
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), ButtonEvent());
nassertr(_input_devices[device].has_button_event(), ButtonEvent());
result = _input_devices[device].get_button_event();
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::has_pointer_event
// Access: Public
// Description: Returns true if the indicated device has a pending
// pointer event (a mouse movement). If this returns
// true, the particular event may be extracted via
// get_pointer_events().
////////////////////////////////////////////////////////////////////
bool GraphicsWindow::
has_pointer_event(int device) const {
bool result;
{
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), false);
result = _input_devices[device].has_pointer_event();
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::get_pointer_events
// Access: Public
// Description: Assuming a previous call to has_pointer_event()
// returned true, this returns the pending pointer event list.
////////////////////////////////////////////////////////////////////
PT(PointerEventList) GraphicsWindow::
get_pointer_events(int device) {
PT(PointerEventList) result;
{
LightMutexHolder holder(_input_lock);
nassertr(device >= 0 && device < (int)_input_devices.size(), NULL);
nassertr(_input_devices[device].has_pointer_event(), NULL);
result = _input_devices[device].get_pointer_events();
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindow::verify_window_sizes
// Access: Public, Virtual
@ -860,11 +799,15 @@ system_changed_size(int x_size, int y_size) {
// Returns the index of the new device.
////////////////////////////////////////////////////////////////////
int GraphicsWindow::
add_input_device(const GraphicsWindowInputDevice &device) {
add_input_device(InputDevice *device) {
LightMutexHolder holder(_input_lock);
int index = (int)_input_devices.size();
_input_devices.push_back(device);
_input_devices.back().set_device_index(index);
if (device->is_of_type(GraphicsWindowInputDevice::get_class_type())) {
((GraphicsWindowInputDevice *)device)->set_device_index(index);
}
return index;
}

View File

@ -82,10 +82,12 @@ PUBLISHED:
INLINE WindowHandle *get_window_handle() const;
MAKE_PROPERTY(window_handle, get_window_handle);
// Mouse and keyboard routines
int get_num_input_devices() const;
InputDevice *get_input_device(int i) const;
string get_input_device_name(int device) const;
MAKE_SEQ(get_input_devices, get_num_input_devices, get_input_device);
MAKE_SEQ(get_input_device_names, get_num_input_devices, get_input_device_name);
bool has_pointer(int device) const;
bool has_keyboard(int device) const;
@ -93,20 +95,14 @@ PUBLISHED:
void enable_pointer_events(int device);
void disable_pointer_events(int device);
void enable_pointer_mode(int device, double speed);
void disable_pointer_mode(int device);
/*void enable_pointer_mode(int device, double speed);
void disable_pointer_mode(int device);*/
MouseData get_pointer(int device) const;
virtual bool move_pointer(int device, int x, int y);
virtual void close_ime();
public:
// No need to publish these.
bool has_button_event(int device) const;
ButtonEvent get_button_event(int device);
bool has_pointer_event(int device) const;
PT(PointerEventList) get_pointer_events(int device);
virtual void add_window_proc( const GraphicsWindowProc* wnd_proc_object ){};
virtual void remove_window_proc( const GraphicsWindowProc* wnd_proc_object ){};
virtual void clear_window_procs(){};
@ -146,8 +142,8 @@ protected:
void system_changed_size(int x_size, int y_size);
protected:
int add_input_device(const GraphicsWindowInputDevice &device);
typedef vector_GraphicsWindowInputDevice InputDevices;
int add_input_device(InputDevice *device);
typedef pvector<PT(InputDevice)> InputDevices;
InputDevices _input_devices;
LightMutex _input_lock;

View File

@ -12,73 +12,14 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::Default Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE GraphicsWindowInputDevice::
GraphicsWindowInputDevice() {
LightMutexHolder holder(_lock);
_flags = 0;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::get_name
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE string GraphicsWindowInputDevice::
get_name() const {
LightMutexHolder holder(_lock);
return _name;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::has_pointer
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsWindowInputDevice::
has_pointer() const {
LightMutexHolder holder(_lock);
return ((_flags & IDF_has_pointer) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::has_keyboard
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsWindowInputDevice::
has_keyboard() const {
LightMutexHolder holder(_lock);
return ((_flags & IDF_has_keyboard) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::get_pointer
// Access: Public
// Description: Returns the MouseData associated with the input
// device's pointer.
////////////////////////////////////////////////////////////////////
INLINE MouseData GraphicsWindowInputDevice::
get_pointer() const {
LightMutexHolder holder(_lock);
return _mouse_data;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::get_raw_pointer
// Access: Public
// Description: Returns the MouseData associated with the input
// device's pointer, in raw form (ie, prior to any
// pointer_mode interpretation).
////////////////////////////////////////////////////////////////////
INLINE MouseData GraphicsWindowInputDevice::
get_raw_pointer() const {
LightMutexHolder holder(_lock);
return _true_mouse_data;
GraphicsWindowInputDevice() : _host(NULL) {
}
////////////////////////////////////////////////////////////////////
@ -90,140 +31,9 @@ get_raw_pointer() const {
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
set_device_index(int index) {
LightMutexHolder holder(_lock);
_device_index = index;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::enable_pointer_events
// Access: Public
// Description: Enables the generation of mouse-movement events.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
enable_pointer_events() {
LightMutexHolder holder(_lock);
_enable_pointer_events = true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::disable_pointer_events
// Access: Public
// Description: Disables the generation of mouse-movement events.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
disable_pointer_events() {
LightMutexHolder holder(_lock);
_enable_pointer_events = false;
_pointer_events.clear();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_down
// Access: Published
// Description: Records that the indicated button has been depressed.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
button_down(ButtonHandle button) {
button_down(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_resume_down
// Access: Published
// Description: Records that the indicated button was depressed
// earlier, and we only just detected the event after
// the fact. This is mainly useful for tracking the
// state of modifier keys.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
button_resume_down(ButtonHandle button) {
button_resume_down(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_up
// Access: Published
// Description: Records that the indicated button has been released.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
button_up(ButtonHandle button) {
button_up(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::keystroke
// Access: Published
// Description: Records that the indicated keystroke has been
// generated.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
keystroke(int keycode) {
keystroke(keycode, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::focus_lost
// Access: Published
// Description: This should be called when the window focus is lost,
// so that we may miss upcoming button events
// (especially "up" events) for the next period of time.
// It generates keyboard and mouse "up" events for those
// buttons that we previously sent unpaired "down"
// events, so that the Panda application will believe
// all buttons are now released.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
focus_lost() {
focus_lost(ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::raw_button_down
// Access: Published
// Description: Records that the indicated button has been depressed.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
raw_button_down(ButtonHandle button) {
raw_button_down(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::raw_button_up
// Access: Published
// Description: Records that the indicated button has been released.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
raw_button_up(ButtonHandle button) {
raw_button_up(button, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer_in_window
// Access: Published
// Description: To be called by a particular kind of GraphicsWindow
// to indicate that the pointer is within the window, at
// the given pixel coordinates.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
set_pointer_in_window(double x, double y) {
// mutex is handled in set pointer .. convience function
set_pointer(true, x, y, ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer_out_of_window
// Access: Published
// Description: To be called by a particular kind of GraphicsWindow
// to indicate that the pointer is no longer within the
// window.
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
set_pointer_out_of_window() {
// mutex is handled in set pointer .. convience function
set_pointer(false, _mouse_data._xpos, _mouse_data._ypos,
ClockObject::get_global_clock()->get_frame_time());
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer_in_window
// Access: Published
@ -233,8 +43,8 @@ set_pointer_out_of_window() {
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
set_pointer_in_window(double x, double y, double time) {
// mutex is handled in set pointer .. convience function
set_pointer(true, x, y, time);
LightMutexHolder holder(_lock);
InputDevice::set_pointer(true, x, y, time);
}
////////////////////////////////////////////////////////////////////
@ -246,36 +56,6 @@ set_pointer_in_window(double x, double y, double time) {
////////////////////////////////////////////////////////////////////
INLINE void GraphicsWindowInputDevice::
set_pointer_out_of_window(double time) {
// mutex is handled in set pointer .. convience function
set_pointer(false, _mouse_data._xpos, _mouse_data._ypos, time);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::operator ==
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsWindowInputDevice::
operator == (const GraphicsWindowInputDevice &) const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::operator !=
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsWindowInputDevice::
operator != (const GraphicsWindowInputDevice &) const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::operator <
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsWindowInputDevice::
operator < (const GraphicsWindowInputDevice &) const {
return false;
LightMutexHolder holder(_lock);
InputDevice::set_pointer_out_of_window(time);
}

View File

@ -18,17 +18,7 @@
#include "mouseButton.h"
#include "keyboardButton.h"
#define EXPCL EXPCL_PANDA_DISPLAY
#define EXPTP EXPTP_PANDA_DISPLAY
#define TYPE GraphicsWindowInputDevice
#define NAME vector_GraphicsWindowInputDevice
#include "vector_src.cxx"
// Tell GCC that we'll take care of the instantiation explicitly here.
#ifdef __GNUC__
#pragma implementation
#endif
TypeHandle GraphicsWindowInputDevice::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::Constructor
@ -43,14 +33,8 @@
////////////////////////////////////////////////////////////////////
GraphicsWindowInputDevice::
GraphicsWindowInputDevice(GraphicsWindow *host, const string &name, int flags) :
_host(host),
_name(name),
_flags(flags),
_device_index(0),
_event_sequence(0),
_pointer_mode_enable(false),
_pointer_speed(1.0),
_enable_pointer_events(false)
InputDevice(name, DC_virtual, flags),
_host(host)
{
}
@ -60,9 +44,9 @@ GraphicsWindowInputDevice(GraphicsWindow *host, const string &name, int flags) :
// Description: This named constructor returns an input device that
// only has a pointing device, no keyboard.
////////////////////////////////////////////////////////////////////
GraphicsWindowInputDevice GraphicsWindowInputDevice::
PT(GraphicsWindowInputDevice) GraphicsWindowInputDevice::
pointer_only(GraphicsWindow *host, const string &name) {
return GraphicsWindowInputDevice(host, name, IDF_has_pointer);
return new GraphicsWindowInputDevice(host, name, IDF_has_pointer);
}
////////////////////////////////////////////////////////////////////
@ -71,9 +55,9 @@ pointer_only(GraphicsWindow *host, const string &name) {
// Description: This named constructor returns an input device that
// only has a keyboard, no pointing device.
////////////////////////////////////////////////////////////////////
GraphicsWindowInputDevice GraphicsWindowInputDevice::
PT(GraphicsWindowInputDevice) GraphicsWindowInputDevice::
keyboard_only(GraphicsWindow *host, const string &name) {
return GraphicsWindowInputDevice(host, name, IDF_has_keyboard);
return new GraphicsWindowInputDevice(host, name, IDF_has_keyboard);
}
////////////////////////////////////////////////////////////////////
@ -82,9 +66,9 @@ keyboard_only(GraphicsWindow *host, const string &name) {
// Description: This named constructor returns an input device that
// has both a keyboard and pointer.
////////////////////////////////////////////////////////////////////
GraphicsWindowInputDevice GraphicsWindowInputDevice::
PT(GraphicsWindowInputDevice) GraphicsWindowInputDevice::
pointer_and_keyboard(GraphicsWindow *host, const string &name) {
return
return new
GraphicsWindowInputDevice(host, name, IDF_has_pointer | IDF_has_keyboard);
}
@ -94,9 +78,8 @@ pointer_and_keyboard(GraphicsWindow *host, const string &name) {
// Description:
////////////////////////////////////////////////////////////////////
GraphicsWindowInputDevice::
GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
{
*this = copy;
GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy) {
*this = copy;
}
////////////////////////////////////////////////////////////////////
@ -105,22 +88,9 @@ GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy)
// Description:
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
operator = (const GraphicsWindowInputDevice &copy)
{
LightMutexHolder holder(_lock);
LightMutexHolder holder1(copy._lock);
operator = (const GraphicsWindowInputDevice &copy) {
_host = copy._host;
_name = copy._name;
_flags = copy._flags;
_device_index = copy._device_index;
_event_sequence = copy._event_sequence;
_pointer_mode_enable = copy._pointer_mode_enable;
_pointer_speed = copy._pointer_speed;
_enable_pointer_events = copy._enable_pointer_events;
_mouse_data = copy._mouse_data;
_true_mouse_data = copy._true_mouse_data;
_button_events = copy._button_events;
_pointer_events = copy._pointer_events;
InputDevice::operator = (copy);
}
////////////////////////////////////////////////////////////////////
@ -132,151 +102,6 @@ GraphicsWindowInputDevice::
~GraphicsWindowInputDevice() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::has_button_event
// Access: Public
// Description: Returns true if this device has a pending button
// event (a mouse button or keyboard button down/up),
// false otherwise. If this returns true, the
// particular event may be extracted via
// get_button_event().
////////////////////////////////////////////////////////////////////
bool GraphicsWindowInputDevice::
has_button_event() const {
LightMutexHolder holder(_lock);
return !_button_events.empty();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::get_button_event
// Access: Public
// Description: Assuming a previous call to has_button_event()
// returned true, this returns the pending button event.
////////////////////////////////////////////////////////////////////
ButtonEvent GraphicsWindowInputDevice::
get_button_event() {
LightMutexHolder holder(_lock);
ButtonEvent be = _button_events.front();
_button_events.pop_front();
return be;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::has_pointer_event
// Access: Public
// Description: Returns true if this device has a pending pointer
// event (a mouse movement), or false otherwise. If
// this returns true, the particular event may be
// extracted via get_pointer_event().
////////////////////////////////////////////////////////////////////
bool GraphicsWindowInputDevice::
has_pointer_event() const {
LightMutexHolder holder(_lock);
return (_pointer_events != 0);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::get_pointer_events
// Access: Public
// Description: Returns a PointerEventList containing all the recent
// pointer events.
////////////////////////////////////////////////////////////////////
PT(PointerEventList) GraphicsWindowInputDevice::
get_pointer_events() {
LightMutexHolder holder(_lock);
PT(PointerEventList) result = _pointer_events;
_pointer_events = 0;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::enable_pointer_mode
// Access: Public
// Description: There are two modes: raw mode, and pointer mode.
// In pointer mode, the mouse stops when it reaches the
// edges of the window. In raw mode, the mouse ignores
// the screen boundaries and can continue indefinitely,
// even into negative coordinates. In raw mode, each
// "blip" from the mouse hardware corresponds to a
// change of 1 unit in the mouse's (x,y) coordinate.
// In pointer mode, a variety of speed adjustment factors
// and concepts like "mouse acceleration" may be applied.
//
// Mouse zero represents the system mouse pointer. This
// is by definition a pointer, not a raw mouse. It is
// an error to try to enable or disable pointer mode on
// mouse zero.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
enable_pointer_mode(double speed) {
LightMutexHolder holder(_lock);
nassertv(_device_index != 0);
_pointer_mode_enable = true;
_pointer_speed = speed;
_mouse_data._xpos = _host->get_x_size() * 0.5;
_mouse_data._ypos = _host->get_y_size() * 0.5;
_mouse_data._in_window = true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::disable_pointer_mode
// Access: Public
// Description: see enable_pointer_mode.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
disable_pointer_mode() {
LightMutexHolder holder(_lock);
nassertv(_device_index != 0);
_pointer_mode_enable = false;
_pointer_speed = 1.0;
_mouse_data = _true_mouse_data;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::set_pointer
// Access: Published
// Description: Records that a mouse movement has taken place.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
set_pointer(bool inwin, double x, double y, double time) {
LightMutexHolder holder(_lock);
double delta_x = x - _true_mouse_data._xpos;
double delta_y = y - _true_mouse_data._ypos;
_true_mouse_data._in_window = inwin;
_true_mouse_data._xpos = x;
_true_mouse_data._ypos = y;
if (_pointer_mode_enable) {
double pointer_x = _mouse_data._xpos;
double pointer_y = _mouse_data._ypos;
pointer_x += (delta_x * _pointer_speed);
pointer_y += (delta_y * _pointer_speed);
double xhi = _host->get_x_size();
double yhi = _host->get_y_size();
if (pointer_x < 0.0) pointer_x = 0.0;
if (pointer_y < 0.0) pointer_y = 0.0;
if (pointer_x > xhi) pointer_x = xhi;
if (pointer_y > yhi) pointer_y = yhi;
_mouse_data._in_window = true;
_mouse_data._xpos = pointer_x;
_mouse_data._ypos = pointer_y;
} else {
_mouse_data = _true_mouse_data;
}
if (_enable_pointer_events) {
int seq = _event_sequence++;
if (_pointer_events == 0) {
_pointer_events = new PointerEventList();
}
_pointer_events->add_event(_mouse_data._in_window,
_mouse_data._xpos,
_mouse_data._ypos,
seq, time);
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::button_down
// Access: Published
@ -285,7 +110,7 @@ set_pointer(bool inwin, double x, double y, double time) {
void GraphicsWindowInputDevice::
button_down(ButtonHandle button, double time) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_down, time));
_button_events->add_event(ButtonEvent(button, ButtonEvent::T_down, time));
_buttons_held.insert(button);
}
@ -300,7 +125,7 @@ button_down(ButtonHandle button, double time) {
void GraphicsWindowInputDevice::
button_resume_down(ButtonHandle button, double time) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_resume_down, time));
_button_events->add_event(ButtonEvent(button, ButtonEvent::T_resume_down, time));
_buttons_held.insert(button);
}
@ -312,7 +137,7 @@ button_resume_down(ButtonHandle button, double time) {
void GraphicsWindowInputDevice::
button_up(ButtonHandle button, double time) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_up, time));
_button_events->add_event(ButtonEvent(button, ButtonEvent::T_up, time));
_buttons_held.erase(button);
}
@ -325,7 +150,7 @@ button_up(ButtonHandle button, double time) {
void GraphicsWindowInputDevice::
keystroke(int keycode, double time) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(keycode, time));
_button_events->add_event(ButtonEvent(keycode, time));
}
////////////////////////////////////////////////////////////////////
@ -340,7 +165,7 @@ void GraphicsWindowInputDevice::
candidate(const wstring &candidate_string, size_t highlight_start,
size_t highlight_end, size_t cursor_pos) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(candidate_string,
_button_events->add_event(ButtonEvent(candidate_string,
highlight_start, highlight_end,
cursor_pos));
}
@ -361,7 +186,7 @@ focus_lost(double time) {
LightMutexHolder holder(_lock);
ButtonsHeld::iterator bi;
for (bi = _buttons_held.begin(); bi != _buttons_held.end(); ++bi) {
_button_events.push_back(ButtonEvent(*bi, ButtonEvent::T_up, time));
_button_events->add_event(ButtonEvent(*bi, ButtonEvent::T_up, time));
}
_buttons_held.clear();
}
@ -374,7 +199,7 @@ focus_lost(double time) {
void GraphicsWindowInputDevice::
raw_button_down(ButtonHandle button, double time) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_raw_down, time));
_button_events->add_event(ButtonEvent(button, ButtonEvent::T_raw_down, time));
}
////////////////////////////////////////////////////////////////////
@ -385,5 +210,5 @@ raw_button_down(ButtonHandle button, double time) {
void GraphicsWindowInputDevice::
raw_button_up(ButtonHandle button, double time) {
LightMutexHolder holder(_lock);
_button_events.push_back(ButtonEvent(button, ButtonEvent::T_raw_up, time));
_button_events->add_event(ButtonEvent(button, ButtonEvent::T_raw_up, time));
}

View File

@ -16,139 +16,79 @@
#define GRAPHICSWINDOWINPUTDEVICE_H
#include "pandabase.h"
#include "buttonEvent.h"
#include "pointerEvent.h"
#include "pointerEventList.h"
#include "mouseData.h"
#include "clockObject.h"
#include "pdeque.h"
#include "pvector.h"
#include "lightMutex.h"
#include "lightMutexHolder.h"
#include "inputDevice.h"
// Forward declarations
class GraphicsWindow;
////////////////////////////////////////////////////////////////////
// Class : GraphicsWindowInputDevice
// Description : This is a structure representing a single input
// device that may be associated with a window.
// Typically this will be a keyboard/mouse pair, and
// there will be exactly one of these associated with
// each window, but other variants are possible.
// Description : This is a virtual input device that represents
// the keyboard and mouse pair that is associated with
// a particular window. It collects mouse and keyboard
// events from the windowing system while the window is
// in focus.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DISPLAY GraphicsWindowInputDevice {
class EXPCL_PANDA_DISPLAY GraphicsWindowInputDevice : public InputDevice {
private:
GraphicsWindowInputDevice(GraphicsWindow *host, const string &name, int flags);
public:
static GraphicsWindowInputDevice pointer_only(GraphicsWindow *host, const string &name);
static GraphicsWindowInputDevice keyboard_only(GraphicsWindow *host, const string &name);
static GraphicsWindowInputDevice pointer_and_keyboard(GraphicsWindow *host, const string &name);
static PT(GraphicsWindowInputDevice) pointer_only(GraphicsWindow *host, const string &name);
static PT(GraphicsWindowInputDevice) keyboard_only(GraphicsWindow *host, const string &name);
static PT(GraphicsWindowInputDevice) pointer_and_keyboard(GraphicsWindow *host, const string &name);
INLINE GraphicsWindowInputDevice();
GraphicsWindowInputDevice(const GraphicsWindowInputDevice &copy);
void operator = (const GraphicsWindowInputDevice &copy);
~GraphicsWindowInputDevice();
INLINE string get_name() const;
INLINE bool has_pointer() const;
INLINE bool has_keyboard() const;
INLINE void set_device_index(int index);
INLINE MouseData get_pointer() const;
INLINE MouseData get_raw_pointer() const;
INLINE void enable_pointer_events();
INLINE void disable_pointer_events();
void enable_pointer_mode(double speed);
void disable_pointer_mode();
bool has_button_event() const;
ButtonEvent get_button_event();
bool has_pointer_event() const;
PT(PointerEventList) get_pointer_events();
PUBLISHED:
// The following interface is for the various kinds of
// GraphicsWindows to record the data incoming on the device.
INLINE void button_down(ButtonHandle button);
INLINE void button_resume_down(ButtonHandle button);
INLINE void button_up(ButtonHandle button);
INLINE void keystroke(int keycode);
INLINE void focus_lost();
INLINE void raw_button_down(ButtonHandle button);
INLINE void raw_button_up(ButtonHandle button);
INLINE void set_pointer_in_window(double x, double y);
INLINE void set_pointer_out_of_window();
void button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void button_resume_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void button_down(ButtonHandle button, double time);
void button_resume_down(ButtonHandle button, double time);
void button_up(ButtonHandle button, double time);
void keystroke(int keycode, double time);
void keystroke(int keycode, double time = ClockObject::get_global_clock()->get_frame_time());
void candidate(const wstring &candidate_string, size_t highlight_start,
size_t highlight_end, size_t cursor_pos);
void focus_lost(double time);
void raw_button_down(ButtonHandle button, double time);
void raw_button_up(ButtonHandle button, double time);
INLINE void set_pointer_in_window(double x, double y, double time);
INLINE void set_pointer_out_of_window(double time);
void set_pointer(bool inwin, double x, double y, double time);
void focus_lost(double time = ClockObject::get_global_clock()->get_frame_time());
public:
// We need these methods to make VC++ happy when we try to
// instantiate a pvector<GraphicsWindowInputDevice>. They don't do
// anything useful.
INLINE bool operator == (const GraphicsWindowInputDevice &other) const;
INLINE bool operator != (const GraphicsWindowInputDevice &other) const;
INLINE bool operator < (const GraphicsWindowInputDevice &other) const;
void raw_button_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void raw_button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE void set_pointer_in_window(double x, double y, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE void set_pointer_out_of_window(double time = ClockObject::get_global_clock()->get_frame_time());
private:
enum InputDeviceFlags {
IDF_has_pointer = 0x01,
IDF_has_keyboard = 0x02
};
typedef pdeque<ButtonEvent> ButtonEvents;
LightMutex _lock;
GraphicsWindow *_host;
string _name;
int _flags;
int _device_index;
int _event_sequence;
bool _pointer_mode_enable;
double _pointer_speed;
bool _enable_pointer_events;
MouseData _mouse_data;
MouseData _true_mouse_data;
ButtonEvents _button_events;
PT(PointerEventList) _pointer_events;
typedef pset<ButtonHandle> ButtonsHeld;
ButtonsHeld _buttons_held;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
InputDevice::init_type();
register_type(_type_handle, "GraphicsWindowInputDevice",
InputDevice::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "graphicsWindowInputDevice.I"
#define EXPCL EXPCL_PANDA_DISPLAY
#define EXPTP EXPTP_PANDA_DISPLAY
#define TYPE GraphicsWindowInputDevice
#define NAME vector_GraphicsWindowInputDevice
#include "vector_src.h"
// Tell GCC that we'll take care of the instantiation explicitly here.
#ifdef __GNUC__
#pragma interface
#endif
#endif

View File

@ -41,7 +41,6 @@ MouseAndKeyboard(GraphicsWindow *window, int device, const string &name) :
_pixel_xy = new EventStoreVec2(LPoint2(0.0f, 0.0f));
_pixel_size = new EventStoreVec2(LPoint2(0.0f, 0.0f));
_xy = new EventStoreVec2(LPoint2(0.0f, 0.0f));
_button_events = new ButtonEventList;
}
////////////////////////////////////////////////////////////////////
@ -93,20 +92,18 @@ get_source_device() const {
void MouseAndKeyboard::
do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
DataNodeTransmit &output) {
if (_window->has_button_event(_device)) {
// Fill up the button events.
_button_events->clear();
while (_window->has_button_event(_device)) {
ButtonEvent be = _window->get_button_event(_device);
_button_events->add_event(be);
}
output.set_data(_button_events_output, EventParameter(_button_events));
PT(InputDevice) device = _window->get_input_device(_device);
if (device->has_button_event()) {
PT(ButtonEventList) bel = device->get_button_events();
output.set_data(_button_events_output, EventParameter(bel));
}
if (_window->has_pointer_event(_device)) {
PT(PointerEventList) pel = _window->get_pointer_events(_device);
if (device->has_pointer_event()) {
PT(PointerEventList) pel = device->get_pointer_events();
output.set_data(_pointer_events_output, EventParameter(pel));
}
// Get the window size.
WindowProperties properties = _window->get_properties();
if (properties.has_size()) {
@ -116,18 +113,18 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &,
_pixel_size->set_value(LPoint2(w, h));
output.set_data(_pixel_size_output, EventParameter(_pixel_size));
if (_window->has_pointer(_device)) {
const MouseData &mdata = _window->get_pointer(_device);
if (device->has_pointer()) {
const MouseData &mdata = device->get_pointer();
if (mdata._in_window) {
// Get mouse motion in pixels.
_pixel_xy->set_value(LPoint2(mdata._xpos, mdata._ypos));
output.set_data(_pixel_xy_output, EventParameter(_pixel_xy));
// Normalize pixel motion to range [-1,1].
PN_stdfloat xf = (PN_stdfloat)(2 * mdata._xpos) / (PN_stdfloat)w - 1.0f;
PN_stdfloat yf = 1.0f - (PN_stdfloat)(2 * mdata._ypos) / (PN_stdfloat)h;
_xy->set_value(LPoint2(xf, yf));
output.set_data(_xy_output, EventParameter(_xy));
}

View File

@ -51,7 +51,7 @@ PUBLISHED:
PT(GraphicsWindow) get_source_window() const;
int get_source_device() const;
protected:
// Inherited from DataNode
virtual void do_transmit_data(DataGraphTraverser *trav,
@ -69,7 +69,6 @@ private:
PT(EventStoreVec2) _pixel_xy;
PT(EventStoreVec2) _pixel_size;
PT(EventStoreVec2) _xy;
PT(ButtonEventList) _button_events;
PT(GraphicsWindow) _window;
int _device;

View File

@ -5,6 +5,7 @@
#include "graphicsWindowProc.cxx"
#include "graphicsWindowProcCallbackData.cxx"
#include "graphicsWindowInputDevice.cxx"
#include "mouseAndKeyboard.cxx"
#include "nativeWindowHandle.cxx"
#include "parasiteBuffer.cxx"
#include "standardMunger.cxx"

View File

@ -32,6 +32,7 @@
#include "datagram.h"
#include "doubleBitMask.h"
#include "factoryParam.h"
#include "gamepadButton.h"
#include "namable.h"
#include "nodeCachedReferenceCount.h"
#include "paramValue.h"
@ -225,6 +226,7 @@ init_libputil() {
WritableConfigurable::init_type();
WritableParam::init_type();
GamepadButton::init_gamepad_buttons();
KeyboardButton::init_keyboard_buttons();
MouseButton::init_mouse_buttons();

View File

@ -0,0 +1,75 @@
// Filename: gamepadButton.cxx
// Created by: rdb (21Aug15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "gamepadButton.h"
#include "buttonRegistry.h"
#define DEFINE_GAMEPAD_BUTTON_HANDLE(KeyName) \
static ButtonHandle _##KeyName; \
ButtonHandle GamepadButton::KeyName() { return _##KeyName; }
DEFINE_GAMEPAD_BUTTON_HANDLE(lstick)
DEFINE_GAMEPAD_BUTTON_HANDLE(rstick)
DEFINE_GAMEPAD_BUTTON_HANDLE(lshoulder)
DEFINE_GAMEPAD_BUTTON_HANDLE(rshoulder)
DEFINE_GAMEPAD_BUTTON_HANDLE(ltrigger)
DEFINE_GAMEPAD_BUTTON_HANDLE(rtrigger)
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_left)
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_right)
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_up)
DEFINE_GAMEPAD_BUTTON_HANDLE(dpad_down)
DEFINE_GAMEPAD_BUTTON_HANDLE(back)
DEFINE_GAMEPAD_BUTTON_HANDLE(guide)
DEFINE_GAMEPAD_BUTTON_HANDLE(start)
DEFINE_GAMEPAD_BUTTON_HANDLE(action_a)
DEFINE_GAMEPAD_BUTTON_HANDLE(action_b)
DEFINE_GAMEPAD_BUTTON_HANDLE(action_c)
DEFINE_GAMEPAD_BUTTON_HANDLE(action_x)
DEFINE_GAMEPAD_BUTTON_HANDLE(action_y)
DEFINE_GAMEPAD_BUTTON_HANDLE(action_z)
////////////////////////////////////////////////////////////////////
// Function: GamepadButton::init_gamepad_buttons
// Access: Public, Static
// Description: This is intended to be called only once, by the
// static initialization performed in config_util.cxx.
////////////////////////////////////////////////////////////////////
void GamepadButton::
init_gamepad_buttons() {
ButtonRegistry::ptr()->register_button(_lstick, "lstick");
ButtonRegistry::ptr()->register_button(_rstick, "rstick");
ButtonRegistry::ptr()->register_button(_lshoulder, "lshoulder");
ButtonRegistry::ptr()->register_button(_rshoulder, "rshoulder");
ButtonRegistry::ptr()->register_button(_ltrigger, "ltrigger");
ButtonRegistry::ptr()->register_button(_rtrigger, "rtrigger");
ButtonRegistry::ptr()->register_button(_dpad_left, "dpad_left");
ButtonRegistry::ptr()->register_button(_dpad_right, "dpad_right");
ButtonRegistry::ptr()->register_button(_dpad_up, "dpad_up");
ButtonRegistry::ptr()->register_button(_dpad_down, "dpad_down");
ButtonRegistry::ptr()->register_button(_back, "back");
ButtonRegistry::ptr()->register_button(_guide, "guide");
ButtonRegistry::ptr()->register_button(_start, "start");
ButtonRegistry::ptr()->register_button(_action_a, "action_a");
ButtonRegistry::ptr()->register_button(_action_b, "action_b");
ButtonRegistry::ptr()->register_button(_action_c, "action_c");
ButtonRegistry::ptr()->register_button(_action_x, "action_x");
ButtonRegistry::ptr()->register_button(_action_y, "action_y");
ButtonRegistry::ptr()->register_button(_action_z, "action_z");
}

View File

@ -0,0 +1,57 @@
// Filename: gamepadButton.h
// Created by: rdb (21Aug15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef GAMEPADBUTTON_H
#define GAMEPADBUTTON_H
#include "pandabase.h"
#include "buttonHandle.h"
////////////////////////////////////////////////////////////////////
// Class : GamepadButton
// Description : This class is just used as a convenient namespace for
// grouping all of these handy functions that return
// buttons which map to gamepad buttons.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_PUTIL GamepadButton {
PUBLISHED:
static ButtonHandle lstick();
static ButtonHandle rstick();
static ButtonHandle lshoulder();
static ButtonHandle rshoulder();
static ButtonHandle ltrigger();
static ButtonHandle rtrigger();
static ButtonHandle dpad_left();
static ButtonHandle dpad_right();
static ButtonHandle dpad_up();
static ButtonHandle dpad_down();
static ButtonHandle back();
static ButtonHandle guide();
static ButtonHandle start();
static ButtonHandle action_a();
static ButtonHandle action_b();
static ButtonHandle action_c();
static ButtonHandle action_x();
static ButtonHandle action_y();
static ButtonHandle action_z();
public:
static void init_gamepad_buttons();
};
#endif

View File

@ -28,4 +28,3 @@
#include "factoryBase.cxx"
#include "factoryParam.cxx"
#include "factoryParams.cxx"
#include "globalPointerRegistry.cxx"

View File

@ -1,3 +1,5 @@
#include "gamepadButton.cxx"
#include "globalPointerRegistry.cxx"
#include "ioPtaDatagramFloat.cxx"
#include "ioPtaDatagramInt.cxx"
#include "ioPtaDatagramShort.cxx"

View File

@ -419,7 +419,7 @@ OSStatus TinyOsxGraphicsWindow::handleTextInput (EventHandlerCallRef myHandler,
}
for (unsigned int x = 0; x < actualSize/sizeof(UniChar); ++x) {
_input_devices[0].keystroke(text[x]);
_input_devices[0]->keystroke(text[x]);
}
DisposePtr((char *)text);
}
@ -492,10 +492,10 @@ TinyOsxGraphicsWindow::TinyOsxGraphicsWindow(GraphicsEngine *engine, GraphicsPip
_current_icon(NULL),
_ID(id_seed++),
_originalMode(NULL) {
GraphicsWindowInputDevice device =
PT(InputDevice) device =
GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard/mouse");
_input_devices.push_back(device);
_input_devices[0].set_pointer_in_window(0, 0);
device->set_pointer_in_window(0, 0);
_last_key_modifiers = 0;
_last_buttons = 0;
@ -579,7 +579,7 @@ bool TinyOsxGraphicsWindow::set_icon_filename(const Filename &icon_filename) {
////////////////////////////////////////////////////////////////////
void TinyOsxGraphicsWindow::
set_pointer_in_window(int x, int y) {
_input_devices[0].set_pointer_in_window(x, y);
_input_devices[0]->set_pointer_in_window(x, y);
if (_cursor_hidden != _display_hide_cursor) {
if (_cursor_hidden) {
@ -600,7 +600,7 @@ set_pointer_in_window(int x, int y) {
////////////////////////////////////////////////////////////////////
void TinyOsxGraphicsWindow::
set_pointer_out_of_window() {
_input_devices[0].set_pointer_out_of_window();
_input_devices[0]->set_pointer_out_of_window();
if (_display_hide_cursor) {
CGDisplayShowCursor(kCGDirectMainDisplay);
@ -1333,13 +1333,13 @@ void TinyOsxGraphicsWindow::SystemPointToLocalPoint(Point &qdGlobalPoint) {
_wheel_delta += this_wheel_delta;
SInt32 wheel_scale = osx_mouse_wheel_scale;
while (_wheel_delta > wheel_scale) {
_input_devices[0].button_down(MouseButton::wheel_up());
_input_devices[0].button_up(MouseButton::wheel_up());
_input_devices[0]->button_down(MouseButton::wheel_up());
_input_devices[0]->button_up(MouseButton::wheel_up());
_wheel_delta -= wheel_scale;
}
while (_wheel_delta < -wheel_scale) {
_input_devices[0].button_down(MouseButton::wheel_down());
_input_devices[0].button_up(MouseButton::wheel_down());
_input_devices[0]->button_down(MouseButton::wheel_down());
_input_devices[0]->button_up(MouseButton::wheel_down());
_wheel_delta += wheel_scale;
}
}
@ -1519,25 +1519,25 @@ HandleButtonDelta(UInt32 new_buttons) {
if (changed & 0x01) {
if (new_buttons & 0x01) {
_input_devices[0].button_down(MouseButton::one());
_input_devices[0]->button_down(MouseButton::one());
} else {
_input_devices[0].button_up(MouseButton::one());
_input_devices[0]->button_up(MouseButton::one());
}
}
if (changed & 0x04) {
if (new_buttons & 0x04) {
_input_devices[0].button_down(MouseButton::two());
_input_devices[0]->button_down(MouseButton::two());
} else {
_input_devices[0].button_up(MouseButton::two());
_input_devices[0]->button_up(MouseButton::two());
}
}
if (changed & 0x02) {
if (new_buttons & 0x02) {
_input_devices[0].button_down(MouseButton::three());
_input_devices[0]->button_down(MouseButton::three());
} else {
_input_devices[0].button_up(MouseButton::three());
_input_devices[0]->button_up(MouseButton::three());
}
}
@ -1745,7 +1745,7 @@ void TinyOsxGraphicsWindow::set_properties_now(WindowProperties &properties) {
if (properties.has_cursor_hidden()) {
_properties.set_cursor_hidden(properties.get_cursor_hidden());
_cursor_hidden = properties.get_cursor_hidden();
if (_cursor_hidden && _input_devices[0].has_pointer()) {
if (_cursor_hidden && _input_devices[0]->has_pointer()) {
if (!_display_hide_cursor) {
CGDisplayHideCursor(kCGDirectMainDisplay);
_display_hide_cursor = true;

View File

@ -46,9 +46,7 @@ TinySDLGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
_pitch = 0;
update_pixel_factor();
GraphicsWindowInputDevice device =
GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
add_input_device(device);
add_input_device(GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse"));
}
////////////////////////////////////////////////////////////////////
@ -184,35 +182,35 @@ process_events() {
switch(evt.type) {
case SDL_KEYDOWN:
if (evt.key.keysym.unicode) {
_input_devices[0].keystroke(evt.key.keysym.unicode);
_input_devices[0]->keystroke(evt.key.keysym.unicode);
}
button = get_keyboard_button(evt.key.keysym.sym);
if (button != ButtonHandle::none()) {
_input_devices[0].button_down(button);
_input_devices[0]->button_down(button);
}
break;
case SDL_KEYUP:
button = get_keyboard_button(evt.key.keysym.sym);
if (button != ButtonHandle::none()) {
_input_devices[0].button_up(button);
_input_devices[0]->button_up(button);
}
break;
case SDL_MOUSEBUTTONDOWN:
button = get_mouse_button(evt.button.button);
_input_devices[0].set_pointer_in_window(evt.button.x, evt.button.y);
_input_devices[0].button_down(button);
_input_devices[0]->set_pointer_in_window(evt.button.x, evt.button.y);
_input_devices[0]->button_down(button);
break;
case SDL_MOUSEBUTTONUP:
button = get_mouse_button(evt.button.button);
_input_devices[0].set_pointer_in_window(evt.button.x, evt.button.y);
_input_devices[0].button_up(button);
_input_devices[0]->set_pointer_in_window(evt.button.x, evt.button.y);
_input_devices[0]->button_up(button);
break;
case SDL_MOUSEMOTION:
_input_devices[0].set_pointer_in_window(evt.motion.x, evt.motion.y);
_input_devices[0]->set_pointer_in_window(evt.motion.x, evt.motion.y);
break;
case SDL_VIDEORESIZE:

View File

@ -215,9 +215,7 @@ process_events() {
if (_xwindow == (X11_Window)0) {
return;
}
poll_raw_mice();
XEvent event;
XKeyEvent keyrelease_event;
bool got_keyrelease_event = false;
@ -294,18 +292,18 @@ process_events() {
case ButtonPress:
// This refers to the mouse buttons.
button = get_mouse_button(event.xbutton);
_input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
_input_devices[0].button_down(button);
_input->set_pointer_in_window(event.xbutton.x, event.xbutton.y);
_input->button_down(button);
break;
case ButtonRelease:
button = get_mouse_button(event.xbutton);
_input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
_input_devices[0].button_up(button);
_input->set_pointer_in_window(event.xbutton.x, event.xbutton.y);
_input->button_up(button);
break;
case MotionNotify:
_input_devices[0].set_pointer_in_window(event.xmotion.x, event.xmotion.y);
_input->set_pointer_in_window(event.xmotion.x, event.xmotion.y);
break;
case KeyPress:
@ -322,11 +320,11 @@ process_events() {
break;
case EnterNotify:
_input_devices[0].set_pointer_in_window(event.xcrossing.x, event.xcrossing.y);
_input->set_pointer_in_window(event.xcrossing.x, event.xcrossing.y);
break;
case LeaveNotify:
_input_devices[0].set_pointer_out_of_window();
_input->set_pointer_out_of_window();
break;
case FocusIn:
@ -335,7 +333,7 @@ process_events() {
break;
case FocusOut:
_input_devices[0].focus_lost();
_input->focus_lost();
properties.set_foreground(false);
system_changed_properties(properties);
break;

View File

@ -115,7 +115,6 @@ vrpn_analog_callback(void *userdata, const vrpn_ANALOGCB info) {
Devices::iterator di;
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
VrpnAnalogDevice *device = (*di);
device->acquire();
for (int i = 0; i < info.num_channel; i++) {
if (vrpn_cat.is_debug()) {
if (device->get_control_state(i) != info.channel[i]) {
@ -125,6 +124,5 @@ vrpn_analog_callback(void *userdata, const vrpn_ANALOGCB info) {
}
device->set_control_state(i, info.channel[i]);
}
device->unlock();
}
}

View File

@ -119,8 +119,6 @@ vrpn_button_callback(void *userdata, const vrpn_BUTTONCB info) {
Devices::iterator di;
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
VrpnButtonDevice *device = (*di);
device->acquire();
device->set_button_state(info.button, info.state != 0);
device->unlock();
}
}

View File

@ -120,8 +120,6 @@ vrpn_dial_callback(void *userdata, const vrpn_DIALCB info) {
Devices::iterator di;
for (di = self->_devices.begin(); di != self->_devices.end(); ++di) {
VrpnDialDevice *device = (*di);
device->acquire();
device->push_dial(info.dial, info.change);
device->unlock();
}
}

View File

@ -123,11 +123,10 @@ vrpn_position_callback(void *userdata, const vrpn_TRACKERCB info) {
VrpnTrackerDevice *device = (*di);
if (device->get_sensor() == info.sensor &&
device->get_data_type() == VrpnTrackerDevice::DT_position) {
device->acquire();
device->_data.set_time(VrpnClient::convert_to_secs(info.msg_time));
device->_data.set_pos(LPoint3(info.pos[0], info.pos[1], info.pos[2]));
device->_data.set_orient(LOrientation(info.quat[3], info.quat[0], info.quat[1], info.quat[2]));
device->unlock();
device->set_tracker(LPoint3(info.pos[0], info.pos[1], info.pos[2]),
LOrientation(info.quat[3], info.quat[0],
info.quat[1], info.quat[2]),
VrpnClient::convert_to_secs(info.msg_time));
}
}
}
@ -152,13 +151,10 @@ vrpn_velocity_callback(void *userdata, const vrpn_TRACKERVELCB info) {
VrpnTrackerDevice *device = (*di);
if (device->get_sensor() == info.sensor &&
device->get_data_type() == VrpnTrackerDevice::DT_velocity) {
device->acquire();
device->_data.set_time(VrpnClient::convert_to_secs(info.msg_time));
device->_data.set_pos(LPoint3(info.vel[0], info.vel[1], info.vel[2]));
device->_data.set_orient(LOrientation(info.vel_quat[3], info.vel_quat[0],
info.vel_quat[1], info.vel_quat[2]));
device->_data.set_dt(info.vel_quat_dt);
device->unlock();
device->set_tracker(LPoint3(info.vel[0], info.vel[1], info.vel[2]),
LOrientation(info.vel_quat[3], info.vel_quat[0],
info.vel_quat[1], info.vel_quat[2]),
VrpnClient::convert_to_secs(info.msg_time));
}
}
}
@ -183,13 +179,10 @@ vrpn_acceleration_callback(void *userdata, const vrpn_TRACKERACCCB info) {
VrpnTrackerDevice *device = (*di);
if (device->get_sensor() == info.sensor &&
device->get_data_type() == VrpnTrackerDevice::DT_acceleration) {
device->acquire();
device->_data.set_time(VrpnClient::convert_to_secs(info.msg_time));
device->_data.set_pos(LPoint3(info.acc[0], info.acc[1], info.acc[2]));
device->_data.set_orient(LOrientation(info.acc_quat[3], info.acc_quat[0],
info.acc_quat[1], info.acc_quat[2]));
device->_data.set_dt(info.acc_quat_dt);
device->unlock();
device->set_tracker(LPoint3(info.acc[0], info.acc[1], info.acc[2]),
LOrientation(info.acc_quat[3], info.acc_quat[0],
info.acc_quat[1], info.acc_quat[2]),
VrpnClient::convert_to_secs(info.msg_time));
}
}
}

View File

@ -2786,9 +2786,9 @@ handle_raw_input(HRAWINPUT hraw) {
if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) {
_input_devices[i].set_pointer_in_window(adjx, adjy);
} else {
int oldx = _input_devices[i].get_raw_pointer().get_x();
int oldy = _input_devices[i].get_raw_pointer().get_y();
_input_devices[i].set_pointer_in_window(oldx + adjx, oldy + adjy);
//int oldx = _input_devices[i].get_raw_pointer().get_x();
//int oldy = _input_devices[i].get_raw_pointer().get_y();
//_input_devices[i].set_pointer_in_window(oldx + adjx, oldy + adjy);
}
if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) {

View File

@ -28,14 +28,10 @@
#include "nativeWindowHandle.h"
#include "virtualFileSystem.h"
#include "get_x11.h"
#include "evdevInputDevice.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#ifdef PHAVE_LINUX_INPUT_H
#include <linux/input.h>
#endif
#include <fcntl.h>
#ifdef HAVE_XCURSOR
static int xcursor_read(XcursorFile *file, unsigned char *buf, int len) {
@ -69,8 +65,6 @@ static int xcursor_seek(XcursorFile *file, long offset, int whence) {
TypeHandle x11GraphicsWindow::_type_handle;
#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7)))
////////////////////////////////////////////////////////////////////
// Function: x11GraphicsWindow::Constructor
// Access: Public
@ -107,9 +101,9 @@ x11GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
_override_redirect = False;
_wm_delete_window = x11_pipe->_wm_delete_window;
GraphicsWindowInputDevice device =
GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
PT(GraphicsWindowInputDevice) device = GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
add_input_device(device);
_input = device;
}
////////////////////////////////////////////////////////////////////
@ -143,26 +137,26 @@ move_pointer(int device, int x, int y) {
if (device == 0) {
// Move the system mouse pointer.
if (!_properties.get_foreground() ||
!_input_devices[0].get_pointer().get_in_window()) {
!_input->get_pointer().get_in_window()) {
// If the window doesn't have input focus, or the mouse isn't
// currently within the window, forget it.
return false;
}
const MouseData &md = _input_devices[0].get_pointer();
const MouseData &md = _input->get_pointer();
if (!md.get_in_window() || md.get_x() != x || md.get_y() != y) {
if (!_dga_mouse_enabled) {
XWarpPointer(_display, None, _xwindow, 0, 0, 0, 0, x, y);
}
_input_devices[0].set_pointer_in_window(x, y);
_input->set_pointer_in_window(x, y);
}
return true;
} else {
// Move a raw mouse.
if ((device < 1)||(device >= _input_devices.size())) {
if (device < 1 || device >= _input_devices.size()) {
return false;
}
_input_devices[device].set_pointer_in_window(x, y);
//_input_devices[device]->set_pointer_in_window(x, y);
return true;
}
}
@ -249,8 +243,6 @@ process_events() {
return;
}
poll_raw_mice();
XEvent event;
XKeyEvent keyrelease_event;
bool got_keyrelease_event = false;
@ -311,25 +303,25 @@ process_events() {
// This refers to the mouse buttons.
button = get_mouse_button(event.xbutton);
if (!_dga_mouse_enabled) {
_input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
_input->set_pointer_in_window(event.xbutton.x, event.xbutton.y);
}
_input_devices[0].button_down(button);
_input->button_down(button);
break;
case ButtonRelease:
button = get_mouse_button(event.xbutton);
if (!_dga_mouse_enabled) {
_input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
_input->set_pointer_in_window(event.xbutton.x, event.xbutton.y);
}
_input_devices[0].button_up(button);
_input->button_up(button);
break;
case MotionNotify:
if (_dga_mouse_enabled) {
const MouseData &md = _input_devices[0].get_raw_pointer();
_input_devices[0].set_pointer_in_window(md.get_x() + event.xmotion.x_root, md.get_y() + event.xmotion.y_root);
const MouseData &md = _input->get_pointer();
_input->set_pointer_in_window(md.get_x() + event.xmotion.x_root, md.get_y() + event.xmotion.y_root);
} else {
_input_devices[0].set_pointer_in_window(event.xmotion.x, event.xmotion.y);
_input->set_pointer_in_window(event.xmotion.x, event.xmotion.y);
}
break;
@ -348,15 +340,15 @@ process_events() {
case EnterNotify:
if (_dga_mouse_enabled) {
const MouseData &md = _input_devices[0].get_raw_pointer();
_input_devices[0].set_pointer_in_window(md.get_x(), md.get_y());
const MouseData &md = _input->get_pointer();
_input->set_pointer_in_window(md.get_x(), md.get_y());
} else {
_input_devices[0].set_pointer_in_window(event.xcrossing.x, event.xcrossing.y);
_input->set_pointer_in_window(event.xcrossing.x, event.xcrossing.y);
}
break;
case LeaveNotify:
_input_devices[0].set_pointer_out_of_window();
_input->set_pointer_out_of_window();
break;
case FocusIn:
@ -365,7 +357,7 @@ process_events() {
break;
case FocusOut:
_input_devices[0].focus_lost();
_input->focus_lost();
properties.set_foreground(false);
changed_properties = true;
break;
@ -751,7 +743,7 @@ set_properties_now(WindowProperties &properties) {
XQueryPointer(_display, _xwindow, &event.xbutton.root,
&event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
_input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
_input->set_pointer_in_window(event.xbutton.x, event.xbutton.y);
}
} else {
x11display_cat.info() << "XF86DGA extension not available\n";
@ -1295,66 +1287,43 @@ open_raw_mice() {
bool any_mice = false;
for (int i=0; i<64; i++) {
uint8_t evtypes[EV_MAX/8 + 1];
ostringstream fnb;
fnb << "/dev/input/event" << i;
string fn = fnb.str();
int fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK, 0);
if (fd >= 0) {
any_present = true;
char name[256];
char phys[256];
char uniq[256];
if ((ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0)||
(ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) < 0)||
(ioctl(fd, EVIOCGPHYS(sizeof(uniq)), uniq) < 0)||
(ioctl(fd, EVIOCGBIT(0, EV_MAX), &evtypes) < 0)) {
close(fd);
x11display_cat.error() <<
"Opening raw mice: ioctl failed on " << fn << "\n";
} else {
if (test_bit(EV_REL, evtypes) || test_bit(EV_ABS, evtypes)) {
for (char *p=name; *p; p++) {
if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) {
*p = '_';
}
}
for (char *p=uniq; *p; p++) {
if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) {
*p = '_';
}
}
string full_id = ((string)name) + "." + uniq;
MouseDeviceInfo inf;
inf._fd = fd;
inf._input_device_index = _input_devices.size();
inf._io_buffer = "";
_mouse_device_info.push_back(inf);
GraphicsWindowInputDevice device =
GraphicsWindowInputDevice::pointer_only(this, full_id);
add_input_device(device);
x11display_cat.info() << "Raw mouse " <<
inf._input_device_index << " detected: " << full_id << "\n";
any_mice = true;
} else {
close(fd);
}
EvdevInputDevice *device = new EvdevInputDevice(fd);
nassertd(device != NULL) continue;
if (device->has_pointer()) {
add_input_device(device);
x11display_cat.info()
<< "Raw mouse " << _input_devices.size()
<< " detected: " << device->get_name() << "\n";
any_mice = true;
any_present = true;
}
} else {
if ((errno == ENOENT)||(errno == ENOTDIR)) {
if (errno == ENOENT || errno == ENOTDIR) {
break;
} else {
any_present = true;
x11display_cat.error() <<
"Opening raw mice: " << strerror(errno) << " " << fn << "\n";
x11display_cat.error()
<< "Opening raw mice: " << strerror(errno) << " " << fn << "\n";
}
}
}
if (!any_present) {
if (any_mice) {
_properties.set_raw_mice(true);
} else if (!any_present) {
x11display_cat.error() <<
"Opening raw mice: files not found: /dev/input/event*\n";
} else if (!any_mice) {
} else {
x11display_cat.error() <<
"Opening raw mice: no mouse devices detected in /dev/input/event*\n";
}
@ -1364,69 +1333,6 @@ open_raw_mice() {
#endif
}
////////////////////////////////////////////////////////////////////
// Function: x11GraphicsWindow::poll_raw_mice
// Access: Private
// Description: Reads events from the raw mouse device files.
////////////////////////////////////////////////////////////////////
void x11GraphicsWindow::
poll_raw_mice() {
#ifdef PHAVE_LINUX_INPUT_H
for (int di = 0; di < _mouse_device_info.size(); ++di) {
MouseDeviceInfo &inf = _mouse_device_info[di];
// Read all bytes into buffer.
if (inf._fd >= 0) {
while (1) {
char tbuf[1024];
int nread = read(inf._fd, tbuf, sizeof(tbuf));
if (nread > 0) {
inf._io_buffer += string(tbuf, nread);
} else {
if ((nread < 0) && ((errno == EWOULDBLOCK) || (errno==EAGAIN))) {
break;
}
close(inf._fd);
inf._fd = -1;
break;
}
}
}
// Process events.
int nevents = inf._io_buffer.size() / sizeof(struct input_event);
if (nevents == 0) {
continue;
}
const input_event *events = (const input_event *)(inf._io_buffer.c_str());
GraphicsWindowInputDevice &dev = _input_devices[inf._input_device_index];
int x = dev.get_raw_pointer().get_x();
int y = dev.get_raw_pointer().get_y();
for (int i = 0; i < nevents; i++) {
if (events[i].type == EV_REL) {
if (events[i].code == REL_X) x += events[i].value;
if (events[i].code == REL_Y) y += events[i].value;
} else if (events[i].type == EV_ABS) {
if (events[i].code == ABS_X) x = events[i].value;
if (events[i].code == ABS_Y) y = events[i].value;
} else if (events[i].type == EV_KEY) {
if ((events[i].code >= BTN_MOUSE) && (events[i].code < BTN_MOUSE + 8)) {
int btn = events[i].code - BTN_MOUSE;
dev.set_pointer_in_window(x, y);
if (events[i].value) {
dev.button_down(MouseButton::button(btn));
} else {
dev.button_up(MouseButton::button(btn));
}
}
}
}
inf._io_buffer.erase(0, nevents * sizeof(struct input_event));
dev.set_pointer_in_window(x, y);
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: x11GraphicsWindow::handle_keystroke
// Access: Private
@ -1436,7 +1342,7 @@ poll_raw_mice() {
void x11GraphicsWindow::
handle_keystroke(XKeyEvent &event) {
if (!_dga_mouse_enabled) {
_input_devices[0].set_pointer_in_window(event.x, event.y);
_input->set_pointer_in_window(event.x, event.y);
}
if (_ic) {
@ -1454,14 +1360,14 @@ handle_keystroke(XKeyEvent &event) {
// Now each of the returned wide characters represents a
// keystroke.
for (int i = 0; i < len; i++) {
_input_devices[0].keystroke(buffer[i]);
_input->keystroke(buffer[i]);
}
} else {
// Without an input context, just get the ascii keypress.
ButtonHandle button = get_button(event, true);
if (button.has_ascii_equivalent()) {
_input_devices[0].keystroke(button.get_ascii_equivalent());
_input->keystroke(button.get_ascii_equivalent());
}
}
}
@ -1475,30 +1381,32 @@ handle_keystroke(XKeyEvent &event) {
void x11GraphicsWindow::
handle_keypress(XKeyEvent &event) {
if (!_dga_mouse_enabled) {
_input_devices[0].set_pointer_in_window(event.x, event.y);
_input->set_pointer_in_window(event.x, event.y);
}
// Now get the raw unshifted button.
ButtonHandle button = get_button(event, false);
if (button != ButtonHandle::none()) {
if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
_input_devices[0].button_down(KeyboardButton::control());
_input->button_down(KeyboardButton::control());
}
if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
_input_devices[0].button_down(KeyboardButton::shift());
_input->button_down(KeyboardButton::shift());
}
if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
_input_devices[0].button_down(KeyboardButton::alt());
_input->button_down(KeyboardButton::alt());
}
if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) {
_input_devices[0].button_down(KeyboardButton::meta());
_input->button_down(KeyboardButton::meta());
}
_input_devices[0].button_down(button);
_input->button_down(button);
}
ButtonHandle raw_button = map_raw_button(event.keycode);
if (raw_button != ButtonHandle::none()) {
_input_devices[0].raw_button_down(raw_button);
if (event.keycode >= 9 && event.keycode <= 135) {
ButtonHandle raw_button = map_raw_button(event.keycode);
if (raw_button != ButtonHandle::none()) {
_input->raw_button_down(raw_button);
}
}
}
@ -1511,30 +1419,32 @@ handle_keypress(XKeyEvent &event) {
void x11GraphicsWindow::
handle_keyrelease(XKeyEvent &event) {
if (!_dga_mouse_enabled) {
_input_devices[0].set_pointer_in_window(event.x, event.y);
_input->set_pointer_in_window(event.x, event.y);
}
// Now get the raw unshifted button.
ButtonHandle button = get_button(event, false);
if (button != ButtonHandle::none()) {
if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) {
_input_devices[0].button_up(KeyboardButton::control());
_input->button_up(KeyboardButton::control());
}
if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) {
_input_devices[0].button_up(KeyboardButton::shift());
_input->button_up(KeyboardButton::shift());
}
if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) {
_input_devices[0].button_up(KeyboardButton::alt());
_input->button_up(KeyboardButton::alt());
}
if (button == KeyboardButton::lmeta() || button == KeyboardButton::rmeta()) {
_input_devices[0].button_up(KeyboardButton::meta());
_input->button_up(KeyboardButton::meta());
}
_input_devices[0].button_up(button);
_input->button_up(button);
}
ButtonHandle raw_button = map_raw_button(event.keycode);
if (raw_button != ButtonHandle::none()) {
_input_devices[0].raw_button_up(raw_button);
if (event.keycode >= 9 && event.keycode <= 135) {
ButtonHandle raw_button = map_raw_button(event.keycode);
if (raw_button != ButtonHandle::none()) {
_input->raw_button_up(raw_button);
}
}
}
@ -1617,7 +1527,7 @@ get_button(XKeyEvent &key_event, bool allow_shift) {
// can do this in just the ASCII set, because we handle
// international keyboards elsewhere (via an input context).
if ((key_event.state & (ShiftMask | LockMask)) != 0) {
if (key >= XK_a and key <= XK_z) {
if (key >= XK_a && key <= XK_z) {
key += (XK_A - XK_a);
}
}
@ -1962,117 +1872,16 @@ map_button(KeySym key) const {
////////////////////////////////////////////////////////////////////
ButtonHandle x11GraphicsWindow::
map_raw_button(KeyCode key) const {
switch (key) {
case 9: return KeyboardButton::escape();
case 10: return KeyboardButton::ascii_key('1');
case 11: return KeyboardButton::ascii_key('2');
case 12: return KeyboardButton::ascii_key('3');
case 13: return KeyboardButton::ascii_key('4');
case 14: return KeyboardButton::ascii_key('5');
case 15: return KeyboardButton::ascii_key('6');
case 16: return KeyboardButton::ascii_key('7');
case 17: return KeyboardButton::ascii_key('8');
case 18: return KeyboardButton::ascii_key('9');
case 19: return KeyboardButton::ascii_key('0');
case 20: return KeyboardButton::ascii_key('-');
case 21: return KeyboardButton::ascii_key('=');
case 22: return KeyboardButton::backspace();
case 23: return KeyboardButton::tab();
case 24: return KeyboardButton::ascii_key('q');
case 25: return KeyboardButton::ascii_key('w');
case 26: return KeyboardButton::ascii_key('e');
case 27: return KeyboardButton::ascii_key('r');
case 28: return KeyboardButton::ascii_key('t');
case 29: return KeyboardButton::ascii_key('y');
case 30: return KeyboardButton::ascii_key('u');
case 31: return KeyboardButton::ascii_key('i');
case 32: return KeyboardButton::ascii_key('o');
case 33: return KeyboardButton::ascii_key('p');
case 34: return KeyboardButton::ascii_key('[');
case 35: return KeyboardButton::ascii_key(']');
case 36: return KeyboardButton::enter();
case 37: return KeyboardButton::lcontrol();
case 38: return KeyboardButton::ascii_key('a');
case 39: return KeyboardButton::ascii_key('s');
case 40: return KeyboardButton::ascii_key('d');
case 41: return KeyboardButton::ascii_key('f');
case 42: return KeyboardButton::ascii_key('g');
case 43: return KeyboardButton::ascii_key('h');
case 44: return KeyboardButton::ascii_key('j');
case 45: return KeyboardButton::ascii_key('k');
case 46: return KeyboardButton::ascii_key('l');
case 47: return KeyboardButton::ascii_key(';');
case 48: return KeyboardButton::ascii_key('\'');
case 49: return KeyboardButton::ascii_key('`');
case 50: return KeyboardButton::lshift();
case 51: return KeyboardButton::ascii_key('\\');
case 52: return KeyboardButton::ascii_key('z');
case 53: return KeyboardButton::ascii_key('x');
case 54: return KeyboardButton::ascii_key('c');
case 55: return KeyboardButton::ascii_key('v');
case 56: return KeyboardButton::ascii_key('b');
case 57: return KeyboardButton::ascii_key('n');
case 58: return KeyboardButton::ascii_key('m');
case 59: return KeyboardButton::ascii_key(',');
case 60: return KeyboardButton::ascii_key('.');
case 61: return KeyboardButton::ascii_key('/');
case 62: return KeyboardButton::rshift();
case 63: return KeyboardButton::ascii_key('*');
case 64: return KeyboardButton::lalt();
case 65: return KeyboardButton::space();
case 66: return KeyboardButton::caps_lock();
case 67: return KeyboardButton::f1();
case 68: return KeyboardButton::f2();
case 69: return KeyboardButton::f3();
case 70: return KeyboardButton::f4();
case 71: return KeyboardButton::f5();
case 72: return KeyboardButton::f6();
case 73: return KeyboardButton::f7();
case 74: return KeyboardButton::f8();
case 75: return KeyboardButton::f9();
case 76: return KeyboardButton::f10();
case 77: return KeyboardButton::num_lock();
case 78: return KeyboardButton::scroll_lock();
case 79: return KeyboardButton::ascii_key('7');
case 80: return KeyboardButton::ascii_key('8');
case 81: return KeyboardButton::ascii_key('9');
case 82: return KeyboardButton::ascii_key('-');
case 83: return KeyboardButton::ascii_key('4');
case 84: return KeyboardButton::ascii_key('5');
case 85: return KeyboardButton::ascii_key('6');
case 86: return KeyboardButton::ascii_key('+');
case 87: return KeyboardButton::ascii_key('1');
case 88: return KeyboardButton::ascii_key('2');
case 89: return KeyboardButton::ascii_key('3');
case 90: return KeyboardButton::ascii_key('0');
case 91: return KeyboardButton::ascii_key('.');
case 95: return KeyboardButton::f11();
case 96: return KeyboardButton::f12();
case 104: return KeyboardButton::enter();
case 105: return KeyboardButton::rcontrol();
case 106: return KeyboardButton::ascii_key('/');
case 107: return KeyboardButton::print_screen();
case 108: return KeyboardButton::ralt();
case 110: return KeyboardButton::home();
case 111: return KeyboardButton::up();
case 112: return KeyboardButton::page_up();
case 113: return KeyboardButton::left();
case 114: return KeyboardButton::right();
case 115: return KeyboardButton::end();
case 116: return KeyboardButton::down();
case 117: return KeyboardButton::page_down();
case 118: return KeyboardButton::insert();
case 119: return KeyboardButton::del();
case 127: return KeyboardButton::pause();
case 133: return KeyboardButton::lmeta();
case 134: return KeyboardButton::rmeta();
case 135: return KeyboardButton::menu();
#ifdef PHAVE_LINUX_INPUT_H
// Most X11 servers are configured to use the evdev driver, which
// adds 8 to the underlying evdev keycodes (not sure why).
// In any case, this means we can use the same mapping as our raw
// input code, which uses evdev directly.
int index = key - 8;
if (index >= 0) {
return EvdevInputDevice::map_button(index);
}
#endif
return ButtonHandle::none();
}

View File

@ -74,7 +74,6 @@ protected:
static Bool check_event(X11_Display *display, XEvent *event, char *arg);
void open_raw_mice();
void poll_raw_mice();
private:
X11_Cursor get_cursor(const Filename &filename);
@ -89,6 +88,7 @@ protected:
Colormap _colormap;
XIC _ic;
XVisualInfo *_visual_info;
GraphicsWindowInputDevice *_input;
bool _have_xrandr;
#ifdef HAVE_XRANDR