use wine;

$wine::debug=0;

wine::declare( "user32",
                RegisterClassExA   => "word",
                CreateWindowExA    => "word",
                DefWindowProcA     => "int",
                SetWindowPos       => "int",
                GetActiveWindow    => "int",
                GetFocus           => "int",
                SetFocus           => "int",
                ShowWindow         => "int",
                UpdateWindow       => "int",
                PostQuitMessage    => "int",
                GetQueueStatus     => "int",
                PostMessageA       => "int",
                WaitMessage        => "int",
                MsgWaitForMultipleObjects => "int",
                PeekMessageA       => "int",
                GetMessageA        => "int",
                DispatchMessageA   => "int"
);



$WM_DESTROY = 2;
$WM_SETFOCUS = 7;
$WM_KILLFOCUS = 8;
$WM_KEYDOWN = 0x100;

$QS_KEY		= 0x0001;
$QS_MOUSEMOVE	= 0x0002;
$QS_MOUSEBUTTON	= 0x0004;
$QS_MOUSE	= +(QS_MOUSEMOVE | QS_MOUSEBUTTON);
$QS_POSTMESSAGE	= 0x0008;
$QS_TIMER	= 0x0010;
$QS_PAINT	= 0x0020;
$QS_SENDMESSAGE	= 0x0040;
$QS_HOTKEY	= 0x0080;
$QS_INPUT	= (QS_MOUSE | QS_KEY);
$QS_ALLEVENTS	= (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY);
$QS_ALLINPUT    = (QS_ALLEVENTS | QS_SENDMESSAGE);

my $in_wait = 0;

sub window_proc
{
    my  ($hwnd, $umsg, $wparam, $lparam) = @_;

    if ($in_wait) { print "***** message during wait\n"; }
    printf "[window_proc] wnd=%x msg=%x wp=%x lp=%x\n", $hwnd, $umsg, $wparam, $lparam;
    if ($umsg == $WM_DESTROY) { PostQuitMessage(0); exit 0; return 0; }
    if ($umsg == 0xdead) { return 0xbeef; }
    if ($umsg == $WM_KILLFOCUS || $umsg == $WM_SETFOCUS)
    {
        printf "cur focus = %x active=%x\n", GetFocus(), GetActiveWindow();
    }
    return DefWindowProcA( $hwnd, $umsg, $wparam, $lparam );
}



$thunk = alloc_callback (\&window_proc, qw(int int int int));

$wndclass = pack
(
 "IILiiIIIILpI",
 48,                #   UINT       cbSize; 
 0,                 #   UINT       style; 
 $thunk,            #   WNDPROC    lpfnWndProc; 
 0,                 #   int        cbClsExtra; 
 0,                 #   int        cbWndExtra; 
 0,                 #   HINSTANCE  hInstance; 
 0,                 #   HICON      hIcon; 
 0,                 #   HCURSOR    hCursor; 
 0,                 #   HBRUSH     hbrBackground; 
 0,                 #   LPCTSTR    lpszMenuName; 
 "Dogblaster",      #   LPCTSTR    lpszClassName; 
 0                  #   HICON      hIconSm; 
);
$atom = RegisterClassExA ($wndclass);
assert( $atom );

$hwnd = CreateWindowExA( 0x00000200,    # DWORD dwExStyle,      // extended window style
                         $atom,         # LPCTSTR lpClassName,  // registered class name
                         "bark",        # LPCTSTR lpWindowName, // window name
                         0x00000000,    # DWORD dwStyle,        // window style
                         0,             # int x,                // horizontal position of window
                         0,             # int y,                // vertical position of window
                         50,            # int nWidth,           // window width
                         50,            # int nHeight,          // window height
                         0,             # HWND hWndParent,      // handle to parent or owner window
                         0,             # HMENU hMenu,          // menu handle or child identifier
                         0,             # HINSTANCE hInstance,  // handle to application instance
                         0              # LPVOID lpParam        // window-creation data
                       );
#ShowWindow ($hwnd, 1);
#UpdateWindow ($hwnd);

$res = SetWindowPos($hwnd,0,100,100,200,200,0x40);
printf "SetWindowPos: %d err %d\n", $res, $wine::err;

printf "queue status=%x\n", GetQueueStatus(0x7f);
printf "queue status=%x\n", GetQueueStatus(0x7f);
PostMessageA( $hwnd, $WM_KEYDOWN, 0, 0 );
printf "wait=%d\n", MsgWaitForMultipleObjects(0, 0, 0, 2000, 8 );
printf "wait=%d\n", MsgWaitForMultipleObjects(0, 0, 0, 2000, 8 );
printf "queue status=%x\n", GetQueueStatus(0x7f);
printf "queue status=%x\n", GetQueueStatus(0x7f);

my $old_status=0x1234;
for (;;)
{
    printf "before wait\n";
    $in_wait = 1;
#    $res = MsgWaitForMultipleObjects(0, 0, 0, 2000, 0 );
    WaitMessage();
    $in_wait = 0;
    printf "after wait\n";
#    printf "wait=%d\n", $res;
#   if (!$res) { MsgWaitForMultipleObjects(0, 0, 0, -1, 0x4f ); }
#    $status = GetQueueStatus(0x7f);
    printf "status=%x\n",$status ;# if ($status != $old_status);

    printf "before wait2\n";
    $in_wait = 1;
    for ($i = 0; $i < 10; $i++) { WaitMessage(); }
    $in_wait = 0;
    printf "after wait2\n";
    $status = GetQueueStatus(0x7f);
    printf "status=%x\n",$status;
    $status = GetQueueStatus(0x7f);
    printf "status2=%x\n",$status;

    $old_status = $status;
    $z = " " x 28;
    if (PeekMessageA (\$z, 0, 0, 0, 1)) { DispatchMessageA( \$z ); }
    $status = GetQueueStatus(0x7f);
    printf "status3=%x\n",$status;
}
    
while (GetMessageA (\$z, 0, 0, 0)) { DispatchMessageA( \$z ); }

print "Bye.\n";
