vout_events.c 22.5 KB
Newer Older
Gildas Bazin's avatar
 
Gildas Bazin committed
1 2 3
/*****************************************************************************
 * vout_events.c: Windows DirectX video output events handler
 *****************************************************************************
4
 * Copyright (C) 2001 VideoLAN
Sam Hocevar's avatar
 
Sam Hocevar committed
5
 * $Id: vout_events.c,v 1.11 2002/02/19 00:50:19 sam Exp $
Gildas Bazin's avatar
 
Gildas Bazin committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * Authors: Gildas Bazin <gbazin@netcourrier.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/


/*****************************************************************************
 * Preamble: This file contains the functions related to the creation of
 *             a window and the handling of its messages (events).
 *****************************************************************************/
#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                                /* free() */
#include <string.h>                                            /* strerror() */

Sam Hocevar's avatar
 
Sam Hocevar committed
33 34
#include <videolan/vlc.h>

Gildas Bazin's avatar
 
Gildas Bazin committed
35 36 37 38 39 40 41
#include "netutils.h"

#include "video.h"
#include "video_output.h"

#include <windows.h>
#include <windowsx.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
42
#include <shellapi.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
43

Gildas Bazin's avatar
 
Gildas Bazin committed
44
#include <ddraw.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
45 46 47 48 49 50 51 52 53 54

#include "interface.h"

#include "vout_directx.h"

/*****************************************************************************
 * Local prototypes.
 *****************************************************************************/
static int  DirectXCreateWindow( vout_thread_t *p_vout );
static void DirectXCloseWindow ( vout_thread_t *p_vout );
Gildas Bazin's avatar
 
Gildas Bazin committed
55
static void DirectXUpdateRects( vout_thread_t *p_vout );
Gildas Bazin's avatar
 
Gildas Bazin committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
static long FAR PASCAL DirectXEventProc ( HWND hwnd, UINT message,
                                          WPARAM wParam, LPARAM lParam );

/*****************************************************************************
 * DirectXEventThread: Create video window & handle its messages
 *****************************************************************************
 * This function creates a video window and then enters an infinite loop
 * that handles the messages sent to that window.
 * The main goal of this thread is to isolate the Win32 PeekMessage function
 * because this one can block for a long time.
 *****************************************************************************/
void DirectXEventThread( vout_thread_t *p_vout )
{
    MSG             msg;

    /* Initialisation */

    /* Create a window for the video */
    /* Creating a window under Windows also initializes the thread's event
     * message qeue */
    if( DirectXCreateWindow( p_vout ) )
    {
        intf_ErrMsg( "vout error: can't create window" );
        p_vout->p_sys->i_event_thread_status = THREAD_FATAL;
        /* signal the creation of the window */
        vlc_mutex_lock( &p_vout->p_sys->event_thread_lock );
        vlc_cond_signal( &p_vout->p_sys->event_thread_wait );
        vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock );
        return;
    }

    /* signal the creation of the window */
    p_vout->p_sys->i_event_thread_status = THREAD_READY;
    vlc_mutex_lock( &p_vout->p_sys->event_thread_lock );
    vlc_cond_signal( &p_vout->p_sys->event_thread_wait );
    vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock );

    /* Main loop */
Gildas Bazin's avatar
 
