/// Adds a new view. Function has to be called just from the inside of view thread with a locked sync_view. int add_view_in_thread(void* view_pars_ptr) { error_if(need_safe_call(), "Calling add_view_in_thread from other thread."); ViewParams& view_params = *((ViewParams*)view_pars_ptr); //create GLUT window glutInitWindowPosition(view_params.x, view_params.y); glutInitWindowSize(view_params.width, view_params.height); int view_id = glutCreateWindow(view_params.title); glutSetWindowData(view_params.view); //initialize GLEW GLenum err = glewInit(); error_if(err != GLEW_OK, "GLEW error: %s", glewGetErrorString(err)); glew_initialized = true; //register callbacks glutDisplayFunc(on_display_stub); glutReshapeFunc(on_reshape_stub); glutMotionFunc(on_mouse_move_stub); glutPassiveMotionFunc(on_mouse_move_stub); glutMouseFunc(on_mouse_click_stub); glutKeyboardFunc(on_key_down_stub); glutSpecialFunc(on_special_key_stub); glutEntryFunc(on_entry_stub); glutCloseFunc(on_close_stub); //add to structures view_instances[view_id] = view_params.view; //call handlers view_params.view->on_create(view_id); return view_id; }
/// Does a cross thread call. static int call_in_thread(CTC_FUNC func, void* param) { //check whether the thread is running if not start it view_sync.enter(); if (view_thread == NULL) { ThreadInfo* new_thread_info = NULL; try { new_thread_info = new ThreadInfo(); } catch(std::bad_alloc&) { error("Failed to allocate structure for view thread"); } int err = pthread_create(&new_thread_info->thread, NULL, view_thread_func, new_thread_info); if (err) { delete new_thread_info; error("Failed to create main thread, error: %d", err); } view_thread = new_thread_info; } view_sync.leave(); //make call if (need_safe_call()) { view_sync.enter(); ctc_function = func; ctc_param = param; view_sync.wait_cross_thread_call(); int result = ctc_result; view_sync.leave(); return result; } else return func(param); }
/// Forces a redisplay of a view. Function has to be called just from the inside of view thread. static int refresh_view_in_thread(void* view_id_ptr) { error_if(need_safe_call(), "Calling refresh_view_in_thread from other thread."); int view_id = *((int*)view_id_ptr); std::map<int, View*>::iterator found_view = view_instances.find(view_id); assert_msg(found_view != view_instances.end(), "Refreshing a view that is not registered"); //redisplay if (found_view != view_instances.end()) { glutSetWindow(view_id); glutPostRedisplay(); } return 0; }
/// Forces a redisplay of a view. Function has to be called just from the inside of view thread. static int refresh_view_in_thread(void* view_id_ptr) { debug_assert(!need_safe_call(), "E refresh_view_in_thread called from other thread."); int view_id = *((int*)view_id_ptr); std::map<int, View*>::iterator found_view = view_instances.find(view_id); //debug_assert(found_view != view_instances.end(), "E removing of a view that is not registered"); //redisplay if (found_view != view_instances.end()) { glutSetWindow(view_id); glutPostRedisplay(); } return 0; }
/// Sets a title of a view. Function has to be called just from the inside of view thread with a locked sync_view. static int set_view_title_in_thread(void* title_pars_ptr) { error_if(need_safe_call(), "Calling set_view_title_in_thread from other thread."); TitleParams& title_params = *((TitleParams*)title_pars_ptr); std::map<int, View*>::iterator found_view = view_instances.find(title_params.view_id); if (found_view == view_instances.end()) { debug_log("Settings title of a view that is not registered."); return -1; } //create GLUT window glutSetWindow(title_params.view_id); glutSetWindowTitle(title_params.title); return 0; }
/// Removes a new view. Function has to be called just from the inside of view thread with a locked sync_view. int remove_view_in_thread(void* remove_params_ptr) { debug_assert(!need_safe_call(), "E remove_view_in_thread called from other thread."); RemoveParams& params = *(RemoveParams*)remove_params_ptr; std::map<int, View*>::iterator found_view = view_instances.find(params.view_id); //debug_assert(found_view != view_instances.end(), "E removing of a view that is not registered"); if (found_view == view_instances.end()) { debug_log("W removing of a view that is not registered\n"); return -1; } //destroy window if requested (it will not be requested when remove is called as a reaction to on_close) if (params.destroy_glut_window) { //remove window from GLUT glutSetWindow(params.view_id); glutSetWindowData(NULL); //prevent stubs from being executed if there is still some message waiting for the window //call on-close event found_view->second->on_close(); //finish removal of window from GLUT glutDestroyWindow(params.view_id); } //remove from structures view_instances.erase(found_view); //thread cleanup if (view_instances.size() == 0) { view_thread->should_quit = true; view_thread = NULL; //signal all events view_sync.signal_close(); view_sync.signal_keypress(); view_sync.signal_drawing_finished(); } return 0; }