Panda3D
androidGraphicsWindow.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file androidGraphicsWindow.cxx
10  * @author rdb
11  * @date 2013-01-11
12  */
13 
14 #include "androidGraphicsWindow.h"
16 #include "config_androiddisplay.h"
17 #include "androidGraphicsPipe.h"
18 
19 #include "graphicsPipe.h"
20 #include "keyboardButton.h"
21 #include "mouseButton.h"
22 #include "clockObject.h"
23 #include "pStatTimer.h"
24 #include "textEncoder.h"
25 #include "throw_event.h"
26 #include "nativeWindowHandle.h"
27 
28 #include "android_native_app_glue.h"
29 #include <android/window.h>
30 #include <android/log.h>
31 
32 extern IMPORT_CLASS struct android_app* panda_android_app;
33 
34 TypeHandle AndroidGraphicsWindow::_type_handle;
35 
36 /**
37  *
38  */
39 AndroidGraphicsWindow::
40 AndroidGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
41  const std::string &name,
42  const FrameBufferProperties &fb_prop,
43  const WindowProperties &win_prop,
44  int flags,
46  GraphicsOutput *host) :
47  GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host),
48  _mouse_button_state(0)
49 {
50  AndroidGraphicsPipe *android_pipe;
51  DCAST_INTO_V(android_pipe, _pipe);
52 
53  _egl_display = android_pipe->_egl_display;
54  _egl_surface = 0;
55 
56  _app = panda_android_app;
57 
58  PT(GraphicsWindowInputDevice) device = GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
59  add_input_device(device);
60  _input = device;
61 }
62 
63 /**
64  *
65  */
66 AndroidGraphicsWindow::
67 ~AndroidGraphicsWindow() {
68  destroy_surface();
69 }
70 
71 /**
72  * This function will be called within the draw thread before beginning
73  * rendering for a given frame. It should do whatever setup is required, and
74  * return true if the frame should be rendered, or false if it should be
75  * skipped.
76  */
78 begin_frame(FrameMode mode, Thread *current_thread) {
79  PStatTimer timer(_make_current_pcollector, current_thread);
80 
81  begin_frame_spam(mode);
82  if (_gsg == nullptr) {
83  return false;
84  }
85 
86  // XXX not open yet.
87  if (_egl_surface == EGL_NO_SURFACE) {
88  return false;
89  }
90 
91  AndroidGraphicsStateGuardian *androidgsg;
92  DCAST_INTO_R(androidgsg, _gsg, false);
93  {
94  if (eglGetCurrentDisplay() == _egl_display &&
95  eglGetCurrentSurface(EGL_READ) == _egl_surface &&
96  eglGetCurrentSurface(EGL_DRAW) == _egl_surface &&
97  eglGetCurrentContext() == androidgsg->_context) {
98  // No need to make the context current again. Short-circuit this
99  // possibly-expensive call.
100  } else {
101  // Need to set the context.
102  if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, androidgsg->_context)) {
103  androiddisplay_cat.error() << "Failed to call eglMakeCurrent: "
104  << get_egl_error_string(eglGetError()) << "\n";
105  }
106  }
107  }
108 
109  // Now that we have made the context current to a window, we can reset the
110  // GSG state if this is the first time it has been used. (We can't just
111  // call reset() when we construct the GSG, because reset() requires having a
112  // current context.)
113  androidgsg->reset_if_new();
114 
115  if (mode == FM_render) {
116  // begin_render_texture();
117  clear_cube_map_selection();
118  }
119 
120  _gsg->set_current_properties(&get_fb_properties());
121  return _gsg->begin_frame(current_thread);
122 }
123 
124 /**
125  * This function will be called within the draw thread after rendering is
126  * completed for a given frame. It should do whatever finalization is
127  * required.
128  */
130 end_frame(FrameMode mode, Thread *current_thread) {
131  end_frame_spam(mode);
132  nassertv(_gsg != nullptr);
133 
134  if (mode == FM_render) {
135  // end_render_texture();
136  copy_to_textures();
137  }
138 
139  _gsg->end_frame(current_thread);
140 
141  if (mode == FM_render) {
142  trigger_flip();
143  clear_cube_map_selection();
144  }
145 }
146 
147 /**
148  * This function will be called within the draw thread after begin_flip() has
149  * been called on all windows, to finish the exchange of the front and back
150  * buffers.
151  *
152  * This should cause the window to wait for the flip, if necessary.
153  */
156  if (_gsg != nullptr && _flip_ready) {
157 
158  // It doesn't appear to be necessary to ensure the graphics context is
159  // current before flipping the windows, and insisting on doing so can be a
160  // significant performance hit.
161 
162  // make_current();
163 
164  if (_egl_surface != EGL_NO_SURFACE) {
165  eglSwapBuffers(_egl_display, _egl_surface);
166  }
167  }
169 }
170 
171 /**
172  * Do whatever processing is necessary to ensure that the window responds to
173  * user events. Also, honor any requests recently made via
174  * request_properties()
175  *
176  * This function is called only within the window thread.
177  */
181 
182  // Read all pending events.
183  int looper_id;
184  int events;
185  struct android_poll_source* source;
186 
187  // Loop until all events are read.
188  while ((looper_id = ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
189  // Process this event.
190  if (source != nullptr) {
191  source->process(_app, source);
192  }
193  }
194 }
195 
196 /**
197  * Applies the requested set of properties to the window, if possible, for
198  * instance to request a change in size or minimization status.
199  *
200  * The window properties are applied immediately, rather than waiting until
201  * the next frame. This implies that this method may *only* be called from
202  * within the window thread.
203  *
204  * The return value is true if the properties are set, false if they are
205  * ignored. This is mainly useful for derived classes to implement extensions
206  * to this function.
207  */
210  if (_pipe == nullptr) {
211  // If the pipe is null, we're probably closing down.
213  return;
214  }
215 
217  if (!properties.is_any_specified()) {
218  // The base class has already handled this case.
219  return;
220  }
221 
222  // There's not really much we can change on Android.
223  if (properties.has_fullscreen()) {
224  uint32_t add_flags = 0;
225  uint32_t del_flags = 0;
226  if (_properties.get_fullscreen()) {
227  add_flags |= AWINDOW_FLAG_FULLSCREEN;
228  } else {
229  del_flags |= AWINDOW_FLAG_FULLSCREEN;
230  }
231  ANativeActivity_setWindowFlags(_app->activity, add_flags, del_flags);
232 
233  _properties.set_fullscreen(properties.get_fullscreen());
234  properties.clear_fullscreen();
235  }
236 }
237 
238 /**
239  * Closes the window right now. Called from the window thread.
240  */
241 void AndroidGraphicsWindow::
242 close_window() {
243  destroy_surface();
244 
245  if (_gsg != nullptr) {
246  _gsg.clear();
247  }
248 
249  GraphicsWindow::close_window();
250 
251  nassertv(_app != nullptr);
252  if (_app->userData == this) {
253  _app->userData = nullptr;
254  _app->onAppCmd = nullptr;
255  _app->onInputEvent = nullptr;
256  }
257 }
258 
259 /**
260  * Opens the window right now. Called from the window thread. Returns true
261  * if the window is successfully opened, or false if there was a problem.
262  */
263 bool AndroidGraphicsWindow::
264 open_window() {
265  // GSG CreationInitialization
266  AndroidGraphicsStateGuardian *androidgsg;
267  if (_gsg == 0) {
268  // There is no old gsg. Create a new one.
269  androidgsg = new AndroidGraphicsStateGuardian(_engine, _pipe, nullptr);
270  androidgsg->choose_pixel_format(_fb_properties, false, false);
271  _gsg = androidgsg;
272  } else {
273  // If the old gsg has the wrong pixel format, create a new one that shares
274  // with the old gsg.
275  DCAST_INTO_R(androidgsg, _gsg, false);
276  if (!androidgsg->get_fb_properties().subsumes(_fb_properties)) {
277  androidgsg = new AndroidGraphicsStateGuardian(_engine, _pipe, androidgsg);
278  androidgsg->choose_pixel_format(_fb_properties, false, false);
279  _gsg = androidgsg;
280  }
281  }
282 
283  // Register the callbacks
284  assert(_app != nullptr);
285  _app->userData = this;
286  _app->onAppCmd = handle_command;
287  _app->onInputEvent = handle_input_event;
288 
289  // Wait until Android has opened the window.
290  while (_app->window == nullptr) {
291  process_events();
292  }
293 
294  // create_surface should have been called by now.
295  if (_egl_surface == EGL_NO_SURFACE) {
296  return false;
297  }
298 
299  // Set some other properties.
300  _properties.set_origin(0, 0);
301  _properties.set_cursor_hidden(true);
302  _properties.set_undecorated(true);
303 
305  (_fb_properties, androidgsg->get_gl_renderer())) {
306  close_window();
307  return false;
308  }
309 
310  _fb_properties = androidgsg->get_fb_properties();
311 
312  return true;
313 }
314 
315 /**
316  * Terminates the EGL surface.
317  */
318 void AndroidGraphicsWindow::
319 destroy_surface() {
320  if (_egl_surface != EGL_NO_SURFACE) {
321  if (!eglDestroySurface(_egl_display, _egl_surface)) {
322  androiddisplay_cat.error() << "Failed to destroy surface: "
323  << get_egl_error_string(eglGetError()) << "\n";
324  }
325  _egl_surface = EGL_NO_SURFACE;
326  }
327 
328  // Destroy the current context.
329  if (_gsg != nullptr) {
330  AndroidGraphicsStateGuardian *androidgsg;
331  DCAST_INTO_V(androidgsg, _gsg);
332  androidgsg->destroy_context();
333  }
334 }
335 
336 /**
337  * Creates the EGL surface.
338  */
339 bool AndroidGraphicsWindow::
340 create_surface() {
341  AndroidGraphicsStateGuardian *androidgsg;
342  DCAST_INTO_R(androidgsg, _gsg, false);
343 
344  // Reconfigure the window buffers to match that of our framebuffer config.
345  ANativeWindow_setBuffersGeometry(_app->window, 0, 0, androidgsg->_format);
346 
347  // Set any window flags
348  uint32_t add_flags = 0;
349  uint32_t del_flags = 0;
350  if (_properties.get_fullscreen()) {
351  add_flags |= AWINDOW_FLAG_FULLSCREEN;
352  } else {
353  del_flags |= AWINDOW_FLAG_FULLSCREEN;
354  }
355  ANativeActivity_setWindowFlags(_app->activity, add_flags, del_flags);
356 
357  // Create the EGL surface.
358  _egl_surface = eglCreateWindowSurface(_egl_display, androidgsg->_fbconfig, _app->window, nullptr);
359  if (eglGetError() != EGL_SUCCESS) {
360  androiddisplay_cat.error()
361  << "Failed to create window surface.\n";
362  return false;
363  }
364 
365  // Create a context.
366  if (androidgsg->_context == EGL_NO_CONTEXT) {
367  if (!androidgsg->create_context()) {
368  return false;
369  }
370  }
371 
372  // Switch to our newly created context.
373  if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, androidgsg->_context)) {
374  androiddisplay_cat.error() << "Failed to call eglMakeCurrent: "
375  << get_egl_error_string(eglGetError()) << "\n";
376  }
377 
378  // Query the size of the surface. EGLint width, height;
379  // eglQuerySurface(_egl_display, _egl_surface, EGL_WIDTH, &width);
380  // eglQuerySurface(_egl_display, _egl_surface, EGL_HEIGHT, &height);
381 
382  androidgsg->reset_if_new();
383  if (!androidgsg->is_valid()) {
384  close_window();
385  return false;
386  }
387 
388  return true;
389 }
390 
391 /**
392  * Android app sends a command from the main thread.
393  */
394 void AndroidGraphicsWindow::
395 handle_command(struct android_app *app, int32_t command) {
396  AndroidGraphicsWindow *window = (AndroidGraphicsWindow *)app->userData;
397  if (window != nullptr) {
398  window->ns_handle_command(command);
399  }
400 }
401 
402 /**
403  * Android app sends a command from the main thread.
404  */
405 void AndroidGraphicsWindow::
406 ns_handle_command(int32_t command) {
407  WindowProperties properties;
408 
409  switch (command) {
410  case APP_CMD_SAVE_STATE:
411  // The system has asked us to save our current state. Do so.
412  // engine->app->savedState = malloc(sizeof(struct saved_state));
413  // *((struct saved_state*)engine->app->savedState) = engine->state;
414  // engine->app->savedStateSize = sizeof(struct saved_state);
415  break;
416  case APP_CMD_INIT_WINDOW:
417  // The window is being shown, get it ready.
418  if (_app->window != nullptr) {
419  create_surface();
420  properties.set_size(ANativeWindow_getWidth(_app->window),
421  ANativeWindow_getHeight(_app->window));
422  properties.set_minimized(false);
423  system_changed_properties(properties);
424  }
425  break;
426  case APP_CMD_CONFIG_CHANGED:
427  properties.set_size(ANativeWindow_getWidth(_app->window),
428  ANativeWindow_getHeight(_app->window));
429  system_changed_properties(properties);
430  break;
431  case APP_CMD_TERM_WINDOW:
432  destroy_surface();
433  properties.set_minimized(true);
434  system_changed_properties(properties);
435  break;
436  case APP_CMD_WINDOW_RESIZED:
437  properties.set_size(ANativeWindow_getWidth(_app->window),
438  ANativeWindow_getHeight(_app->window));
439  break;
440  case APP_CMD_WINDOW_REDRAW_NEEDED:
441  break;
442  case APP_CMD_CONTENT_RECT_CHANGED:
443  properties.set_origin(_app->contentRect.left, _app->contentRect.top);
444  properties.set_size(_app->contentRect.right - _app->contentRect.left,
445  _app->contentRect.bottom - _app->contentRect.top);
446  system_changed_properties(properties);
447  break;
448  case APP_CMD_GAINED_FOCUS:
449  properties.set_foreground(true);
450  system_changed_properties(properties);
451  break;
452  case APP_CMD_LOST_FOCUS:
453  properties.set_foreground(false);
454  system_changed_properties(properties);
455  break;
456  case APP_CMD_DESTROY:
457  close_window();
458  properties.set_open(false);
459  system_changed_properties(properties);
460  break;
461  }
462 }
463 
464 /**
465  * Processes an input event. Returns 1 if the event was handled, 0 otherwise.
466  */
467 int32_t AndroidGraphicsWindow::
468 handle_input_event(struct android_app* app, AInputEvent *event) {
469  AndroidGraphicsWindow* window = (AndroidGraphicsWindow*) app->userData;
470 
471  int32_t event_type = AInputEvent_getType(event);
472  switch (event_type) {
473  case AINPUT_EVENT_TYPE_KEY:
474  return window->handle_key_event(event);
475  case AINPUT_EVENT_TYPE_MOTION:
476  return window->handle_motion_event(event);
477  }
478  return 0;
479 }
480 
481 /**
482  * Processes a key event.
483  */
484 int32_t AndroidGraphicsWindow::
485 handle_key_event(const AInputEvent *event) {
486  /*
487  int32_t meta = AKeyEvent_getMetaState(event);
488  if (meta | AMETA_ALT_ON) {
489  _input->button_down(KeyboardButton.alt());
490  }
491  if (meta | AMETA_ALT_LEFT_ON) {
492  _input->button_down(KeyboardButton.lalt());
493  }
494  if (meta | AMETA_ALT_RIGHT_ON) {
495  _input->button_down(KeyboardButton.ralt());
496  }
497  if (meta | AMETA_SHIFT_ON) {
498  _input->button_down(KeyboardButton.shift());
499  }
500  if (meta | AMETA_SHIFT_LEFT_ON) {
501  _input->button_down(KeyboardButton.lshift());
502  }
503  if (meta | AMETA_SHIFT_RIGHT_ON) {
504  _input->button_down(KeyboardButton.rshift());
505  }*/
506 
507  int32_t keycode = AKeyEvent_getKeyCode(event);
508  ButtonHandle button = map_button(keycode);
509 
510  if (button == ButtonHandle::none()) {
511  androiddisplay_cat.warning()
512  << "Unknown keycode: " << keycode << "\n";
513  return 0;
514  }
515 
516  // Is it an up or down event?
517  int32_t action = AKeyEvent_getAction(event);
518  if (action == AKEY_EVENT_ACTION_DOWN) {
519  if (AKeyEvent_getRepeatCount(event) > 0) {
520  _input->button_resume_down(button);
521  } else {
522  _input->button_down(button);
523  }
524  } else if (action == AKEY_EVENT_ACTION_UP) {
525  _input->button_up(button);
526  }
527  // TODO AKEY_EVENT_ACTION_MULTIPLE
528 
529  return 1;
530 }
531 
532 /**
533  * Processes a motion event.
534  */
535 int32_t AndroidGraphicsWindow::
536 handle_motion_event(const AInputEvent *event) {
537  int32_t action = AMotionEvent_getAction(event);
538  action &= AMOTION_EVENT_ACTION_MASK;
539 
540  if (action == AMOTION_EVENT_ACTION_DOWN ||
541  action == AMOTION_EVENT_ACTION_UP) {
542  // The up event doesn't let us know which button is up, so we need to
543  // keep track of the button state ourselves.
544  int32_t button_state = AMotionEvent_getButtonState(event);
545  if (button_state == 0 && action == AMOTION_EVENT_ACTION_DOWN) {
546  button_state = AMOTION_EVENT_BUTTON_PRIMARY;
547  }
548  int32_t changed = _mouse_button_state ^ button_state;
549  if (changed != 0) {
550  if (changed & AMOTION_EVENT_BUTTON_PRIMARY) {
551  if (button_state & AMOTION_EVENT_BUTTON_PRIMARY) {
552  _input->button_down(MouseButton::one());
553  } else {
554  _input->button_up(MouseButton::one());
555  }
556  }
557  if (changed & AMOTION_EVENT_BUTTON_SECONDARY) {
558  if (button_state & AMOTION_EVENT_BUTTON_SECONDARY) {
559  _input->button_down(MouseButton::three());
560  } else {
561  _input->button_up(MouseButton::three());
562  }
563  }
564  _mouse_button_state = button_state;
565  }
566  }
567 
568  float x = AMotionEvent_getX(event, 0) - _app->contentRect.left;
569  float y = AMotionEvent_getY(event, 0) - _app->contentRect.top;
570 
571  _input->set_pointer_in_window(x, y);
572 
573  return 1;
574 }
575 
576 /**
577  * Given an Android keycode, returns an appropriate ButtonHandle object, or
578  * ButtonHandle::none() if a matching ButtonHandle does not exist.
579  */
580 ButtonHandle AndroidGraphicsWindow::
581 map_button(int32_t keycode) {
582  switch (keycode) {
583  case AKEYCODE_SOFT_LEFT:
584  case AKEYCODE_SOFT_RIGHT:
585  case AKEYCODE_HOME:
586  case AKEYCODE_BACK:
587  case AKEYCODE_CALL:
588  case AKEYCODE_ENDCALL:
589  break;
590  case AKEYCODE_0:
591  return KeyboardButton::ascii_key('0');
592  case AKEYCODE_1:
593  return KeyboardButton::ascii_key('1');
594  case AKEYCODE_2:
595  return KeyboardButton::ascii_key('2');
596  case AKEYCODE_3:
597  return KeyboardButton::ascii_key('3');
598  case AKEYCODE_4:
599  return KeyboardButton::ascii_key('4');
600  case AKEYCODE_5:
601  return KeyboardButton::ascii_key('5');
602  case AKEYCODE_6:
603  return KeyboardButton::ascii_key('6');
604  case AKEYCODE_7:
605  return KeyboardButton::ascii_key('7');
606  case AKEYCODE_8:
607  return KeyboardButton::ascii_key('8');
608  case AKEYCODE_9:
609  return KeyboardButton::ascii_key('9');
610  case AKEYCODE_STAR:
611  return KeyboardButton::ascii_key('*');
612  case AKEYCODE_POUND:
613  return KeyboardButton::ascii_key('#');
614  case AKEYCODE_DPAD_UP:
615  return KeyboardButton::up();
616  case AKEYCODE_DPAD_DOWN:
617  return KeyboardButton::down();
618  case AKEYCODE_DPAD_LEFT:
619  return KeyboardButton::left();
620  case AKEYCODE_DPAD_RIGHT:
621  return KeyboardButton::right();
622  case AKEYCODE_DPAD_CENTER:
623  case AKEYCODE_VOLUME_UP:
624  case AKEYCODE_VOLUME_DOWN:
625  case AKEYCODE_POWER:
626  case AKEYCODE_CAMERA:
627  case AKEYCODE_CLEAR:
628  break;
629  case AKEYCODE_A:
630  return KeyboardButton::ascii_key('a');
631  case AKEYCODE_B:
632  return KeyboardButton::ascii_key('b');
633  case AKEYCODE_C:
634  return KeyboardButton::ascii_key('c');
635  case AKEYCODE_D:
636  return KeyboardButton::ascii_key('d');
637  case AKEYCODE_E:
638  return KeyboardButton::ascii_key('e');
639  case AKEYCODE_F:
640  return KeyboardButton::ascii_key('f');
641  case AKEYCODE_G:
642  return KeyboardButton::ascii_key('g');
643  case AKEYCODE_H:
644  return KeyboardButton::ascii_key('h');
645  case AKEYCODE_I:
646  return KeyboardButton::ascii_key('i');
647  case AKEYCODE_J:
648  return KeyboardButton::ascii_key('j');
649  case AKEYCODE_K:
650  return KeyboardButton::ascii_key('k');
651  case AKEYCODE_L:
652  return KeyboardButton::ascii_key('l');
653  case AKEYCODE_M:
654  return KeyboardButton::ascii_key('m');
655  case AKEYCODE_N:
656  return KeyboardButton::ascii_key('n');
657  case AKEYCODE_O:
658  return KeyboardButton::ascii_key('o');
659  case AKEYCODE_P:
660  return KeyboardButton::ascii_key('p');
661  case AKEYCODE_Q:
662  return KeyboardButton::ascii_key('q');
663  case AKEYCODE_R:
664  return KeyboardButton::ascii_key('r');
665  case AKEYCODE_S:
666  return KeyboardButton::ascii_key('s');
667  case AKEYCODE_T:
668  return KeyboardButton::ascii_key('t');
669  case AKEYCODE_U:
670  return KeyboardButton::ascii_key('u');
671  case AKEYCODE_V:
672  return KeyboardButton::ascii_key('v');
673  case AKEYCODE_W:
674  return KeyboardButton::ascii_key('w');
675  case AKEYCODE_X:
676  return KeyboardButton::ascii_key('x');
677  case AKEYCODE_Y:
678  return KeyboardButton::ascii_key('y');
679  case AKEYCODE_Z:
680  return KeyboardButton::ascii_key('z');
681  case AKEYCODE_COMMA:
682  return KeyboardButton::ascii_key(',');
683  case AKEYCODE_PERIOD:
684  return KeyboardButton::ascii_key('.');
685  case AKEYCODE_ALT_LEFT:
686  return KeyboardButton::lalt();
687  case AKEYCODE_ALT_RIGHT:
688  return KeyboardButton::ralt();
689  case AKEYCODE_SHIFT_LEFT:
690  return KeyboardButton::lshift();
691  case AKEYCODE_SHIFT_RIGHT:
692  return KeyboardButton::rshift();
693  case AKEYCODE_TAB:
694  return KeyboardButton::tab();
695  case AKEYCODE_SPACE:
696  return KeyboardButton::space();
697  case AKEYCODE_SYM:
698  case AKEYCODE_EXPLORER:
699  case AKEYCODE_ENVELOPE:
700  break;
701  case AKEYCODE_ENTER:
702  return KeyboardButton::enter();
703  case AKEYCODE_DEL:
704  return KeyboardButton::backspace();
705  case AKEYCODE_GRAVE:
706  return KeyboardButton::ascii_key('`');
707  case AKEYCODE_MINUS:
708  return KeyboardButton::ascii_key('-');
709  case AKEYCODE_EQUALS:
710  return KeyboardButton::ascii_key('=');
711  case AKEYCODE_LEFT_BRACKET:
712  return KeyboardButton::ascii_key('[');
713  case AKEYCODE_RIGHT_BRACKET:
714  return KeyboardButton::ascii_key(']');
715  case AKEYCODE_BACKSLASH:
716  return KeyboardButton::ascii_key('\\');
717  case AKEYCODE_SEMICOLON:
718  return KeyboardButton::ascii_key(';');
719  case AKEYCODE_APOSTROPHE:
720  return KeyboardButton::ascii_key('\'');
721  case AKEYCODE_SLASH:
722  return KeyboardButton::ascii_key('/');
723  case AKEYCODE_AT:
724  return KeyboardButton::ascii_key('@');
725  case AKEYCODE_NUM:
726  case AKEYCODE_HEADSETHOOK:
727  case AKEYCODE_FOCUS:
728  break;
729  case AKEYCODE_PLUS:
730  return KeyboardButton::ascii_key('+');
731  case AKEYCODE_MENU:
732  return KeyboardButton::menu();
733  case AKEYCODE_NOTIFICATION:
734  case AKEYCODE_SEARCH:
735  case AKEYCODE_MEDIA_PLAY_PAUSE:
736  case AKEYCODE_MEDIA_STOP:
737  case AKEYCODE_MEDIA_NEXT:
738  case AKEYCODE_MEDIA_PREVIOUS:
739  case AKEYCODE_MEDIA_REWIND:
740  case AKEYCODE_MEDIA_FAST_FORWARD:
741  case AKEYCODE_MUTE:
742  break;
743  case AKEYCODE_PAGE_UP:
744  return KeyboardButton::page_up();
745  case AKEYCODE_PAGE_DOWN:
746  return KeyboardButton::page_down();
747  case AKEYCODE_PICTSYMBOLS:
748  case AKEYCODE_SWITCH_CHARSET:
749  case AKEYCODE_BUTTON_A:
750  case AKEYCODE_BUTTON_B:
751  case AKEYCODE_BUTTON_C:
752  case AKEYCODE_BUTTON_X:
753  case AKEYCODE_BUTTON_Y:
754  case AKEYCODE_BUTTON_Z:
755  case AKEYCODE_BUTTON_L1:
756  case AKEYCODE_BUTTON_R1:
757  case AKEYCODE_BUTTON_L2:
758  case AKEYCODE_BUTTON_R2:
759  case AKEYCODE_BUTTON_THUMBL:
760  case AKEYCODE_BUTTON_THUMBR:
761  case AKEYCODE_BUTTON_START:
762  case AKEYCODE_BUTTON_SELECT:
763  case AKEYCODE_BUTTON_MODE:
764  break;
765  case AKEYCODE_ESCAPE:
766  return KeyboardButton::escape();
767  case AKEYCODE_FORWARD_DEL:
768  return KeyboardButton::del();
769  case AKEYCODE_CTRL_LEFT:
770  return KeyboardButton::lcontrol();
771  case AKEYCODE_CTRL_RIGHT:
772  return KeyboardButton::rcontrol();
773  case AKEYCODE_CAPS_LOCK:
774  return KeyboardButton::caps_lock();
775  case AKEYCODE_SCROLL_LOCK:
776  return KeyboardButton::scroll_lock();
777  case AKEYCODE_META_LEFT:
778  return KeyboardButton::lmeta();
779  case AKEYCODE_META_RIGHT:
780  return KeyboardButton::rmeta();
781  case AKEYCODE_FUNCTION:
782  break;
783  case AKEYCODE_SYSRQ:
784  return KeyboardButton::print_screen();
785  case AKEYCODE_BREAK:
786  return KeyboardButton::pause();
787  case AKEYCODE_MOVE_HOME:
788  return KeyboardButton::home();
789  case AKEYCODE_MOVE_END:
790  return KeyboardButton::end();
791  case AKEYCODE_INSERT:
792  return KeyboardButton::insert();
793  case AKEYCODE_F1:
794  return KeyboardButton::f1();
795  case AKEYCODE_F2:
796  return KeyboardButton::f2();
797  case AKEYCODE_F3:
798  return KeyboardButton::f3();
799  case AKEYCODE_F4:
800  return KeyboardButton::f4();
801  case AKEYCODE_F5:
802  return KeyboardButton::f5();
803  case AKEYCODE_F6:
804  return KeyboardButton::f6();
805  case AKEYCODE_F7:
806  return KeyboardButton::f7();
807  case AKEYCODE_F8:
808  return KeyboardButton::f8();
809  case AKEYCODE_F9:
810  return KeyboardButton::f9();
811  case AKEYCODE_F10:
812  return KeyboardButton::f10();
813  case AKEYCODE_F11:
814  return KeyboardButton::f11();
815  case AKEYCODE_F12:
816  return KeyboardButton::f12();
817  case AKEYCODE_NUM_LOCK:
818  return KeyboardButton::num_lock();
819  default:
820  break;
821  }
822  return ButtonHandle::none();
823 }
MouseButton::one
static ButtonHandle one()
Returns the ButtonHandle associated with the first mouse button.
Definition: mouseButton.cxx:43
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
GraphicsWindow::set_properties_now
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
Definition: graphicsWindow.cxx:495
AndroidGraphicsPipe
This graphics pipe represents the interface for creating OpenGL ES graphics windows on an X-based (e....
Definition: androidGraphicsPipe.h:40
throw_event.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsWindowInputDevice::button_resume_down
void button_resume_down(ButtonHandle button, double time=ClockObject::get_global_clock() ->get_frame_time())
Records that the indicated button was depressed earlier, and we only just detected the event after th...
Definition: graphicsWindowInputDevice.cxx:87
GraphicsWindowInputDevice
This is a virtual input device that represents the keyboard and mouse pair that is associated with a ...
Definition: graphicsWindowInputDevice.h:28
AndroidGraphicsStateGuardian
A tiny specialization on GLESGraphicsStateGuardian to add some egl-specific information.
Definition: androidGraphicsStateGuardian.h:27
WindowProperties::clear_fullscreen
clear_fullscreen
Removes the fullscreen specification from the properties.
Definition: windowProperties.h:119
AndroidGraphicsStateGuardian::get_fb_properties
const FrameBufferProperties & get_fb_properties() const
Gets the FrameBufferProperties for all windows and buffers that use this GSG.
Definition: androidGraphicsStateGuardian.I:19
WindowProperties::set_origin
set_origin
Specifies the origin on the screen (in pixels, relative to the top-left corner) at which the window s...
Definition: windowProperties.h:76
config_androiddisplay.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
mouseButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsWindowInputDevice::button_down
void button_down(ButtonHandle button, double time=ClockObject::get_global_clock() ->get_frame_time())
Records that the indicated button has been depressed.
Definition: graphicsWindowInputDevice.cxx:75
GraphicsWindowInputDevice::button_up
void button_up(ButtonHandle button, double time=ClockObject::get_global_clock() ->get_frame_time())
Records that the indicated button has been released.
Definition: graphicsWindowInputDevice.cxx:97
clockObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ButtonHandle
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
Definition: buttonHandle.h:26
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowProperties::set_open
set_open
Specifies whether the window should be open.
Definition: windowProperties.h:144
WindowProperties
A container for the various kinds of properties we might ask to have on a graphics window before we o...
Definition: windowProperties.h:29
AndroidGraphicsWindow::end_frame
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame.
Definition: androidGraphicsWindow.cxx:130
keyboardButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowProperties::set_foreground
set_foreground
Specifies whether the window should be opened in the foreground (true), or left in the background (fa...
Definition: windowProperties.h:126
FrameBufferProperties::subsumes
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
Definition: frameBufferProperties.cxx:25
KeyboardButton::ascii_key
static ButtonHandle ascii_key(char ascii_equivalent)
Returns the ButtonHandle associated with the particular ASCII character, if there is one,...
Definition: keyboardButton.cxx:24
graphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FrameBufferProperties::verify_hardware_software
bool verify_hardware_software(const FrameBufferProperties &props, const std::string &renderer) const
Validates that the properties represent the desired kind of renderer (hardware or software).
Definition: frameBufferProperties.cxx:604
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
PStatTimer
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
AndroidGraphicsWindow::end_flip
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
Definition: androidGraphicsWindow.cxx:155
AndroidGraphicsWindow::begin_frame
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame.
Definition: androidGraphicsWindow.cxx:78
WindowProperties::set_size
set_size
Specifies the requested size of the window, in pixels.
Definition: windowProperties.h:85
AndroidGraphicsStateGuardian::choose_pixel_format
void choose_pixel_format(const FrameBufferProperties &properties, bool need_pbuffer, bool need_pixmap)
Selects a visual or fbconfig for all the windows and buffers that use this gsg.
Definition: androidGraphicsStateGuardian.cxx:127
WindowProperties::get_fullscreen
get_fullscreen
Returns true if the window is in fullscreen mode.
Definition: windowProperties.h:119
AndroidGraphicsWindow
An interface to manage Android windows and their appropriate EGL surfaces.
Definition: androidGraphicsWindow.h:33
AndroidGraphicsWindow::process_events
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
Definition: androidGraphicsWindow.cxx:179
WindowProperties::set_minimized
set_minimized
Specifies whether the window should be created minimized (true), or normal (false).
Definition: windowProperties.h:133
WindowProperties::is_any_specified
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
Definition: windowProperties.I:41
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
GraphicsOutput::get_fb_properties
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
Definition: graphicsOutput.I:413
GraphicsWindowInputDevice::set_pointer_in_window
void set_pointer_in_window(double x, double y, double time=ClockObject::get_global_clock() ->get_frame_time())
To be called by a particular kind of GraphicsWindow to indicate that the pointer is within the window...
Definition: graphicsWindowInputDevice.cxx:166
AndroidGraphicsWindow::set_properties_now
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
Definition: androidGraphicsWindow.cxx:209
androidGraphicsStateGuardian.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_egl_error_string
const std::string get_egl_error_string(int error)
Returns the given EGL error as string.
Definition: config_androiddisplay.cxx:67
androidGraphicsWindow.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowProperties::has_fullscreen
has_fullscreen
Returns true if set_fullscreen() has been specified.
Definition: windowProperties.h:119
nativeWindowHandle.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
MouseButton::three
static ButtonHandle three()
Returns the ButtonHandle associated with the third mouse button.
Definition: mouseButton.cxx:59
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
GraphicsWindow::process_events
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
Definition: graphicsWindow.cxx:459
GraphicsOutput::end_flip
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
Definition: graphicsOutput.cxx:1299
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
androidGraphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsWindow
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
Definition: graphicsWindow.h:40
textEncoder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AndroidGraphicsStateGuardian::destroy_context
void destroy_context()
Destroys the context previously created by create_context.
Definition: androidGraphicsStateGuardian.cxx:250
AndroidGraphicsStateGuardian::create_context
bool create_context()
Creates the context based on the config previously obtained in choose_pixel_format.
Definition: androidGraphicsStateGuardian.cxx:222