[vlc-devel] Re: [PATCH] Win32 directx/direct3d/opengl: fullscreen mode improved

Sergey Volk sergey.volk at gmail.com
Thu May 3 13:52:48 CEST 2007


Here is a very similar patch for WinGdi output module. It also adds support
for hotkeys to WinGdi video_output module.

On 5/2/07, Sergey Volk <sergey.volk at gmail.com> wrote:
>
> Hi,
> Current implementation of directx video output modules (directx, direct3d,
> glwin32) leaves main interface window visible when the user toggles
> fullscreen mode. This causes two problems: (a) the user sees empty main
> interface window when he switches to another application or cycles through
> existing windows using Alt-Tab and (b) main interface window overlaps video
> window when he toggles "video-on-top" option while fullscreen mode is
> active. In order to fix both these issues, we should hide main interface
> window when entering fullscreen mode and restore it when leaving fullscreen
> mode. But some GUI modules (in particular qt4 module) may need to call
> show() for main interface window in order to apply "video-on-top" flag, so
> in order to avoid condition (b) described earlier we need also to hide
> VOUT_SET_STAY_ON_TOP queries from main interface window while we are in
> fullscreen mode and update "video-on-top" status for main window when we are
> leaving fullscreen mode.
>
> I have also noticed that there is a code in
> src/video_output/vout_intf.c:FullscreenCallback (line 1151), which sets
> video-on-top variable to false, when entering fullscreen mode. I think this
> code should be removed, there is no point in disabling video-on-top option,
> as the user may change this option in fullscreen mode anyway (through mouse
> / hotkey controls, at least). So video_output modules should be aware that
> video-on-top variable may be toggled in fullscreen mode and should handle
> such situations appropriately. I'm developing under win32/cygwin, so I
> haven't checked if similar reasoning applies to X11 module or any of the
> other video output modules. It seems that at least wingdi output module has
> the same problem, but it's code is somewhat different from
> DirectX/Direct3D/Win32 OpenGL code, so I'll provide patch for wingdi module
> later. In the meantime, I think it is safe to leave that old code as it is.
>
> Two patches are attached to this message: vlc-vout-dx-fullscreen.patch is
> a version which fixes fullscreen mode for DirectX module only, it is
> intended only to demonstrate what changes are being applied to current
> version. Another one - vlc-vout-dx-fullscreen2.patch, does essentially the
> same, only it fixes all three modules (directx, direct3d and opengl) and
> refactors some common code for toggling fullscreen mode into
> Win32ToggleFullscreen function, to remove code duplication between those
> modules.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20070503/0bf35dce/attachment.html>
-------------- next part --------------
Index: video_output/wingdi.c
===================================================================
--- video_output/wingdi.c	(revision 19952)
+++ video_output/wingdi.c	(working copy)
@@ -35,6 +35,8 @@
 
 #include <commctrl.h>
 
+#include "vlc_keys.h"
+
 #define SHFS_SHOWSIPBUTTON 0x0004
 #define SHFS_HIDESIPBUTTON 0x0008
 
@@ -438,6 +440,28 @@
 {
 }
 
