1use {
2 std::{
3 cell::{
4 RefCell,
5 Cell,
6 },
7 rc::Rc,
8 ffi::OsStr,
9 os::windows::ffi::OsStrExt,
10 mem,
11 },
12
13 crate::{
14 windows::{
15 core::PCWSTR,
16 core::IntoParam,
17 core::Result as coreResult,
18 core::HRESULT,
19 Win32::{
20 Foundation::{
21 HWND,
22 HANDLE,
23 HGLOBAL,
24 WPARAM,
25 LPARAM,
26 LRESULT,
27 RECT,
28 POINT,
29 POINTL,
30 },
31 System::{
32 Memory::{
33 GlobalLock,
34 GlobalAlloc,
35 GlobalSize,
36 GlobalUnlock,
37 GLOBAL_ALLOC_FLAGS,
38 },
39 Ole::{
40 CF_UNICODETEXT,
41 DROPEFFECT,
44 DROPEFFECT_COPY,
45 DROPEFFECT_MOVE,
46 DROPEFFECT_LINK,
47 },
48 SystemServices::{
49 MODIFIERKEYS_FLAGS,
50 MK_CONTROL,
51 MK_SHIFT,
52 },
53 WindowsProgramming::GMEM_DDESHARE,
54 DataExchange::{
55 OpenClipboard,
56 EmptyClipboard,
57 GetClipboardData,
58 SetClipboardData,
59 CloseClipboard,
60 },
61 LibraryLoader::GetModuleHandleW,
62 },
63 UI::{
64 WindowsAndMessaging::{
65 CreateWindowExW,
66 SetWindowLongPtrW,
67 GetWindowLongPtrW,
68 DefWindowProcW,
69 ShowWindow,
70 PostMessageW,
71 GetWindowRect,
72 DestroyWindow,
73 SetWindowPos,
74 GetWindowPlacement,
75 WINDOWPLACEMENT,
76 GetClientRect,
77 MoveWindow,
78 GWL_EXSTYLE,
79 HWND_TOPMOST,
80 HWND_NOTOPMOST,
81 WS_SIZEBOX,
82 WS_MAXIMIZEBOX,
83 WS_MINIMIZEBOX,
84 WS_POPUP,
85 WS_CLIPSIBLINGS,
86 WS_CLIPCHILDREN,
87 WS_SYSMENU,
88 WS_EX_WINDOWEDGE,
89 WS_EX_APPWINDOW,
90 WS_EX_ACCEPTFILES,
91 WS_EX_TOPMOST,
92 CW_USEDEFAULT,
93 GWLP_USERDATA,
94 SW_SHOW,
95 SW_RESTORE,
96 SW_MAXIMIZE,
97 SW_MINIMIZE,
98 SWP_NOMOVE,
99 SWP_NOSIZE,
100 WM_ACTIVATE,
101 WM_NCCALCSIZE,
102 WM_NCHITTEST,
103 WA_ACTIVE,
104 WM_ERASEBKGND,
105 WM_MOUSEMOVE,
106 WM_MOUSEWHEEL,
107 WM_LBUTTONDOWN,
108 WM_LBUTTONUP,
109 WM_RBUTTONDOWN,
110 WM_RBUTTONUP,
111 WM_MBUTTONDOWN,
112 WM_MBUTTONUP,
113 WM_KEYDOWN,
114 WM_SYSKEYDOWN,
115 WM_CLOSE,
116 WM_KEYUP,
117 WM_SYSKEYUP,
118 WM_CHAR,
119 WM_ENTERSIZEMOVE,
120 WM_EXITSIZEMOVE,
121 WM_SIZE,
122 WM_DPICHANGED,
123 WM_DESTROY,
124 HTTOPLEFT,
125 HTBOTTOMLEFT,
126 HTLEFT,
127 HTTOPRIGHT,
128 HTBOTTOMRIGHT,
129 HTRIGHT,
130 HTTOP,
131 HTBOTTOM,
132 HTCLIENT,
133 HTCAPTION,
134 HTSYSMENU
135 },
136 Controls::{
137 MARGINS,
138 WM_MOUSELEAVE
139 },
140 Input::KeyboardAndMouse::{
141 VIRTUAL_KEY,
142 ReleaseCapture,
143 SetCapture,
144 TrackMouseEvent,
145 GetKeyState,
146 TRACKMOUSEEVENT,
147 TME_LEAVE,
148 VK_CONTROL,
149 VK_SHIFT,
150 VK_MENU,
151 VK_LWIN,
152 VK_RWIN,
153 VK_ESCAPE,
154 VK_OEM_3,
155 VK_0,
156 VK_1,
157 VK_2,
158 VK_3,
159 VK_4,
160 VK_5,
161 VK_6,
162 VK_7,
163 VK_8,
164 VK_9,
165 VK_OEM_MINUS,
166 VK_OEM_PLUS,
167 VK_BACK,
168 VK_TAB,
169 VK_Q,
170 VK_W,
171 VK_E,
172 VK_R,
173 VK_T,
174 VK_Y,
175 VK_U,
176 VK_I,
177 VK_O,
178 VK_P,
179 VK_OEM_4,
180 VK_OEM_6,
181 VK_RETURN,
182 VK_A,
183 VK_S,
184 VK_D,
185 VK_F,
186 VK_G,
187 VK_H,
188 VK_J,
189 VK_K,
190 VK_L,
191 VK_OEM_1,
192 VK_OEM_7,
193 VK_OEM_5,
194 VK_Z,
195 VK_X,
196 VK_C,
197 VK_V,
198 VK_B,
199 VK_N,
200 VK_M,
201 VK_OEM_COMMA,
202 VK_OEM_PERIOD,
203 VK_OEM_2,
204 VK_LCONTROL,
205 VK_RCONTROL,
206 VK_LMENU,
207 VK_RMENU,
208 VK_LSHIFT,
209 VK_RSHIFT,
210 VK_SPACE,
211 VK_CAPITAL,
212 VK_F1,
213 VK_F2,
214 VK_F3,
215 VK_F4,
216 VK_F5,
217 VK_F6,
218 VK_F7,
219 VK_F8,
220 VK_F9,
221 VK_F10,
222 VK_F11,
223 VK_F12,
224 VK_SNAPSHOT,
225 VK_SCROLL,
226 VK_PAUSE,
227 VK_INSERT,
228 VK_DELETE,
229 VK_HOME,
230 VK_END,
231 VK_PRIOR,
232 VK_NEXT,
233 VK_NUMPAD0,
234 VK_NUMPAD1,
235 VK_NUMPAD2,
236 VK_NUMPAD3,
237 VK_NUMPAD4,
238 VK_NUMPAD5,
239 VK_NUMPAD6,
240 VK_NUMPAD7,
241 VK_NUMPAD8,
242 VK_NUMPAD9,
243 VK_SUBTRACT,
244 VK_ADD,
245 VK_DECIMAL,
246 VK_MULTIPLY,
247 VK_DIVIDE,
248 VK_NUMLOCK,
249 VK_UP,
250 VK_DOWN,
251 VK_LEFT,
252 VK_RIGHT,
253 },
254 },
255 Graphics::{
256 Dwm::DwmExtendFrameIntoClientArea,
257 Gdi::ScreenToClient,
258 },
259 },
260 },
261 event::*,
262 area::Area,
263 os::windows::{
264 win32_app::{
265 Win32App,
266 encode_wide,
267 FALSE,
268 get_win32_app_global,
269 },
270 win32_event::*,
271 droptarget::*,
272 },
273 window::WindowId,
274 cx::*,
275 cursor::MouseCursor,
276 },
277};
278
279#[allow(non_snake_case)]
281pub unsafe fn RegisterDragDrop<P0, P1>(hwnd: P0, pdroptarget: P1) -> coreResult<()>
282where
283 P0: IntoParam<HWND>,
284 P1: IntoParam<IDropTarget>,
285{
286 ::windows_targets::link!("ole32.dll" "system" fn RegisterDragDrop(hwnd : HWND, pdroptarget : * mut::core::ffi::c_void) -> HRESULT);
287 RegisterDragDrop(hwnd.into_param().abi(), pdroptarget.into_param().abi()).ok()
288}
289
290pub struct Win32Window {
292 pub window_id: WindowId,
293 pub last_window_geom: WindowGeom,
294
295 pub mouse_buttons_down: usize,
296 pub last_key_mod: KeyModifiers,
297 pub ime_spot: DVec2,
298 pub current_cursor: MouseCursor,
299 pub last_mouse_pos: DVec2,
300 pub ignore_wmsize: usize,
301 pub hwnd: HWND,
302 pub track_mouse_event: bool,
303}
304
305impl Win32Window {
306
307 pub fn new(window_id: WindowId,title: &str, position: Option<DVec2>) -> Win32Window {
311
312 let title = encode_wide(title);
313
314 let style = WS_SIZEBOX
315 | WS_MAXIMIZEBOX
316 | WS_MINIMIZEBOX
317 | WS_POPUP
318 | WS_CLIPSIBLINGS
319 | WS_CLIPCHILDREN
320 | WS_SYSMENU;
321
322 let style_ex = WS_EX_WINDOWEDGE
323 | WS_EX_APPWINDOW
324 | WS_EX_ACCEPTFILES;
325
326 let (x, y) = if let Some(position) = position {
327 (position.x as i32, position.y as i32)
328 }
329 else {
330 (CW_USEDEFAULT, CW_USEDEFAULT)
331 };
332
333 let hwnd = unsafe { CreateWindowExW(
334 style_ex,
335 PCWSTR(get_win32_app_global().window_class_name.as_ptr()),
336 PCWSTR(title.as_ptr()),
337 style,
338 x,
339 y,
340 CW_USEDEFAULT,
341 CW_USEDEFAULT,
342 None,
343 None,
344 GetModuleHandleW(None).unwrap(),
345 None,
346 ) };
347
348 let drop_target: IDropTarget = DropTarget { drag_item: RefCell::new(None),hwnd, }.into();
350 unsafe { RegisterDragDrop(hwnd, &drop_target).unwrap() };
351
352 Win32Window {
353 window_id,
354 mouse_buttons_down: 0,
355 last_window_geom: WindowGeom::default(),
356 last_key_mod: KeyModifiers::default(),
357 ime_spot: DVec2::default(),
358 current_cursor: MouseCursor::Default,
359 last_mouse_pos: DVec2::default(),
360 ignore_wmsize: 0,
361 hwnd,
362 track_mouse_event: false,
363 }
364 }
365
366 pub fn init(&mut self,size: DVec2) {
368
369 unsafe { SetWindowLongPtrW(self.hwnd, GWLP_USERDATA, self as *const _ as isize) };
370
371 get_win32_app_global().dpi_functions.enable_non_client_dpi_scaling(self.hwnd);
372 get_win32_app_global().all_windows.push(self.hwnd);
373
374 self.set_outer_size(size);
375 }
376
377 pub unsafe extern "system" fn window_class_proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM,) -> LRESULT {
378
379 let user_data = GetWindowLongPtrW(hwnd, GWLP_USERDATA);
380 if user_data == 0 {
381 return DefWindowProcW(hwnd, msg, wparam, lparam);
382 };
383
384 let window = &mut (*(user_data as *mut Win32Window));
385 match msg {
386 WM_ACTIVATE => {
387 if wparam.0 & 0xffff == WA_ACTIVE as usize {
388 window.do_callback(Win32Event::AppGotFocus);
389 }
390 else {
391 window.do_callback(Win32Event::AppLostFocus);
392 }
393 },
394 WM_NCCALCSIZE => {
395 if window.get_is_maximized() {
397 return DefWindowProcW(hwnd, msg, wparam, lparam);
398 }
399 if wparam == WPARAM(1) {
400 let margins = MARGINS {
401 cxLeftWidth: 0,
402 cxRightWidth: 0,
403 cyTopHeight: 0,
404 cyBottomHeight: 1
405 };
406 DwmExtendFrameIntoClientArea(hwnd, &margins).unwrap();
407 return LRESULT(0)
408 }
409 },
410 WM_NCHITTEST => {
411 let abs = window.get_mouse_pos_from_lparam(lparam);
414 let mut rect = RECT {left: 0, top: 0, bottom: 0, right: 0};
415 const EDGE: f64 = 4.0;
416 let dpi = window.get_dpi_factor();
417 GetWindowRect(hwnd, &mut rect).unwrap();
418 let rect = Rect{pos:dvec2(rect.left as f64 / dpi, rect.top as f64 / dpi),
419 size:dvec2( (rect.right-rect.left) as f64 / dpi, (rect.bottom-rect.top) as f64/ dpi)
420 };
421 if abs.x < rect.pos.x + EDGE {
422 if abs.y < rect.pos.y + EDGE {
423 get_win32_app_global().set_mouse_cursor(MouseCursor::NwseResize);
424 return LRESULT(HTTOPLEFT as isize);
425 }
426 if abs.y > rect.pos.y + rect.size.y - EDGE {
427 get_win32_app_global().set_mouse_cursor(MouseCursor::NeswResize);
428 return LRESULT(HTBOTTOMLEFT as isize);
429 }
430 get_win32_app_global().set_mouse_cursor(MouseCursor::EwResize);
431 return LRESULT(HTLEFT as isize);
432 }
433 if abs.x > rect.pos.x+rect.size.x - EDGE {
434 if abs.y < rect.pos.y + EDGE {
435 get_win32_app_global().set_mouse_cursor(MouseCursor::NeswResize);
436 return LRESULT(HTTOPRIGHT as isize);
437 }
438 if abs.y > rect.pos.y + rect.size.y - EDGE {
439 get_win32_app_global().set_mouse_cursor(MouseCursor::NwseResize);
440 return LRESULT(HTBOTTOMRIGHT as isize);
441 }
442 get_win32_app_global().set_mouse_cursor(MouseCursor::EwResize);
443 return LRESULT(HTRIGHT as isize);
444 }
445 if abs.y < rect.pos.y + EDGE {
446 get_win32_app_global().set_mouse_cursor(MouseCursor::NsResize);
447 return LRESULT(HTTOP as isize);
448 }
449 if abs.y > rect.pos.y+rect.size.y - EDGE {
450 get_win32_app_global().set_mouse_cursor(MouseCursor::NsResize);
451 return LRESULT(HTBOTTOM as isize);
452 }
453 let response = Rc::new(Cell::new(WindowDragQueryResponse::NoAnswer));
454 window.do_callback(
455 Win32Event::WindowDragQuery(WindowDragQueryEvent {
456 window_id: window.window_id,
457 abs: window.get_mouse_pos_from_lparam(lparam)- rect.pos,
458 response: response.clone()
459 })
460 );
461 match response.get() {
462 WindowDragQueryResponse::Client => {
463 return LRESULT(HTCLIENT as isize);
464 }
465 WindowDragQueryResponse::Caption => {
466 get_win32_app_global().set_mouse_cursor(MouseCursor::Default);
467 return LRESULT(HTCAPTION as isize);
468 },
469 WindowDragQueryResponse::SysMenu => {
470 get_win32_app_global().set_mouse_cursor(MouseCursor::Default);
471 return LRESULT(HTSYSMENU as isize);
472 }
473 _ => ()
474 }
475 return LRESULT(HTCLIENT as isize);
476 },
477 WM_ERASEBKGND => {
478 return LRESULT(1)
479 },
480 WM_MOUSEMOVE => {
481 if get_win32_app_global().start_dragging_items.is_some(){
482 return LRESULT(0)
483 }
484 if !window.track_mouse_event {
485 window.track_mouse_event = true;
486 let mut tme = TRACKMOUSEEVENT {
487 cbSize: mem::size_of::<TRACKMOUSEEVENT>() as u32,
488 dwFlags: TME_LEAVE,
489 hwndTrack: hwnd,
490 dwHoverTime: 0
491 };
492 TrackMouseEvent(&mut tme).unwrap();
493 }
494 window.send_mouse_move(
495 window.get_mouse_pos_from_lparam(lparam),
496 Self::get_key_modifiers()
497 )
498 },
499 WM_MOUSELEAVE => {
500 if get_win32_app_global().start_dragging_items.is_some() {
501 return LRESULT(0)
502 }
503 window.track_mouse_event = false;
504 window.send_mouse_move(
505 window.last_mouse_pos,
506 Self::get_key_modifiers()
507 );
508 get_win32_app_global().current_cursor = MouseCursor::Hidden;
509 },
510 WM_MOUSEWHEEL => {
511 let delta = (wparam.0 >> 16) as u16 as i16 as f64;
512 window.send_scroll(DVec2 {x: 0.0, y: -delta}, Self::get_key_modifiers(), true);
513 },
514 WM_LBUTTONDOWN => {
515 get_win32_app_global().currently_clicked_window_id = Some(window.window_id);
517 window.send_mouse_down(0, Self::get_key_modifiers());
518 },
519 WM_LBUTTONUP => window.send_mouse_up(0, Self::get_key_modifiers()),
520 WM_RBUTTONDOWN => window.send_mouse_down(1, Self::get_key_modifiers()),
521 WM_RBUTTONUP => window.send_mouse_up(1, Self::get_key_modifiers()),
522 WM_MBUTTONDOWN => window.send_mouse_down(2, Self::get_key_modifiers()),
523 WM_MBUTTONUP => window.send_mouse_up(2, Self::get_key_modifiers()),
524 WM_KEYDOWN | WM_SYSKEYDOWN => {
525 let modifiers = Self::get_key_modifiers();
527 let key_code = Self::virtual_key_to_key_code(wparam);
528 if modifiers.alt && key_code == KeyCode::F4 {
529 PostMessageW(hwnd, WM_CLOSE, WPARAM(0), LPARAM(0)).unwrap();
530 }
531 if modifiers.control || modifiers.logo {
532 match key_code {
533 KeyCode::KeyV => { if let Ok(()) = OpenClipboard(None) {
535 let mut data: Vec<u16> = Vec::new();
536 let h_clipboard_data = GetClipboardData(CF_UNICODETEXT.0 as u32).unwrap();
537 let h_clipboard_ptr = GlobalLock(std::mem::transmute::<_,HGLOBAL>(h_clipboard_data)) as *mut u16;
538 let clipboard_size = GlobalSize(std::mem::transmute::<_,HGLOBAL>(h_clipboard_data));
539 if clipboard_size > 2 {
540 data.resize((clipboard_size >> 1) - 1, 0);
541 std::ptr::copy_nonoverlapping(h_clipboard_ptr, data.as_mut_ptr(), data.len());
542 GlobalUnlock(std::mem::transmute::<_,HGLOBAL>(h_clipboard_data)).unwrap();
543 CloseClipboard().unwrap();
544 if let Ok(utf8) = String::from_utf16(&data) {
545 window.do_callback(
546 Win32Event::TextInput(TextInputEvent {
547 input: utf8,
548 was_paste: true,
549 replace_last: false
550 })
551 );
552 }
553 }
554 else {
555 GlobalUnlock(std::mem::transmute::<_,HGLOBAL>(h_clipboard_data)).unwrap();
556 CloseClipboard().unwrap();
557 }
558 }
559 }
560 KeyCode::KeyC => {
561 let response = Rc::new(RefCell::new(None));
562 window.do_callback(
563 Win32Event::TextCut(TextClipboardEvent {
564 response: response.clone()
565 })
566 );
567 let response = response.borrow();
568 if let Some(response) = response.as_ref() {
569 Self::copy_to_clipboard(response);
570 }
571 },
572 KeyCode::KeyX => {
573 let response = Rc::new(RefCell::new(None));
574 window.do_callback(
575 Win32Event::TextCut(TextClipboardEvent {
576 response: response.clone()
577 })
578 );
579 let response = response.borrow();
580 if let Some(response) = response.as_ref() {
581 Self::copy_to_clipboard(response);
582 }
583 }
584 _ => ()
585 }
586 }
587 window.do_callback(
588 Win32Event::KeyDown(KeyEvent {
589 key_code: key_code,
590 is_repeat: (lparam.0 & 0x7000_0000)>0,
591 modifiers: modifiers,
592 time: window.time_now()
593 })
594 );
595 },
596 WM_KEYUP | WM_SYSKEYUP => {
597 window.do_callback(
598 Win32Event::KeyUp(KeyEvent {
599 key_code: Self::virtual_key_to_key_code(wparam),
600 is_repeat: lparam.0 & 0x7fff>0,
601 modifiers: Self::get_key_modifiers(),
602 time: window.time_now()
603 })
604 );
605
606 },
607 WM_CHAR => {
608 if let Ok(utf8) = String::from_utf16(&[wparam.0 as u16]) {
609 let char_code = utf8.chars().next().unwrap();
610 if char_code >= ' ' {
611 window.do_callback(
612 Win32Event::TextInput(TextInputEvent {
613 input: utf8,
614 was_paste: false,
615 replace_last: false
616 })
617 );
618 }
619 }
620 },
621 WM_ENTERSIZEMOVE => {
622 get_win32_app_global().start_resize();
623 window.do_callback(Win32Event::WindowResizeLoopStart(window.window_id));
624 }
625 WM_EXITSIZEMOVE => {
626 get_win32_app_global().stop_resize();
627 window.do_callback(Win32Event::WindowResizeLoopStop(window.window_id));
628 },
629 WM_SIZE | WM_DPICHANGED => {
630 window.send_change_event();
631 },
632 WM_CLOSE => { let accept_close = Rc::new(Cell::new(true));
634 window.do_callback(Win32Event::WindowCloseRequested(WindowCloseRequestedEvent {
635 window_id: window.window_id,
636 accept_close: accept_close.clone()
637 }));
638 if accept_close.get() {
639 DestroyWindow(hwnd).unwrap();
640 }
641 },
642 WM_DESTROY => { window.do_callback(
644 Win32Event::WindowClosed(WindowClosedEvent {
645 window_id: window.window_id,
646 })
647 );
648 },
649
650 WM_DROPTARGET => {
652
653 let message = unsafe { Box::from_raw(lparam.0 as *mut DropTargetMessage) };
655
656 match *message {
657
658 DropTargetMessage::Leave => {
659 if get_win32_app_global().is_dragging_internal.get() {
660 window.do_callback(Win32Event::DragEnd);
662 }
663 },
664 DropTargetMessage::Enter(flags,mut point,effect,drag_item) |
665 DropTargetMessage::Over(flags,mut point,effect,drag_item) => {
666
667 unsafe { ScreenToClient(window.hwnd,&mut point as *mut POINTL as *mut POINT) };
669 let response = if (effect & DROPEFFECT_LINK) != DROPEFFECT(0) { DragResponse::Link }
670 else if (effect & DROPEFFECT_MOVE) != DROPEFFECT(0) { DragResponse::Move }
671 else if (effect & DROPEFFECT_COPY) != DROPEFFECT(0) { DragResponse::Copy }
672 else { DragResponse::None };
673
674 let dpi_factor = window.get_dpi_factor();
675
676 window.do_callback(
678 Win32Event::Drag(
679 DragEvent {
680 modifiers: KeyModifiers {
681 shift: (flags & MK_SHIFT) != MODIFIERKEYS_FLAGS(0),
682 control: (flags & MK_CONTROL) != MODIFIERKEYS_FLAGS(0),
683 alt: false, logo: false, },
686 handled: Cell::new(false),
687 abs: DVec2 { x: point.x as f64 / dpi_factor,y: point.y as f64 / dpi_factor, },
688 items: Rc::new(vec![drag_item]),
689 response: Rc::new(Cell::new(response)),
690 }
691 )
692 );
693 },
694
695 DropTargetMessage::Drop(flags,mut point,_effect,drag_item) => {
696
697 unsafe { ScreenToClient(window.hwnd,&mut point as *mut POINTL as *mut POINT) };
699
700 let dpi_factor = window.get_dpi_factor();
702
703 window.do_callback(
705 Win32Event::Drop(
706 DropEvent {
707 modifiers: KeyModifiers {
708 shift: (flags & MK_SHIFT) != MODIFIERKEYS_FLAGS(0),
709 control: (flags & MK_CONTROL) != MODIFIERKEYS_FLAGS(0),
710 alt: false, logo: false, },
713 handled: Cell::new(false),
714 abs: DVec2 { x: point.x as f64 / dpi_factor,y: point.y as f64 / dpi_factor, },
715 items: Rc::new(vec![drag_item]),
716 }
717 )
718 );
719
720 window.do_callback(
721 Win32Event::DragEnd
722 );
723 },
724 }
725 },
726
727 _ => {
728 return DefWindowProcW(hwnd, msg, wparam, lparam)
729 }
730 }
731 return LRESULT(1)
732 }
737
738 unsafe fn copy_to_clipboard(text: &String) {
739 if let Ok(()) = OpenClipboard(None) {
742 EmptyClipboard().unwrap();
743
744 let data: Vec<u16> = OsStr::new(text).encode_wide().chain(Some(0).into_iter()).collect();
745
746 let h_clipboard_data = GlobalAlloc(GLOBAL_ALLOC_FLAGS(GMEM_DDESHARE), 2 * data.len()).expect("GlobalAlloc for clipboard failed");
747
748 let h_clipboard_ptr = GlobalLock(h_clipboard_data) as *mut u16;
749
750 std::ptr::copy_nonoverlapping(data.as_ptr(), h_clipboard_ptr, data.len());
751
752 GlobalUnlock(h_clipboard_data).unwrap();
753 SetClipboardData(CF_UNICODETEXT.0 as u32, std::mem::transmute::<_,HANDLE>(h_clipboard_data)).unwrap();
754 CloseClipboard().unwrap();
755 }
756 }
757
758 pub fn get_mouse_pos_from_lparam(&self, lparam: LPARAM) -> DVec2 {
759 let dpi = self.get_dpi_factor();
760 let ycoord = (lparam.0 >> 16) as u16 as i16 as f64;
761 let xcoord = (lparam.0 & 0xffff) as u16 as i16 as f64;
762 DVec2 {x: xcoord / dpi, y: ycoord / dpi}
763 }
764
765 pub fn get_key_modifiers() -> KeyModifiers {
766 unsafe {
767 KeyModifiers {
768 control: GetKeyState(VK_CONTROL.0 as i32) & 0x80>0,
769 shift: GetKeyState(VK_SHIFT.0 as i32) & 0x80>0,
770 alt: GetKeyState(VK_MENU.0 as i32) & 0x80>0,
771 logo: GetKeyState(VK_LWIN.0 as i32) & 0x80>0
772 || GetKeyState(VK_RWIN.0 as i32) & 0x80>0,
773 }
774 }
775 }
776
777 pub fn on_mouse_move(&self) {
778 }
779
780 pub fn set_mouse_cursor(&mut self, _cursor: MouseCursor) {
781 }
782
783 pub fn restore(&self) {
784 unsafe {
785 ShowWindow(self.hwnd, SW_RESTORE);
786 PostMessageW(self.hwnd, WM_SIZE, WPARAM(0), LPARAM(0)).unwrap();
787 }
788 }
789
790 pub fn maximize(&self) {
791 unsafe {
792 ShowWindow(self.hwnd, SW_MAXIMIZE);
793 PostMessageW(self.hwnd, WM_SIZE, WPARAM(0), LPARAM(0)).unwrap();
794 }
795 }
796
797 pub fn close_window(&self) {
798 unsafe {
799 DestroyWindow(self.hwnd).unwrap();
800 }
801 }
802
803 pub fn show(&self) {
804 unsafe {
805 ShowWindow(self.hwnd, SW_SHOW);
806 }
807 }
808
809 pub fn minimize(&self) {
810 unsafe {
811 ShowWindow(self.hwnd, SW_MINIMIZE);
812 }
813 }
814
815 pub fn set_topmost(&self, topmost: bool) {
816 unsafe {
817 if topmost {
818 SetWindowPos(
819 self.hwnd,
820 HWND_TOPMOST,
821 0,
822 0,
823 0,
824 0,
825 SWP_NOMOVE | SWP_NOSIZE
826 ).unwrap();
827 }
828 else {
829 SetWindowPos(
830 self.hwnd,
831 HWND_NOTOPMOST,
832 0,
833 0,
834 0,
835 0,
836 SWP_NOMOVE | SWP_NOSIZE
837 ).unwrap();
838 }
839 }
840 }
841
842 pub fn get_is_topmost(&self) -> bool {
843 unsafe {
844 let ex_style = GetWindowLongPtrW(self.hwnd, GWL_EXSTYLE);
845 if ex_style as u32 & WS_EX_TOPMOST.0 != 0 {
846 return true
847 }
848 return false
849 }
850 }
851
852 pub fn get_window_geom(&self) -> WindowGeom {
853 WindowGeom {
854 xr_is_presenting: false,
855 can_fullscreen: false,
856 is_topmost: self.get_is_topmost(),
857 is_fullscreen: self.get_is_maximized(),
858 inner_size: if self.get_is_maximized(){self.get_outer_size()}else{self.get_inner_size()},
859 outer_size: self.get_outer_size(),
860 dpi_factor: self.get_dpi_factor(),
861 position: self.get_position()
862 }
863 }
864
865 pub fn get_is_maximized(&self) -> bool {
866 unsafe {
867 let wp: mem::MaybeUninit<WINDOWPLACEMENT> = mem::MaybeUninit::uninit();
868 let mut wp = wp.assume_init();
869 wp.length = mem::size_of::<WINDOWPLACEMENT>() as u32;
870 GetWindowPlacement(self.hwnd, &mut wp).unwrap();
871 if wp.showCmd == SW_MAXIMIZE.0 as u32 {
872 return true
873 }
874 return false
875 }
876 }
877
878 pub fn time_now(&self) -> f64 {
879 get_win32_app_global().time_now()
880 }
881
882 pub fn set_ime_spot(&mut self, spot: DVec2) {
883 self.ime_spot = spot;
884 }
885
886 pub fn get_position(&self) -> DVec2 {
887 unsafe {
888 let mut rect = RECT {left: 0, top: 0, bottom: 0, right: 0};
889 GetWindowRect(self.hwnd, &mut rect).unwrap();
890 DVec2 {x: rect.left as f64, y: rect.top as f64}
891 }
892 }
893
894 pub fn get_inner_size(&self) -> DVec2 {
895 unsafe {
896 let mut rect = RECT {left: 0, top: 0, bottom: 0, right: 0};
897 GetClientRect(self.hwnd, &mut rect).unwrap();
898 let dpi = self.get_dpi_factor();
899 DVec2 {x: (rect.right - rect.left) as f64 / dpi, y: (rect.bottom - rect.top)as f64 / dpi}
900 }
901 }
902
903 pub fn get_outer_size(&self) -> DVec2 {
904 unsafe {
905 let mut rect = RECT {left: 0, top: 0, bottom: 0, right: 0};
906 GetWindowRect(self.hwnd, &mut rect).unwrap();
907 let dpi = self.get_dpi_factor();
908 DVec2 {x: (rect.right - rect.left) as f64/ dpi, y: (rect.bottom - rect.top)as f64/ dpi}
909 }
910 }
911
912 pub fn set_position(&mut self, pos: DVec2) {
913 unsafe {
914 let mut window_rect = RECT {left: 0, top: 0, bottom: 0, right: 0};
915 GetWindowRect(self.hwnd, &mut window_rect).unwrap();
916 let dpi = self.get_dpi_factor();
917 MoveWindow(
918 self.hwnd,
919 (pos.x * dpi) as i32,
920 (pos.y * dpi) as i32,
921 window_rect.right - window_rect.left,
922 window_rect.bottom - window_rect.top,
923 FALSE
924 ).unwrap();
925 }
926 }
927
928 pub fn set_outer_size(&self, size: DVec2) {
929 unsafe {
930 let mut window_rect = RECT {left: 0, top: 0, bottom: 0, right: 0};
931 GetWindowRect(self.hwnd, &mut window_rect).unwrap();
932 let dpi = self.get_dpi_factor();
933 MoveWindow(
934 self.hwnd,
935 window_rect.left,
936 window_rect.top,
937 (size.x * dpi) as i32,
938 (size.y * dpi) as i32,
939 FALSE
940 ).unwrap();
941 }
942 }
943
944 pub fn set_inner_size(&self, size: DVec2) {
945 unsafe {
946 let mut window_rect = RECT {left: 0, top: 0, bottom: 0, right: 0};
947 GetWindowRect(self.hwnd, &mut window_rect).unwrap();
948 let mut client_rect = RECT {left: 0, top: 0, bottom: 0, right: 0};
949 GetClientRect(self.hwnd, &mut client_rect).unwrap();
950 let dpi = self.get_dpi_factor();
951 MoveWindow(
952 self.hwnd,
953 window_rect.left,
954 window_rect.top,
955 (size.x * dpi) as i32
956 + ((window_rect.right - window_rect.left) - (client_rect.right - client_rect.left)),
957 (size.y * dpi) as i32
958 + ((window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top)),
959 FALSE
960 ).unwrap();
961 }
962 }
963
964 pub fn get_dpi_factor(&self) -> f64 {
965 get_win32_app_global().dpi_functions.hwnd_dpi_factor(self.hwnd) as f64
966 }
967
968 pub fn do_callback(&mut self, event: Win32Event) {
969 Win32App::do_callback(event);
970 }
971
972 pub fn send_change_event(&mut self) {
973
974 let new_geom = self.get_window_geom();
975 let old_geom = self.last_window_geom.clone();
976 self.last_window_geom = new_geom.clone();
977
978 self.do_callback(
979 Win32Event::WindowGeomChange(WindowGeomChangeEvent {
980 window_id: self.window_id,
981 old_geom: old_geom,
982 new_geom: new_geom
983 }),
984 );
985 self.do_callback(
986 Win32Event::Paint
987 );
988 }
989
990 pub fn send_focus_event(&mut self) {
991 self.do_callback(Win32Event::AppGotFocus);
992 }
993
994 pub fn send_focus_lost_event(&mut self) {
995 self.do_callback(Win32Event::AppLostFocus);
996 }
997
998 pub fn send_mouse_down(&mut self, button: usize, modifiers: KeyModifiers) {
999 if self.mouse_buttons_down == 0 {
1000 unsafe {SetCapture(self.hwnd);}
1001 }
1002 self.mouse_buttons_down += 1;
1003 self.do_callback(Win32Event::MouseDown(MouseDownEvent {
1004 button,
1005 modifiers,
1006 window_id: self.window_id,
1007 abs: self.last_mouse_pos,
1008 time: self.time_now(),
1009 handled: Cell::new(Area::Empty),
1010 }));
1011 }
1012
1013 pub fn send_mouse_up(&mut self, button: usize, modifiers: KeyModifiers) {
1014 if self.mouse_buttons_down > 1 {
1015 self.mouse_buttons_down -= 1;
1016 }
1017 else {
1018 unsafe { ReleaseCapture().unwrap(); }
1019 self.mouse_buttons_down = 0;
1020 }
1021 self.do_callback(Win32Event::MouseUp(MouseUpEvent {
1022 button,
1023 modifiers,
1024 window_id: self.window_id,
1025 abs: self.last_mouse_pos,
1026 time: self.time_now()
1027 }));
1028 }
1029
1030 pub fn send_mouse_move(&mut self, pos: DVec2, modifiers: KeyModifiers) {
1031 self.last_mouse_pos = pos;
1032 self.do_callback(Win32Event::MouseMove(MouseMoveEvent {
1033 window_id: self.window_id,
1034 abs: pos,
1035 modifiers: modifiers,
1036 time: self.time_now(),
1037 handled: Cell::new(Area::Empty),
1038 }));
1039 }
1040
1041 pub fn send_scroll(&mut self, scroll: DVec2, modifiers: KeyModifiers, is_mouse: bool) {
1042 self.do_callback(
1043 Win32Event::Scroll(ScrollEvent {
1044 window_id: self.window_id,
1045 scroll,
1046 abs: self.last_mouse_pos,
1047 modifiers,
1048 time: self.time_now(),
1049 is_mouse,
1050 handled_x: Cell::new(false),
1051 handled_y: Cell::new(false),
1052 })
1053 );
1054 }
1055
1056 pub fn send_close_requested_event(&mut self) -> bool {
1057 let accept_close = Rc::new(Cell::new(true));
1058 self.do_callback(Win32Event::WindowCloseRequested(WindowCloseRequestedEvent {
1059 window_id: self.window_id,
1060 accept_close: accept_close.clone()
1061 }));
1062 if !accept_close.get() {
1063 return false
1064 }
1065 true
1066 }
1067
1068 pub fn send_text_input(&mut self, input: String, replace_last: bool) {
1069 self.do_callback(Win32Event::TextInput(TextInputEvent {
1070 input: input,
1071 was_paste: false,
1072 replace_last: replace_last
1073 }))
1074 }
1075
1076 pub fn virtual_key_to_key_code(wparam: WPARAM) -> KeyCode {
1077 match VIRTUAL_KEY(wparam.0 as u16) {
1078 VK_ESCAPE => KeyCode::Escape,
1079 VK_OEM_3 => KeyCode::Backtick,
1080 VK_0 => KeyCode::Key0,
1081 VK_1 => KeyCode::Key1,
1082 VK_2 => KeyCode::Key2,
1083 VK_3 => KeyCode::Key3,
1084 VK_4 => KeyCode::Key4,
1085 VK_5 => KeyCode::Key5,
1086 VK_6 => KeyCode::Key6,
1087 VK_7 => KeyCode::Key7,
1088 VK_8 => KeyCode::Key8,
1089 VK_9 => KeyCode::Key9,
1090 VK_OEM_MINUS => KeyCode::Minus,
1091 VK_OEM_PLUS => KeyCode::Equals,
1092 VK_BACK => KeyCode::Backspace,
1093 VK_TAB => KeyCode::Tab,
1094 VK_Q => KeyCode::KeyQ,
1095 VK_W => KeyCode::KeyW,
1096 VK_E => KeyCode::KeyE,
1097 VK_R => KeyCode::KeyR,
1098 VK_T => KeyCode::KeyT,
1099 VK_Y => KeyCode::KeyY,
1100 VK_U => KeyCode::KeyU,
1101 VK_I => KeyCode::KeyI,
1102 VK_O => KeyCode::KeyO,
1103 VK_P => KeyCode::KeyP,
1104 VK_OEM_4 => KeyCode::LBracket,
1105 VK_OEM_6 => KeyCode::RBracket,
1106 VK_RETURN => KeyCode::ReturnKey,
1107 VK_A => KeyCode::KeyA,
1108 VK_S => KeyCode::KeyS,
1109 VK_D => KeyCode::KeyD,
1110 VK_F => KeyCode::KeyF,
1111 VK_G => KeyCode::KeyG,
1112 VK_H => KeyCode::KeyH,
1113 VK_J => KeyCode::KeyJ,
1114 VK_K => KeyCode::KeyK,
1115 VK_L => KeyCode::KeyL,
1116 VK_OEM_1 => KeyCode::Semicolon,
1117 VK_OEM_7 => KeyCode::Quote,
1118 VK_OEM_5 => KeyCode::Backslash,
1119 VK_Z => KeyCode::KeyZ,
1120 VK_X => KeyCode::KeyX,
1121 VK_C => KeyCode::KeyC,
1122 VK_V => KeyCode::KeyV,
1123 VK_B => KeyCode::KeyB,
1124 VK_N => KeyCode::KeyN,
1125 VK_M => KeyCode::KeyM,
1126 VK_OEM_COMMA => KeyCode::Comma,
1127 VK_OEM_PERIOD => KeyCode::Period,
1128 VK_OEM_2 => KeyCode::Slash,
1129 VK_LCONTROL => KeyCode::Control,
1130 VK_RCONTROL => KeyCode::Control,
1131 VK_CONTROL => KeyCode::Control,
1132 VK_LMENU => KeyCode::Alt,
1133 VK_RMENU => KeyCode::Alt,
1134 VK_MENU => KeyCode::Alt,
1135 VK_LSHIFT => KeyCode::Shift,
1136 VK_RSHIFT => KeyCode::Shift,
1137 VK_SHIFT => KeyCode::Shift,
1138 VK_LWIN => KeyCode::Logo,
1139 VK_RWIN => KeyCode::Logo,
1140 VK_SPACE => KeyCode::Space,
1141 VK_CAPITAL => KeyCode::Capslock,
1142 VK_F1 => KeyCode::F1,
1143 VK_F2 => KeyCode::F2,
1144 VK_F3 => KeyCode::F3,
1145 VK_F4 => KeyCode::F4,
1146 VK_F5 => KeyCode::F5,
1147 VK_F6 => KeyCode::F6,
1148 VK_F7 => KeyCode::F7,
1149 VK_F8 => KeyCode::F8,
1150 VK_F9 => KeyCode::F9,
1151 VK_F10 => KeyCode::F10,
1152 VK_F11 => KeyCode::F11,
1153 VK_F12 => KeyCode::F12,
1154 VK_SNAPSHOT => KeyCode::PrintScreen,
1155 VK_SCROLL => KeyCode::ScrollLock,
1156 VK_PAUSE => KeyCode::Pause,
1157 VK_INSERT => KeyCode::Insert,
1158 VK_DELETE => KeyCode::Delete,
1159 VK_HOME => KeyCode::Home,
1160 VK_END => KeyCode::End,
1161 VK_PRIOR => KeyCode::PageUp,
1162 VK_NEXT => KeyCode::PageDown,
1163 VK_NUMPAD0 => KeyCode::Numpad0,
1164 VK_NUMPAD1 => KeyCode::Numpad1,
1165 VK_NUMPAD2 => KeyCode::Numpad2,
1166 VK_NUMPAD3 => KeyCode::Numpad3,
1167 VK_NUMPAD4 => KeyCode::Numpad4,
1168 VK_NUMPAD5 => KeyCode::Numpad5,
1169 VK_NUMPAD6 => KeyCode::Numpad6,
1170 VK_NUMPAD7 => KeyCode::Numpad7,
1171 VK_NUMPAD8 => KeyCode::Numpad8,
1172 VK_NUMPAD9 => KeyCode::Numpad9,
1173 VK_SUBTRACT => KeyCode::NumpadSubtract,
1174 VK_ADD => KeyCode::NumpadAdd,
1175 VK_DECIMAL => KeyCode::NumpadDecimal,
1176 VK_MULTIPLY => KeyCode::NumpadMultiply,
1177 VK_DIVIDE => KeyCode::NumpadDivide,
1178 VK_NUMLOCK => KeyCode::Numlock,
1179 VK_UP => KeyCode::ArrowUp,
1180 VK_DOWN => KeyCode::ArrowDown,
1181 VK_LEFT => KeyCode::ArrowLeft,
1182 VK_RIGHT => KeyCode::ArrowRight,
1183 _ => KeyCode::Unknown
1184 }
1185 }
1186}
1187