Gildas Bazin committed
94 95
    /* GetMessage will sleep if there's no message in the queue */
    while( GetMessage( &msg, p_vout->p_sys->hwnd, 0, 0 ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
96 97
    {

Gildas Bazin's avatar
 
Gildas Bazin committed
98 99 100 101 102
        /* Check if we are asked to exit */
        if( p_vout->b_die || p_vout->p_sys->b_event_thread_die )
            break;

        switch( msg.message )
Gildas Bazin's avatar
 
Gildas Bazin committed
103
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
104 105 106

        case WM_MOUSEMOVE:
            if( p_vout->p_sys->b_cursor )
Gildas Bazin's avatar
 
Gildas Bazin committed
107
            {
Gildas Bazin's avatar
 
Gildas Bazin committed
108
                if( p_vout->p_sys->b_cursor_autohidden )
Gildas Bazin's avatar
 
Gildas Bazin committed
109
                {
Gildas Bazin's avatar
 
Gildas Bazin committed
110 111 112
                    p_vout->p_sys->b_cursor_autohidden = 0;
                    p_vout->p_sys->i_lastmoved = mdate();
                    ShowCursor( TRUE );
Gildas Bazin's avatar
 
Gildas Bazin committed
113
                }
Gildas Bazin's avatar
 
Gildas Bazin committed
114
                else
Gildas Bazin's avatar
 
Gildas Bazin committed
115
                {
Gildas Bazin's avatar
 
Gildas Bazin committed
116
                    p_vout->p_sys->i_lastmoved = mdate();
Gildas Bazin's avatar
 
Gildas Bazin committed
117
                }
Gildas Bazin's avatar
 
Gildas Bazin committed
118
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
119
            DispatchMessage(&msg);
Gildas Bazin's avatar
 
Gildas Bazin committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
            break;

        case WM_RBUTTONUP:
            intf_WarnMsg( 4, "vout: vout_Manage WM_RBUTTONUP" );
            p_main->p_intf->b_menu_change = 1;
            break;

        case WM_KEYDOWN:
            /* the key events are first processed here. The next
             * message processed by this main message loop will be the
             * char translation of the key event */
            intf_WarnMsg( 3, "vout: vout_Manage WM_KEYDOWN" );
            switch( msg.wParam )
            {
            case VK_ESCAPE:
            case VK_F12:
Gildas Bazin's avatar
 
Gildas Bazin committed
136 137
                /* exit application */
                p_main->p_intf->b_die = 1;
Gildas Bazin's avatar
 
Gildas Bazin committed
138
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
139 140 141 142 143 144 145 146 147 148
            }
            TranslateMessage(&msg);
            break;

        case WM_CHAR:
            intf_WarnMsg( 3, "vout: vout_Manage WM_CHAR" );
            switch( msg.wParam )
            {
            case 'q':
            case 'Q':
Gildas Bazin's avatar
 
Gildas Bazin committed
149 150
                /* exit application */
                p_main->p_intf->b_die = 1;
Gildas Bazin's avatar
 
Gildas Bazin committed
151
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
152 153 154 155

            case 'f':                            /* switch to fullscreen */
            case 'F':
                p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
Gildas Bazin's avatar
 
Gildas Bazin committed
156
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
157 158 159 160 161

            case 'c':                                /* toggle grayscale */
            case 'C':
                p_vout->b_grayscale = ! p_vout->b_grayscale;
                p_vout->p_sys->i_changes |= VOUT_GRAYSCALE_CHANGE;
Gildas Bazin's avatar
 
Gildas Bazin committed
162
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
163 164 165 166 167

            case 'i':                                     /* toggle info */
            case 'I':
                p_vout->b_info = ! p_vout->b_info;
                p_vout->p_sys->i_changes |= VOUT_INFO_CHANGE;
Gildas Bazin's avatar
 
Gildas Bazin committed
168 169
                break;

Gildas Bazin's avatar
 
Gildas Bazin committed
170 171 172 173
            case 's':                                  /* toggle scaling */
            case 'S':
                p_vout->b_scale = ! p_vout->b_scale;
                p_vout->p_sys->i_changes |= VOUT_SCALE_CHANGE;
Gildas Bazin's avatar
 
Gildas Bazin committed
174
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
175 176 177 178

            case ' ':                                /* toggle interface */
                p_vout->b_interface = ! p_vout->b_interface;
                p_vout->p_sys->i_changes |= VOUT_INTF_CHANGE;
Gildas Bazin's avatar
 
Gildas Bazin committed
179 180
                break;

Gildas Bazin's avatar
 
Gildas Bazin committed
181 182 183 184 185 186 187 188 189 190
            case '0': network_ChannelJoin( 0 ); break;
            case '1': network_ChannelJoin( 1 ); break;
            case '2': network_ChannelJoin( 2 ); break;
            case '3': network_ChannelJoin( 3 ); break;
            case '4': network_ChannelJoin( 4 ); break;
            case '5': network_ChannelJoin( 5 ); break;
            case '6': network_ChannelJoin( 6 ); break;
            case '7': network_ChannelJoin( 7 ); break;
            case '8': network_ChannelJoin( 8 ); break;
            case '9': network_ChannelJoin( 9 ); break;
Gildas Bazin's avatar
 
Gildas Bazin committed
191

Gildas Bazin's avatar
 
Gildas Bazin committed
192 193
            default:
                break;
Gildas Bazin's avatar
 
Gildas Bazin committed
194 195
            }

Gildas Bazin's avatar
 
Gildas Bazin committed
196 197 198 199 200 201 202 203 204 205
        default:
            /* Messages we don't handle directly are dispatched to the
             * window procedure */
#if 0
            intf_WarnMsg( 5, "vout: vout_Manage unhandled message",
                          msg.message );
#endif
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            break;
Gildas Bazin's avatar
 
Gildas Bazin committed
206

Gildas Bazin's avatar
 
Gildas Bazin committed
207
        } /* End Switch */
Gildas Bazin's avatar
 
Gildas Bazin committed
208 209 210

    } /* End Main loop */

Gildas Bazin's avatar
 
Gildas Bazin committed
211 212
    if( msg.message == WM_QUIT )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
213 214
        intf_WarnMsg( 3, "vout: DirectXEventThread WM_QUIT... "
                      "shouldn't happen!!" );
Gildas Bazin's avatar
 
Gildas Bazin committed
215 216 217 218
        p_vout->p_sys->hwnd = NULL; /* Window already destroyed */
    }

    intf_WarnMsg( 3, "vout: DirectXEventThread Terminating" );
Gildas Bazin's avatar
 
Gildas Bazin committed
219

Gildas Bazin's avatar
 
Gildas Bazin committed
220 221
    /* clear the changes formerly signaled */
    p_vout->p_sys->i_changes = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
222

Gildas Bazin's avatar
 
Gildas Bazin committed
223
    DirectXCloseWindow( p_vout );
Gildas Bazin's avatar
 
Gildas Bazin committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
}