+/* Internal wrapper over GetWindowPlacement / SetWindowPlacement */ 
+static void SetWindowState(HWND hwnd, int nShowCmd)
+{
+    WINDOWPLACEMENT window_placement;
+    window_placement.length = sizeof(WINDOWPLACEMENT);
+    GetWindowPlacement( hwnd, &window_placement );
+    window_placement.showCmd = nShowCmd;
+    SetWindowPlacement( hwnd, &window_placement );
+    SetWindowPos( hwnd, 0, 0, 0, 0, 0,
+        SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
+}
+
+/* Internal wrapper to call vout_ControlWindow for hparent */
+static void ControlParentWindow( vout_thread_t *p_vout, int i_query, ... )
+{
+    va_list args;
+    va_start( args, i_query );
+    vout_ControlWindow( p_vout,
+        (void *)p_vout->p_sys->hparent, i_query, args );
+    va_end( args );
+}
+
 /*****************************************************************************
  * Manage: handle events
  *****************************************************************************
@@ -446,10 +470,6 @@
  *****************************************************************************/
 static int Manage( vout_thread_t *p_vout )
 {
-#ifndef UNDER_CE
-    WINDOWPLACEMENT window_placement;
-#endif
-
     /* If we do not control our window, we check for geometry changes
      * ourselves because the parent might not send us its events. */
     if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
@@ -505,11 +525,6 @@
 
         p_vout->b_fullscreen = ! p_vout->b_fullscreen;
 
-        /* We need to switch between Maximized and Normal sized window */
-#ifndef UNDER_CE
-        window_placement.length = sizeof(WINDOWPLACEMENT);
-        GetWindowPlacement( hwnd, &window_placement );
-#endif
         if( p_vout->b_fullscreen )
         {
 #ifndef UNDER_CE
@@ -528,14 +543,10 @@
                 SetWindowPos( hwnd, 0, point.x, point.y,
                               rect.right, rect.bottom,
                               SWP_NOZORDER|SWP_FRAMECHANGED );
-                GetWindowPlacement( hwnd, &window_placement );
             }
 
             /* Maximize window */
-            window_placement.showCmd = SW_SHOWMAXIMIZED;
-            SetWindowPlacement( hwnd, &window_placement );
-            SetWindowPos( hwnd, 0, 0, 0, 0, 0,
-                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
+            SetWindowState( hwnd, SW_SHOWMAXIMIZED );
 #endif
 
             if( p_vout->p_sys->hparent )
@@ -546,6 +557,11 @@
                 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
                               rect.right, rect.bottom,
                               SWP_NOZORDER|SWP_FRAMECHANGED );
+/* Not sure if GetAncestor is available on WinCE */
+#ifndef UNDER_CE
+                HWND topLevelParent = GetAncestor( p_vout->p_sys->hparent, GA_ROOT );
+                ShowWindow( topLevelParent, SW_HIDE );
+#endif
             }
 
             ShowWindow( hwnd, SW_SHOW );
@@ -558,10 +574,7 @@
 
 #ifndef UNDER_CE
             /* Normal window */
-            window_placement.showCmd = SW_SHOWNORMAL;
-            SetWindowPlacement( hwnd, &window_placement );
-            SetWindowPos( hwnd, 0, 0, 0, 0, 0,
-                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
+            SetWindowState( hwnd, SW_SHOWNORMAL );
 #endif
 
             if( p_vout->p_sys->hparent )
@@ -574,7 +587,17 @@
                               SWP_NOZORDER|SWP_FRAMECHANGED );
 
                 ShowWindow( hwnd, SW_HIDE );
+#ifndef UNDER_CE
+                HWND topLevelParent = GetAncestor( p_vout->p_sys->hparent, GA_ROOT );
+                ShowWindow( topLevelParent, SW_SHOW );
+#endif
                 SetForegroundWindow( p_vout->p_sys->hparent );
+
+                /* Update "video-on-top" status for main interface window, it
+                needs to be updated as we were hiding VOUT_SET_STAY_ON_TOP
+                queries from it while we were in fullscreen mode */
+                int b_ontop = var_GetBool( p_vout, "video-on-top" );
+                ControlParentWindow( p_vout, VOUT_SET_STAY_ON_TOP, b_ontop );
             }
 
             /* Make sure the mouse cursor is displayed */
