NEURON
ivocwin.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include "oc2iv.h"
3 
4 #if HAVE_IV
5 #include <IV-Win/MWlib.h>
6 #if defined(_MSC_VER)
7 #undef min
8 #undef max
9 #undef near
10 #define near mynear
11 
12 #else
13 #undef near
14 #endif
15 
16 #undef MOVE
17 #undef DELETE
18 #undef IGNORE
19 #define MOVE mlhmove
20 #define DELETE mlhdelete
21 #include <Dispatch/dispatcher.h>
22 #include <InterViews/window.h>
23 #include <IV-Win/window.h>
24 #include <InterViews/display.h>
25 #include <InterViews/cursor.h>
26 #include <IV-Win/canvas.h>
27 #include "apwindow.h"
28 #include "ivoc.h"
29 #include "rubband.h"
30 #include "symdir.h"
31 #undef max
32 #undef min
33 #include "graph.h"
34 
35 #include <condition_variable>
36 #include <mutex>
37 
38 #ifdef MINGW
39 // the link step needs liboc after libivoc but liboc refers to some
40 // things in libivoc that wouldn't normally be linked because nothing
41 // refers to them while libivoc is linking. So force them to link here
42 int ivoc_list_look(Object*, Object*, char*, int);
44 static void dummy() {
47 }
48 #endif
49 
50 int iv_mswin_to_pixel(int);
51 int iv_pixel_to_mswin(int);
52 
53 void pwmimpl_redraw(Window* w) {
54  w->rep()->WMpaint(0, 0);
55 }
56 
57 void ivoc_bring_to_top(Window* w) {
58  BringWindowToTop(w->rep()->msWindow());
59 }
60 
61 void* mswin_setclip(Canvas* c, int x0, int y0, int x1, int y1) {
62  HRGN clip = CreateRectRgn(x0, y0, x1, y1);
63  SelectClipRgn(((MWcanvas*) c)->hdcOf(), clip);
64  return clip;
65 }
66 
67 void mswin_delete_object(void* v) {
68  DeleteObject((HRGN) v);
69 }
70 
71 //---------------------------------------------------------
72 
73 void ivoc_win32_cleanup() {
74  Oc::cleanup();
75 }
76 
77 void Oc::cleanup() {
78  if (help_cursor_) {
79  delete help_cursor_;
80  }
81 }
82 
83 #ifdef MINGW
84 static void hidewindow(void* v) {
85  HWND w = (HWND) v;
86  ShowWindow(w, SW_HIDE);
87 }
88 
89 static int gui_thread_xmove_x;
90 static int gui_thread_xmove_y;
91 void gui_thread_xmove(void* v) {
93  w->xmove(gui_thread_xmove_x, gui_thread_xmove_y);
94 }
95 
96 #endif
97 
98 void PrintableWindow::hide() {
99  if (is_mapped()) {
100  HWND hwnd = Window::rep()->msWindow();
101 // printf("hide %p\n", this);
102 #ifdef MINGW
103  if (!nrn_is_gui_thread()) {
104  nrn_gui_exec(hidewindow, hwnd);
105  return;
106  }
107 #endif
108  ShowWindow(hwnd, SW_HIDE);
109  }
110 }
111 
112 void PrintableWindow::xmove(int x, int y) {
113 #ifdef MINGW
114  if (!nrn_is_gui_thread()) {
115  gui_thread_xmove_x = x;
116  gui_thread_xmove_y = y;
117  nrn_gui_exec(gui_thread_xmove, this);
118  return;
119  }
120 #endif
121  HWND hwnd = Window::rep()->msWindow();
122  // int width = canvas()->pwidth();
123  // int height = canvas()->pheight();
124  RECT r;
125  GetWindowRect(hwnd, &r);
126  MoveWindow(
127  hwnd, iv_pixel_to_mswin(x), iv_pixel_to_mswin(y), r.right - r.left, r.bottom - r.top, TRUE);
128 }
129 int PrintableWindow::xleft() const {
130  WindowRep& w = *Window::rep();
131  if (w.bound()) {
132  HWND hwnd = w.msWindow();
133  RECT winRect;
134  GetWindowRect(hwnd, &winRect);
135  return iv_mswin_to_pixel(winRect.left);
136  } else {
137  return 0;
138  }
139 }
140 int PrintableWindow::xtop() const {
141  WindowRep& w = *Window::rep();
142  if (w.bound()) {
143  HWND hwnd = w.msWindow();
144  RECT winRect;
145  GetWindowRect(hwnd, &winRect);
146  return iv_mswin_to_pixel(winRect.top);
147  } else {
148  return 0;
149  }
150 }
151 
152 void PrintableWindow::xplace(int x, int y) {
153  WindowRep& wr = *Window::rep();
154  if (wr.bound()) {
155  xmove(x, y);
156  } else {
157  xplace_ = true;
158  xleft_ = x;
159  xtop_ = y;
160  }
161 }
163  DismissableWindow::default_geometry();
164  if (xplace_) {
165  pplace(iv_pixel_to_mswin(xleft_),
166  display()->pheight() - iv_pixel_to_mswin(xtop_) -
167  canvas()->to_pixels(height(), Dimension_Y));
168  }
169 }
170 #if 0
171 Object** Graph::new_vect(const DataVec*) {
172  return 0;
173 }
174 #endif
175 //#include "\nrn\src\mswin\winio\debug.h"
177  // DebugEnterMessage("Rubberband::rubber_on\n");
178  c->front_buffer();
179 }
181  c->back_buffer();
182 #ifdef WIN32
183  // this prevents failure for all future paints
184  c->damage_all();
185 #endif
186  // DebugExitMessage("Rubberband::rubber_off\n");
187 }
188 #if 0
189 double* ivoc_vector_ptr(Object*, int) {return 0;}
190 int ivoc_vector_size(Object*) {return 0;}
191 #endif
192 
193 #ifdef MINGW
194 IOHandler::IOHandler() {}
195 IOHandler::~IOHandler() {}
196 int IOHandler::inputReady(int) {
197  return 0;
198 }
199 int IOHandler::outputReady(int) {
200  return 0;
201 }
202 int IOHandler::exceptionRaised(int) {
203  return 0;
204 }
205 void IOHandler::timerExpired(long, long) {}
206 void IOHandler::childStatus(pid_t, int) {}
207 #endif // MINGW
208 
209 #ifdef MINGW
210 
211 #include <nrnmutdec.h>
212 static int bind_tid_;
213 void nrniv_bind_thread(void);
214 extern int (*iv_bind_enqueue_)(void (*)(void*), void* w);
215 extern void iv_bind_call(void* w, int type);
216 extern void nrnpy_setwindowtext(void*);
217 
218 static void* w_;
219 static void (*nrn_gui_exec_)(void*);
220 
221 namespace {
222 std::unique_ptr<std::condition_variable> cond_;
223 std::mutex mut_;
224 } // namespace
225 
226 bool nrn_is_gui_thread() {
227  if (cond_ && GetCurrentThreadId() != bind_tid_) {
228  return false;
229  }
230  return true;
231 }
232 
233 int iv_bind_enqueue(void (*cb)(void*), void* w) {
234  // printf("iv_bind_enqueue %p thread %d\n", w, GetCurrentThreadId());
235  if (GetCurrentThreadId() == bind_tid_) {
236  return 0;
237  }
238  nrn_gui_exec(cb, w);
239  return 1;
240 }
241 
242 void nrn_gui_exec(void (*cb)(void*), void* v) {
243  assert(GetCurrentThreadId() != bind_tid_);
244  // wait for the gui thread to handle the operation
245  auto* const gs = neuron::python::methods.save_thread();
246  {
247  std::unique_lock<std::mutex> lock{mut_};
248  w_ = v;
249  nrn_gui_exec_ = cb;
250  cond_->wait(lock, [] { return !w_; });
251  }
253 }
254 
255 void nrniv_bind_call() {
256  if (!cond_) {
257  return;
258  }
259  std::lock_guard<std::mutex> _{mut_};
260  void* w = w_;
261  if (w_) {
262  w_ = NULL;
263  (*nrn_gui_exec_)(w);
264  // TODO: slight optimisation to release the mutex first
265  cond_->notify_one();
266  }
267 }
268 
269 
270 #endif // MINGW
271 
272 #endif // HAVE_IV
273 
275 #if HAVE_IV
276  if (hoc_usegui) {
277  bind_tid_ = int(*hoc_getarg(1));
278  // printf("nrniv_bind_thread %d\n", bind_tid_);
279  iv_bind_enqueue_ = iv_bind_enqueue;
280  cond_ = std::make_unique<std::condition_variable>();
281  w_ = NULL;
282  }
283 #endif
284  hoc_pushx(1.);
285  hoc_ret();
286 }
287 
289 #if HAVE_IV
290  if (hoc_usegui) {
291  static DWORD main_threadid = -1;
292  if (main_threadid == -1) {
293  main_threadid = GetCurrentThreadId();
294  return 1;
295  }
296  PostThreadMessage(main_threadid, WM_QUIT, 0, 0);
297  }
298 #endif
299  return 1;
300 }
#define Window
Definition: _defines.h:330
#define Canvas
Definition: _defines.h:63
#define WindowRep
Definition: _defines.h:332
Definition: graph.h:196
static Cursor * help_cursor_
Definition: ivoc.h:86
static void cleanup()
virtual void default_geometry()
void xmove(int left, int top)
void xplace(int left, int top)
virtual void hide()
int xleft() const
int xtop() const
void rubber_off(Canvas *)
void rubber_on(Canvas *)
#define v
Definition: md1redef.h:11
@ Dimension_Y
Definition: geometry.h:39
#define TRUE
Definition: grids.h:22
double * hoc_getarg(int narg)
Definition: code.cpp:1641
int ivoc_list_look(Object *ob, Object *oblook, char *path, int)
Definition: oclist.cpp:462
void hoc_ret()
void hoc_class_registration(void)
Definition: classreg.cpp:31
static int c
Definition: hoc.cpp:169
int hoc_usegui
Definition: hoc.cpp:121
#define assert(ex)
Definition: hocassrt.h:24
double * ivoc_vector_ptr(Object *o, int index)
Definition: ivocvect.cpp:3843
Object ** new_vect(Vect *v, ssize_t delta, ssize_t start, ssize_t step)
Definition: ivocvect.cpp:386
int ivoc_vector_size(Object *o)
Definition: ivocvect.cpp:3838
void hoc_pushx(double)
Definition: code.cpp:779
void nrniv_bind_thread()
Definition: ivocwin.cpp:274
int stdin_event_ready()
Definition: ivocwin.cpp:288
impl_ptrs methods
Collection of pointers to functions with python-version-specific implementations.
Definition: nrnpy.cpp:21
short type
Definition: cabvars.h:10
#define lock
static N_Vector w_
static double clip
Definition: axis.cpp:168
static double dummy
Definition: ocptrvector.cpp:23
#define NULL
Definition: spdefs.h:105
Definition: hocdec.h:173
PyThreadState *(* save_thread)()
Definition: nrnpy.h:54
void(* restore_thread)(PyThreadState *)
Definition: nrnpy.h:53