reflexion 0.2.1 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/application.cpp +1 -1
  3. data/.doc/ext/reflex/capture_event.cpp +1 -1
  4. data/.doc/ext/reflex/contact_event.cpp +1 -1
  5. data/.doc/ext/reflex/draw_event.cpp +1 -1
  6. data/.doc/ext/reflex/ellipse_shape.cpp +1 -1
  7. data/.doc/ext/reflex/event.cpp +1 -1
  8. data/.doc/ext/reflex/filter.cpp +1 -1
  9. data/.doc/ext/reflex/focus_event.cpp +1 -1
  10. data/.doc/ext/reflex/frame_event.cpp +1 -1
  11. data/.doc/ext/reflex/image_view.cpp +1 -1
  12. data/.doc/ext/reflex/key_event.cpp +74 -69
  13. data/.doc/ext/reflex/line_shape.cpp +1 -1
  14. data/.doc/ext/reflex/motion_event.cpp +1 -1
  15. data/.doc/ext/reflex/pointer.cpp +1 -1
  16. data/.doc/ext/reflex/pointer_event.cpp +1 -1
  17. data/.doc/ext/reflex/polygon_shape.cpp +1 -1
  18. data/.doc/ext/reflex/rect_shape.cpp +1 -1
  19. data/.doc/ext/reflex/reflex.cpp +58 -50
  20. data/.doc/ext/reflex/screen.cpp +1 -1
  21. data/.doc/ext/reflex/scroll_event.cpp +1 -1
  22. data/.doc/ext/reflex/selector.cpp +2 -2
  23. data/.doc/ext/reflex/shape.cpp +1 -1
  24. data/.doc/ext/reflex/style.cpp +1 -1
  25. data/.doc/ext/reflex/style_length.cpp +2 -2
  26. data/.doc/ext/reflex/timer.cpp +1 -1
  27. data/.doc/ext/reflex/timer_event.cpp +1 -1
  28. data/.doc/ext/reflex/update_event.cpp +1 -1
  29. data/.doc/ext/reflex/view.cpp +1 -1
  30. data/.doc/ext/reflex/wheel_event.cpp +1 -1
  31. data/.doc/ext/reflex/window.cpp +1 -1
  32. data/.github/workflows/release-gem.yml +1 -1
  33. data/.github/workflows/test.yml +3 -0
  34. data/ChangeLog.md +5 -0
  35. data/Rakefile +1 -1
  36. data/VERSION +1 -1
  37. data/ext/reflex/application.cpp +1 -1
  38. data/ext/reflex/capture_event.cpp +1 -1
  39. data/ext/reflex/contact_event.cpp +1 -1
  40. data/ext/reflex/defs.h +2 -0
  41. data/ext/reflex/draw_event.cpp +1 -1
  42. data/ext/reflex/ellipse_shape.cpp +1 -1
  43. data/ext/reflex/event.cpp +1 -1
  44. data/ext/reflex/extconf.rb +4 -4
  45. data/ext/reflex/filter.cpp +1 -1
  46. data/ext/reflex/focus_event.cpp +1 -1
  47. data/ext/reflex/frame_event.cpp +1 -1
  48. data/ext/reflex/image_view.cpp +1 -1
  49. data/ext/reflex/key_event.cpp +74 -69
  50. data/ext/reflex/line_shape.cpp +1 -1
  51. data/ext/reflex/motion_event.cpp +1 -1
  52. data/ext/reflex/pointer.cpp +1 -1
  53. data/ext/reflex/pointer_event.cpp +1 -1
  54. data/ext/reflex/polygon_shape.cpp +1 -1
  55. data/ext/reflex/rect_shape.cpp +1 -1
  56. data/ext/reflex/reflex.cpp +58 -50
  57. data/ext/reflex/screen.cpp +1 -1
  58. data/ext/reflex/scroll_event.cpp +1 -1
  59. data/ext/reflex/selector.cpp +2 -2
  60. data/ext/reflex/shape.cpp +1 -1
  61. data/ext/reflex/style.cpp +1 -1
  62. data/ext/reflex/style_length.cpp +2 -2
  63. data/ext/reflex/timer.cpp +1 -1
  64. data/ext/reflex/timer_event.cpp +1 -1
  65. data/ext/reflex/update_event.cpp +1 -1
  66. data/ext/reflex/view.cpp +1 -1
  67. data/ext/reflex/wheel_event.cpp +1 -1
  68. data/ext/reflex/window.cpp +1 -1
  69. data/include/reflex/defs.h +204 -187
  70. data/include/reflex/reflex.h +1 -0
  71. data/include/reflex/ruby/application.h +2 -2
  72. data/include/reflex/ruby/event.h +26 -26
  73. data/include/reflex/ruby/exception.h +3 -3
  74. data/include/reflex/ruby/filter.h +2 -2
  75. data/include/reflex/ruby/image_view.h +2 -2
  76. data/include/reflex/ruby/pointer.h +2 -2
  77. data/include/reflex/ruby/reflex.h +1 -1
  78. data/include/reflex/ruby/screen.h +2 -2
  79. data/include/reflex/ruby/selector.h +2 -2
  80. data/include/reflex/ruby/shape.h +10 -10
  81. data/include/reflex/ruby/style.h +4 -4
  82. data/include/reflex/ruby/timer.h +2 -2
  83. data/include/reflex/ruby/view.h +2 -2
  84. data/include/reflex/ruby/window.h +2 -2
  85. data/lib/reflex/extension.rb +4 -0
  86. data/reflex.gemspec +4 -4
  87. data/src/event.cpp +7 -3
  88. data/src/event.h +2 -0
  89. data/src/ios/event.mm +21 -27
  90. data/src/shape.cpp +2 -2
  91. data/src/view.cpp +1 -0
  92. data/src/win32/application.cpp +48 -35
  93. data/src/win32/device.cpp +18 -0
  94. data/src/win32/event.cpp +221 -0
  95. data/src/win32/event.h +50 -0
  96. data/src/win32/opengl.cpp +54 -27
  97. data/src/win32/opengl.h +15 -13
  98. data/src/win32/reflex.cpp +10 -16
  99. data/src/win32/screen.cpp +61 -0
  100. data/src/win32/screen.h +21 -0
  101. data/src/win32/window.cpp +445 -240
  102. data/src/window.cpp +1 -0
  103. data/test/test_window.rb +24 -21
  104. metadata +14 -11
  105. data/src/win32/defs.cpp +0 -303
  106. data/src/win32/defs.h +0 -34