/* following functions are local */

/*****************************************************************************
 * DirectXCreateWindow: create a window for the video.
 *****************************************************************************
 * Before creating a direct draw surface, we need to create a window in which
 * the video will be displayed. This window will also allow us to capture the
 * events.
 *****************************************************************************/
static int DirectXCreateWindow( vout_thread_t *p_vout )
{
    HINSTANCE  hInstance;
    WNDCLASSEX wc;                                /* window class components */
    RECT       rect_window;
    COLORREF   colorkey; 
    HDC        hdc;
Gildas Bazin's avatar
 
Gildas Bazin committed
243 244
    HICON      vlc_icon = NULL;
    char       vlc_path[_MAX_PATH+1];
Gildas Bazin's avatar
 
Gildas Bazin committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

    intf_WarnMsg( 3, "vout: DirectXCreateWindow" );

    /* get this module's instance */
    hInstance = GetModuleHandle(NULL);

    /* Create a BRUSH that will be used by Windows to paint the window
     * background.
     * This window background is important for us as it will be used by the
     * graphics card to display the overlay.
     * This is why we carefully choose the color for this background, the goal
     * being to choose a color which isn't complete black but nearly. We
     * obviously don't want to use black as a colorkey for the overlay because
     * black is one of the most used color and thus would give us undesirable
     * effects */
    /* the first step is to find the colorkey we want to use. The difficulty
     * comes from the potential dithering (depends on the display depth)
     * because we need to know the real RGB value of the chosen colorkey */
Gildas Bazin's avatar
 
Gildas Bazin committed
263
    hdc = GetDC( NULL );
Gildas Bazin's avatar
 
Gildas Bazin committed
264 265 266 267 268 269 270 271 272
    for( colorkey = 5; colorkey < 0xFF /*all shades of red*/; colorkey++ )
    {
        if( colorkey == GetNearestColor( hdc, colorkey ) )
          break;
    }
    intf_WarnMsg(3,"vout: DirectXCreateWindow background color:%i", colorkey);

    /* create the actual brush */  
    p_vout->p_sys->hbrush = CreateSolidBrush(colorkey);
Gildas Bazin's avatar
 
Gildas Bazin committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
    p_vout->p_sys->i_rgb_colorkey = (int)colorkey;

    /* Get the current size of the display and its colour depth */
    p_vout->p_sys->rect_display.right = GetDeviceCaps( hdc, HORZRES );
    p_vout->p_sys->rect_display.bottom = GetDeviceCaps( hdc, VERTRES );
    p_vout->p_sys->i_display_depth = GetDeviceCaps( hdc, BITSPIXEL );
    intf_WarnMsg( 3, "vout: Screen dimensions %ix%i colour depth %i",
                  p_vout->p_sys->rect_display.right,
                  p_vout->p_sys->rect_display.bottom,
                  p_vout->p_sys->i_display_depth );

    ReleaseDC( p_vout->p_sys->hwnd, hdc );

    /* Get the Icon from the main app */
    if( GetModuleFileName( NULL, vlc_path, _MAX_PATH ) )
    {
        vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
    }
    if( !vlc_icon )
        vlc_icon = LoadIcon( NULL, IDI_APPLICATION );

Gildas Bazin's avatar
 
Gildas Bazin committed
294 295 296 297 298 299 300 301

    /* fill in the window class structure */
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;                               /* no special styles */
    wc.lpfnWndProc   = (WNDPROC)DirectXEventProc;           /* event handler */
    wc.cbClsExtra    = 0;                             /* no extra class data */
    wc.cbWndExtra    = 0;                            /* no extra window data */
    wc.hInstance     = hInstance;                                /* instance */
Gildas Bazin's avatar
 
Gildas Bazin committed
302
    wc.hIcon         = CopyIcon( vlc_icon );            /* load the vlc icon */
Gildas Bazin's avatar
 
Gildas Bazin committed
303 304 305 306
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW); /* load a default cursor */
    wc.hbrBackground = p_vout->p_sys->hbrush;            /* background color */
    wc.lpszMenuName  = NULL;                                      /* no menu */
    wc.lpszClassName = "VLC DirectX";                 /* use a special class */
