wita/
procedure.rs

1#[cfg(feature = "raw_input")]
2use crate::raw_input;
3use crate::{
4    api::*,
5    context::*,
6    device::*,
7    event,
8    event::{EventHandler, ResizingEdge},
9    geometry::*,
10    ime,
11    window::{Style, Window},
12};
13use std::panic::catch_unwind;
14use std::path::PathBuf;
15use windows::core::HSTRING;
16use windows::Win32::{
17    Foundation::*, Graphics::Gdi::*, System::SystemServices::*, UI::Controls::WM_MOUSELEAVE,
18    UI::HiDpi::*, UI::Input::Ime::*, UI::Input::KeyboardAndMouse::*, UI::Shell::*,
19    UI::WindowsAndMessaging::*,
20};
21
22#[derive(Clone, Copy, PartialEq, Eq, Debug)]
23#[repr(usize)]
24pub(crate) enum UserMessage {
25    SetTitle,
26    SetPosition,
27    SetInnerSize,
28    EnableIme,
29    DisableIme,
30    SetStyle,
31    AcceptDragFiles,
32}
33
34/*
35#[inline]
36fn loword(x: i32) -> i16 {
37    (x & 0xffff) as _
38}
39*/
40
41#[inline]
42fn hiword(x: i32) -> i16 {
43    ((x >> 16) & 0xffff) as _
44}
45
46#[inline]
47fn get_x_lparam(lp: LPARAM) -> i16 {
48    (lp.0 & 0xffff) as _
49}
50
51#[inline]
52fn get_y_lparam(lp: LPARAM) -> i16 {
53    ((lp.0 >> 16) & 0xffff) as _
54}
55
56#[inline]
57fn get_xbutton_wparam(wp: WPARAM) -> u16 {
58    ((wp.0 >> 16) & 0xffff) as _
59}
60
61#[inline]
62fn get_keystate_wparam(wp: WPARAM) -> u32 {
63    (wp.0 & 0xffff) as _
64}
65
66#[inline]
67fn lparam_to_point(lparam: LPARAM) -> PhysicalPosition<i32> {
68    PhysicalPosition::new(get_x_lparam(lparam) as i32, get_y_lparam(lparam) as i32)
69}
70
71#[inline]
72fn wparam_to_button(wparam: WPARAM) -> MouseButton {
73    match get_xbutton_wparam(wparam) {
74        0x0001 => MouseButton::Ex(0),
75        0x0002 => MouseButton::Ex(1),
76        _ => unreachable!(),
77    }
78}
79
80fn update_buttons(buttons: &mut Vec<MouseButton>, wparam: WPARAM) {
81    buttons.clear();
82    let values = get_keystate_wparam(wparam);
83    if values & MK_LBUTTON.0 != 0 {
84        buttons.push(MouseButton::Left);
85    }
86    if values & MK_RBUTTON.0 != 0 {
87        buttons.push(MouseButton::Right);
88    }
89    if values & MK_MBUTTON.0 != 0 {
90        buttons.push(MouseButton::Middle);
91    }
92    if values & MK_XBUTTON1.0 != 0 {
93        buttons.push(MouseButton::Ex(0));
94    }
95    if values & MK_XBUTTON2.0 != 0 {
96        buttons.push(MouseButton::Ex(1));
97    }
98}
99
100fn mouse_input<T: EventHandler + 'static>(
101    window: &Window,
102    button: MouseButton,
103    button_state: KeyState,
104    wparam: WPARAM,
105    lparam: LPARAM,
106) -> LRESULT {
107    call_handler(|eh: &mut T, state| {
108        match button_state {
109            KeyState::Pressed => unsafe {
110                SetCapture(HWND(window.raw_handle() as _));
111            },
112            KeyState::Released => unsafe {
113                ReleaseCapture();
114            },
115        }
116        let buttons = &mut state.mouse_buttons;
117        update_buttons(buttons, wparam);
118        let ev = event::MouseInput {
119            window,
120            button,
121            button_state,
122            mouse_state: MouseState {
123                position: lparam_to_point(lparam),
124                buttons,
125            },
126        };
127        eh.mouse_input(ev);
128    });
129    LRESULT(0)
130}
131
132fn mouse_wheel<T: EventHandler + 'static>(
133    window: &Window,
134    dir: MouseWheelAxis,
135    wparam: WPARAM,
136    lparam: LPARAM,
137) -> LRESULT {
138    call_handler(|eh: &mut T, state| {
139        let delta = hiword(wparam.0 as _);
140        let buttons = &mut state.mouse_buttons;
141        update_buttons(buttons, wparam);
142        let ev = event::MouseWheel {
143            window,
144            axis: dir,
145            distance: delta as i32,
146            mouse_state: MouseState {
147                position: lparam_to_point(lparam),
148                buttons,
149            },
150        };
151        eh.mouse_wheel(ev);
152    });
153    LRESULT(0)
154}
155
156fn key_input<T: EventHandler + 'static>(
157    window: &Window,
158    state: KeyState,
159    wparam: WPARAM,
160    lparam: LPARAM,
161) -> LRESULT {
162    let scan_code = ScanCode(((lparam.0 >> 16) & 0x7f) as u32);
163    call_handler(|eh: &mut T, _| {
164        let ev = event::KeyInput {
165            window,
166            key_code: KeyCode::new(as_virtual_key(VIRTUAL_KEY(wparam.0 as _)), scan_code),
167            state,
168            prev_pressed: (lparam.0 >> 30) & 0x01 != 0,
169        };
170        eh.key_input(ev);
171    });
172    LRESULT(0)
173}
174
175pub(crate) extern "system" fn window_proc<T: EventHandler + 'static>(
176    hwnd: HWND,
177    msg: u32,
178    wparam: WPARAM,
179    lparam: LPARAM,
180) -> LRESULT {
181    let ret = catch_unwind(|| unsafe {
182        let window = find_window(hwnd);
183        if window.is_none() {
184            return DefWindowProcW(hwnd, msg, wparam, lparam);
185        }
186        let window = window.unwrap();
187        let handle = &window.handle;
188        match msg {
189            WM_PAINT => {
190                let mut ps = PAINTSTRUCT::default();
191                BeginPaint(hwnd, &mut ps);
192                call_handler(|eh: &mut T, _| eh.draw(event::Draw { window: handle }));
193                EndPaint(hwnd, &ps);
194                LRESULT(0)
195            }
196            #[cfg(feature = "raw_input")]
197            WM_INPUT => raw_input::wm_input::<T>(handle, hwnd, wparam, lparam),
198            WM_MOUSEMOVE => {
199                call_handler(|eh: &mut T, state| {
200                    let position = lparam_to_point(lparam);
201                    update_buttons(&mut state.mouse_buttons, wparam);
202                    if state.entered_window.is_none() {
203                        TrackMouseEvent(&mut TRACKMOUSEEVENT {
204                            cbSize: std::mem::size_of::<TRACKMOUSEEVENT>() as _,
205                            dwFlags: TME_LEAVE,
206                            hwndTrack: hwnd,
207                            dwHoverTime: 0,
208                        });
209                        state.entered_window = Some(window.clone());
210                        eh.cursor_entered(event::CursorEntered {
211                            window: handle,
212                            mouse_state: MouseState {
213                                position,
214                                buttons: &state.mouse_buttons,
215                            },
216                        });
217                    } else {
218                        eh.cursor_moved(event::CursorMoved {
219                            window: handle,
220                            mouse_state: MouseState {
221                                position,
222                                buttons: &state.mouse_buttons,
223                            },
224                        });
225                    }
226                });
227                let wnd = handle.state.read().unwrap();
228                wnd.cursor.set();
229                LRESULT(0)
230            }
231            WM_MOUSELEAVE => {
232                call_handler(|eh: &mut T, state| {
233                    state.entered_window = None;
234                    update_buttons(&mut state.mouse_buttons, wparam);
235                    let mut pos = POINT::default();
236                    GetCursorPos(&mut pos);
237                    eh.cursor_left(event::CursorLeft {
238                        window: handle,
239                        mouse_state: MouseState {
240                            position: PhysicalPosition::new(pos.x, pos.y),
241                            buttons: &mut state.mouse_buttons,
242                        },
243                    });
244                });
245                LRESULT(0)
246            }
247            WM_LBUTTONDOWN => {
248                mouse_input::<T>(handle, MouseButton::Left, KeyState::Pressed, wparam, lparam)
249            }
250            WM_RBUTTONDOWN => mouse_input::<T>(
251                handle,
252                MouseButton::Right,
253                KeyState::Pressed,
254                wparam,
255                lparam,
256            ),
257            WM_MBUTTONDOWN => mouse_input::<T>(
258                handle,
259                MouseButton::Middle,
260                KeyState::Pressed,
261                wparam,
262                lparam,
263            ),
264            WM_XBUTTONDOWN => mouse_input::<T>(
265                handle,
266                wparam_to_button(wparam),
267                KeyState::Pressed,
268                wparam,
269                lparam,
270            ),
271            WM_LBUTTONUP => mouse_input::<T>(
272                handle,
273                MouseButton::Left,
274                KeyState::Released,
275                wparam,
276                lparam,
277            ),
278            WM_RBUTTONUP => mouse_input::<T>(
279                handle,
280                MouseButton::Right,
281                KeyState::Released,
282                wparam,
283                lparam,
284            ),
285            WM_MBUTTONUP => mouse_input::<T>(
286                handle,
287                MouseButton::Middle,
288                KeyState::Released,
289                wparam,
290                lparam,
291            ),
292            WM_XBUTTONUP => mouse_input::<T>(
293                handle,
294                wparam_to_button(wparam),
295                KeyState::Released,
296                wparam,
297                lparam,
298            ),
299            WM_MOUSEWHEEL => mouse_wheel::<T>(handle, MouseWheelAxis::Vertical, wparam, lparam),
300            WM_MOUSEHWHEEL => mouse_wheel::<T>(handle, MouseWheelAxis::Horizontal, wparam, lparam),
301            WM_KEYDOWN => key_input::<T>(handle, KeyState::Pressed, wparam, lparam),
302            WM_KEYUP => key_input::<T>(handle, KeyState::Released, wparam, lparam),
303            WM_CHAR => {
304                call_handler(|eh: &mut T, _| {
305                    if let Some(c) = std::char::from_u32(wparam.0 as u32) {
306                        eh.char_input(event::CharInput { window: handle, c });
307                    }
308                });
309                LRESULT(0)
310            }
311            WM_IME_SETCONTEXT => {
312                let lparam = {
313                    let state = handle.state.read().unwrap();
314                    let mut lparam = lparam.0 as u32;
315                    if !state.visible_ime_composition_window {
316                        lparam &= !ISC_SHOWUICOMPOSITIONWINDOW;
317                    }
318                    if !state.visible_ime_candidate_window {
319                        lparam &= !ISC_SHOWUICANDIDATEWINDOW;
320                        lparam &= !(ISC_SHOWUICANDIDATEWINDOW << 1);
321                        lparam &= !(ISC_SHOWUICANDIDATEWINDOW << 2);
322                        lparam &= !(ISC_SHOWUICANDIDATEWINDOW << 3);
323                    }
324                    LPARAM(lparam as _)
325                };
326                DefWindowProcW(hwnd, msg, wparam, lparam)
327            }
328            WM_IME_STARTCOMPOSITION => {
329                {
330                    let imc = ime::Imc::get(hwnd);
331                    let state = handle.state.read().unwrap();
332                    if state.visible_ime_composition_window {
333                        imc.set_composition_window_position(state.ime_position);
334                    }
335                    if state.visible_ime_candidate_window {
336                        imc.set_candidate_window_position(
337                            state.ime_position,
338                            state.visible_ime_composition_window,
339                        );
340                    }
341                }
342                call_handler(|eh: &mut T, _| {
343                    eh.ime_start_composition(event::ImeStartComposition { window: handle });
344                });
345                DefWindowProcW(hwnd, msg, wparam, lparam)
346            }
347            WM_IME_COMPOSITION => {
348                call_handler(|eh: &mut T, _| {
349                    let imc = ime::Imc::get(hwnd);
350                    if (lparam.0 as u32) & GCS_COMPSTR.0 != 0 {
351                        let s = imc.get_composition_string(GCS_COMPSTR);
352                        let attrs = imc.get_composition_string(GCS_COMPATTR);
353                        let clause = imc.get_composition_string(GCS_COMPCLAUSE);
354                        if let (
355                            Some(ime::CompositionString::CompStr(s)),
356                            Some(ime::CompositionString::CompAttr(attrs)),
357                            Some(ime::CompositionString::CompClause(clause)),
358                        ) = (s, attrs, clause)
359                        {
360                            eh.ime_composition(event::ImeComposition {
361                                window: handle,
362                                composition: &ime::Composition::new(s, attrs, clause),
363                                candidate_list: imc.get_candidate_list().as_ref(),
364                                cursor_position: imc.get_cursor_position(),
365                            });
366                        }
367                    } else if (lparam.0 as u32) & GCS_RESULTSTR.0 != 0 {
368                        let s = imc.get_composition_string(GCS_COMPSTR);
369                        let attrs = imc.get_composition_string(GCS_COMPATTR);
370                        let clause = imc.get_composition_string(GCS_COMPCLAUSE);
371                        if let (
372                            Some(ime::CompositionString::CompStr(s)),
373                            Some(ime::CompositionString::CompAttr(attrs)),
374                            Some(ime::CompositionString::CompClause(clause)),
375                        ) = (s, attrs, clause)
376                        {
377                            eh.ime_composition(event::ImeComposition {
378                                window: handle,
379                                composition: &ime::Composition::new(s, attrs, clause),
380                                candidate_list: None,
381                                cursor_position: imc.get_cursor_position(),
382                            });
383                        }
384                    }
385                });
386                let show_composition_window = {
387                    let state = handle.state.read().unwrap();
388                    state.visible_ime_composition_window
389                };
390                if show_composition_window {
391                    DefWindowProcW(hwnd, msg, wparam, lparam)
392                } else {
393                    LRESULT(0)
394                }
395            }
396            WM_IME_ENDCOMPOSITION => {
397                call_handler(|eh: &mut T, _| {
398                    let imc = ime::Imc::get(hwnd);
399                    let ret = imc.get_composition_string(GCS_RESULTSTR);
400                    let ret = if let Some(ime::CompositionString::ResultStr(s)) = &ret {
401                        Some(s.as_str())
402                    } else {
403                        None
404                    };
405                    let ev = event::ImeEndComposition {
406                        window: handle,
407                        result: ret,
408                    };
409                    eh.ime_end_composition(ev);
410                });
411                DefWindowProcW(hwnd, msg, wparam, lparam)
412            }
413            WM_ACTIVATE => {
414                let active = ((wparam.0 as u32) & WA_ACTIVE) != 0;
415                let click_active = ((wparam.0 as u32) & WA_CLICKACTIVE) != 0;
416                if active || click_active {
417                    call_handler(|eh: &mut T, _| eh.activated(event::Activated { window: handle }));
418                } else {
419                    call_handler(|eh: &mut T, _| {
420                        eh.inactivated(event::Inactivated { window: handle })
421                    });
422                }
423                LRESULT(0)
424            }
425            WM_SIZING => {
426                set_resizing(true);
427                let d = {
428                    let mut wrc = RECT::default();
429                    GetWindowRect(hwnd, &mut wrc);
430                    let mut crc = RECT::default();
431                    GetClientRect(hwnd, &mut crc);
432                    PhysicalSize::new(
433                        (wrc.right - wrc.left) - (crc.right - crc.left),
434                        (wrc.bottom - wrc.top) - (crc.bottom - crc.top),
435                    )
436                };
437                let mut rc = (lparam.0 as *mut RECT).as_mut().unwrap();
438                let mut size = Size::new(
439                    (rc.right - rc.left - d.width) as u32,
440                    (rc.bottom - rc.top - d.height) as u32,
441                );
442                let edge = match wparam.0 as u32 {
443                    WMSZ_LEFT => ResizingEdge::Left,
444                    WMSZ_RIGHT => ResizingEdge::Right,
445                    WMSZ_TOP => ResizingEdge::Top,
446                    WMSZ_TOPLEFT => ResizingEdge::TopLeft,
447                    WMSZ_TOPRIGHT => ResizingEdge::TopRight,
448                    WMSZ_BOTTOM => ResizingEdge::Bottom,
449                    WMSZ_BOTTOMLEFT => ResizingEdge::BottomLeft,
450                    WMSZ_BOTTOMRIGHT => ResizingEdge::BottomRight,
451                    _ => unreachable!(),
452                };
453                call_handler(|eh: &mut T, _| {
454                    eh.resizing(event::Resizing {
455                        window: handle,
456                        size: &mut size,
457                        edge,
458                    });
459                });
460                let tmp = adjust_window_rect(
461                    size,
462                    handle.style().value(),
463                    WINDOW_EX_STYLE(0),
464                    handle.dpi(),
465                );
466                rc.right = rc.left + tmp.right - tmp.left;
467                rc.bottom = rc.top + tmp.bottom - tmp.top;
468                DefWindowProcW(hwnd, msg, wparam, lparam)
469            }
470            WM_SIZE => {
471                match wparam.0 as u32 {
472                    SIZE_MINIMIZED => {
473                        call_handler(|eh: &mut T, _| {
474                            eh.minimized(event::Minimized { window: handle });
475                        });
476                        set_minimized(true);
477                        set_maximized(false);
478                    }
479                    SIZE_MAXIMIZED => {
480                        call_handler(|eh: &mut T, _| {
481                            eh.maximized(event::Maximized {
482                                window: handle,
483                                size: PhysicalSize::new(
484                                    get_x_lparam(lparam) as u32,
485                                    get_y_lparam(lparam) as u32,
486                                ),
487                            });
488                        });
489                        set_minimized(false);
490                        set_maximized(true);
491                    }
492                    SIZE_RESTORED => {
493                        call_handler(|eh: &mut T, state| {
494                            if state.minimized || state.maximized {
495                                eh.restored(event::Restored {
496                                    window: handle,
497                                    size: PhysicalSize::new(
498                                        get_x_lparam(lparam) as u32,
499                                        get_y_lparam(lparam) as u32,
500                                    ),
501                                });
502                                set_minimized(false);
503                                set_maximized(false);
504                            }
505                        });
506                    }
507                    _ => {}
508                }
509                LRESULT(0)
510            }
511            WM_WINDOWPOSCHANGED => {
512                let pos = &*(lparam.0 as *const WINDOWPOS);
513                if pos.flags & SWP_NOMOVE == SET_WINDOW_POS_FLAGS(0) {
514                    call_handler(|eh: &mut T, _| {
515                        eh.moved(event::Moved {
516                            window: handle,
517                            position: ScreenPosition::new(pos.x, pos.y),
518                        });
519                    });
520                }
521                DefWindowProcW(hwnd, msg, wparam, lparam)
522            }
523            WM_EXITSIZEMOVE => {
524                let size = handle.inner_size();
525                call_handler(|eh: &mut T, state| {
526                    if state.resizing {
527                        eh.resized(event::Resized {
528                            window: handle,
529                            size,
530                        });
531                        set_resizing(false);
532                    }
533                });
534                DefWindowProcW(hwnd, msg, wparam, lparam)
535            }
536            WM_DPICHANGED => {
537                let mut prev_rc = RECT::default();
538                GetWindowRect(hwnd, &mut prev_rc);
539                let rc = *(lparam.0 as *const RECT);
540                SetWindowPos(
541                    hwnd,
542                    HWND(0),
543                    rc.left,
544                    rc.top,
545                    rc.right - rc.left,
546                    rc.bottom - rc.top,
547                    SWP_NOZORDER | SWP_NOACTIVATE,
548                );
549                let new_dpi = hiword(wparam.0 as _) as u32;
550                call_handler(|eh: &mut T, _| {
551                    eh.dpi_changed(event::DpiChanged {
552                        window: handle,
553                        new_dpi,
554                    })
555                });
556                let prev_size = prev_rc.right - prev_rc.left;
557                let next_size = rc.right - rc.left;
558                let children = child_windows(hwnd);
559                for child in children {
560                    let child_rc = {
561                        let mut rc = RECT::default();
562                        let mut screen = RECT::default();
563                        GetWindowRect(child, &mut screen);
564                        let mut pt = POINT {
565                            x: screen.left,
566                            y: screen.top,
567                        };
568                        ScreenToClient(hwnd, &mut pt);
569                        rc.left = pt.x;
570                        rc.top = pt.y;
571                        let mut pt = POINT {
572                            x: screen.right,
573                            y: screen.bottom,
574                        };
575                        ScreenToClient(hwnd, &mut pt);
576                        rc.right = pt.x;
577                        rc.bottom = pt.y;
578                        rc
579                    };
580                    let pt = PhysicalPosition::new(
581                        child_rc.left * next_size / prev_size,
582                        child_rc.top * next_size / prev_size,
583                    );
584                    let size = PhysicalSize::new(
585                        (child_rc.right - child_rc.left) * next_size / prev_size,
586                        (child_rc.bottom - child_rc.top) * next_size / prev_size,
587                    );
588                    SetWindowPos(
589                        child,
590                        HWND(0),
591                        pt.x,
592                        pt.y,
593                        size.width,
594                        size.height,
595                        SWP_NOACTIVATE | SWP_NOZORDER,
596                    );
597                    if let Some(child) = find_window(child) {
598                        call_handler(|eh: &mut T, _| {
599                            eh.dpi_changed(event::DpiChanged {
600                                window: &child.handle,
601                                new_dpi,
602                            })
603                        });
604                    }
605                }
606                LRESULT(0)
607            }
608            WM_GETDPISCALEDSIZE => {
609                let prev_dpi = GetDpiForWindow(hwnd) as i32;
610                let next_dpi = wparam.0 as i32;
611                let mut rc = RECT::default();
612                GetClientRect(hwnd, &mut rc);
613                let size = PhysicalSize::new(
614                    ((rc.right - rc.left) * next_dpi / prev_dpi) as u32,
615                    ((rc.bottom - rc.top) * next_dpi / prev_dpi) as u32,
616                );
617                let rc = adjust_window_rect(
618                    size,
619                    WINDOW_STYLE(GetWindowLongPtrW(hwnd, GWL_STYLE) as _),
620                    WINDOW_EX_STYLE(GetWindowLongPtrW(hwnd, GWL_EXSTYLE) as _),
621                    next_dpi as u32,
622                );
623                let mut ret = (lparam.0 as *mut SIZE).as_mut().unwrap();
624                ret.cx = rc.right - rc.left;
625                ret.cy = rc.bottom - rc.top;
626                LRESULT(1)
627            }
628            WM_DROPFILES => {
629                let hdrop = HDROP(wparam.0 as _);
630                let file_count = DragQueryFileW(hdrop, std::u32::MAX, None);
631                let mut buffer = Vec::new();
632                let files = (0..file_count)
633                    .map(|i| {
634                        let len = DragQueryFileW(hdrop, i, None) as usize + 1;
635                        buffer.resize(len, 0);
636                        DragQueryFileW(hdrop, i, Some(&mut buffer));
637                        buffer.pop();
638                        PathBuf::from(String::from_utf16_lossy(&buffer))
639                    })
640                    .collect::<Vec<_>>();
641                let files_ref = files.iter().map(|pb| pb.as_path()).collect::<Vec<_>>();
642                let mut pt = POINT::default();
643                DragQueryPoint(hdrop, &mut pt);
644                call_handler(|eh: &mut T, _| {
645                    eh.drop_files(event::DropFiles {
646                        window: handle,
647                        paths: &files_ref,
648                        position: PhysicalPosition::new(pt.x, pt.y),
649                    });
650                });
651                DragFinish(hdrop);
652                LRESULT(0)
653            }
654            #[cfg(feature = "raw_input")]
655            WM_INPUT_DEVICE_CHANGE => {
656                raw_input::wm_input_device_change::<T>(handle, hwnd, wparam, lparam)
657            }
658            WM_DESTROY => {
659                {
660                    let mut state = handle.state.write().unwrap();
661                    state.closed = true;
662                }
663                call_handler(|eh: &mut T, _| {
664                    eh.closed(event::Closed { window: handle });
665                    {
666                        let state = handle.state.read().unwrap();
667                        for child in state.children.iter() {
668                            child.close();
669                        }
670                    }
671                });
672                remove_window(hwnd);
673                if window_table_is_empty() {
674                    PostQuitMessage(0);
675                }
676                LRESULT(0)
677            }
678            WM_NCCREATE => {
679                EnableNonClientDpiScaling(hwnd);
680                DefWindowProcW(hwnd, msg, wparam, lparam)
681            }
682            WM_USER => {
683                match wparam.0 {
684                    w if w == UserMessage::SetTitle as usize => {
685                        let state = handle.state.read().unwrap();
686                        SetWindowTextW(hwnd, &HSTRING::from(&state.title));
687                    }
688                    w if w == UserMessage::SetPosition as usize => {
689                        let state = handle.state.read().unwrap();
690                        SetWindowPos(
691                            hwnd,
692                            HWND(0),
693                            state.set_position.0,
694                            state.set_position.1,
695                            0,
696                            0,
697                            SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE,
698                        );
699                    }
700                    w if w == UserMessage::SetInnerSize as usize => {
701                        let state = handle.state.read().unwrap();
702                        let rc = adjust_window_rect(
703                            state.set_inner_size,
704                            WINDOW_STYLE(GetWindowLongPtrW(hwnd, GWL_STYLE) as _),
705                            WINDOW_EX_STYLE(GetWindowLongPtrW(hwnd, GWL_EXSTYLE) as _),
706                            GetDpiForWindow(hwnd),
707                        );
708                        SetWindowPos(
709                            hwnd,
710                            HWND(0),
711                            0,
712                            0,
713                            rc.right - rc.left,
714                            rc.bottom - rc.top,
715                            SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE,
716                        );
717                    }
718                    w if w == UserMessage::EnableIme as usize => {
719                        window.ime_context.borrow().enable();
720                    }
721                    w if w == UserMessage::DisableIme as usize => {
722                        window.ime_context.borrow().disable();
723                    }
724                    w if w == UserMessage::SetStyle as usize => {
725                        let style = {
726                            let state = handle.state.read().unwrap();
727                            state.style
728                        };
729                        let rc = adjust_window_rect(
730                            handle.inner_size().to_physical(handle.dpi()),
731                            style,
732                            WINDOW_EX_STYLE(0),
733                            GetDpiForWindow(hwnd),
734                        );
735                        SetWindowLongPtrW(hwnd, GWL_STYLE, style.0 as _);
736                        SetWindowPos(
737                            hwnd,
738                            HWND(0),
739                            0,
740                            0,
741                            rc.right - rc.left,
742                            rc.bottom - rc.top,
743                            SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED,
744                        );
745                        ShowWindow(hwnd, SW_SHOW);
746                    }
747                    w if w == UserMessage::AcceptDragFiles as usize => {
748                        DragAcceptFiles(hwnd, BOOL(lparam.0 as _));
749                    }
750                    _ => {
751                        return call_other::<T>(hwnd, msg, wparam, lparam);
752                    }
753                }
754                LRESULT(0)
755            }
756            _ => call_other::<T>(hwnd, msg, wparam, lparam),
757        }
758    });
759    ret.unwrap_or_else(|e| {
760        set_unwind(e);
761        LRESULT(0)
762    })
763}