data/src/win32/window.cpp CHANGED
@@ -1,12 +1,19 @@
1
- #include "reflex/window.h"
1
+ #include "../window.h"
2
2
 
3
3
 
4
+ #include <assert.h>
5
+ #include <map>
4
6
  #include <memory>
5
- #define NOMINMAX
6
- #include <windows.h>
7
- #include <rays/painter.h>
8
- #include "reflex/reflex.h"
9
- #include "reflex/view.h"
7
+ #include <xot/time.h>
8
+ #include <xot/windows.h>
9
+ #include <rays/rays.h>
10
+ #include "reflex/defs.h"
11
+ #include "reflex/application.h"
12
+ #include "reflex/exception.h"
13
+ #include "reflex/debug.h"
14
+ #include "../view.h"
15
+ #include "event.h"
16
+ #include "screen.h"
10
17
  #include "opengl.h"
11
18
 
12
19
 
@@ -14,77 +21,48 @@ namespace Reflex
14
21
  {
15
22
 
16
23
 
17
- struct Window::Data
18
- {
19
-
20
- Window* this_;
21
-
22
- HWND hwnd;
23
-
24
- int hidecount;
24
+ typedef std::map<int, String> PressingKeyMap;
25
25
 
26
- bool redraw;
27
26
 
28
- Painter painter;
29
-
30
- View::Ref root;
31
-
32
- String title_tmp;
27
+ static const char* WINDOWCLASS = "Reflex:WindowClass";
33
28
 
34
- OpenGL opengl;
29
+ static const char* USERDATA_PROP = "Reflex:Window:HWND";
35
30
 
36
- Data ()
37
- : this_(NULL), hwnd(NULL), hidecount(1), redraw(true), root(new View)
38
- {
39
- root->set_name("root");
40
- }
31
+ enum {UPDATE_TIMER_ID = 99999};
41
32
 
42
- ~Data ()
43
- {
44
- unbind();
45
- }
46
33
 
47
- void bind_reflex (Window* obj)
48
- {
49
- if (!obj) return;
34
+ struct WindowData : public Window::Data
35
+ {
50
36
 
51
- this_ = obj;
52
- }
37
+ HWND hwnd = NULL;
53
38
 
54
- void unbind_reflex ()
55
- {
56
- this_ = NULL;
57
- }
39
+ OpenGLContext context;
58
40
 
59
- void unbind ()
60
- {
61
- unbind_reflex();
62
- }
41
+ PressingKeyMap pressing_keys;
63
42
 
64
- operator bool () const
65
- {
66
- return this_ && hwnd && IsWindow(hwnd);
67
- }
43
+ mutable String title_tmp;
68
44
 
69
- bool operator ! () const
45
+ bool is_valid () const
70
46
  {
71
- return !operator bool();
47
+ return hwnd && IsWindow(hwnd);
72
48
  }
73
49
 
74
- };// Window::Data
75
-
76
- typedef std::shared_ptr<Window::Data> WindowData;
77
-
78
-
79
- static const char* WINDOWCLASS = "Reflex:WindowClass";
80
-
81
- static const char* USERDATA_PROP = "Reflex:Window:HWND";
82
-
83
- enum {UPDATE_TIMER_ID = 99999};
50
+ };// WindowData
84
51
 
85
52
 
86
53
  static LRESULT CALLBACK wndproc (HWND, UINT, WPARAM, LPARAM);
87
54
 
55
+ static WindowData*
56
+ get_data (Window* window)
57
+ {
58
+ return (WindowData*) window->self.get();
59
+ }
60
+
61
+ static const WindowData*
62
+ get_data (const Window* window)
63
+ {
64
+ return get_data(const_cast<Window*>(window));
65
+ }
88
66
 
89
67
  static bool
90
68
  window_has_wndproc (HWND hwnd)
@@ -113,88 +91,270 @@ namespace Reflex
113
91
  static Window*
114
92
  get_window_from_hwnd (HWND hwnd)
115
93
  {
116
- WindowData* data = NULL;
117
94
  if (window_has_wndproc(hwnd))
118
- data = (WindowData*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
95
+ return (Window*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
119
96
  else
120
- data = (WindowData*) GetProp(hwnd, USERDATA_PROP);
121
-
122
- return data ? (*data)->this_ : NULL;
97
+ return (Window*) GetProp(hwnd, USERDATA_PROP);
123
98
  }
124
99
 
125
- static bool
100
+ static void
126
101
  setup_window (Window* win, HWND hwnd)
127
102
  {
128
- if (!win || *win) return false;
103
+ if (*win)
104
+ Xot::invalid_state_error(__FILE__, __LINE__);
129
105
 
130
- WindowData* data = new WindowData(win->self);
106
+ WindowData* self = get_data(win);
131
107
 
132
- bool ret = false;
133
108
  if (window_has_wndproc(hwnd))
134
109
  {
135
110
  SetLastError(0);
136
- SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) data);
137
- ret = GetLastError() == 0;
111
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) win);
112
+ if (GetLastError() != 0)
113
+ system_error(__FILE__, __LINE__);
138
114
  }
