// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef toolx_X11_sg_viewer #define toolx_X11_sg_viewer #ifndef GL_GLEXT_LEGACY #define GL_GLEXT_LEGACY #endif #include #ifndef GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES #endif #include #include "session" #include "../GL/gl_functions" #include "../sg/GL_action" #include "../sg/GL_viewer" namespace toolx { namespace sg { using GL_action = GL_action_T; using GL_manager = GL_manager_T; using GL_viewer = GL_viewer_T; }} #include "simple_dispatcher" #include namespace toolx { namespace X11 { class sg_viewer: public sg::GL_viewer { typedef sg::GL_viewer parent; private: class dispatcher : public simple_dispatcher { typedef simple_dispatcher parent; public: virtual bool dispatch(XEvent& a_event) { if(parent::dispatch(a_event)) return true; bool shift_modifier = a_event.xkey.state & ShiftMask; bool control_modifier = a_event.xkey.state & ControlMask; if(a_event.type==ButtonPress && a_event.xbutton.button==1) { if(!m_viewer.device_interactor()) return false; tools::sg::mouse_down_event event(a_event.xbutton.x,a_event.xbutton.y,shift_modifier,control_modifier); m_viewer.device_interactor()->mouse_press(event); return true; } else if(a_event.type==ButtonRelease && a_event.xbutton.button==1) { if(!m_viewer.device_interactor()) return false; tools::sg::mouse_up_event event(a_event.xbutton.x,a_event.xbutton.y,shift_modifier,control_modifier); m_viewer.device_interactor()->mouse_release(event); return true; } else if(a_event.type==MotionNotify) { if(!m_viewer.device_interactor()) return false; if((a_event.xmotion.state & Button1MotionMask)==Button1MotionMask) { tools::sg::mouse_move_event event(a_event.xmotion.x,a_event.xmotion.y,shift_modifier,control_modifier,0,0,false); m_viewer.device_interactor()->mouse_move(event); } } else if((a_event.type==ButtonPress)&&(a_event.xbutton.button==4)) { // mouse scrollwheel down : if(!m_viewer.device_interactor()) return false; tools::sg::wheel_rotate_event event(8,a_event.xbutton.x,a_event.xbutton.y,shift_modifier,control_modifier); //8=cooking. m_viewer.device_interactor()->wheel_rotate(event); return true; } else if((a_event.type==ButtonPress)&&(a_event.xbutton.button==5)) { // mouse scrollwheel up : if(!m_viewer.device_interactor()) return false; tools::sg::wheel_rotate_event event(-8,a_event.xbutton.x,a_event.xbutton.y,shift_modifier,control_modifier); //8=cooking. m_viewer.device_interactor()->wheel_rotate(event); return true; } return false; } virtual void win_render() {m_viewer.win_render();} virtual void set_size(unsigned int a_width,unsigned int a_height) {m_viewer.set_size(a_width,a_height);} virtual dispatcher* copy() const {return new dispatcher(*this);} public: dispatcher(sg_viewer& a_viewer) :parent(a_viewer.m_session,a_viewer.m_win) ,m_viewer(a_viewer){} virtual ~dispatcher(){} protected: dispatcher(const dispatcher& a_from) :parent(a_from) ,m_viewer(a_from.m_viewer) {} dispatcher& operator=(const dispatcher& a_from) { parent::operator=(a_from); return *this; } protected: sg_viewer& m_viewer; }; public: sg_viewer(session& a_session, int a_x = 0,int a_y = 0, unsigned int a_width = 500,unsigned int a_height = 500, const std::string& a_win_title = "") :parent(a_session.out(),a_width,a_height) ,m_session(a_session) ,m_win(0) ,m_interactor(0) { if(!m_session.display()) return; //throw m_win = m_session.create_window(a_win_title.c_str(),a_x,a_y,a_width,a_height); if(!m_win) return; //throw m_session.add_dispatcher(new dispatcher(*this)); } virtual ~sg_viewer() { if(m_win) { m_session.remove_dispatchers_with_window(m_win); m_session.delete_window(m_win); m_session.sync(); } } protected: sg_viewer(const sg_viewer& a_from) :parent(a_from) ,m_session(a_from.m_session) ,m_win(a_from.m_win) ,m_interactor(0) {} sg_viewer& operator=(const sg_viewer& a_from){ parent::operator=(a_from); m_win = a_from.m_win; return *this; } public: bool has_window() const {return m_win?true:false;} //for SWIG Window window() const {return m_win;} bool show() { if(!m_win) return false; m_session.show_window(m_win); return true; } void win_render() { if(!m_win) return; if(::glXMakeCurrent(m_session.display(),m_win,m_session.context())==False){ m_session.out() << "toolx::X11::sg_viewer::win_render : glXMakeCurrent failed." << std::endl; return; } render(); //viewer::render() ::glXSwapBuffers(m_session.display(),m_win); if(::glXMakeCurrent(m_session.display(),None,NULL)==False){ m_session.out() << "toolx::X11::sg_viewer::win_render : glXMakeCurrent(None,NULL) failed." << std::endl; } m_session.sync(); } void emit_win_render() { if(!m_win) return; m_session.post_expose(m_win); } bool window_size(unsigned int& a_w,unsigned int& a_h) { if(!m_win) {a_w = 0;a_h = 0;return false;} int width,height; if(!m_session.window_size(m_win,width,height)) {a_w = 0;a_h = 0;return false;} a_w = (unsigned int)width; a_h = (unsigned int)height; return true; } void render_area_size(unsigned int& a_w,unsigned int& a_h) { a_w = parent::width(); a_h = parent::height(); } void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} public: tools::sg::device_interactor* device_interactor() {return m_interactor;} protected: session& m_session; Window m_win; tools::sg::device_interactor* m_interactor; }; }} #endif