Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef toolx_Xt_sg_viewer 5 #define toolx_Xt_sg_viewer 6 7 #include "session" 8 9 #include "../sg/GL_viewer" 10 11 #include "OpenGLArea" 12 13 #include <X11/Shell.h> 14 #include <X11/StringDefs.h> 15 #include <X11/IntrinsicP.h> 16 17 #include <tools/num2s> 18 #include <tools/sg/device_interactor> 19 #include <tools/sg/keys> 20 21 namespace toolx { 22 namespace Xt { 23 24 class sg_viewer : public sg::GL_viewer { 25 typedef sg::GL_viewer parent; 26 public: 27 sg_viewer(session& a_session, 28 int a_x = 0,int a_y = 0, 29 unsigned int a_width = 500,unsigned int a_height = 500, 30 const std::string& a_win_title = "") 31 :parent(a_session.out(),a_width,a_height) 32 ,m_session(a_session) 33 ,m_shell(0) 34 ,m_glarea(0) 35 ,m_interactor(0) 36 { 37 Widget app_widget = a_session.get_app_widget(); 38 if(!app_widget) return; 39 40 std::string sgeom; 41 tools::numas(a_width,sgeom); 42 sgeom += "x"; 43 tools::numas(a_height,sgeom); 44 sgeom += "+"; 45 tools::numas(a_x,sgeom); 46 sgeom += "+"; 47 tools::numas(a_y,sgeom); 48 49 Arg args[2]; 50 XtSetArg(args[0],XtNgeometry,XtNewString(sgeom.c_str())); 51 XtSetArg(args[1],XtNborderWidth,0); 52 53 m_shell = ::XtAppCreateShell((char*)a_win_title.c_str(), 54 (char*)"sg_viewer_shell", 55 topLevelShellWidgetClass,XtDisplay(app_widget),args,2); 56 ::XtSetMappedWhenManaged(m_shell,True); 57 58 m_glarea = ::XtCreateManagedWidget("glarea",OpenGLArea::widget_class(),m_shell,args,0); 59 ::XtAddCallback(m_glarea,XoNpaintCallback,paint_cbk,(XtPointer)this); 60 ::XtAddCallback(m_glarea,XoNeventCallback,event_cbk,(XtPointer)this); 61 62 ::XtAddCallback(m_shell,XtNdestroyCallback,destroy_shell_callback,(XtPointer)this); 63 64 ::XtRealizeWidget(m_shell); 65 66 //Atom WM_DELETE_WINDOW_atom = ::XInternAtom(XtDisplay(m_shell),"WM_DELETE_WINDOW",False); 67 //::XSetWMProtocols(XtDisplay(m_shell),XtWindow(m_shell),&WM_DELETE_WINDOW_atom,1); 68 } 69 virtual ~sg_viewer() { 70 if(m_shell) { 71 ::XtRemoveCallback(m_glarea,XoNpaintCallback,paint_cbk,(XtPointer)this); 72 ::XtRemoveCallback(m_shell,XtNdestroyCallback,destroy_shell_callback,(XtPointer)this); 73 ::XtDestroyWidget(m_shell); 74 } 75 m_shell = 0; 76 m_glarea = 0; 77 } 78 protected: 79 sg_viewer(const sg_viewer& a_from) 80 :parent(a_from) 81 ,m_session(a_from.m_session) 82 ,m_shell(0) 83 ,m_glarea(0) 84 ,m_interactor(0) 85 {} 86 sg_viewer& operator=(const sg_viewer& a_from){ 87 parent::operator=(a_from); 88 return *this; 89 } 90 public: 91 bool has_window() const {return m_glarea?true:false;} 92 93 bool show() { 94 if(!m_shell) return false; 95 ::XtRealizeWidget(m_shell); 96 ::XtMapWidget(m_shell); 97 // Raise window : 98 if(XtIsWidget(m_shell) && XtIsRealized(m_shell) ) { 99 Display* display = XtDisplay(m_shell); 100 Atom atom = ::XInternAtom(display,"WM_DELETE_WINDOW",False); 101 ::XSetWMProtocols(display,XtWindow(m_shell),&atom,1); 102 ::XRaiseWindow(display,XtWindow(m_shell)); 103 } 104 return true; 105 } 106 107 void win_render() { 108 if(m_glarea) OpenGLArea::paint(m_glarea); 109 } 110 111 public: 112 void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership. 113 protected: 114 static void paint_cbk(Widget a_widget,XtPointer a_tag,XtPointer){ 115 unsigned int width = a_widget->core.width; 116 unsigned int height = a_widget->core.height; 117 //::printf("debug : toolx::Xt::sg_viewer::paint_cbk : %d %d\n",width,height); 118 sg_viewer* _this = (sg_viewer*)a_tag; 119 _this->set_size(width,height); 120 _this->render(); 121 } 122 static void event_cbk(Widget,XtPointer a_tag,XtPointer a_data){ 123 sg_viewer* _this = (sg_viewer*)a_tag; 124 if(!_this->m_interactor) return; 125 XoAnyCallbackStruct* data = (XoAnyCallbackStruct*)a_data; 126 XEvent* xevent = data->event; 127 switch( xevent->type ) { 128 case KeyPress:{ 129 KeySym key_sym; 130 ::XLookupString(&(xevent->xkey),NULL,0,&key_sym,NULL); 131 tools::sg::key_down_event event(_this->convert(key_sym)); 132 _this->m_interactor->key_press(event); 133 }return; 134 case KeyRelease:{ 135 KeySym key_sym; 136 ::XLookupString(&(xevent->xkey),NULL,0,&key_sym,NULL); 137 tools::sg::key_up_event event(_this->convert(key_sym)); 138 _this->m_interactor->key_release(event); 139 }return; 140 case ButtonPress:{ 141 if(xevent->xbutton.button==Button4) { //4=wheel down, or move down double touch on trackpad = zoom in. 142 tools::sg::wheel_rotate_event event(8); //8=cooking. 143 _this->m_interactor->wheel_rotate(event); 144 } else if(xevent->xbutton.button==Button5) { //5=wheel up, or move up double touch on trackpad = zoom out. 145 tools::sg::wheel_rotate_event event(-8); //8=cooking. 146 _this->m_interactor->wheel_rotate(event); 147 } else { 148 tools::sg::mouse_down_event event(xevent->xbutton.x,xevent->xbutton.y); 149 _this->m_interactor->mouse_press(event); 150 } 151 }return; 152 case ButtonRelease:{ 153 tools::sg::mouse_up_event event(xevent->xbutton.x,xevent->xbutton.y); 154 _this->m_interactor->mouse_release(event); 155 }return; 156 case MotionNotify:{ 157 tools::sg::mouse_move_event event(xevent->xmotion.x,xevent->xmotion.y,0,0,false); 158 _this->m_interactor->mouse_move(event); 159 }return; 160 default:return;} 161 } 162 static void destroy_shell_callback(Widget,XtPointer a_tag,XtPointer) { 163 sg_viewer* _this = (sg_viewer*)a_tag; 164 _this->m_shell = 0; 165 _this->m_glarea = 0; 166 } 167 protected: 168 tools::key_code convert(KeySym a_key) { 169 if(a_key==XK_Shift_L) return tools::sg::key_shift(); 170 if(a_key==XK_Shift_R) return tools::sg::key_shift(); 171 return (tools::key_code)a_key; 172 } 173 protected: 174 session& m_session; 175 Widget m_shell; 176 Widget m_glarea; 177 tools::sg::device_interactor* m_interactor; 178 }; 179 180 }} 181 182 #endif 183