Panda3D
Loading...
Searching...
No Matches
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
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
32extern IMPORT_CLASS struct android_app* panda_android_app;
33
34TypeHandle AndroidGraphicsWindow::_type_handle;
35
36/**
37 *
38 */
39AndroidGraphicsWindow::
40AndroidGraphicsWindow(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 */
66AndroidGraphicsWindow::
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 */
78begin_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
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 */
130end_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 */
155end_flip() {
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 */
241void AndroidGraphicsWindow::
242close_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 */
263bool AndroidGraphicsWindow::
264open_window() {
265 // GSG CreationInitialization
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) {
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 */
318void AndroidGraphicsWindow::
319destroy_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) {
331 DCAST_INTO_V(androidgsg, _gsg);
332 androidgsg->destroy_context();
333 }
334}
335
336/**
337 * Creates the EGL surface.
338 */
339bool AndroidGraphicsWindow::
340create_surface() {
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 */
394void AndroidGraphicsWindow::
395handle_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 */
405void AndroidGraphicsWindow::
406ns_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 */
467int32_t AndroidGraphicsWindow::
468handle_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 */
484int32_t AndroidGraphicsWindow::
485handle_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 */
535int32_t AndroidGraphicsWindow::
536handle_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) {
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 */
580ButtonHandle AndroidGraphicsWindow::
581map_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}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This graphics pipe represents the interface for creating OpenGL ES graphics windows on an X-based (e....
A tiny specialization on GLESGraphicsStateGuardian to add some egl-specific information.
const FrameBufferProperties & get_fb_properties() const
Gets the FrameBufferProperties for all windows and buffers that use this GSG.
bool create_context()
Creates the context based on the config previously obtained in choose_pixel_format.
void destroy_context()
Destroys the context previously created by create_context.
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.
An interface to manage Android windows and their appropriate EGL surfaces.
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
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.
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
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.
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
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).
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
This class is the main interface to controlling the render process.
This is a base class for the various different classes that represent the result of a frame of render...
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
An object to create GraphicsOutputs that share a particular 3-D API.
Encapsulates all the communication with a particular instance of a given rendering backend.
This is a virtual input device that represents the keyboard and mouse pair that is associated with a ...
void button_down(ButtonHandle button, double time=ClockObject::get_global_clock() ->get_frame_time())
Records that the indicated button has been depressed.
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...
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...
void button_up(ButtonHandle button, double time=ClockObject::get_global_clock() ->get_frame_time())
Records that the indicated button has been released.
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
virtual void set_properties_now(WindowProperties &properties)
Applies the requested set of properties to the window, if possible, for instance to request a change ...
static ButtonHandle ascii_key(char ascii_equivalent)
Returns the ButtonHandle associated with the particular ASCII character, if there is one,...
static ButtonHandle one()
Returns the ButtonHandle associated with the first mouse button.
static ButtonHandle three()
Returns the ButtonHandle associated with the third mouse button.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition pStatTimer.h:30
A thread; that is, a lightweight process.
Definition thread.h:46
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
A container for the various kinds of properties we might ask to have on a graphics window before we o...
has_fullscreen
Returns true if set_fullscreen() has been specified.
set_size
Specifies the requested size of the window, in pixels.
bool is_any_specified() const
Returns true if any properties have been specified, false otherwise.
clear_fullscreen
Removes the fullscreen specification from the properties.
set_foreground
Specifies whether the window should be opened in the foreground (true), or left in the background (fa...
set_open
Specifies whether the window should be open.
get_fullscreen
Returns true if the window is in fullscreen mode.
set_minimized
Specifies whether the window should be created minimized (true), or normal (false).
set_origin
Specifies the origin on the screen (in pixels, relative to the top-left corner) at which the window s...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const std::string get_egl_error_string(int error)
Returns the given EGL error as string.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.