139
115
  else
140
- ret = SetProp(hwnd, USERDATA_PROP, (HANDLE) data);
116
+ {
117
+ if (!SetProp(hwnd, USERDATA_PROP, (HANDLE) win))
118
+ system_error(__FILE__, __LINE__);
119
+ }
141
120
 
142
- if (ret)
121
+ self->hwnd = hwnd;
122
+ self->context.init(hwnd);
123
+ win->retain();
124
+ }
125
+
126
+ static void
127
+ cleanup_window (Window* win)
128
+ {
129
+ if (!*win)
130
+ Xot::invalid_state_error(__FILE__, __LINE__);
131
+
132
+ WindowData* self = get_data(win);
133
+
134
+ if (window_has_wndproc(self->hwnd))
143
135
  {
144
- win->self->hwnd = hwnd;
145
- win->self->opengl.init(hwnd);
136
+ SetLastError(0);
137
+ SetWindowLongPtr(self->hwnd, GWLP_USERDATA, 0);
138
+ if (GetLastError() != 0)
139
+ system_error(__FILE__, __LINE__);
146
140
  }
147
141
  else
148
- delete data;
142
+ {
143
+ if (!RemoveProp(self->hwnd, USERDATA_PROP))
144
+ system_error(__FILE__, __LINE__);
145
+ }
149
146
 
150
- return ret;
147
+ if (self->context.is_active())
148
+ Rays::activate_offscreen_context();
149
+
150
+ self->context.fin();
151
+ self->hwnd = NULL;
152
+ win->release();
151
153
  }
152
154
 