Gildas Bazin's avatar
 
Gildas Bazin committed
307
    wc.hIconSm       = CopyIcon( vlc_icon );            /* load the vlc icon */
Gildas Bazin's avatar
 
Gildas Bazin committed
308 309 310 311

    /* register the window class */
    if (!RegisterClassEx(&wc))
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
312 313 314 315 316 317 318
        /* Check why it failed. If it's because one already exists then fine */
        WNDCLASS wndclass;
        if( !GetClassInfo( hInstance, "VLC DirectX", &wndclass ) )
        {
            intf_ErrMsg( "vout: DirectXCreateWindow RegisterClass FAILED" );
            return (1);
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
    }

    /* when you create a window you give the dimensions you wish it to have.
     * Unfortunatly these dimensions will include the borders and title bar.
     * We use the following function to find out the size of the window
     * corresponding to the useable surface we want */
    rect_window.top    = 10;
    rect_window.left   = 10;
    rect_window.right  = rect_window.left + p_vout->p_sys->i_window_width;
    rect_window.bottom = rect_window.top + p_vout->p_sys->i_window_height;
    AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 );

    /* create the window */
    p_vout->p_sys->hwnd = CreateWindow("VLC DirectX",/* name of window class */
                    "VLC DirectX",                  /* window title bar text */
                    WS_OVERLAPPEDWINDOW
Gildas Bazin's avatar
 
Gildas Bazin committed
335
                    | WS_SIZEBOX,               /* window style */
Gildas Bazin's avatar
 
Gildas Bazin committed
336 337
                    CW_USEDEFAULT,                   /* default X coordinate */
                    0,                               /* default Y coordinate */
Gildas Bazin's avatar
 
Gildas Bazin committed
338 339 340 341 342 343 344 345 346 347 348 349
                    rect_window.right - rect_window.left,    /* window width */
                    rect_window.bottom - rect_window.top,   /* window height */
                    NULL,                                /* no parent window */
                    NULL,                          /* no menu in this window */
                    hInstance,            /* handle of this program instance */
                    NULL);                        /* no additional arguments */

    if (p_vout->p_sys->hwnd == NULL) {
        intf_WarnMsg( 3, "vout: DirectXCreateWindow create window FAILED" );
        return (1);
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
350 351 352 353 354
    /* store a p_vout pointer into the window local storage (for later use
     * in DirectXEventProc).
     * We need to use SetWindowLongPtr when it is available in mingw */
    SetWindowLong( p_vout->p_sys->hwnd, GWL_USERDATA, (LONG)p_vout );

Gildas Bazin's avatar
 
Gildas Bazin committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
    /* now display the window */
    ShowWindow(p_vout->p_sys->hwnd, SW_SHOW);

    return ( 0 );
}

/*****************************************************************************
 * DirectXCloseWindow: close the window created by DirectXCreateWindow
 *****************************************************************************
 * This function returns all resources allocated by DirectXCreateWindow.
 *****************************************************************************/