@@ -761,6 +784,77 @@
 }
 
 /*****************************************************************************
+ * ConvertWinKeyToVLC: converts Windows virtual key codes to VLC key codes
+ *****************************************************************************/
+static struct
+{
+    int i_winkey;
+    int i_vlckey;
+
+} winkeys_to_vlckeys[] =
+{
+    { VK_F1, KEY_F1 }, { VK_F2, KEY_F2 }, { VK_F3, KEY_F3 }, { VK_F4, KEY_F4 },
+    { VK_F5, KEY_F5 }, { VK_F6, KEY_F6 }, { VK_F7, KEY_F7 }, { VK_F8, KEY_F8 },
+    { VK_F9, KEY_F9 }, { VK_F10, KEY_F10 }, { VK_F11, KEY_F11 },
+    { VK_F12, KEY_F12 },
+
+    { VK_RETURN, KEY_ENTER },
+    { VK_SPACE, KEY_SPACE },
+    { VK_ESCAPE, KEY_ESC },
+
+    { VK_LEFT, KEY_LEFT },
+    { VK_RIGHT, KEY_RIGHT },
+    { VK_UP, KEY_UP },
+    { VK_DOWN, KEY_DOWN },
+
+    { VK_HOME, KEY_HOME },
+    { VK_END, KEY_END },
+    { VK_PRIOR, KEY_PAGEUP },
+    { VK_NEXT, KEY_PAGEDOWN },
+
+    { VK_INSERT, KEY_INSERT },
+    { VK_DELETE, KEY_DELETE },
+
+    { VK_CONTROL, 0 },
+    { VK_SHIFT, 0 },
+    { VK_MENU, 0 },
+
+/* Not sure if these keys are available under WinCE */
+#if 0
+    { VK_BROWSER_BACK, KEY_BROWSER_BACK },
+    { VK_BROWSER_FORWARD, KEY_BROWSER_FORWARD },
+    { VK_BROWSER_REFRESH, KEY_BROWSER_REFRESH },
+    { VK_BROWSER_STOP, KEY_BROWSER_STOP },
+    { VK_BROWSER_SEARCH, KEY_BROWSER_SEARCH },
+    { VK_BROWSER_FAVORITES, KEY_BROWSER_FAVORITES },
+    { VK_BROWSER_HOME, KEY_BROWSER_HOME },
+    { VK_VOLUME_MUTE, KEY_VOLUME_MUTE },
+    { VK_VOLUME_DOWN, KEY_VOLUME_DOWN },
+    { VK_VOLUME_UP, KEY_VOLUME_UP },
+    { VK_MEDIA_NEXT_TRACK, KEY_MEDIA_NEXT_TRACK },
+    { VK_MEDIA_PREV_TRACK, KEY_MEDIA_PREV_TRACK },
+    { VK_MEDIA_STOP, KEY_MEDIA_STOP },
+    { VK_MEDIA_PLAY_PAUSE, KEY_MEDIA_PLAY_PAUSE },
+#endif
+
+    { 0, 0 }
+};
+
+static int ConvertWinKeyToVLC( int i_key )
+{
+    int i;
+
+    for( i = 0; winkeys_to_vlckeys[i].i_winkey != 0; i++ )
+    {
+        if( winkeys_to_vlckeys[i].i_winkey == i_key )
+        {
+            return winkeys_to_vlckeys[i].i_vlckey;
+        }
+    }
+
+    return 0;
+}
+/*****************************************************************************
  * EventThread: Event handling thread
  *****************************************************************************/
 static void EventThread ( vlc_object_t *p_event )
@@ -887,6 +981,34 @@
                 p_event->p_libvlc->b_die = VLC_TRUE;
                 break;
             }
+
+            /* The key events are first processed here and not translated
+             * into WM_CHAR events because we need to know the status of the
+             * modifier keys. */
+            int i_key = ConvertWinKeyToVLC( msg.wParam );
+            if( !i_key )
+            {
+                /* This appears to be a "normal" (ascii) key */
+                i_key = tolower( MapVirtualKey( msg.wParam, 2 ) );
+            }
+
+            if( i_key )
+            {
+                if( GetKeyState(VK_CONTROL) & 0x8000 )
+                {
+                    i_key |= KEY_MODIFIER_CTRL;
+                }
+                if( GetKeyState(VK_SHIFT) & 0x8000 )
+                {
+                    i_key |= KEY_MODIFIER_SHIFT;
+                }
+                if( GetKeyState(VK_MENU) & 0x8000 )
+                {
+                    i_key |= KEY_MODIFIER_ALT;
+                }
+
+                var_SetInteger( p_event->p_libvlc, "key-pressed", i_key );
+            }
             TranslateMessage( &msg );
             break;
 
@@ -1356,6 +1478,14 @@
 
         return VLC_SUCCESS;
 
+    case VOUT_SET_STAY_ON_TOP:
+        if( p_vout->p_sys->hparent && !var_GetBool( p_vout, "fullscreen" ) )
+            return vout_ControlWindow( p_vout,
+                    (void *)p_vout->p_sys->hparent, i_query, args );
+
+        //p_vout->p_sys->b_on_top_change = VLC_TRUE;
+        return VLC_SUCCESS;
+
     default:
         return vout_vaControlDefault( p_vout, i_query, args );
     }


More information about the vlc-devel mailing list