155
+ static void
156
+ update (Window* win)
157
+ {
158
+ WindowData* self = get_data(win);
159
+
160
+ double now = Xot::time();
161
+ Reflex::UpdateEvent e(now, now - self->prev_time_update);
162
+ self->prev_time_update = now;
163
+
164
+ win->on_update(&e);
165
+ if (!e.is_blocked())
166
+ Reflex::View_update_tree(win->root(), e);
167
+
168
+ if (self->redraw)
169
+ {
170
+ #if 1
171
+ InvalidateRect(self->hwnd, NULL, FALSE);
172
+ #else
173
+ RedrawWindow(
174
+ self->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | EDW_ALLCHILDREN);
175
+ #endif
176
+
177
+ self->redraw = false;
178
+ }
179
+ }
180
+
181
+ static void
182
+ draw (Window* win)
183
+ {
184
+ WindowData* self = get_data(win);
185
+
186
+ //update_pixel_density(win);
187
+
188
+ //if (update_count == 0)
189
+ //update(win);
190
+
191
+ double now = Xot::time();
192
+ double dt = now - self->prev_time_draw;
193
+ double fps = 1. / dt;
194
+
195
+ fps = self->prev_fps * 0.9 + fps * 0.1;// LPF
196
+
197
+ self->prev_time_draw = now;
198
+ self->prev_fps = fps;
199
+
200
+ Reflex::DrawEvent e(dt, fps);
201
+ Window_call_draw_event(win, &e);
202
+ }
203
+
204
+ static void
205
+ frame_changed (Window* win)
206
+ {
207
+ Rays::Bounds b = win->frame();
208
+ Rays::Point dpos = b.position() - win->self->prev_position;
209
+ Rays::Point dsize = b.size() - win->self->prev_size;
210
+ win->self->prev_position = b.position();
211
+ win->self->prev_size = b.size();
212
+
213
+ if (dpos == 0 && dsize == 0) return;
214
+
215
+ Reflex::FrameEvent e(b, dpos.x, dpos.y, 0, dsize.x, dsize.y, 0);
216
+ if (dpos != 0) win->on_move(&e);
217
+ if (dsize != 0)
218
+ {
219
+ Rays::Bounds b = win->frame();
220
+ b.move_to(0, 0);
221
+
222
+ if (win->painter())
223
+ win->painter()->canvas(b, win->painter()->pixel_density());
224
+
225
+ if (win->root())
226
+ View_set_frame(win->root(), b);
227
+
228
+ win->on_resize(&e);
229
+ }
230
+ }
231
+
232
+ static void
233
+ key_down (Window* win, UINT msg, WPARAM wp, LPARAM lp)
234
+ {
235
+ assert(*win);
236
+
237
+ WindowData* self = get_data(win);
238
+
239
+ MSG wmchar;
240
+ UINT filter = msg == WM_SYSKEYDOWN ? WM_SYSCHAR : WM_CHAR;
241
+ BOOL peeked = PeekMessage(&wmchar, self->hwnd, filter, filter, PM_NOREMOVE);
242
+
243
+ String chars;
244
+ if (peeked) chars += (char) wmchar.wParam;
245
+
246
+ NativeKeyEvent e(msg, wp, lp, chars);
247
+
248
+ self->pressing_keys.insert_or_assign(e.code(), chars);
249
+ #if 0
250
+ for (auto kv : self->pressing_keys)
251
+ doutln("0x%x : %s", kv.first, (const char*) kv.second);
252
+ #endif
253
+
254
+ Window_call_key_event(win, &e);
255
+ }
256
+
257
+ static void
258
+ key_up (Window* win, UINT msg, WPARAM wp, LPARAM lp)
259
+ {
260
+ assert(*win);
261
+
262
+ WindowData* self = get_data(win);
263
+
264
+ NativeKeyEvent e(msg, wp, lp);
265
+
266
+ auto it = self->pressing_keys.find(e.code());
267
+ if (it != self->pressing_keys.end())
268
+ KeyEvent_set_chars(&e, it->second);
269
+
270
+ Window_call_key_event(win, &e);
271
+
272
+ if (it != self->pressing_keys.end()) self->pressing_keys.erase(it);
273
+ }
274
+
275
+ #ifndef MOUSEEVENTF_FROMTOUCH
276
+ #define MOUSEEVENTF_FROMTOUCH 0xff515700
277
+ #endif
278
+
153
279
  static bool
154
- cleanup_window (Window* win)
280
+ is_from_touch_event ()
155
281
  {
156
- if (!win || !*win) return false;
282
+ return (GetMessageExtraInfo() & 0xffffff00) == MOUSEEVENTF_FROMTOUCH;
283
+ }
157
284
 
