SDL  2.0
SDLControllerManager.java
Go to the documentation of this file.
1 package org.libsdl.app;
2 
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.Comparator;
6 import java.util.List;
7 
8 import android.content.Context;
9 import android.os.*;
10 import android.view.*;
11 import android.util.Log;
12 
13 
15 {
16 
17  public static native int nativeSetupJNI();
18 
19  public static native int nativeAddJoystick(int device_id, String name, String desc,
20  int vendor_id, int product_id,
21  boolean is_accelerometer, int button_mask,
22  int naxes, int nhats, int nballs);
23  public static native int nativeRemoveJoystick(int device_id);
24  public static native int nativeAddHaptic(int device_id, String name);
25  public static native int nativeRemoveHaptic(int device_id);
26  public static native int onNativePadDown(int device_id, int keycode);
27  public static native int onNativePadUp(int device_id, int keycode);
28  public static native void onNativeJoy(int device_id, int axis,
29  float value);
30  public static native void onNativeHat(int device_id, int hat_id,
31  int x, int y);
32 
33  protected static SDLJoystickHandler mJoystickHandler;
34  protected static SDLHapticHandler mHapticHandler;
35 
36  private static final String TAG = "SDLControllerManager";
37 
38  public static void initialize() {
39  if (mJoystickHandler == null) {
40  if (Build.VERSION.SDK_INT >= 19) {
41  mJoystickHandler = new SDLJoystickHandler_API19();
42  } else if (Build.VERSION.SDK_INT >= 16) {
43  mJoystickHandler = new SDLJoystickHandler_API16();
44  } else if (Build.VERSION.SDK_INT >= 12) {
45  mJoystickHandler = new SDLJoystickHandler_API12();
46  } else {
47  mJoystickHandler = new SDLJoystickHandler();
48  }
49  }
50 
51  if (mHapticHandler == null) {
52  if (Build.VERSION.SDK_INT >= 26) {
53  mHapticHandler = new SDLHapticHandler_API26();
54  } else {
55  mHapticHandler = new SDLHapticHandler();
56  }
57  }
58  }
59 
60  // Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
61  public static boolean handleJoystickMotionEvent(MotionEvent event) {
62  return mJoystickHandler.handleMotionEvent(event);
63  }
64 
65  /**
66  * This method is called by SDL using JNI.
67  */
68  public static void pollInputDevices() {
69  mJoystickHandler.pollInputDevices();
70  }
71 
72  /**
73  * This method is called by SDL using JNI.
74  */
75  public static void pollHapticDevices() {
76  mHapticHandler.pollHapticDevices();
77  }
78 
79  /**
80  * This method is called by SDL using JNI.
81  */
82  public static void hapticRun(int device_id, float intensity, int length) {
83  mHapticHandler.run(device_id, intensity, length);
84  }
85 
86  /**
87  * This method is called by SDL using JNI.
88  */
89  public static void hapticStop(int device_id)
90  {
91  mHapticHandler.stop(device_id);
92  }
93 
94  // Check if a given device is considered a possible SDL joystick
95  public static boolean isDeviceSDLJoystick(int deviceId) {
96  InputDevice device = InputDevice.getDevice(deviceId);
97  // We cannot use InputDevice.isVirtual before API 16, so let's accept
98  // only nonnegative device ids (VIRTUAL_KEYBOARD equals -1)
99  if ((device == null) || (deviceId < 0)) {
100  return false;
101  }
102  int sources = device.getSources();
103 
104  /* This is called for every button press, so let's not spam the logs */
105  /**
106  if ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK) {
107  Log.v(TAG, "Input device " + device.getName() + " is a joystick.");
108  }
109  if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) {
110  Log.v(TAG, "Input device " + device.getName() + " is a dpad.");
111  }
112  if ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) {
113  Log.v(TAG, "Input device " + device.getName() + " is a gamepad.");
114  }
115  **/
116 
117  return (((sources & InputDevice.SOURCE_CLASS_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK) ||
118  ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) ||
119  ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
120  );
121  }
122 
123 }
124 
125 /* A null joystick handler for API level < 12 devices (the accelerometer is handled separately) */
126 class SDLJoystickHandler {
127 
128  /**
129  * Handles given MotionEvent.
130  * @param event the event to be handled.
131  * @return if given event was processed.
132  */
133  public boolean handleMotionEvent(MotionEvent event) {
134  return false;
135  }
136 
137  /**
138  * Handles adding and removing of input devices.
139  */
140  public void pollInputDevices() {
141  }
142 }
143 
144 /* Actual joystick functionality available for API >= 12 devices */
145 class SDLJoystickHandler_API12 extends SDLJoystickHandler {
146 
147  static class SDLJoystick {
148  public int device_id;
149  public String name;
150  public String desc;
151  public ArrayList<InputDevice.MotionRange> axes;
152  public ArrayList<InputDevice.MotionRange> hats;
153  }
154  static class RangeComparator implements Comparator<InputDevice.MotionRange> {
155  @Override
156  public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {
157  // Some controllers, like the Moga Pro 2, return AXIS_GAS (22) for right trigger and AXIS_BRAKE (23) for left trigger - swap them so they're sorted in the right order for SDL
158  int arg0Axis = arg0.getAxis();
159  int arg1Axis = arg1.getAxis();
160  if (arg0Axis == MotionEvent.AXIS_GAS) {
161  arg0Axis = MotionEvent.AXIS_BRAKE;
162  } else if (arg0Axis == MotionEvent.AXIS_BRAKE) {
163  arg0Axis = MotionEvent.AXIS_GAS;
164  }
165  if (arg1Axis == MotionEvent.AXIS_GAS) {
166  arg1Axis = MotionEvent.AXIS_BRAKE;
167  } else if (arg1Axis == MotionEvent.AXIS_BRAKE) {
168  arg1Axis = MotionEvent.AXIS_GAS;
169  }
170 
171  return arg0Axis - arg1Axis;
172  }
173  }
174 
175  private ArrayList<SDLJoystick> mJoysticks;
176 
177  public SDLJoystickHandler_API12() {
178 
179  mJoysticks = new ArrayList<SDLJoystick>();
180  }
181 
182  @Override
183  public void pollInputDevices() {
184  int[] deviceIds = InputDevice.getDeviceIds();
185  for(int i=0; i < deviceIds.length; ++i) {
186  SDLJoystick joystick = getJoystick(deviceIds[i]);
187  if (joystick == null) {
188  joystick = new SDLJoystick();
189  InputDevice joystickDevice = InputDevice.getDevice(deviceIds[i]);
190  if (SDLControllerManager.isDeviceSDLJoystick(deviceIds[i])) {
191  joystick.device_id = deviceIds[i];
192  joystick.name = joystickDevice.getName();
193  joystick.desc = getJoystickDescriptor(joystickDevice);
194  joystick.axes = new ArrayList<InputDevice.MotionRange>();
195  joystick.hats = new ArrayList<InputDevice.MotionRange>();
196 
197  List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
198  Collections.sort(ranges, new RangeComparator());
199  for (InputDevice.MotionRange range : ranges ) {
200  if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
201  if (range.getAxis() == MotionEvent.AXIS_HAT_X ||
202  range.getAxis() == MotionEvent.AXIS_HAT_Y) {
203  joystick.hats.add(range);
204  }
205  else {
206  joystick.axes.add(range);
207  }
208  }
209  }
210 
211  mJoysticks.add(joystick);
212  SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc, getVendorId(joystickDevice), getProductId(joystickDevice), false, getButtonMask(joystickDevice), joystick.axes.size(), joystick.hats.size()/2, 0);
213  }
214  }
215  }
216 
217  /* Check removed devices */
218  ArrayList<Integer> removedDevices = new ArrayList<Integer>();
219  for(int i=0; i < mJoysticks.size(); i++) {
220  int device_id = mJoysticks.get(i).device_id;
221  int j;
222  for (j=0; j < deviceIds.length; j++) {
223  if (device_id == deviceIds[j]) break;
224  }
225  if (j == deviceIds.length) {
226  removedDevices.add(Integer.valueOf(device_id));
227  }
228  }
229 
230  for(int i=0; i < removedDevices.size(); i++) {
231  int device_id = removedDevices.get(i).intValue();
233  for (int j=0; j < mJoysticks.size(); j++) {
234  if (mJoysticks.get(j).device_id == device_id) {
235  mJoysticks.remove(j);
236  break;
237  }
238  }
239  }
240  }
241 
242  protected SDLJoystick getJoystick(int device_id) {
243  for(int i=0; i < mJoysticks.size(); i++) {
244  if (mJoysticks.get(i).device_id == device_id) {
245  return mJoysticks.get(i);
246  }
247  }
248  return null;
249  }
250 
251  @Override
252  public boolean handleMotionEvent(MotionEvent event) {
253  if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) {
254  int actionPointerIndex = event.getActionIndex();
255  int action = event.getActionMasked();
256  switch(action) {
257  case MotionEvent.ACTION_MOVE:
258  SDLJoystick joystick = getJoystick(event.getDeviceId());
259  if ( joystick != null ) {
260  for (int i = 0; i < joystick.axes.size(); i++) {
261  InputDevice.MotionRange range = joystick.axes.get(i);
262  /* Normalize the value to -1...1 */
263  float value = ( event.getAxisValue( range.getAxis(), actionPointerIndex) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
264  SDLControllerManager.onNativeJoy(joystick.device_id, i, value );
265  }
266  for (int i = 0; i < joystick.hats.size(); i+=2) {
267  int hatX = Math.round(event.getAxisValue( joystick.hats.get(i).getAxis(), actionPointerIndex ) );
268  int hatY = Math.round(event.getAxisValue( joystick.hats.get(i+1).getAxis(), actionPointerIndex ) );
269  SDLControllerManager.onNativeHat(joystick.device_id, i/2, hatX, hatY );
270  }
271  }
272  break;
273  default:
274  break;
275  }
276  }
277  return true;
278  }
279 
280  public String getJoystickDescriptor(InputDevice joystickDevice) {
281  return joystickDevice.getName();
282  }
283  public int getProductId(InputDevice joystickDevice) {
284  return 0;
285  }
286  public int getVendorId(InputDevice joystickDevice) {
287  return 0;
288  }
289  public int getButtonMask(InputDevice joystickDevice) {
290  return -1;
291  }
292 }
293 
294 class SDLJoystickHandler_API16 extends SDLJoystickHandler_API12 {
295 
296  @Override
297  public String getJoystickDescriptor(InputDevice joystickDevice) {
298  String desc = joystickDevice.getDescriptor();
299 
300  if (desc != null && !desc.isEmpty()) {
301  return desc;
302  }
303 
304  return super.getJoystickDescriptor(joystickDevice);
305  }
306 }
307 
308 class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {
309 
310  @Override
311  public int getProductId(InputDevice joystickDevice) {
312  return joystickDevice.getProductId();
313  }
314 
315  @Override
316  public int getVendorId(InputDevice joystickDevice) {
317  return joystickDevice.getVendorId();
318  }
319 
320  @Override
321  public int getButtonMask(InputDevice joystickDevice) {
322  int button_mask = 0;
323  int[] keys = new int[] {
324  KeyEvent.KEYCODE_BUTTON_A,
325  KeyEvent.KEYCODE_BUTTON_B,
326  KeyEvent.KEYCODE_BUTTON_X,
327  KeyEvent.KEYCODE_BUTTON_Y,
328  KeyEvent.KEYCODE_BACK,
329  KeyEvent.KEYCODE_BUTTON_MODE,
330  KeyEvent.KEYCODE_BUTTON_START,
331  KeyEvent.KEYCODE_BUTTON_THUMBL,
332  KeyEvent.KEYCODE_BUTTON_THUMBR,
333  KeyEvent.KEYCODE_BUTTON_L1,
334  KeyEvent.KEYCODE_BUTTON_R1,
335  KeyEvent.KEYCODE_DPAD_UP,
336  KeyEvent.KEYCODE_DPAD_DOWN,
337  KeyEvent.KEYCODE_DPAD_LEFT,
338  KeyEvent.KEYCODE_DPAD_RIGHT,
339  KeyEvent.KEYCODE_BUTTON_SELECT,
340  KeyEvent.KEYCODE_DPAD_CENTER,
341 
342  // These don't map into any SDL controller buttons directly
343  KeyEvent.KEYCODE_BUTTON_L2,
344  KeyEvent.KEYCODE_BUTTON_R2,
345  KeyEvent.KEYCODE_BUTTON_C,
346  KeyEvent.KEYCODE_BUTTON_Z,
347  KeyEvent.KEYCODE_BUTTON_1,
348  KeyEvent.KEYCODE_BUTTON_2,
349  KeyEvent.KEYCODE_BUTTON_3,
350  KeyEvent.KEYCODE_BUTTON_4,
351  KeyEvent.KEYCODE_BUTTON_5,
352  KeyEvent.KEYCODE_BUTTON_6,
353  KeyEvent.KEYCODE_BUTTON_7,
354  KeyEvent.KEYCODE_BUTTON_8,
355  KeyEvent.KEYCODE_BUTTON_9,
356  KeyEvent.KEYCODE_BUTTON_10,
357  KeyEvent.KEYCODE_BUTTON_11,
358  KeyEvent.KEYCODE_BUTTON_12,
359  KeyEvent.KEYCODE_BUTTON_13,
360  KeyEvent.KEYCODE_BUTTON_14,
361  KeyEvent.KEYCODE_BUTTON_15,
362  KeyEvent.KEYCODE_BUTTON_16,
363  };
364  int[] masks = new int[] {
365  (1 << 0), // A -> A
366  (1 << 1), // B -> B
367  (1 << 2), // X -> X
368  (1 << 3), // Y -> Y
369  (1 << 4), // BACK -> BACK
370  (1 << 5), // MODE -> GUIDE
371  (1 << 6), // START -> START
372  (1 << 7), // THUMBL -> LEFTSTICK
373  (1 << 8), // THUMBR -> RIGHTSTICK
374  (1 << 9), // L1 -> LEFTSHOULDER
375  (1 << 10), // R1 -> RIGHTSHOULDER
376  (1 << 11), // DPAD_UP -> DPAD_UP
377  (1 << 12), // DPAD_DOWN -> DPAD_DOWN
378  (1 << 13), // DPAD_LEFT -> DPAD_LEFT
379  (1 << 14), // DPAD_RIGHT -> DPAD_RIGHT
380  (1 << 4), // SELECT -> BACK
381  (1 << 0), // DPAD_CENTER -> A
382  (1 << 15), // L2 -> ??
383  (1 << 16), // R2 -> ??
384  (1 << 17), // C -> ??
385  (1 << 18), // Z -> ??
386  (1 << 20), // 1 -> ??
387  (1 << 21), // 2 -> ??
388  (1 << 22), // 3 -> ??
389  (1 << 23), // 4 -> ??
390  (1 << 24), // 5 -> ??
391  (1 << 25), // 6 -> ??
392  (1 << 26), // 7 -> ??
393  (1 << 27), // 8 -> ??
394  (1 << 28), // 9 -> ??
395  (1 << 29), // 10 -> ??
396  (1 << 30), // 11 -> ??
397  (1 << 31), // 12 -> ??
398  // We're out of room...
399  0xFFFFFFFF, // 13 -> ??
400  0xFFFFFFFF, // 14 -> ??
401  0xFFFFFFFF, // 15 -> ??
402  0xFFFFFFFF, // 16 -> ??
403  };
404  boolean[] has_keys = joystickDevice.hasKeys(keys);
405  for (int i = 0; i < keys.length; ++i) {
406  if (has_keys[i]) {
407  button_mask |= masks[i];
408  }
409  }
410  return button_mask;
411  }
412 }
413 
414 class SDLHapticHandler_API26 extends SDLHapticHandler {
415  @Override
416  public void run(int device_id, float intensity, int length) {
417  SDLHaptic haptic = getHaptic(device_id);
418  if (haptic != null) {
419  Log.d("SDL", "Rtest: Vibe with intensity " + intensity + " for " + length);
420  if (intensity == 0.0f) {
421  stop(device_id);
422  return;
423  }
424 
425  int vibeValue = Math.round(intensity * 255);
426 
427  if (vibeValue > 255) {
428  vibeValue = 255;
429  }
430  if (vibeValue < 1) {
431  stop(device_id);
432  return;
433  }
434  try {
435  haptic.vib.vibrate(VibrationEffect.createOneShot(length, vibeValue));
436  }
437  catch (Exception e) {
438  // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
439  // something went horribly wrong with the Android 8.0 APIs.
440  haptic.vib.vibrate(length);
441  }
442  }
443  }
444 }
445 
446 class SDLHapticHandler {
447 
448  class SDLHaptic {
449  public int device_id;
450  public String name;
451  public Vibrator vib;
452  }
453 
454  private ArrayList<SDLHaptic> mHaptics;
455 
456  public SDLHapticHandler() {
457  mHaptics = new ArrayList<SDLHaptic>();
458  }
459 
460  public void run(int device_id, float intensity, int length) {
461  SDLHaptic haptic = getHaptic(device_id);
462  if (haptic != null) {
463  haptic.vib.vibrate(length);
464  }
465  }
466 
467  public void stop(int device_id) {
468  SDLHaptic haptic = getHaptic(device_id);
469  if (haptic != null) {
470  haptic.vib.cancel();
471  }
472  }
473 
474  public void pollHapticDevices() {
475 
476  final int deviceId_VIBRATOR_SERVICE = 999999;
477  boolean hasVibratorService = false;
478 
479  int[] deviceIds = InputDevice.getDeviceIds();
480  // It helps processing the device ids in reverse order
481  // For example, in the case of the XBox 360 wireless dongle,
482  // so the first controller seen by SDL matches what the receiver
483  // considers to be the first controller
484 
485  if (Build.VERSION.SDK_INT >= 16)
486  {
487  for (int i = deviceIds.length - 1; i > -1; i--) {
488  SDLHaptic haptic = getHaptic(deviceIds[i]);
489  if (haptic == null) {
490  InputDevice device = InputDevice.getDevice(deviceIds[i]);
491  Vibrator vib = device.getVibrator();
492  if (vib.hasVibrator()) {
493  haptic = new SDLHaptic();
494  haptic.device_id = deviceIds[i];
495  haptic.name = device.getName();
496  haptic.vib = vib;
497  mHaptics.add(haptic);
498  SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
499  }
500  }
501  }
502  }
503 
504  /* Check VIBRATOR_SERVICE */
505  Vibrator vib = (Vibrator) SDL.getContext().getSystemService(Context.VIBRATOR_SERVICE);
506  if (vib != null) {
507  if (Build.VERSION.SDK_INT >= 11) {
508  hasVibratorService = vib.hasVibrator();
509  } else {
510  hasVibratorService = true;
511  }
512 
513  if (hasVibratorService) {
514  SDLHaptic haptic = getHaptic(deviceId_VIBRATOR_SERVICE);
515  if (haptic == null) {
516  haptic = new SDLHaptic();
517  haptic.device_id = deviceId_VIBRATOR_SERVICE;
518  haptic.name = "VIBRATOR_SERVICE";
519  haptic.vib = vib;
520  mHaptics.add(haptic);
521  SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
522  }
523  }
524  }
525 
526  /* Check removed devices */
527  ArrayList<Integer> removedDevices = new ArrayList<Integer>();
528  for(int i=0; i < mHaptics.size(); i++) {
529  int device_id = mHaptics.get(i).device_id;
530  int j;
531  for (j=0; j < deviceIds.length; j++) {
532  if (device_id == deviceIds[j]) break;
533  }
534 
535  if (device_id == deviceId_VIBRATOR_SERVICE && hasVibratorService) {
536  // don't remove the vibrator if it is still present
537  } else if (j == deviceIds.length) {
538  removedDevices.add(device_id);
539  }
540  }
541 
542  for(int i=0; i < removedDevices.size(); i++) {
543  int device_id = removedDevices.get(i);
545  for (int j=0; j < mHaptics.size(); j++) {
546  if (mHaptics.get(j).device_id == device_id) {
547  mHaptics.remove(j);
548  break;
549  }
550  }
551  }
552  }
553 
554  protected SDLHaptic getHaptic(int device_id) {
555  for(int i=0; i < mHaptics.size(); i++) {
556  if (mHaptics.get(i).device_id == device_id) {
557  return mHaptics.get(i);
558  }
559  }
560  return null;
561  }
562 }
563 
564 class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
565  // Generic Motion (mouse hover, joystick...) events go here
566  @Override
567  public boolean onGenericMotion(View v, MotionEvent event) {
568  float x, y;
569  int action;
570 
571  switch ( event.getSource() ) {
572  case InputDevice.SOURCE_JOYSTICK:
573  case InputDevice.SOURCE_GAMEPAD:
574  case InputDevice.SOURCE_DPAD:
576 
577  case InputDevice.SOURCE_MOUSE:
579  break;
580  }
581  action = event.getActionMasked();
582  switch (action) {
583  case MotionEvent.ACTION_SCROLL:
584  x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
585  y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
586  SDLActivity.onNativeMouse(0, action, x, y, false);
587  return true;
588 
589  case MotionEvent.ACTION_HOVER_MOVE:
590  x = event.getX(0);
591  y = event.getY(0);
592 
593  SDLActivity.onNativeMouse(0, action, x, y, false);
594  return true;
595 
596  default:
597  break;
598  }
599  break;
600 
601  default:
602  break;
603  }
604 
605  // Event was not managed
606  return false;
607  }
608 
609  public boolean supportsRelativeMouse() {
610  return false;
611  }
612 
613  public boolean inRelativeMode() {
614  return false;
615  }
616 
617  public boolean setRelativeMouseEnabled(boolean enabled) {
618  return false;
619  }
620 
621  public void reclaimRelativeMouseModeIfNeeded()
622  {
623 
624  }
625 
626  public float getEventX(MotionEvent event) {
627  return event.getX(0);
628  }
629 
630  public float getEventY(MotionEvent event) {
631  return event.getY(0);
632  }
633 
634 }
635 
636 class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 {
637  // Generic Motion (mouse hover, joystick...) events go here
638 
639  private boolean mRelativeModeEnabled;
640 
641  @Override
642  public boolean onGenericMotion(View v, MotionEvent event) {
643  float x, y;
644  int action;
645 
646  switch ( event.getSource() ) {
647  case InputDevice.SOURCE_JOYSTICK:
648  case InputDevice.SOURCE_GAMEPAD:
649  case InputDevice.SOURCE_DPAD:
651 
652  case InputDevice.SOURCE_MOUSE:
654  break;
655  }
656  action = event.getActionMasked();
657  switch (action) {
658  case MotionEvent.ACTION_SCROLL:
659  x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
660  y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
661  SDLActivity.onNativeMouse(0, action, x, y, false);
662  return true;
663 
664  case MotionEvent.ACTION_HOVER_MOVE:
665  if (mRelativeModeEnabled) {
666  x = event.getAxisValue(MotionEvent.AXIS_RELATIVE_X);
667  y = event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);
668  }
669  else {
670  x = event.getX(0);
671  y = event.getY(0);
672  }
673 
674  SDLActivity.onNativeMouse(0, action, x, y, mRelativeModeEnabled);
675  return true;
676 
677  default:
678  break;
679  }
680  break;
681 
682  default:
683  break;
684  }
685 
686  // Event was not managed
687  return false;
688  }
689 
690  @Override
691  public boolean supportsRelativeMouse() {
692  return true;
693  }
694 
695  @Override
696  public boolean inRelativeMode() {
697  return mRelativeModeEnabled;
698  }
699 
700  @Override
701  public boolean setRelativeMouseEnabled(boolean enabled) {
702  mRelativeModeEnabled = enabled;
703  return true;
704  }
705 
706  @Override
707  public float getEventX(MotionEvent event) {
708  if (mRelativeModeEnabled) {
709  return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X);
710  }
711  else {
712  return event.getX(0);
713  }
714  }
715 
716  @Override
717  public float getEventY(MotionEvent event) {
718  if (mRelativeModeEnabled) {
719  return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);
720  }
721  else {
722  return event.getY(0);
723  }
724  }
725 }
726 
727 
728 class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
729  // Generic Motion (mouse hover, joystick...) events go here
730  private boolean mRelativeModeEnabled;
731 
732  @Override
733  public boolean onGenericMotion(View v, MotionEvent event) {
734  float x, y;
735  int action;
736 
737  switch ( event.getSource() ) {
738  case InputDevice.SOURCE_JOYSTICK:
739  case InputDevice.SOURCE_GAMEPAD:
740  case InputDevice.SOURCE_DPAD:
742 
743  case InputDevice.SOURCE_MOUSE:
744  case 12290: // DeX desktop mouse cursor is a separate non-standard input type.
746  break;
747  }
748 
749  action = event.getActionMasked();
750  switch (action) {
751  case MotionEvent.ACTION_SCROLL:
752  x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
753  y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
754  SDLActivity.onNativeMouse(0, action, x, y, false);
755  return true;
756 
757  case MotionEvent.ACTION_HOVER_MOVE:
758  x = event.getX(0);
759  y = event.getY(0);
760  SDLActivity.onNativeMouse(0, action, x, y, false);
761  return true;
762 
763  default:
764  break;
765  }
766  break;
767 
768  case InputDevice.SOURCE_MOUSE_RELATIVE:
770  break;
771  }
772  action = event.getActionMasked();
773  switch (action) {
774  case MotionEvent.ACTION_SCROLL:
775  x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
776  y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
777  SDLActivity.onNativeMouse(0, action, x, y, false);
778  return true;
779 
780  case MotionEvent.ACTION_HOVER_MOVE:
781  x = event.getX(0);
782  y = event.getY(0);
783  SDLActivity.onNativeMouse(0, action, x, y, true);
784  return true;
785 
786  default:
787  break;
788  }
789  break;
790 
791  default:
792  break;
793  }
794 
795  // Event was not managed
796  return false;
797  }
798 
799  @Override
800  public boolean supportsRelativeMouse() {
801  return (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27));
802  }
803 
804  @Override
805  public boolean inRelativeMode() {
806  return mRelativeModeEnabled;
807  }
808 
809  @Override
810  public boolean setRelativeMouseEnabled(boolean enabled) {
811  if (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27)) {
812  if (enabled) {
813  SDLActivity.getContentView().requestPointerCapture();
814  }
815  else {
816  SDLActivity.getContentView().releasePointerCapture();
817  }
818  mRelativeModeEnabled = enabled;
819  return true;
820  }
821  else
822  {
823  return false;
824  }
825  }
826 
827  @Override
828  public void reclaimRelativeMouseModeIfNeeded()
829  {
830  if (mRelativeModeEnabled && !SDLActivity.isDeXMode()) {
831  SDLActivity.getContentView().requestPointerCapture();
832  }
833  }
834 
835  @Override
836  public float getEventX(MotionEvent event) {
837  // Relative mouse in capture mode will only have relative for X/Y
838  return event.getX(0);
839  }
840 
841  @Override
842  public float getEventY(MotionEvent event) {
843  // Relative mouse in capture mode will only have relative for X/Y
844  return event.getY(0);
845  }
846 }
static boolean isDeXMode()
static boolean isDeviceSDLJoystick(int deviceId)
static native int nativeAddJoystick(int device_id, String name, String desc, int vendor_id, int product_id, boolean is_accelerometer, int button_mask, int naxes, int nhats, int nballs)
static void hapticRun(int device_id, float intensity, int length)
static native void onNativeMouse(int button, int action, float x, float y, boolean relative)
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 Uint32 * e
GLsizei GLenum * sources
static native int nativeRemoveHaptic(int device_id)
const GLdouble * v
Definition: SDL_opengl.h:2064
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLuint GLuint GLuint GLuint arg1
GLfloat f
static native int onNativePadUp(int device_id, int keycode)
static native int onNativePadDown(int device_id, int keycode)
SDL_Texture * axis
static boolean handleJoystickMotionEvent(MotionEvent event)
GLuint const GLchar * name
static native int nativeSetupJNI()
static native void onNativeJoy(int device_id, int axis, float value)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
struct _cl_event * event
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:50
static boolean mSeparateMouseAndTouch
GLenum GLint * range
GLsizei const GLfloat * value
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
static native int nativeRemoveJoystick(int device_id)
GLenum GLenum GLsizei const GLuint GLboolean enabled
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
static SDLJoystickHandler mJoystickHandler
static native void onNativeHat(int device_id, int hat_id, int x, int y)
static SDL_Haptic * haptic
Definition: testhaptic.c:25
static Context getContext()
Definition: SDL.java:34
static native int nativeAddHaptic(int device_id, String name)
GLuint GLsizei GLsizei * length