static int ControlReopenDevice(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; if (!sys->use_desktop) { /* Save non-desktop state */ sys->desktop_save.is_fullscreen = vd->cfg->is_fullscreen; sys->desktop_save.is_on_top = sys->is_on_top; WINDOWPLACEMENT wp = { .length = sizeof(wp), }; GetWindowPlacement(sys->hparent ? sys->hparent : sys->hwnd, &wp); sys->desktop_save.win = wp.rcNormalPosition; } /* */ Direct3DClose(vd); EventThreadStop(sys->event); /* */ vlc_mutex_lock(&sys->lock); sys->use_desktop = sys->desktop_requested; sys->ch_desktop = false; vlc_mutex_unlock(&sys->lock); /* */ event_cfg_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.use_desktop = sys->use_desktop; if (!sys->use_desktop) { cfg.win.type = VOUT_WINDOW_TYPE_HWND; cfg.win.x = sys->desktop_save.win.left; cfg.win.y = sys->desktop_save.win.top; cfg.win.width = sys->desktop_save.win.right - sys->desktop_save.win.left; cfg.win.height = sys->desktop_save.win.bottom - sys->desktop_save.win.top; } event_hwnd_t hwnd; if (EventThreadStart(sys->event, &hwnd, &cfg)) { msg_Err(vd, "Failed to restart event thread"); return VLC_EGENERIC; } sys->parent_window = hwnd.parent_window; sys->hparent = hwnd.hparent; sys->hwnd = hwnd.hwnd; sys->hvideownd = hwnd.hvideownd; sys->hfswnd = hwnd.hfswnd; SetRectEmpty(&sys->rect_parent); /* */ video_format_t fmt; if (Direct3DOpen(vd, &fmt)) { CommonClean(vd); msg_Err(vd, "Failed to reopen device"); return VLC_EGENERIC; } vd->fmt = fmt; sys->is_first_display = true; if (sys->use_desktop) { /* Disable fullscreen/on_top while using desktop */ if (sys->desktop_save.is_fullscreen) vout_display_SendEventFullscreen(vd, false); if (sys->desktop_save.is_on_top) vout_display_SendWindowState(vd, VOUT_WINDOW_STATE_NORMAL); } else { /* Restore fullscreen/on_top */ if (sys->desktop_save.is_fullscreen) vout_display_SendEventFullscreen(vd, true); if (sys->desktop_save.is_on_top) vout_display_SendWindowState(vd, VOUT_WINDOW_STATE_ABOVE); } return VLC_SUCCESS; }
/***************************************************************************** * 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 * (using the GetMessage and DispatchMessage functions). * Nonqueued Messages are those that Windows will send directly to this * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...) *****************************************************************************/ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { event_thread_t *p_event; if( message == WM_CREATE ) { /* Store vd for future use */ p_event = (event_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams; SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_event ); return TRUE; } else { LONG_PTR p_user_data = GetWindowLongPtr( hwnd, GWLP_USERDATA ); p_event = (event_thread_t *)p_user_data; if( !p_event ) { /* Hmmm mozilla does manage somehow to save the pointer to our * windowproc and still calls it after the vout has been closed. */ return DefWindowProc(hwnd, message, wParam, lParam); } } vout_display_t *vd = p_event->vd; #ifndef UNDER_CE /* Catch the screensaver and the monitor turn-off */ if( message == WM_SYSCOMMAND && ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) ) { //if( vd ) msg_Dbg( vd, "WinProc WM_SYSCOMMAND screensaver" ); return 0; /* this stops them from happening */ } #endif #if 0 if( message == WM_SETCURSOR ) { msg_Err(vd, "WM_SETCURSOR: %d (t2)", p_event->is_cursor_hidden); SetCursor( p_event->is_cursor_hidden ? p_event->cursor_empty : p_event->cursor_arrow ); return 1; } #endif if( message == WM_CAPTURECHANGED ) { for( int button = 0; p_event->button_pressed; button++ ) { unsigned m = 1 << button; if( p_event->button_pressed & m ) vout_display_SendEventMouseReleased( p_event->vd, button ); p_event->button_pressed &= ~m; } p_event->button_pressed = 0; return 0; } if( hwnd == p_event->hvideownd ) { #ifdef MODULE_NAME_IS_directx vlc_mutex_lock( &p_event->lock ); const bool use_overlay = p_event->use_overlay; vlc_mutex_unlock( &p_event->lock ); #endif switch( message ) { #ifdef MODULE_NAME_IS_directx case WM_ERASEBKGND: /* For overlay, we need to erase background */ return !use_overlay ? 1 : DefWindowProc(hwnd, message, wParam, lParam); case WM_PAINT: /* ** For overlay, DefWindowProc() will erase dirty regions ** with colorkey. ** For non-overlay, vout will paint the whole window at ** regular interval, therefore dirty regions can be ignored ** to minimize repaint. */ if( !use_overlay ) { ValidateRect(hwnd, NULL); } // fall through to default #else /* ** For OpenGL and Direct3D, vout will update the whole ** window at regular interval, therefore dirty region ** can be ignored to minimize repaint. */ case WM_ERASEBKGND: /* nothing to erase */ return 1; case WM_PAINT: /* nothing to repaint */ ValidateRect(hwnd, NULL); // fall through #endif default: return DefWindowProc(hwnd, message, wParam, lParam); } } switch( message ) { case WM_WINDOWPOSCHANGED: vlc_mutex_lock( &p_event->lock ); p_event->has_moved = true; vlc_mutex_unlock( &p_event->lock ); return 0; /* the user wants to close the window */ case WM_CLOSE: vout_display_SendEventClose(vd); return 0; /* the window has been closed so shut down everything now */ case WM_DESTROY: msg_Dbg( vd, "WinProc WM_DESTROY" ); /* just destroy the window */ PostQuitMessage( 0 ); return 0; case WM_SYSCOMMAND: switch (wParam) { case IDM_TOGGLE_ON_TOP: /* toggle the "on top" status */ { msg_Dbg(vd, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP"); HMENU hMenu = GetSystemMenu(vd->sys->hwnd, FALSE); vout_display_SendWindowState(vd, (GetMenuState(hMenu, IDM_TOGGLE_ON_TOP, MF_BYCOMMAND) & MF_CHECKED) ? VOUT_WINDOW_STATE_NORMAL : VOUT_WINDOW_STATE_ABOVE); return 0; } default: break; } break; case WM_PAINT: case WM_NCPAINT: case WM_ERASEBKGND: return DefWindowProc(hwnd, message, wParam, lParam); case WM_KILLFOCUS: #ifdef MODULE_NAME_IS_wingapi GXSuspend(); #endif #ifdef UNDER_CE if( hwnd == p_event->hfswnd ) { HWND htbar = FindWindow( _T("HHTaskbar"), NULL ); ShowWindow( htbar, SW_SHOW ); } if( !p_event->hparent || hwnd == p_event->hfswnd ) { SHFullScreen( hwnd, SHFS_SHOWSIPBUTTON ); } #endif return 0; case WM_SETFOCUS: #ifdef MODULE_NAME_IS_wingapi GXResume(); #endif #ifdef UNDER_CE /* FIXME vd->cfg is not lock[ed/able] */ #warning "FIXME: race condition" if( p_event->hparent && hwnd != p_event->hfswnd && vd->cfg->is_fullscreen ) vout_display_SendEventFullscreen(vd, false); if( hwnd == p_event->hfswnd ) { HWND htbar = FindWindow( _T("HHTaskbar"), NULL ); ShowWindow( htbar, SW_HIDE ); } if( !p_event->hparent || hwnd == p_event->hfswnd ) { SHFullScreen( hwnd, SHFS_HIDESIPBUTTON ); } #endif return 0; default: //msg_Dbg( vd, "WinProc WM Default %i", message ); break; } /* Let windows handle the message */ return DefWindowProc(hwnd, message, wParam, lParam); }
/***************************************************************************** * WinVoutEventProc: 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 * (using the GetMessage and DispatchMessage functions). * Nonqueued Messages are those that Windows will send directly to this * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...) *****************************************************************************/ static long FAR PASCAL WinVoutEventProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { event_thread_t *p_event; if( message == WM_CREATE ) { /* Store vd for future use */ p_event = (event_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams; SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_event ); return TRUE; } else { LONG_PTR p_user_data = GetWindowLongPtr( hwnd, GWLP_USERDATA ); p_event = (event_thread_t *)p_user_data; if( !p_event ) { /* Hmmm mozilla does manage somehow to save the pointer to our * windowproc and still calls it after the vout has been closed. */ return DefWindowProc(hwnd, message, wParam, lParam); } } vout_display_t *vd = p_event->vd; #if 0 if( message == WM_SETCURSOR ) { msg_Err(vd, "WM_SETCURSOR: %d (t2)", p_event->is_cursor_hidden); SetCursor( p_event->is_cursor_hidden ? p_event->cursor_empty : p_event->cursor_arrow ); return 1; } #endif if( message == WM_CAPTURECHANGED ) { for( int button = 0; p_event->button_pressed; button++ ) { unsigned m = 1 << button; if( p_event->button_pressed & m ) vout_display_SendEventMouseReleased( p_event->vd, button ); p_event->button_pressed &= ~m; } p_event->button_pressed = 0; return 0; } if( hwnd == p_event->hvideownd ) { #ifdef MODULE_NAME_IS_directdraw vlc_mutex_lock( &p_event->lock ); const bool use_overlay = p_event->use_overlay; vlc_mutex_unlock( &p_event->lock ); #endif switch( message ) { #ifdef MODULE_NAME_IS_directdraw case WM_ERASEBKGND: /* For overlay, we need to erase background */ return !use_overlay ? 1 : DefWindowProc(hwnd, message, wParam, lParam); case WM_PAINT: /* ** For overlay, DefWindowProc() will erase dirty regions ** with colorkey. ** For non-overlay, vout will paint the whole window at ** regular interval, therefore dirty regions can be ignored ** to minimize repaint. */ if( !use_overlay ) { ValidateRect(hwnd, NULL); } // fall through to default #else /* ** For OpenGL and Direct3D, vout will update the whole ** window at regular interval, therefore dirty region ** can be ignored to minimize repaint. */ case WM_ERASEBKGND: /* nothing to erase */ return 1; case WM_PAINT: /* nothing to repaint */ ValidateRect(hwnd, NULL); // fall through #endif default: return DefWindowProc(hwnd, message, wParam, lParam); } } switch( message ) { case WM_WINDOWPOSCHANGED: atomic_store(&p_event->has_moved, true); return 0; /* the user wants to close the window */ case WM_CLOSE: vout_display_SendEventClose(vd); return 0; /* the window has been closed so shut down everything now */ case WM_DESTROY: msg_Dbg( vd, "WinProc WM_DESTROY" ); /* just destroy the window */ PostQuitMessage( 0 ); return 0; case WM_SYSCOMMAND: switch (wParam) { case IDM_TOGGLE_ON_TOP: /* toggle the "on top" status */ { msg_Dbg(vd, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP"); HMENU hMenu = GetSystemMenu(vd->sys->hwnd, FALSE); vout_display_SendWindowState(vd, (GetMenuState(hMenu, IDM_TOGGLE_ON_TOP, MF_BYCOMMAND) & MF_CHECKED) ? VOUT_WINDOW_STATE_NORMAL : VOUT_WINDOW_STATE_ABOVE); return 0; } default: break; } break; case WM_PAINT: case WM_NCPAINT: case WM_ERASEBKGND: return DefWindowProc(hwnd, message, wParam, lParam); case WM_KILLFOCUS: return 0; case WM_SETFOCUS: return 0; case WM_GESTURE: return DecodeGesture( VLC_OBJECT(vd), p_event->p_gesture, hwnd, message, wParam, lParam ); default: //msg_Dbg( vd, "WinProc WM Default %i", message ); break; } /* Let windows handle the message */ return DefWindowProc(hwnd, message, wParam, lParam); }