static void DirectXCloseWindow( vout_thread_t *p_vout )
{
    intf_WarnMsg( 3, "vout: DirectXCloseWindow" );
    if( p_vout->p_sys->hwnd != NULL )
    {
        DestroyWindow( p_vout->p_sys->hwnd);
        p_vout->p_sys->hwnd = NULL;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
375 376 377
    /* We don't unregister the Window Class because it could lead to race
     * conditions and it will be done anyway by the system when the app will
     * exit */
Gildas Bazin's avatar
 
Gildas Bazin committed
378 379

    /* free window background brush */
Gildas Bazin's avatar
 
Gildas Bazin committed
380
    if( p_vout->p_sys->hbrush != NULL )
Gildas Bazin's avatar
 
Gildas Bazin committed
381 382 383 384 385 386
    {
        DeleteObject( p_vout->p_sys->hbrush );
        p_vout->p_sys->hbrush = NULL;
    }
}

Gildas Bazin's avatar
 
Gildas Bazin committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
/*****************************************************************************
 * DirectXUpdateRects: 
 *****************************************************************************
 * This function is called when the window position and size is changed, and
 * its job is to update the source and destination RECTs used to display the
 * picture.
 *****************************************************************************/
static void DirectXUpdateRects( vout_thread_t *p_vout )
{
    int i_width, i_height, i_x, i_y;

#define rect_src p_vout->p_sys->rect_src
#define rect_src_clipped p_vout->p_sys->rect_src_clipped
#define rect_dest p_vout->p_sys->rect_dest
#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
#define rect_display p_vout->p_sys->rect_display

    vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
                       p_vout->p_sys->i_window_height,
                       &i_x, &i_y, &i_width, &i_height );

    /* Destination image position and dimensions */
    rect_dest.left = i_x + p_vout->p_sys->i_window_x;
    rect_dest.top = i_y + p_vout->p_sys->i_window_y;
    rect_dest.right = rect_dest.left + i_width;
    rect_dest.bottom = rect_dest.top + i_height;


    /* UpdateOverlay directdraw function doesn't automatically clip to the
     * display size so we need to do it otherwise it will fails */

    /* Clip the destination window */
    IntersectRect( &rect_dest_clipped, &rect_dest, &rect_display );

    intf_WarnMsg( 3, "vout: DirectXUpdateRects image_dst_clipped coords:"
                  " %i,%i,%i,%i",
                  rect_dest_clipped.left, rect_dest_clipped.top,
                  rect_dest_clipped.right, rect_dest_clipped.bottom);

    /* the 2 following lines are to fix a bug when clicking on the desktop */
    if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
        (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
    {
        SetRectEmpty( &rect_src_clipped );
        return;
    }

    /* src image dimensions */
    rect_src.left = 0;
    rect_src.top = 0;
    rect_src.right = p_vout->render.i_width;
    rect_src.bottom = p_vout->render.i_height;

    /* Clip the source image */
    rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) *
      p_vout->render.i_width / (rect_dest.right - rect_dest.left);
    rect_src_clipped.right = p_vout->render.i_width - 
      (rect_dest.right - rect_dest_clipped.right) * p_vout->render.i_width /
      (rect_dest.right - rect_dest.left);
    rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) *
      p_vout->render.i_height / (rect_dest.bottom - rect_dest.top);
    rect_src_clipped.bottom = p_vout->render.i_height -
      (rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->render.i_height /
      (rect_dest.bottom - rect_dest.top);

    intf_WarnMsg( 3, "vout: DirectXUpdateRects image_src_clipped"
                  " coords: %i,%i,%i,%i",
                  rect_src_clipped.left, rect_src_clipped.top,
                  rect_src_clipped.right, rect_src_clipped.bottom);

#undef rect_src
#undef rect_src_clipped
#undef rect_dest
#undef rect_dest_clipped
#undef rect_display
}

Gildas Bazin's avatar
 
Gildas Bazin committed
464 465 466 467 468 469 470
/*****************************************************************************
 * DirectXEventProc: This is the window event processing function.
 *****************************************************************************
 * On Windows, when you create a window you have to attach an event processing
 * function to it. The aim of this function is to manage "Queued Messages" and
 * "Nonqueued Messages".
 * Queued Messages are those picked up and retransmitted by vout_Manage
Gildas Bazin's avatar
 
Gildas Bazin committed
471
 * (using the GetMessage and DispatchMessage functions).
Gildas Bazin's avatar
 
Gildas Bazin committed
472
 * Nonqueued Messages are those that Windows will send directly to this
Gildas Bazin's avatar
 
Gildas Bazin committed
473
 * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
Gildas Bazin's avatar
 
Gildas Bazin committed
474 475 476 477
 *****************************************************************************/
