00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "subprocessWindow.h"
00016
00017 #ifdef SUPPORT_SUBPROCESS_WINDOW
00018
00019 #include "graphicsEngine.h"
00020 #include "config_display.h"
00021 #include "nativeWindowHandle.h"
00022
00023 TypeHandle SubprocessWindow::_type_handle;
00024
00025
00026
00027
00028
00029
00030
00031
00032 SubprocessWindow::
00033 SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
00034 const string &name,
00035 const FrameBufferProperties &fb_prop,
00036 const WindowProperties &win_prop,
00037 int flags,
00038 GraphicsStateGuardian *gsg,
00039 GraphicsOutput *host) :
00040 GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00041 {
00042 GraphicsWindowInputDevice device =
00043 GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard/mouse");
00044 _input_devices.push_back(device);
00045
00046
00047
00048 _buffer = NULL;
00049
00050
00051
00052 _texture = new Texture(name);
00053
00054 _fd = -1;
00055 _mmap_size = 0;
00056 _filename = string();
00057 _swbuffer = NULL;
00058 _last_event_flags = 0;
00059 }
00060
00061
00062
00063
00064
00065
00066 SubprocessWindow::
00067 ~SubprocessWindow() {
00068 nassertv(_buffer == NULL);
00069 nassertv(_swbuffer == NULL);
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 void SubprocessWindow::
00083 process_events() {
00084 GraphicsWindow::process_events();
00085
00086 if (_swbuffer != NULL) {
00087 SubprocessWindowBuffer::Event swb_event;
00088 while (_swbuffer->get_event(swb_event)) {
00089
00090 if (swb_event._flags & SubprocessWindowBuffer::EF_mouse_position) {
00091 _input_devices[0].set_pointer_in_window(swb_event._x, swb_event._y);
00092 } else if ((swb_event._flags & SubprocessWindowBuffer::EF_has_mouse) == 0) {
00093 _input_devices[0].set_pointer_out_of_window();
00094 }
00095
00096 unsigned int diff = swb_event._flags ^ _last_event_flags;
00097 _last_event_flags = swb_event._flags;
00098
00099 if (diff & SubprocessWindowBuffer::EF_shift_held) {
00100 transition_button(swb_event._flags & SubprocessWindowBuffer::EF_shift_held, KeyboardButton::shift());
00101 }
00102 if (diff & SubprocessWindowBuffer::EF_control_held) {
00103 transition_button(swb_event._flags & SubprocessWindowBuffer::EF_control_held, KeyboardButton::control());
00104 }
00105 if (diff & SubprocessWindowBuffer::EF_alt_held) {
00106 transition_button(swb_event._flags & SubprocessWindowBuffer::EF_alt_held, KeyboardButton::alt());
00107 }
00108 if (diff & SubprocessWindowBuffer::EF_meta_held) {
00109 transition_button(swb_event._flags & SubprocessWindowBuffer::EF_meta_held, KeyboardButton::meta());
00110 }
00111
00112 ButtonHandle button = ButtonHandle::none();
00113 if (swb_event._source == SubprocessWindowBuffer::ES_mouse) {
00114 button = MouseButton::button(swb_event._code);
00115
00116 } else if (swb_event._source == SubprocessWindowBuffer::ES_keyboard) {
00117 int keycode;
00118 button = translate_key(keycode, swb_event._code, swb_event._flags);
00119 if (keycode != 0 && swb_event._type != SubprocessWindowBuffer::ET_button_up) {
00120 _input_devices[0].keystroke(keycode);
00121 }
00122 }
00123
00124 if (swb_event._type == SubprocessWindowBuffer::ET_button_up) {
00125 _input_devices[0].button_up(button);
00126 } else if (swb_event._type == SubprocessWindowBuffer::ET_button_down) {
00127 _input_devices[0].button_down(button);
00128 }
00129 }
00130 }
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 bool SubprocessWindow::
00143 begin_frame(FrameMode mode, Thread *current_thread) {
00144 if (_swbuffer == NULL || _buffer == NULL) {
00145 return false;
00146 }
00147
00148 bool result = _buffer->begin_frame(mode, current_thread);
00149 return result;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159 void SubprocessWindow::
00160 end_frame(FrameMode mode, Thread *current_thread) {
00161 _buffer->end_frame(mode, current_thread);
00162
00163 if (mode == FM_render) {
00164 _flip_ready = true;
00165 }
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 void SubprocessWindow::
00183 begin_flip() {
00184 nassertv(_buffer != (GraphicsBuffer *)NULL);
00185 if (_swbuffer == NULL) {
00186 return;
00187 }
00188
00189 RenderBuffer buffer(_gsg, DrawableRegion::get_renderbuffer_type(RTP_color));
00190 buffer = _gsg->get_render_buffer(_buffer->get_draw_buffer_type(),
00191 _buffer->get_fb_properties());
00192
00193 bool copied =
00194 _gsg->framebuffer_copy_to_ram(_texture, -1,
00195 _overlay_display_region, buffer);
00196
00197 if (copied) {
00198 CPTA_uchar image = _texture->get_ram_image();
00199 size_t framebuffer_size = _swbuffer->get_framebuffer_size();
00200 nassertv(image.size() == framebuffer_size);
00201
00202 if (!_swbuffer->ready_for_write()) {
00203
00204
00205
00206
00207
00208 ClockObject *clock = ClockObject::get_global_clock();
00209 double start = clock->get_real_time();
00210 while (!_swbuffer->ready_for_write()) {
00211 Thread::force_yield();
00212 double now = clock->get_real_time();
00213 if (now - start > subprocess_window_max_wait) {
00214
00215 return;
00216 }
00217 }
00218 }
00219
00220
00221 void *target = _swbuffer->open_write_framebuffer();
00222 memcpy(target, image.p(), framebuffer_size);
00223 _swbuffer->close_write_framebuffer();
00224 }
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 void SubprocessWindow::
00247 set_properties_now(WindowProperties &properties) {
00248 Filename filename;
00249 WindowHandle *window_handle = properties.get_parent_window();
00250 if (window_handle != NULL) {
00251 WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
00252 if (os_handle != NULL) {
00253 if (os_handle->is_of_type(NativeWindowHandle::SubprocessHandle::get_class_type())) {
00254 NativeWindowHandle::SubprocessHandle *subprocess_handle = DCAST(NativeWindowHandle::SubprocessHandle, os_handle);
00255 filename = subprocess_handle->get_filename();
00256 }
00257 }
00258 }
00259
00260 if (!filename.empty() && filename != _filename) {
00261
00262
00263 display_cat.info() << "Re-opening SubprocessWindow\n";
00264 internal_close_window();
00265
00266 _properties.add_properties(properties);
00267 properties.clear();
00268
00269 internal_open_window();
00270 set_size_and_recalc(_properties.get_x_size(), _properties.get_y_size());
00271 throw_event(get_window_event(), this);
00272 return;
00273 }
00274
00275 GraphicsWindow::set_properties_now(properties);
00276 if (!properties.is_any_specified()) {
00277
00278 return;
00279 }
00280
00281 if (properties.has_parent_window()) {
00282
00283 properties.clear_parent_window();
00284 }
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 void SubprocessWindow::
00294 close_window() {
00295 internal_close_window();
00296
00297 WindowProperties properties;
00298 properties.set_open(false);
00299 properties.set_foreground(false);
00300 system_changed_properties(properties);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310 bool SubprocessWindow::
00311 open_window() {
00312 if (!internal_open_window()) {
00313 return false;
00314 }
00315
00316 WindowProperties properties;
00317 properties.set_open(true);
00318 properties.set_foreground(true);
00319 system_changed_properties(properties);
00320
00321 return true;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330 void SubprocessWindow::
00331 internal_close_window() {
00332 if (_swbuffer != NULL) {
00333 SubprocessWindowBuffer::close_buffer
00334 (_fd, _mmap_size, _filename.to_os_specific(), _swbuffer);
00335 _fd = -1;
00336 _filename = string();
00337
00338 _swbuffer = NULL;
00339 }
00340
00341 if (_buffer != NULL) {
00342 _buffer->request_close();
00343 _buffer->process_events();
00344 _engine->remove_window(_buffer);
00345 _buffer = NULL;
00346 }
00347
00348
00349 if (_window_handle != (WindowHandle *)NULL &&
00350 _parent_window_handle != (WindowHandle *)NULL) {
00351 _parent_window_handle->detach_child(_window_handle);
00352 }
00353
00354 _window_handle = NULL;
00355 _parent_window_handle = NULL;
00356 _is_valid = false;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365 bool SubprocessWindow::
00366 internal_open_window() {
00367 nassertr(_buffer == NULL, false);
00368
00369
00370 int flags = _creation_flags;
00371 flags = ((flags & ~GraphicsPipe::BF_require_window) | GraphicsPipe::BF_refuse_window);
00372 WindowProperties win_props = WindowProperties::size(_properties.get_x_size(), _properties.get_y_size());
00373
00374 GraphicsOutput *buffer =
00375 _engine->make_output(_pipe, _name, 0, _fb_properties, win_props,
00376 flags, _gsg, _host);
00377 if (buffer != NULL) {
00378 _buffer = DCAST(GraphicsBuffer, buffer);
00379
00380
00381 _buffer->set_active(false);
00382
00383 _buffer->request_open();
00384 _buffer->process_events();
00385
00386 _is_valid = _buffer->is_valid();
00387 }
00388
00389 if (!_is_valid) {
00390 display_cat.error()
00391 << "Failed to open SubprocessWindowBuffer's internal offscreen buffer.\n";
00392 return false;
00393 }
00394
00395 _gsg = _buffer->get_gsg();
00396
00397 WindowHandle *window_handle = _properties.get_parent_window();
00398 if (window_handle != NULL) {
00399 WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
00400 if (os_handle != NULL) {
00401 if (os_handle->is_of_type(NativeWindowHandle::SubprocessHandle::get_class_type())) {
00402 NativeWindowHandle::SubprocessHandle *subprocess_handle = DCAST(NativeWindowHandle::SubprocessHandle, os_handle);
00403 _filename = subprocess_handle->get_filename();
00404 }
00405 }
00406 }
00407 _parent_window_handle = window_handle;
00408
00409 if (_filename.empty()) {
00410 _is_valid = false;
00411 display_cat.error()
00412 << "No filename given to SubprocessWindow.\n";
00413 return false;
00414 }
00415
00416 _swbuffer = SubprocessWindowBuffer::open_buffer
00417 (_fd, _mmap_size, _filename.to_os_specific());
00418
00419 if (_swbuffer == NULL) {
00420 close(_fd);
00421 _fd = -1;
00422 _filename = string();
00423 _is_valid = false;
00424 display_cat.error()
00425 << "Failed to open SubprocessWindowBuffer's shared-memory buffer "
00426 << _filename << "\n";
00427 return false;
00428 }
00429
00430 if (display_cat.is_debug()) {
00431 display_cat.debug()
00432 << "SubprocessWindow reading " << _filename << "\n";
00433 }
00434
00435
00436 _window_handle = NativeWindowHandle::make_subprocess(_filename);
00437
00438
00439 if (_parent_window_handle != (WindowHandle *)NULL) {
00440 _parent_window_handle->attach_child(_window_handle);
00441 }
00442
00443 return true;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453 ButtonHandle SubprocessWindow::
00454 translate_key(int &keycode, int os_code, unsigned int flags) const {
00455 keycode = 0;
00456 ButtonHandle nk = ButtonHandle::none();
00457
00458 #ifdef __APPLE__
00459 switch ((os_code >> 8) & 0xff) {
00460 case 0: nk = KeyboardButton::ascii_key('a'); break;
00461 case 11: nk = KeyboardButton::ascii_key('b'); break;
00462 case 8: nk = KeyboardButton::ascii_key('c'); break;
00463 case 2: nk = KeyboardButton::ascii_key('d'); break;
00464 case 14: nk = KeyboardButton::ascii_key('e'); break;
00465 case 3: nk = KeyboardButton::ascii_key('f'); break;
00466 case 5: nk = KeyboardButton::ascii_key('g'); break;
00467 case 4: nk = KeyboardButton::ascii_key('h'); break;
00468 case 34: nk = KeyboardButton::ascii_key('i'); break;
00469 case 38: nk = KeyboardButton::ascii_key('j'); break;
00470 case 40: nk = KeyboardButton::ascii_key('k'); break;
00471 case 37: nk = KeyboardButton::ascii_key('l'); break;
00472 case 46: nk = KeyboardButton::ascii_key('m'); break;
00473 case 45: nk = KeyboardButton::ascii_key('n'); break;
00474 case 31: nk = KeyboardButton::ascii_key('o'); break;
00475 case 35: nk = KeyboardButton::ascii_key('p'); break;
00476 case 12: nk = KeyboardButton::ascii_key('q'); break;
00477 case 15: nk = KeyboardButton::ascii_key('r'); break;
00478 case 1: nk = KeyboardButton::ascii_key('s'); break;
00479 case 17: nk = KeyboardButton::ascii_key('t'); break;
00480 case 32: nk = KeyboardButton::ascii_key('u'); break;
00481 case 9: nk = KeyboardButton::ascii_key('v'); break;
00482 case 13: nk = KeyboardButton::ascii_key('w'); break;
00483 case 7: nk = KeyboardButton::ascii_key('x'); break;
00484 case 16: nk = KeyboardButton::ascii_key('y'); break;
00485 case 6: nk = KeyboardButton::ascii_key('z'); break;
00486
00487
00488 case 29: nk = KeyboardButton::ascii_key('0'); break;
00489 case 18: nk = KeyboardButton::ascii_key('1'); break;
00490 case 19: nk = KeyboardButton::ascii_key('2'); break;
00491 case 20: nk = KeyboardButton::ascii_key('3'); break;
00492 case 21: nk = KeyboardButton::ascii_key('4'); break;
00493 case 23: nk = KeyboardButton::ascii_key('5'); break;
00494 case 22: nk = KeyboardButton::ascii_key('6'); break;
00495 case 26: nk = KeyboardButton::ascii_key('7'); break;
00496 case 28: nk = KeyboardButton::ascii_key('8'); break;
00497 case 25: nk = KeyboardButton::ascii_key('9'); break;
00498
00499
00500 case 82: nk = KeyboardButton::ascii_key('0'); break;
00501 case 83: nk = KeyboardButton::ascii_key('1'); break;
00502 case 84: nk = KeyboardButton::ascii_key('2'); break;
00503 case 85: nk = KeyboardButton::ascii_key('3'); break;
00504 case 86: nk = KeyboardButton::ascii_key('4'); break;
00505 case 87: nk = KeyboardButton::ascii_key('5'); break;
00506 case 88: nk = KeyboardButton::ascii_key('6'); break;
00507 case 89: nk = KeyboardButton::ascii_key('7'); break;
00508 case 91: nk = KeyboardButton::ascii_key('8'); break;
00509 case 92: nk = KeyboardButton::ascii_key('9'); break;
00510
00511
00512 case 49: nk = KeyboardButton::space(); break;
00513 case 51: nk = KeyboardButton::backspace(); break;
00514 case 48: nk = KeyboardButton::tab(); break;
00515 case 53: nk = KeyboardButton::escape(); break;
00516 case 76: nk = KeyboardButton::enter(); break;
00517 case 36: nk = KeyboardButton::enter(); break;
00518
00519 case 123: nk = KeyboardButton::left(); break;
00520 case 124: nk = KeyboardButton::right(); break;
00521 case 125: nk = KeyboardButton::down(); break;
00522 case 126: nk = KeyboardButton::up(); break;
00523 case 116: nk = KeyboardButton::page_up(); break;
00524 case 121: nk = KeyboardButton::page_down(); break;
00525 case 115: nk = KeyboardButton::home(); break;
00526 case 119: nk = KeyboardButton::end(); break;
00527 case 114: nk = KeyboardButton::help(); break;
00528 case 117: nk = KeyboardButton::del(); break;
00529
00530
00531
00532 case 122: nk = KeyboardButton::f1(); break;
00533 case 120: nk = KeyboardButton::f2(); break;
00534 case 99: nk = KeyboardButton::f3(); break;
00535 case 118: nk = KeyboardButton::f4(); break;
00536 case 96: nk = KeyboardButton::f5(); break;
00537 case 97: nk = KeyboardButton::f6(); break;
00538 case 98: nk = KeyboardButton::f7(); break;
00539 case 100: nk = KeyboardButton::f8(); break;
00540 case 101: nk = KeyboardButton::f9(); break;
00541 case 109: nk = KeyboardButton::f10(); break;
00542 case 103: nk = KeyboardButton::f11(); break;
00543 case 111: nk = KeyboardButton::f12(); break;
00544
00545 case 105: nk = KeyboardButton::f13(); break;
00546 case 107: nk = KeyboardButton::f14(); break;
00547 case 113: nk = KeyboardButton::f15(); break;
00548 case 106: nk = KeyboardButton::f16(); break;
00549
00550
00551 case 50: nk = KeyboardButton::ascii_key('`'); break;
00552 case 27: nk = KeyboardButton::ascii_key('-'); break;
00553 case 24: nk = KeyboardButton::ascii_key('='); break;
00554 case 33: nk = KeyboardButton::ascii_key('['); break;
00555 case 30: nk = KeyboardButton::ascii_key(']'); break;
00556 case 42: nk = KeyboardButton::ascii_key('\\'); break;
00557 case 41: nk = KeyboardButton::ascii_key(';'); break;
00558 case 39: nk = KeyboardButton::ascii_key('\''); break;
00559 case 43: nk = KeyboardButton::ascii_key(','); break;
00560 case 47: nk = KeyboardButton::ascii_key('.'); break;
00561 case 44: nk = KeyboardButton::ascii_key('/'); break;
00562
00563 default:
00564
00565 nk = KeyboardButton::ascii_key(os_code & 0xff);
00566 }
00567
00568 if (nk.has_ascii_equivalent()) {
00569
00570
00571
00572
00573
00574 keycode = os_code & 0xff;
00575 }
00576
00577 #endif __APPLE__
00578
00579 return nk;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589 void SubprocessWindow::
00590 transition_button(unsigned int flags, ButtonHandle button) {
00591 if (flags) {
00592 _input_devices[0].button_down(button);
00593 } else {
00594 _input_devices[0].button_up(button);
00595 }
00596 }
00597
00598
00599 #endif // SUPPORT_SUBPROCESS_WINDOW