158
- HWND hwnd = win->self->hwnd;
159
- WindowData* data = NULL;
285
+ static void
286
+ mouse (Window* win, UINT msg, WPARAM wp, LPARAM lp)
287
+ {
288
+ if (is_from_touch_event()) return;
160
289
 
161
- bool has_wndproc = window_has_wndproc(hwnd);
162
- if (has_wndproc)
163
- data = (WindowData*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
164
- else
165
- data = (WindowData*) GetProp(hwnd, USERDATA_PROP);
290
+ NativePointerEvent e(msg, wp, lp);
291
+ Window_call_pointer_event(win, &e);
292
+ }
166
293
 
167
- if (!data || data->get() != win->self.get())
168
- return false;
294
+ static void
295
+ mouse_wheel (Window* win, UINT msg, WPARAM wp, LPARAM lp)
296
+ {
297
+ assert(msg == WM_MOUSEWHEEL || msg == WM_MOUSEHWHEEL);
298
+
299
+ WindowData* self = get_data(win);
169
300
 
170
- bool ret = false;
171
- if (has_wndproc)
301
+ WPARAM wp_x = 0, wp_y = 0;
302
+ if (msg == WM_MOUSEWHEEL)
172
303
  {
173
- SetLastError(0);
174
- SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
175
- ret = GetLastError() == 0;
304
+ wp_y = wp;
305
+ MSG m;
306
+ if (PeekMessage(&m, self->hwnd, WM_MOUSEHWHEEL, WM_MOUSEHWHEEL, PM_REMOVE))
307
+ wp_x = m.wParam;
176
308
  }
177
309
  else
178
- ret = RemoveProp(hwnd, USERDATA_PROP) != NULL;
179
-
180
- if (ret)
181
310
  {
182
- win->self->opengl.fin();
183
- win->self->hwnd = NULL;
184
- delete data;
311
+ wp_x = wp;
312
+ MSG m;
313
+ if (PeekMessage(&m, self->hwnd, WM_MOUSEWHEEL, WM_MOUSEWHEEL, PM_REMOVE))
314
+ wp_y = m.wParam;
185
315
  }
186
316
 
187
- return ret;
317
+ NativeWheelEvent e(wp_x, wp_y, lp);
318
+ Window_call_wheel_event(win, &e);
319
+ }
320
+
321
+ static void
322
+ touch (Window* win, UINT msg, WPARAM wp, LPARAM lp)
323
+ {
324
+ WindowData* self = get_data(win);
325
+
326
+ size_t size = LOWORD(wp);
327
+ if (size <= 0) return;
328
+
329
+ HTOUCHINPUT handle = (HTOUCHINPUT) lp;
330
+ std::unique_ptr<TOUCHINPUT[]> touches(new TOUCHINPUT[size]);
331
+
332
+ if (!GetTouchInputInfo(handle, size, &touches[0], sizeof(TOUCHINPUT)))
333
+ return;
334
+
335
+ NativePointerEvent e(self->hwnd, &touches[0], size);
336
+ Window_call_pointer_event(win, &e);
337
+
338
+ CloseTouchInputHandle(handle);
188
339
  }
189
340
 
190
341
  static LRESULT CALLBACK
191
342
  window_proc (Window* win, HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
192
343
  {
193
- if (!win || !*win || win->self->hwnd != hwnd)
344
+ if (!win || !*win || hwnd != get_data(win)->hwnd)
194
345
  return DefWindowProc(hwnd, msg, wp, lp);
195
346
 
347
+ WindowData* self = get_data(win);
348
+
196
349
  switch (msg)
197
350
  {
351
+ case WM_ACTIVATE:
352
+ {
353
+ if ((wp & 0xFFFF) == WA_INACTIVE)
354
+ self->pressing_keys.clear();
355
+ break;
356
+ }
357
+
198
358
  case WM_CLOSE:
199
359
  {
200
360
  win->close();
@@ -203,45 +363,82 @@ namespace Reflex
203
363
 
204
364
  case WM_PAINT:
205
365
  {
366
+ self->context.make_current();
367
+
206
368
  PAINTSTRUCT ps;
207
369
  BeginPaint(hwnd, &ps);
208
370
 
209
- if (win->self->opengl.make_current())
210
- {
211
- win->draw();
212
- win->self->opengl.swap_buffers();
213
- }
371
+ draw(win);
372
+ self->context.swap_buffers();
214
373
 
215
374
  EndPaint(hwnd, &ps);
216
375
  return 0;
217
376
  }
218
377
 
378
+ case WM_ERASEBKGND:
379
+ {
380
+ // do nothing.
381
+ return 0;
382
+ }
383
+
219
384
  case WM_MOVE:
220
385
  {
221
- coord x = 0, y = 0;
222
- win->get_bounds(&x, &y);
223
- win->moved(x, y);
386
+ frame_changed(win);
224
387
  break;
225
388
  }
226
389
 
227
390
  case WM_SIZE:
228
391
  {
229
- coord w = 0, h = 0;
230
- win->get_bounds(NULL, NULL, &w, &h);
231
- win->resized(w, h);
392
+ frame_changed(win);
232
393
  break;
233
394
  }
234
395
 
235
- case WM_ERASEBKGND:
396
+ case WM_KEYDOWN:
397
+ case WM_SYSKEYDOWN:
236
398
  {
237
- // do nothing.
238
- return 0;
399
+ key_down(win, msg, wp, lp);
400
+ break;
401
+ }
402
+
403
+ case WM_KEYUP:
404
+ case WM_SYSKEYUP:
405
+ {
406
+ key_up(win, msg, wp, lp);
407
+ break;
408
+ }
409
+
410
+ case WM_LBUTTONDOWN:
411
+ case WM_RBUTTONDOWN:
412
+ case WM_MBUTTONDOWN:
413
+ case WM_LBUTTONDBLCLK:
414
+ case WM_RBUTTONDBLCLK:
415
+ case WM_MBUTTONDBLCLK:
416
+ case WM_LBUTTONUP:
417
+ case WM_RBUTTONUP:
418
+ case WM_MBUTTONUP:
419
+ case WM_MOUSEMOVE:
420
+ {
421
+ mouse(win, msg, wp, lp);
422
+ break;
423
+ }
424
+
425
+ case WM_MOUSEWHEEL:
426
+ case WM_MOUSEHWHEEL:
427
+ {
428
+ mouse_wheel(win, msg, wp, lp);
429
+ break;
430
+ }
431
+
432
+ case WM_TOUCH:
433
+ {
434
+ touch(win, msg, wp, lp);
435
+ break;
239
436
  }
240
437
 
241
438
  case WM_TIMER:
242
439
  {
243
440
  if (wp == UPDATE_TIMER_ID)
244
- win->update(1);
441
+ update(win);
245
442
  return 0;
246
443
  }
247
444
 
@@ -283,17 +480,17 @@ namespace Reflex
283
480
  cleanup_window(win);
284
481
 
285
482
  if (--window_total == 0)
286
- Reflex::quit();
483
+ Reflex::app()->quit();
287
484
  }
288
485
 
289
486
  return ret;
290
487
  }
291
488
 
292
- static bool
489
+ static void
293
490
  register_windowclass ()
294
491
  {
295
492
  static bool registered = false;
296
- if (registered) return true;
493
+ if (registered) return;
297
494
 
298
495
  WNDCLASSEX wc;
299
496
  memset(&wc, 0, sizeof(wc));
@@ -301,7 +498,7 @@ namespace Reflex
301
498
  wc.cbSize = sizeof(wc);
302
499
  wc.lpszClassName = WINDOWCLASS;
303
500
  wc.lpfnWndProc = (WNDPROC) wndproc;
304
- wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
501
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
305
502
  wc.hInstance = GetModuleHandle(NULL);
306
503
  //wc.hIcon = LoadIcon(wc.hInstance, IDI_APP_LARGE);
307
504
  //wc.hIconSm = LoadIcon(wc.hInstance, IDI_APP_SMALL);
@@ -311,130 +508,135 @@ namespace Reflex
311
508
  wc.cbWndExtra = sizeof(Window*);
312
509
 
313
510
  if (!RegisterClassEx(&wc))
314
- return false;
511
+ system_error(__FILE__, __LINE__);
315
512
 
316
- return registered = true;
513
+ registered = true;
317
514
  }
318
515
 
319
- static bool
516
+ static void
320
517
  create_window (Window* win)
321
518
  {
322
- if (!win) return false;
519
+ if (*win)
520
+ invalid_state_error(__FILE__, __LINE__);
323
521
 
324
- if (!register_windowclass())
325
- return false;
326
-
327
- CreateWindowEx(
522
+ register_windowclass();
523
+ HWND hwnd = CreateWindowEx(
328
524
  0, WINDOWCLASS, "",
329
525
  WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
330
526
  0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), win);
331
- return *win;
332
- }
527
+ if (!hwnd)
528
+ system_error(__FILE__, __LINE__);
333
529
 
530
+ if (!*win)
531
+ invalid_state_error(__FILE__, __LINE__);
334
532
 
335
- Window::Window ()
336
- {
337
- self->bind_reflex(this);
533
+ if (!RegisterTouchWindow(hwnd, 0))
534
+ system_error(__FILE__, __LINE__);
535
+ }
338
536
 
339
- create_window(this);
340
537
 
341
- self->painter.canvas(0, 0, 1, 1);
538
+ Window::Data*
539
+ Window_create_data ()
540
+ {
541
+ return new WindowData();
342
542
  }
343
543
 
344
- Window::~Window ()
544
+ uint
545
+ Window_default_flags ()
345
546
  {
346
- close();
547
+ return
548
+ Window::FLAG_CLOSABLE |
549
+ Window::FLAG_RESIZABLE |
550
+ Window::FLAG_MINIMIZABLE;
551
+ }
347
552
 
348
- self->unbind_reflex();
553
+ void
554
+ Window_initialize (Window* window)
555
+ {
556
+ create_window(window);
349
557
  }
350
558
 
351
- static bool
559
+ static void
352
560
  start_timer (HWND hwnd, UINT id, UINT interval)
353
561
  {
354
- if (!hwnd) return false;
562
+ if (!hwnd)
563
+ argument_error(__FILE__, __LINE__);
355
564
 
356
- return SetTimer(hwnd, id, interval, NULL) != 0;
565
+ if (!SetTimer(hwnd, id, interval, NULL))
566
+ system_error(__FILE__, __LINE__);
357
567
  }
358
568
 
359
- static bool
569
+ static void
360
570
  stop_timer (HWND hwnd, UINT id)
361
571
  {
362
- if (!hwnd || id == 0) return false;
572
+ if (!hwnd)
573
+ argument_error(__FILE__, __LINE__);
574
+
575
+ if (id == 0) return;
363
576
 
364
- return KillTimer(hwnd, id) != FALSE;
577
+ if (!KillTimer(hwnd, id))
578
+ system_error(__FILE__, __LINE__);
365
579
  }
366
580
 
367
- bool
368
- Window::show ()
581
+ void
582
+ Window_show (Window* window)
369
583
  {
370
- if (!*this) return false;
584
+ if (!*window)
585
+ invalid_state_error(__FILE__, __LINE__);
371
586
 
372
- if (--self->hidecount != 0) return true;
587
+ WindowData* self = get_data(window);
373
588
 
374
- SetLastError(0);
375
- ShowWindow(self->hwnd, SW_SHOW);
376
- if (GetLastError() != 0) return false;
377
-
378
- if (!UpdateWindow(self->hwnd))
379
- return false;
589
+ SetWindowPos(
590
+ self->hwnd, HWND_TOP, 0, 0, 0, 0,
591
+ SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
592
+ UpdateWindow(self->hwnd);
380
593
 
381
594
  start_timer(self->hwnd, UPDATE_TIMER_ID, 1000 / 60);
382
- return true;
383
595
  }
384
596
 
385
- bool
386
- Window::hide ()
597
+ void
598
+ Window_hide (Window* window)
387
599
  {
388
- if (!*this) return false;
600
+ if (!*window)
601
+ invalid_state_error(__FILE__, __LINE__);
389
602
 
390
- if (++self->hidecount != 1) return true;
603
+ WindowData* self = get_data(window);
391
604
 
392
- SetLastError(0);
393
- ShowWindow(self->hwnd, SW_HIDE);
394
- if (GetLastError() != 0) return false;
605
+ SetWindowPos(
606
+ self->hwnd, NULL, 0, 0, 0, 0,
607
+ SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE);
395
608
 
396
609
  stop_timer(self->hwnd, UPDATE_TIMER_ID);
397
- return true;
398
610
  }
399
611
 
400
- bool
401
- Window::close ()
612
+ void
613
+ Window_close (Window* window)
402
614
  {
403
- if (!self->hwnd || !IsWindow(self->hwnd))
404
- return false;
615
+ if (!*window)
616
+ invalid_state_error(__FILE__, __LINE__);
405
617
 
406
- return DestroyWindow(self->hwnd) != FALSE;
618
+ if (!DestroyWindow(get_data(window)->hwnd))
619
+ system_error(__FILE__, __LINE__);
407
620
  }
408
621
 
409
- bool
410
- Window::redraw ()
622
+ void
623
+ Window_set_title (Window* window, const char* title)
411
624
  {
412
- if (!*this) return false;
413
-
414
- #if 1
415
- self->redraw = true;
416
- return true;
417
- #elif 1
418
- InvalidateRect(self->hwnd, NULL, FALSE);
419
- return true;
420
- #else
421
- return FALSE != RedrawWindow(
422
- self->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | EDW_ALLCHILDREN);
423
- #endif
424
- }
625
+ if (!title)
626
+ argument_error(__FILE__, __LINE__);
425
627
 
426
- bool
427
- Window::set_title (const char* title)
428
- {
429
- if (!*this || !title) return false;
628
+ if (!*window) return;
430
629
 
431
- return SetWindowText(self->hwnd, title) != FALSE;
630
+ if (!SetWindowText(get_data(window)->hwnd, title))
631
+ system_error(__FILE__, __LINE__);
432
632
  }
433
633
 
434
634
  const char*
435
- Window::title () const
635
+ Window_get_title (const Window& window)
436
636
  {
437
- if (!*this) return "";
637
+ if (!window) return "";
638
+
639
+ const WindowData* self = get_data(&window);
438
640
 
439
641
  int size = GetWindowTextLength(self->hwnd);
440
642
  if (size <= 0) return "";
@@ -447,58 +649,51 @@ namespace Reflex
447
649
  return self->title_tmp.c_str();
448
650
  }
449
651
 
450
- static bool
652
+ static void
451
653
  get_window_bounds (
452
654
  HWND hwnd, coord* x, coord* y, coord* width, coord* height,
453
655
  coord* nonclient_width = NULL, coord* nonclient_height = NULL)
454
656
  {
455
- if (
456
- !hwnd ||
457
- (!x && !y && !width && !height) ||
458
- !!nonclient_width != !!nonclient_height)
459
- {
460
- return false;
461
- }
657
+ if (!x && !y && !width && !height && !nonclient_width && !nonclient_height)
658
+ argument_error(__FILE__, __LINE__);
462
659
 
463
- RECT window, client;
464
- if (
465
- !GetWindowRect(hwnd, &window) ||
466
- !GetClientRect(hwnd, &client))
467
- {
468
- return false;
469
- }
660
+ RECT window;
661
+ if (!GetWindowRect(hwnd, &window))
662
+ system_error(__FILE__, __LINE__);
663
+
664
+ RECT client;
665
+ if (!GetClientRect(hwnd, &client))
666
+ system_error(__FILE__, __LINE__);
470
667
 
471
668
  if (x) *x = window.left;
472
669
  if (y) *y = window.top;
473
670
  if (width) *width = client.right - client.left;
474
671
  if (height) *height = client.bottom - client.top;
475
672
 
476
- if (nonclient_width || nonclient_height)
673
+ if (nonclient_width)
477
674
  {
478
675
  coord ww = window.right - window.left;
479
- coord wh = window.bottom - window.top;
480
676
  coord cw = client.right - client.left;
481
- coord ch = client.bottom - client.top;
482
-
483
677
  *nonclient_width = ww - cw;
678
+ }
679
+ if (nonclient_height)
680
+ {
681
+ coord wh = window.bottom - window.top;
682
+ coord ch = client.bottom - client.top;
484
683
  *nonclient_height = wh - ch;
485
684
  }
486
-
487
- return true;
488
685
  }
489
686
 
490
- bool
491
- Window::set_bounds (coord x, coord y, coord width, coord height)
687
+ void
688
+ Window_set_frame (Window* window, coord x, coord y, coord width, coord height)
492
689
  {
493
- if (!*this) return false;
690
+ if (!*window) return;
691
+
692
+ WindowData* self = get_data(window);
494
693
 
495
694
  coord xx, yy, ww, hh, nonclient_w, nonclient_h;
496
- if (
497
- !get_window_bounds(
498
- self->hwnd, &xx, &yy, &ww, &hh, &nonclient_w, &nonclient_h))
499
- {
500
- return false;
501
- }
695
+ get_window_bounds(
696
+ self->hwnd, &xx, &yy, &ww, &hh, &nonclient_w, &nonclient_h);
502
697
 
503
698
  width += nonclient_w;
504
699
  height += nonclient_h;
@@ -507,42 +702,52 @@ namespace Reflex
507
702
  if (x == xx && y == yy) flags |= SWP_NOMOVE;
508
703
  if (width == ww && height == hh) flags |= SWP_NOSIZE;
509
704
 
510
- if (flags == (SWP_NOMOVE | SWP_NOSIZE)) return true;
705
+ if (flags == (SWP_NOMOVE | SWP_NOSIZE))
706
+ return;
511
707
 
512
- return FALSE != SetWindowPos(
708
+ if (!SetWindowPos(
513
709
  self->hwnd, NULL, (int) x, (int) y, (int) width, (int) height,
514
- flags | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER);
515
- }
516
-
517
- bool
518
- Window::get_bounds (coord* x, coord* y, coord* width, coord* height)
519
- {
520
- return *this && get_window_bounds(self->hwnd, x, y, width, height);
710
+ flags | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER))
711
+ {
712
+ system_error(__FILE__, __LINE__);
713
+ }
521
714
  }
522
715
 
523
- bool
524
- Window::hidden () const
716
+ Bounds
717
+ Window_get_frame (const Window& window)
525
718
  {
526
- if (!*this) return true;
719
+ if (!window)
720
+ invalid_state_error(__FILE__, __LINE__);
527
721
 
528
- return self->hidecount > 0;
722
+ coord x, y, w, h;
723
+ get_window_bounds(get_data(&window)->hwnd, &x, &y, &w, &h);
724
+ return Bounds(x, y, w, h);
529
725
  }
530
726
 
531
- View*
532
- Window::root ()
727
+ Screen
728
+ Window_get_screen (const Window& window)
533
729
  {
534
- return self->root.get();
730
+ Screen s;
731
+ HMONITOR hmonitor =
732
+ MonitorFromWindow(get_data(&window)->hwnd, MONITOR_DEFAULTTONULL);
733
+ if (hmonitor) Screen_initialize(&s, hmonitor);
734
+ return s;
535
735
  }
536
736
 
537
- Painter*
538
- Window::painter ()
737
+ void
738
+ Window_set_flags (Window* window, uint flags)
539
739
  {
540
- return &self->painter;
740
+ if (Xot::has_flag(flags, Window::FLAG_PORTRAIT))
741
+ argument_error(__FILE__, __LINE__, "FLAG_PORTRAIT is not supported");
742
+
743
+ if (Xot::has_flag(flags, Window::FLAG_LANDSCAPE))
744
+ argument_error(__FILE__, __LINE__, "FLAG_LANDSCAPE is not supported");
541
745
  }
542
746
 
543
- Window::operator bool () const
747
+ float
748
+ Window_get_pixel_density (const Window& window)
544
749
  {
545
- return self && *self;
750
+ return 1;
546
751
  }
547
752
 
548
753