static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
                                         WPARAM wParam, LPARAM lParam )
{
Gildas Bazin's avatar
 
Gildas Bazin committed
478 479
    vout_thread_t *p_vout;

Gildas Bazin's avatar
 
Gildas Bazin committed
480 481 482
    switch( message )
    {

Gildas Bazin's avatar
 
Gildas Bazin committed
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
    case WM_WINDOWPOSCHANGED:
        {
        RECT     rect_window;
        POINT    point_window;

        p_vout = (vout_thread_t *)GetWindowLong( hwnd, GWL_USERDATA );

        /* update the window position */
        point_window.x = 0;
        point_window.y = 0;
        ClientToScreen( hwnd, &point_window );
        p_vout->p_sys->i_window_x = point_window.x;
        p_vout->p_sys->i_window_y = point_window.y;

        /* update the window size */
        GetClientRect( hwnd, &rect_window );
        p_vout->p_sys->i_window_width = rect_window.right;
        p_vout->p_sys->i_window_height = rect_window.bottom;
        intf_WarnMsg( 3, "vout: WinProc WM_WINDOWPOSCHANGED %i,%i,%i,%i",
                      p_vout->p_sys->i_window_x, p_vout->p_sys->i_window_y,
                      p_vout->p_sys->i_window_width,
                      p_vout->p_sys->i_window_height );

        DirectXUpdateRects( p_vout );
Gildas Bazin's avatar
 
Gildas Bazin committed
507 508
        if( p_vout->p_sys->b_using_overlay &&
            !p_vout->p_sys->b_event_thread_die )
Gildas Bazin's avatar
 
Gildas Bazin committed
509 510 511 512 513 514 515
            DirectXUpdateOverlay( p_vout );

        /* signal the size change */
        p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE;

        return 0;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
516 517 518
        break;

    case WM_ACTIVATE:
Gildas Bazin's avatar
 
Gildas Bazin committed
519
        intf_WarnMsg( 4, "vout: WinProc WM_ACTIVE" );
Gildas Bazin's avatar
 
Gildas Bazin committed
520 521 522 523 524 525 526 527 528
        break;

    case WM_CREATE:
        intf_WarnMsg( 4, "vout: WinProc WM_CREATE" );
        break;

    /* the user wants to close the window */
    case WM_CLOSE:
        intf_WarnMsg( 4, "vout: WinProc WM_CLOSE" );
Gildas Bazin's avatar
 
Gildas Bazin committed
529 530 531
        /* exit application */
        p_main->p_intf->b_die = 1;
        return 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
532 533 534 535 536
        break;

    /* the window has been closed so shut down everything now */
    case WM_DESTROY:
        intf_WarnMsg( 4, "vout: WinProc WM_DESTROY" );
Gildas Bazin's avatar
 
Gildas Bazin committed
537
        /* just destroy the window */
Gildas Bazin's avatar
 
Gildas Bazin committed
538
        PostQuitMessage( 0 );
Gildas Bazin's avatar
 
Gildas Bazin committed
539
        return 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
540 541 542 543 544 545 546 547 548 549 550 551
        break;

    case WM_SYSCOMMAND:
        switch (wParam)
        {
            case SC_SCREENSAVE:                     /* catch the screensaver */
            case SC_MONITORPOWER:              /* catch the monitor turn-off */
            intf_WarnMsg( 3, "vout: WinProc WM_SYSCOMMAND" );
            return 0;                      /* this stops them from happening */
        }
        break;

Gildas Bazin's avatar
 
Gildas Bazin committed
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
#if 0
    case WM_PAINT:
        intf_WarnMsg( 4, "vout: WinProc WM_PAINT" );
        break;
#endif

    case WM_ERASEBKGND:
        p_vout = (vout_thread_t *)GetWindowLong( hwnd, GWL_USERDATA );
        if( !p_vout->p_sys->b_using_overlay )
        {
            /* We want to eliminate unnecessary background redraws which create
             * an annoying flickering */
            int i_width, i_height, i_x, i_y;
            RECT rect_temp;
            GetClipBox( (HDC)wParam, &rect_temp );
#if 0
            intf_WarnMsg( 4, "vout: WinProc WM_ERASEBKGND %i,%i,%i,%i",
                          rect_temp.left, rect_temp.top,
                          rect_temp.right, rect_temp.bottom );
#endif
            vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
                               p_vout->p_sys->i_window_height,
                               &i_x, &i_y, &i_width, &i_height );
            ExcludeClipRect( (HDC)wParam, i_x, i_y,
                             i_x + i_width, i_y + i_height );
        }
        break;

Gildas Bazin's avatar
 
Gildas Bazin committed
580 581 582 583 584 585 586 587 588
#if 0
    default:
        intf_WarnMsg( 4, "vout: WinProc WM Default %i", message );
        break;
#endif
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}