reflexion 0.2.1 → 0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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