/* ** ClanLib SDK ** Copyright (c) 1997-2005 The ClanLib Team ** ** This software is provided 'as-is', without any express or implied ** warranty. In no event will the authors be held liable for any damages ** arising from the use of this software. ** ** Permission is granted to anyone to use this software for any purpose, ** including commercial applications, and to alter it and redistribute it ** freely, subject to the following restrictions: ** ** 1. The origin of this software must not be misrepresented; you must not ** claim that you wrote the original software. If you use this software ** in a product, an acknowledgment in the product documentation would be ** appreciated but is not required. ** 2. Altered source versions must be plainly marked as such, and must not be ** misrepresented as being the original software. ** 3. This notice may not be removed or altered from any source distribution. ** ** Note: Some of the libraries ClanLib may link to may have additional ** requirements or restrictions. ** ** File Author(s): ** ** Magnus Norddahl ** (if your name is missing here, please add it) */ #include #include "API/Core/System/log.h" #include "API/Display/input_device.h" #include "API/Display/input_event.h" #include "API/Core/System/clanstring.h" #include "API/Core/System/error.h" #include "input_device_xinput.h" #include "display_window_opengl.h" #define INVALID_EVENT_TYPE -1 CL_InputDevice_XInput::CL_InputDevice_XInput(CL_DisplayWindow_OpenGL *owner_, XDeviceInfo* info) : owner(owner_), name(info->name), absolute(false), num_keys (0), motion_type (INVALID_EVENT_TYPE), button_press_type (INVALID_EVENT_TYPE), button_release_type(INVALID_EVENT_TYPE), key_press_type (INVALID_EVENT_TYPE), key_release_type (INVALID_EVENT_TYPE), proximity_in_type (INVALID_EVENT_TYPE), proximity_out_type (INVALID_EVENT_TYPE) { type = CL_InputDevice::tablet; //info = find_device_info(owner->get_display(), name.c_str(), True); //if (!info) // throw CL_Error("CL_InputDeviceXInput Error: Couldn't find device: " + name); get_info(info); if (!register_events(owner->get_display(), info, name.c_str(), True)) { CL_Log::log("debug", "CL_InputDeviceXInput: Couldn't find device: " + name); } else { slot_xevent = owner->sig_unknown_xevent.connect(this, &CL_InputDevice_XInput::on_xevent); } } CL_InputDevice_XInput::~CL_InputDevice_XInput() { } void CL_InputDevice_XInput::get_info(XDeviceInfo *info) { int i,j; XAnyClassPtr any; XKeyInfoPtr k; XButtonInfoPtr b; XValuatorInfoPtr v; XAxisInfoPtr a; //printf("\"%s\"\tid=%ld\t[%s]\n", info->name, info->id, // (info->use == IsXExtensionDevice) ? "XExtensionDevice" : // ((info->use == IsXPointer) ? "XPointer" : "XKeyboard")); if (info->num_classes > 0) { any = (XAnyClassPtr) (info->inputclassinfo); for (i=0; inum_classes; i++) { switch (any->c_class) { case KeyClass: k = (XKeyInfoPtr) any; //printf("\tNum_keys is %d\n", k->num_keys); //printf("\tMin_keycode is %d\n", k->min_keycode); //printf("\tMax_keycode is %d\n", k->max_keycode); num_keys = k->num_keys; break; case ButtonClass: b = (XButtonInfoPtr) any; //printf("\tNum_buttons is %d\n", b->num_buttons); buttons.resize(b->num_buttons, false); break; case ValuatorClass: v = (XValuatorInfoPtr) any; a = (XAxisInfoPtr) ((char *) v + sizeof (XValuatorInfo)); //printf("\tNum_axes is %d\n", v->num_axes); //printf("\tMode is %s\n", (v->mode == Absolute) ? "Absolute" : "Relative"); //printf("\tMotion_buffer is %ld\n", v->motion_buffer); absolute = (v->mode == Absolute); for (j=0; jnum_axes; j++, a++) { //printf("\tAxis %d :\n", j); //printf("\t\tMin_value is %d\n", a->min_value); //printf("\t\tMax_value is %d\n", a->max_value); //printf ("\t\tResolution is %d\n", a->resolution); axis.push_back(AxisInfo(a->min_value, a->max_value, a->resolution)); } break; default: printf ("unknown class\n"); } any = (XAnyClassPtr) ((char *) any + any->length); } } } XDeviceInfo* CL_InputDevice_XInput::find_device_info(Display *display, const char *name, Bool only_extended) { // FIXME: Not really needed could simply pass XDeviceInfo to the // constructor, might however make a nicer interface XDeviceInfo *devices; int loop; int num_devices; int len = strlen(name); Bool is_id = True; XID id = 0; for(loop=0; loopid); if (!device) { fprintf(stderr, "unable to open device %s\n", dev_name); return 0; } if (device->num_classes > 0) { for (ip = device->classes, i=0; inum_classes; ip++, i++) { switch (ip->input_class) { case KeyClass: DeviceKeyPress (device, key_press_type, event_list[number]); number++; DeviceKeyRelease(device, key_release_type, event_list[number]); number++; break; case ButtonClass: DeviceButtonPress (device, button_press_type, event_list[number]); number++; DeviceButtonRelease(device, button_release_type, event_list[number]); number++; break; case ValuatorClass: DeviceMotionNotify(device, motion_type, event_list[number]); number++; if (handle_proximity) { ProximityIn (device, proximity_in_type, event_list[number]); number++; ProximityOut(device, proximity_out_type, event_list[number]); number++; } break; default: fprintf(stderr, "unknown class\n"); break; } } if (XSelectExtensionEvent(dpy, root_win, event_list, number)) { fprintf(stderr, "error selecting extended events\n"); return 0; } } //std::cout << "### Registered events: " << number << std::endl; return number; } void CL_InputDevice_XInput::on_xevent(XEvent &event) { if (0) std::cout << this << " event: " << event.type << " Defs: " << motion_type << " " << button_press_type << " " << button_release_type << " " << key_press_type << " " << key_release_type << " " << proximity_out_type << " " << proximity_in_type << " " << std::endl; std::vector old_axis = axis; std::vector old_buttons = buttons; if (event.type == motion_type) { XDeviceMotionEvent *motion = (XDeviceMotionEvent *) &event; //printf("motion "); for(int loop=0; loopaxes_count; loop++) { //printf("a[%d]=%d ", motion->first_axis + loop, motion->axis_data[loop]); axis[loop + motion->first_axis].pos = motion->axis_data[loop]; } //printf("\n"); } else if ((event.type == button_press_type) || (event.type == button_release_type)) { int loop; XDeviceButtonEvent *button = (XDeviceButtonEvent *) &event; //printf("button %s %d ", (event.type == button_release_type) ? "release" : "press ", button->button); buttons[button->button] = (event.type == button_press_type); for(loop=0; loopaxes_count; loop++) { //printf("a[%d]=%d ", button->first_axis + loop, button->axis_data[loop]); axis[loop + button->first_axis].pos = button->axis_data[loop]; } //printf("\n"); } else if ((event.type == key_press_type) || (event.type == key_release_type)) { int loop; XDeviceKeyEvent *key = (XDeviceKeyEvent *) &event; //printf("key %s %d ", (event.type == key_release_type) ? "release" : "press ", key->keycode); for(loop=0; loopaxes_count; loop++) { //printf("a[%d]=%d ", key->first_axis + loop, key->axis_data[loop]); axis[loop + key->first_axis].pos = key->axis_data[loop]; } //printf("\n"); } else if ((event.type == proximity_out_type) || (event.type == proximity_in_type)) { int loop; XProximityNotifyEvent *prox = (XProximityNotifyEvent *) &event; //printf("proximity %s ", (event.type == proximity_in_type) ? "in " : "out"); for(loop=0; loopaxes_count; loop++) { //printf("a[%d]=%d ", prox->first_axis + loop, prox->axis_data[loop]); axis[loop + prox->first_axis].pos = prox->axis_data[loop]; } //printf("\n"); } else { //printf("CL_InputDevice_XInput: what's that %d\n", event.type); } for (std::vector::size_type i = 0; i < buttons.size(); ++i) { if (buttons[i] != old_buttons[i]) { CL_InputEvent ie; ie.id = i; ie.type = CL_InputEvent::pressed; ie.device = CL_InputDevice(this); ie.mouse_pos = CL_Point(0, 0); ie.axis_pos = 0; ie.repeat_count = false; sig_axis_move(ie); } } for (std::vector::size_type i = 0; i < axis.size(); ++i) { if (axis[i].pos != old_axis[i].pos) { CL_InputEvent ie; ie.id = i; ie.type = CL_InputEvent::axis_moved; ie.device = CL_InputDevice(this); ie.mouse_pos = CL_Point(0, 0); ie.axis_pos = get_axis(i); ie.repeat_count = false; sig_axis_move(ie); } } } int CL_InputDevice_XInput::get_x() const { return 0; } int CL_InputDevice_XInput::get_y() const { return 0; } bool CL_InputDevice_XInput::get_keycode(int keycode) const { if (keycode >=0 && keycode < int(buttons.size())) { return buttons[keycode]; } else { return false; } } std::string CL_InputDevice_XInput::get_key_name(int id) const { return "button" + CL_String::from_int(id); } float CL_InputDevice_XInput::get_axis(int index) const { if (index >= 0 && index < get_axis_count()) { return float(axis[index].pos)/(axis[index].max_value - axis[index].min_value); } else { return 0.0f; } } int CL_InputDevice_XInput::get_axis_count() const { return axis.size(); } std::string CL_InputDevice_XInput::get_name() const { return name; } std::string CL_InputDevice_XInput::get_device_name() const { return "xinput:" + name; } int CL_InputDevice_XInput::get_button_count() const { return buttons.size(); } // Local Variables: *** // mode: clanlib *** // End: ***