Commit 732e300c authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Xlib: rely on window provider for full-screen and always-on-top

This fixes always-on-top going away when toggling full-screen and back.
parent 36938ceb
......@@ -255,7 +255,7 @@ int InitGLX13( vout_thread_t *p_vout )
* configuration was chosen, instead of selecting the frame buffer from
* the window. That requires reworking xcommon.c though.
* -- Courmisch */
XGetWindowAttributes( p_sys->p_display, p_sys->p_win->video_window, &att );
XGetWindowAttributes( p_sys->p_display, p_sys->window.video_window, &att );
for( int i = 0; i < i_nb && !fbconf; i++ )
{
XVisualInfo *p_vi;
......@@ -277,7 +277,7 @@ int InitGLX13( vout_thread_t *p_vout )
/* Create the GLX window */
p_sys->gwnd = glXCreateWindow( p_sys->p_display, fbconf,
p_sys->p_win->video_window, NULL );
p_sys->window.video_window, NULL );
if( p_sys->gwnd == None )
{
msg_Err( p_vout, "Cannot create GLX window" );
......@@ -305,8 +305,8 @@ static void SwapBuffers( vout_thread_t *p_vout )
vout_sys_t *p_sys = p_vout->p_sys;
unsigned int i_width, i_height, i_x, i_y;
vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
p_vout->p_sys->p_win->i_height,
vout_PlacePicture( p_vout, p_vout->p_sys->window.i_width,
p_vout->p_sys->window.i_height,
&i_x, &i_y, &i_width, &i_height );
glViewport( 0, 0, (GLint)i_width, (GLint)i_height );
......@@ -317,7 +317,7 @@ static void SwapBuffers( vout_thread_t *p_vout )
}
else
{
glXSwapBuffers( p_sys->p_display, p_sys->p_win->video_window );
glXSwapBuffers( p_sys->p_display, p_sys->window.video_window );
}
}
......@@ -333,7 +333,7 @@ void SwitchContext( vout_thread_t *p_vout )
}
else
{
glXMakeCurrent( p_sys->p_display, p_sys->p_win->video_window,
glXMakeCurrent( p_sys->p_display, p_sys->window.video_window,
p_sys->gwctx );
}
}
......@@ -148,8 +148,6 @@ static void xvmc_update_XV_DOUBLE_BUFFER( vout_thread_t *p_vout );
static void TestNetWMSupport( vout_thread_t * );
static int ConvertKey( int );
static int WindowOnTop( vout_thread_t *, bool );
static int X11ErrorHandler( Display *, XErrorEvent * );
#ifdef HAVE_XSP
......@@ -337,14 +335,14 @@ int Activate ( vlc_object_t *p_this )
CreateCursor( p_vout );
/* Set main window's size */
p_vout->p_sys->original_window.i_x = 0;
p_vout->p_sys->original_window.i_y = 0;
p_vout->p_sys->original_window.i_width = p_vout->i_window_width;
p_vout->p_sys->original_window.i_height = p_vout->i_window_height;
p_vout->p_sys->window.i_x = 0;
p_vout->p_sys->window.i_y = 0;
p_vout->p_sys->window.i_width = p_vout->i_window_width;
p_vout->p_sys->window.i_height = p_vout->i_window_height;
var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
/* Spawn base window - this window will include the video output window,
* but also command buttons, subtitles and other indicators */
if( CreateWindow( p_vout, &p_vout->p_sys->original_window ) )
if( CreateWindow( p_vout, &p_vout->p_sys->window ) )
{
msg_Err( p_vout, "cannot create X11 window" );
DestroyCursor( p_vout );
......@@ -358,7 +356,7 @@ int Activate ( vlc_object_t *p_this )
{
msg_Err( p_vout, "cannot initialize X11 display" );
DestroyCursor( p_vout );
DestroyWindow( p_vout, &p_vout->p_sys->original_window );
DestroyWindow( p_vout, &p_vout->p_sys->window );
XCloseDisplay( p_vout->p_sys->p_display );
free( p_vout->p_sys );
return VLC_EGENERIC;
......@@ -498,7 +496,7 @@ void Deactivate ( vlc_object_t *p_this )
DestroyCursor( p_vout );
EnableXScreenSaver( p_vout );
DestroyWindow( p_vout, &p_vout->p_sys->original_window );
DestroyWindow( p_vout, &p_vout->p_sys->window );
XCloseDisplay( p_vout->p_sys->p_display );
/* Destroy structure */
......@@ -753,8 +751,8 @@ static void RenderVideo( vout_thread_t *p_vout, picture_t *p_pic )
*****************************************************************************/
static void EnablePixelDoubling( vout_thread_t *p_vout )
{
int i_hor_scale = ( p_vout->p_sys->p_win->i_width ) / p_vout->render.i_width;
int i_vert_scale = ( p_vout->p_sys->p_win->i_height ) / p_vout->render.i_height;
int i_hor_scale = ( p_vout->p_sys->window.i_width ) / p_vout->render.i_width;
int i_vert_scale = ( p_vout->p_sys->window.i_height ) / p_vout->render.i_height;
if ( ( i_hor_scale > 1 ) && ( i_vert_scale > 1 ) ) {
p_vout->p_sys->i_hw_scale = 2;
msg_Dbg( p_vout, "Enabling pixel doubling, scaling factor %d", p_vout->p_sys->i_hw_scale );
......@@ -852,14 +850,14 @@ static int InitVideo( vout_thread_t *p_vout )
}
#ifdef HAVE_XSP
vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width / p_vout->p_sys->i_hw_scale,
p_vout->p_sys->p_win->i_height / p_vout->p_sys->i_hw_scale,
vout_PlacePicture( p_vout, p_vout->p_sys->window.i_width / p_vout->p_sys->i_hw_scale,
p_vout->p_sys->window.i_height / p_vout->p_sys->i_hw_scale,
&i_index, &i_index,
&p_vout->fmt_out.i_visible_width,
&p_vout->fmt_out.i_visible_height );
#else
vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
p_vout->p_sys->p_win->i_height,
vout_PlacePicture( p_vout, p_vout->p_sys->window.i_width,
p_vout->p_sys->window.i_height,
&i_index, &i_index,
&p_vout->fmt_out.i_visible_width,
&p_vout->fmt_out.i_visible_height );
......@@ -941,8 +939,8 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
{
unsigned int i_width, i_height, i_x, i_y;
vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
p_vout->p_sys->p_win->i_height,
vout_PlacePicture( p_vout, p_vout->p_sys->window.i_width,
p_vout->p_sys->window.i_height,
&i_x, &i_y, &i_width, &i_height );
#ifdef MODULE_NAME_IS_xvmc
......@@ -1015,7 +1013,7 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
/* XvMCSyncSurface(p_vout->p_sys->p_display, p_picture->p_sys->xvmc_surf); */
XvMCPutSurface( p_vout->p_sys->p_display,
p_pic->p_sys->xvmc_surf,
p_vout->p_sys->p_win->video_window,
p_vout->p_sys->window.video_window,
src_x,
src_y,
src_width,
......@@ -1063,8 +1061,8 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
/* Display rendered image using shared memory extension */
#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
p_vout->p_sys->p_win->video_window,
p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
p_vout->p_sys->window.video_window,
p_vout->p_sys->window.gc, p_pic->p_sys->p_image,
p_vout->fmt_out.i_x_offset,
p_vout->fmt_out.i_y_offset,
p_vout->fmt_out.i_visible_width,
......@@ -1073,8 +1071,8 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
False /* Don't put True here or you'll waste your CPU */ );
#else
XShmPutImage( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->video_window,
p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
p_vout->p_sys->window.video_window,
p_vout->p_sys->window.gc, p_pic->p_sys->p_image,
p_vout->fmt_out.i_x_offset,
p_vout->fmt_out.i_y_offset,
0 /*dest_x*/, 0 /*dest_y*/,
......@@ -1089,8 +1087,8 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
/* Use standard XPutImage -- this is gonna be slow ! */
#if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
XvPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
p_vout->p_sys->p_win->video_window,
p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
p_vout->p_sys->window.video_window,
p_vout->p_sys->window.gc, p_pic->p_sys->p_image,
p_vout->fmt_out.i_x_offset,
p_vout->fmt_out.i_y_offset,
p_vout->fmt_out.i_visible_width,
......@@ -1098,8 +1096,8 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
0 /*dest_x*/, 0 /*dest_y*/, i_width, i_height );
#else
XPutImage( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->video_window,
p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
p_vout->p_sys->window.video_window,
p_vout->p_sys->window.gc, p_pic->p_sys->p_image,
p_vout->fmt_out.i_x_offset,
p_vout->fmt_out.i_y_offset,
0 /*dest_x*/, 0 /*dest_y*/,
......@@ -1129,22 +1127,17 @@ static int ManageVideo( vout_thread_t *p_vout )
#endif
/* Handle events from the owner window */
if( p_vout->p_sys->p_win->owner_window )
while( XCheckWindowEvent( p_vout->p_sys->p_display,
p_vout->p_sys->window.owner_window->handle.xid,
StructureNotifyMask, &xevent ) == True )
{
while( XCheckWindowEvent( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->owner_window->handle.xid,
StructureNotifyMask, &xevent ) == True )
{
/* ConfigureNotify event: prepare */
if( xevent.type == ConfigureNotify )
{
/* Update dimensions */
XResizeWindow( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
xevent.xconfigure.width,
xevent.xconfigure.height );
}
}
/* ConfigureNotify event: prepare */
if( xevent.type == ConfigureNotify )
/* Update dimensions */
XResizeWindow( p_vout->p_sys->p_display,
p_vout->p_sys->window.base_window,
xevent.xconfigure.width,
xevent.xconfigure.height );
}
/* Handle X11 events: ConfigureNotify events are parsed to know if the
......@@ -1153,7 +1146,7 @@ static int ManageVideo( vout_thread_t *p_vout )
* to intercept window destruction requests */
while( XCheckWindowEvent( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
p_vout->p_sys->window.base_window,
StructureNotifyMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | Button1MotionMask , &xevent )
......@@ -1163,14 +1156,14 @@ static int ManageVideo( vout_thread_t *p_vout )
if( xevent.type == ConfigureNotify )
{
if( (unsigned int)xevent.xconfigure.width
!= p_vout->p_sys->p_win->i_width
!= p_vout->p_sys->window.i_width
|| (unsigned int)xevent.xconfigure.height
!= p_vout->p_sys->p_win->i_height )
!= p_vout->p_sys->window.i_height )
{
/* Update dimensions */
p_vout->i_changes |= VOUT_SIZE_CHANGE;
p_vout->p_sys->p_win->i_width = xevent.xconfigure.width;
p_vout->p_sys->p_win->i_height = xevent.xconfigure.height;
p_vout->p_sys->window.i_width = xevent.xconfigure.width;
p_vout->p_sys->window.i_height = xevent.xconfigure.height;
}
}
/* Keyboard event */
......@@ -1322,8 +1315,8 @@ static int ManageVideo( vout_thread_t *p_vout )
/* somewhat different use for vout_PlacePicture:
* here the values are needed to give to mouse coordinates
* in the original picture space */
vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
p_vout->p_sys->p_win->i_height,
vout_PlacePicture( p_vout, p_vout->p_sys->window.i_width,
p_vout->p_sys->window.i_height,
&i_x, &i_y, &i_width, &i_height );
/* Compute the x coordinate and check if the value is
......@@ -1374,7 +1367,7 @@ static int ManageVideo( vout_thread_t *p_vout )
/* Handle events for video output sub-window */
while( XCheckWindowEvent( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->video_window,
p_vout->p_sys->window.video_window,
ExposureMask, &xevent ) == True )
{
/* Window exposed (only handled if stream playback is paused) */
......@@ -1385,7 +1378,7 @@ static int ManageVideo( vout_thread_t *p_vout )
/* (if this is the last a collection of expose events...) */
#if defined(MODULE_NAME_IS_xvideo)
x11_window_t *p_win = p_vout->p_sys->p_win;
x11_window_t *p_win = &p_vout->p_sys->window;
/* Paint the colour key if needed */
if( p_vout->p_sys->b_paint_colourkey &&
......@@ -1419,9 +1412,9 @@ static int ManageVideo( vout_thread_t *p_vout )
while( XCheckTypedEvent( p_vout->p_sys->p_display,
ClientMessage, &xevent ) )
{
if( (xevent.xclient.message_type == p_vout->p_sys->p_win->wm_protocols)
if( (xevent.xclient.message_type == p_vout->p_sys->window.wm_protocols)
&& ((Atom)xevent.xclient.data.l[0]
== p_vout->p_sys->p_win->wm_delete_window ) )
== p_vout->p_sys->window.wm_delete_window ) )
{
/* the user wants to close the window */
playlist_t * p_playlist = pl_Hold( p_vout );
......@@ -1503,12 +1496,12 @@ static int ManageVideo( vout_thread_t *p_vout )
p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
#endif
vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
p_vout->p_sys->p_win->i_height,
vout_PlacePicture( p_vout, p_vout->p_sys->window.i_width,
p_vout->p_sys->window.i_height,
&i_x, &i_y, &i_width, &i_height );
XMoveResizeWindow( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->video_window,
p_vout->p_sys->window.video_window,
i_x, i_y, i_width, i_height );
}
......@@ -1584,7 +1577,6 @@ static int CreateWindow( vout_thread_t *p_vout, x11_window_t *p_win )
XEvent xevent;
bool b_map_notify = false;
vlc_value_t val;
/* Prepare window manager hints and properties */
p_win->wm_protocols =
......@@ -1602,7 +1594,6 @@ static int CreateWindow( vout_thread_t *p_vout, x11_window_t *p_win )
p_vout->p_sys->i_screen);
xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
if( !p_vout->b_fullscreen )
{
vout_window_cfg_t wnd_cfg;
memset( &wnd_cfg, 0, sizeof(wnd_cfg) );
......@@ -1650,50 +1641,6 @@ static int CreateWindow( vout_thread_t *p_vout, x11_window_t *p_win )
CWBackingStore | CWBackPixel | CWEventMask,
&xwindow_attributes );
}
else
{
/* Fullscreen window size and position */
p_win->owner_window = NULL;
p_win->i_x = p_win->i_y = 0;
p_win->i_width =
DisplayWidth( p_vout->p_sys->p_display, p_vout->p_sys->i_screen );
p_win->i_height =
DisplayHeight( p_vout->p_sys->p_display, p_vout->p_sys->i_screen );
/* Create the window and set hints - the window must receive
* ConfigureNotify events, and until it is displayed, Expose and
* MapNotify events. */
p_win->base_window =
XCreateWindow( p_vout->p_sys->p_display,
DefaultRootWindow( p_vout->p_sys->p_display ),
p_win->i_x, p_win->i_y,
p_win->i_width, p_win->i_height,
0,
0, InputOutput, 0,
CWBackingStore | CWBackPixel | CWEventMask,
&xwindow_attributes );
var_Get( p_vout, "video-title", &val );
if( !val.psz_string || !*val.psz_string )
{
XStoreName( p_vout->p_sys->p_display, p_win->base_window,
#ifdef MODULE_NAME_IS_x11
VOUT_TITLE " (X11 output)"
#elif defined(MODULE_NAME_IS_glx)
VOUT_TITLE " (GLX output)"
#else
VOUT_TITLE " (XVideo output)"
#endif
);
}
else
{
XStoreName( p_vout->p_sys->p_display,
p_win->base_window, val.psz_string );
}
free( val.psz_string );
}
if( (p_win->wm_protocols == None) /* use WM_DELETE_WINDOW */
|| (p_win->wm_delete_window == None)
......@@ -1793,10 +1740,6 @@ static int CreateWindow( vout_thread_t *p_vout, x11_window_t *p_win )
/* Do NOT use XFlush here ! */
XSync( p_vout->p_sys->p_display, False );
/* At this stage, the window is open, displayed, and ready to
* receive data */
p_vout->p_sys->p_win = p_win;
return VLC_SUCCESS;
}
......@@ -2042,349 +1985,16 @@ static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
*****************************************************************************/
static void ToggleFullScreen ( vout_thread_t *p_vout )
{
Atom prop;
mwmhints_t mwmhints;
XSetWindowAttributes attributes;
#ifdef HAVE_XINERAMA
int i_d1, i_d2;
#endif
p_vout->b_fullscreen = !p_vout->b_fullscreen;
if( p_vout->b_fullscreen )
{
msg_Dbg( p_vout, "entering fullscreen mode" );
/* Getting current window position */
Window root_win;
Window* child_windows;
unsigned int num_child_windows;
Window parent_win;
Window child_win;
XWindowAttributes win_attr;
int screen_x,screen_y,win_width,win_height;
XGetWindowAttributes(
p_vout->p_sys->p_display,
p_vout->p_sys->p_win->video_window,
&win_attr);
XQueryTree(
p_vout->p_sys->p_display,
p_vout->p_sys->p_win->video_window,
&root_win,
&parent_win,
&child_windows,
&num_child_windows);
XFree(child_windows);
XTranslateCoordinates(
p_vout->p_sys->p_display,
parent_win, win_attr.root,
win_attr.x,win_attr.y,
&screen_x,&screen_y,
&child_win);
win_width = p_vout->p_sys->p_win->i_width;
win_height = p_vout->p_sys->p_win->i_height;
msg_Dbg( p_vout, "X %d/%d Y %d/%d",
win_width, screen_x, win_height, screen_y );
/* screen_x and screen_y are current position */
p_vout->p_sys->b_altfullscreen =
config_GetInt( p_vout, MODULE_STRING "-altfullscreen" );
XUnmapWindow( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window );
p_vout->p_sys->p_win = &p_vout->p_sys->fullscreen_window;
CreateWindow( p_vout, p_vout->p_sys->p_win );
XDestroyWindow( p_vout->p_sys->p_display,
p_vout->p_sys->fullscreen_window.video_window );
XReparentWindow( p_vout->p_sys->p_display,
p_vout->p_sys->original_window.video_window,
p_vout->p_sys->fullscreen_window.base_window, 0, 0 );
p_vout->p_sys->fullscreen_window.video_window =
p_vout->p_sys->original_window.video_window;
/* To my knowledge there are two ways to create a borderless window.
* There's the generic way which is to tell x to bypass the window
* manager, but this creates problems with the focus of other
* applications.
* The other way is to use the motif property "_MOTIF_WM_HINTS" which
* luckily seems to be supported by most window managers. */
if( !p_vout->p_sys->b_altfullscreen )
{
mwmhints.flags = MWM_HINTS_DECORATIONS;
mwmhints.decorations = False;
prop = XInternAtom( p_vout->p_sys->p_display, "_MOTIF_WM_HINTS",
False );
XChangeProperty( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
prop, prop, 32, PropModeReplace,
(unsigned char *)&mwmhints,
PROP_MWM_HINTS_ELEMENTS );
}
else
{
/* brute force way to remove decorations */
attributes.override_redirect = True;
XChangeWindowAttributes( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
CWOverrideRedirect,
&attributes);
/* Make sure the change is effective */
XReparentWindow( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
DefaultRootWindow( p_vout->p_sys->p_display ),
0, 0 );
}
if( p_vout->p_sys->b_net_wm_state_fullscreen )
{
XClientMessageEvent event;
memset( &event, 0, sizeof( XClientMessageEvent ) );
event.type = ClientMessage;
event.message_type = p_vout->p_sys->net_wm_state;
event.display = p_vout->p_sys->p_display;
event.window = p_vout->p_sys->p_win->base_window;
event.format = 32;
event.data.l[ 0 ] = 1; /* set property */
event.data.l[ 1 ] = p_vout->p_sys->net_wm_state_fullscreen;
XSendEvent( p_vout->p_sys->p_display,
DefaultRootWindow( p_vout->p_sys->p_display ),
False, SubstructureRedirectMask,
(XEvent*)&event );
}
/* "bad fullscreen" - set this to 0. doing fullscreen this way is problematic
* for many reasons and basically fights with the window manager as the wm
* reparents AND vlc goes and reparents - multiple times. don't do it. it just
* makes it more inefficient and less "nice" to the x11 citizenry. this turns
* it off */
#define BADFS 0
/* explicitly asking for focus when you fullscreened is a little silly. the
* window manager SHOULD be handling this itself based on its own focus
* policies. if the user is "using" a given xinerama/xrandr screen or x11
* multihead screen AND vlc wants to fullscreen the wm should also focus it
* as its the only thing on the screen. if vlc fullscreens and its on
* "another monitor" to the one the user is using - this may "steal" the focus
* as really the wm should be deciding if, on fullscreening of a window
* the focus should go there or not, so let the wm decided */
#define APPFOCUS 0
/* Make sure the change is effective */
XReparentWindow( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
DefaultRootWindow( p_vout->p_sys->p_display ),
0, 0 );
#ifdef HAVE_XINERAMA
if( XineramaQueryExtension( p_vout->p_sys->p_display, &i_d1, &i_d2 ) &&
XineramaIsActive( p_vout->p_sys->p_display ) )
{
XineramaScreenInfo *screens; /* infos for xinerama */
int i_num_screens;
msg_Dbg( p_vout, "using XFree Xinerama extension");
#define SCREEN p_vout->p_sys->p_win->i_screen
/* Get Information about Xinerama (num of screens) */
screens = XineramaQueryScreens( p_vout->p_sys->p_display,
&i_num_screens );
SCREEN = config_GetInt( p_vout,
MODULE_STRING "-xineramascreen" );
/* just check that user has entered a good value,
* otherwise use that screen where window is */
if( SCREEN >= i_num_screens || SCREEN < 0 )
{
int overlapping=0;
int rightmost_left=0;
int leftmost_right=0;
int bottommost_top=0;
int topmost_bottom=0;
int best_screen=0;
int best_overlapping=0;
int dx,dy;
msg_Dbg( p_vout, "requested screen number invalid (%d/%d)", SCREEN, i_num_screens );
#define left ( screens[SCREEN].x_org )
#define right ( left + screens[SCREEN].width )
#define top screens[SCREEN].y_org
#define bottom ( top + screens[SCREEN].height )
/* Code mostly same as http://superswitcher.googlecode.com/svn/trunk/src/xinerama.c
* by Nigel Tao, as it was pretty clean implemention what's needed here. Checks what display
* contains most of the window, and use that as fullscreen screen instead screen what
* contains videowindows 0.0 */
for( SCREEN = i_num_screens-1; SCREEN >= 0; SCREEN--)
{
rightmost_left = __MAX( left, screen_x );
leftmost_right = __MIN( right, screen_x + win_width );
bottommost_top = __MAX( top, screen_y );
topmost_bottom = __MIN( bottom , screen_y + win_height );
dx = leftmost_right - rightmost_left;
dy = topmost_bottom - bottommost_top;
overlapping=0;
if ( dx > 0 && dy > 0 )
overlapping = dx*dy;
if( SCREEN == (i_num_screens-1) ||
overlapping > best_overlapping )
{
best_overlapping = overlapping;
best_screen = SCREEN;
}
}
msg_Dbg( p_vout, "setting best screen to %d", best_screen );
SCREEN = best_screen;
#undef bottom
#undef top
#undef right
#undef left
}
/* Get the X/Y upper left corner coordinate of the above screen */
p_vout->p_sys->p_win->i_x = screens[SCREEN].x_org;
p_vout->p_sys->p_win->i_y = screens[SCREEN].y_org;
/* Set the Height/width to the screen resolution */
p_vout->p_sys->p_win->i_width = screens[SCREEN].width;
p_vout->p_sys->p_win->i_height = screens[SCREEN].height;
XFree(screens);
#undef SCREEN
}
else
#endif
{
/* The window wasn't necessarily created at the requested size */
p_vout->p_sys->p_win->i_x = p_vout->p_sys->p_win->i_y = 0;
#ifdef HAVE_XF86VIDMODE
XF86VidModeModeLine mode;
int i_dummy;
if( XF86VidModeGetModeLine( p_vout->p_sys->p_display,
p_vout->p_sys->i_screen, &i_dummy,
&mode ) )
{
p_vout->p_sys->p_win->i_width = mode.hdisplay;
p_vout->p_sys->p_win->i_height = mode.vdisplay;
/* move cursor to the middle of the window to prevent
* unwanted display move if the display is smaller than the
* full desktop */
XWarpPointer( p_vout->p_sys->p_display, None,
p_vout->p_sys->p_win->base_window, 0, 0, 0, 0,
mode.hdisplay / 2 , mode.vdisplay / 2 );
/* force desktop view to upper left corner */
XF86VidModeSetViewPort( p_vout->p_sys->p_display,
p_vout->p_sys->i_screen, 0, 0 );
}
else
#endif
{
p_vout->p_sys->p_win->i_width =
DisplayWidth( p_vout->p_sys->p_display,
p_vout->p_sys->i_screen );
p_vout->p_sys->p_win->i_height =
DisplayHeight( p_vout->p_sys->p_display,
p_vout->p_sys->i_screen );
}
}
XMoveResizeWindow( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
p_vout->p_sys->p_win->i_x,
p_vout->p_sys->p_win->i_y,
p_vout->p_sys->p_win->i_width,
p_vout->p_sys->p_win->i_height );
vout_window_SetFullScreen( p_vout->p_sys->window.owner_window,
p_vout->b_fullscreen );
#ifdef HAVE_XSP
if( p_vout->b_fullscreen )
EnablePixelDoubling( p_vout );
#endif
#if APPFOCUS // RASTER: let the wm do focus policy
/* Activate the window (give it the focus) */
XClientMessageEvent event;
memset( &event, 0, sizeof( XClientMessageEvent ) );
event.type = ClientMessage;
event.message_type =
XInternAtom( p_vout->p_sys->p_display, "_NET_ACTIVE_WINDOW", False );
event.display = p_vout->p_sys->p_display;
event.window = p_vout->p_sys->p_win->base_window;
event.format = 32;
event.data.l[ 0 ] = 1; /* source indication (1 = from an application */
event.data.l[ 1 ] = 0; /* timestamp */
event.data.l[ 2 ] = 0; /* requestor's currently active window */
/* XXX: window manager would be more likely to obey if we already have
* an active window (and give it to the event), such as an interface */
XSendEvent( p_vout->p_sys->p_display,
DefaultRootWindow( p_vout->p_sys->p_display ),
False, SubstructureRedirectMask,
(XEvent*)&event );
#endif
}
else
{
msg_Dbg( p_vout, "leaving fullscreen mode" );
#ifdef HAVE_XSP
DisablePixelDoubling( p_vout );
#endif
XReparentWindow( p_vout->p_sys->p_display,
p_vout->p_sys->original_window.video_window,
p_vout->p_sys->original_window.base_window, 0, 0 );
p_vout->p_sys->fullscreen_window.video_window = None;
DestroyWindow( p_vout, &p_vout->p_sys->fullscreen_window );
p_vout->p_sys->p_win = &p_vout->p_sys->original_window;
XMapWindow( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window );
}
/* Unfortunately, using XSync() here is not enough to ensure the
* window has already been mapped because the XMapWindow() request
* has not necessarily been sent directly to our window (remember,
* the call is first redirected to the window manager) */
#if BADFS // RASTER: this is silly... if we have already mapped before
XEvent xevent;
do
{
XWindowEvent( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
StructureNotifyMask, &xevent );
} while( xevent.type != MapNotify );
#else
XSync(p_vout->p_sys->p_display, False);
#endif
/* Be careful, this can generate a BadMatch error if the window is not
* already mapped by the server (see above) */
XSetInputFocus(p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
RevertToParent,
CurrentTime);
/* signal that the size needs to be updated */
p_vout->i_changes |= VOUT_SIZE_CHANGE;
}
/*****************************************************************************
......@@ -2508,14 +2118,14 @@ static void ToggleCursor( vout_thread_t *p_vout )
if( p_vout->p_sys->b_mouse_pointer_visible )
{
XDefineCursor( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
p_vout->p_sys->window.base_window,
p_vout->p_sys->blank_cursor );
p_vout->p_sys->b_mouse_pointer_visible = 0;
}
else
{
XUndefineCursor( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window );
p_vout->p_sys->window.base_window );
p_vout->p_sys->b_mouse_pointer_visible = 1;
}
}
......@@ -3113,7 +2723,6 @@ static void SetPalette( vout_thread_t *p_vout,
*****************************************************************************/
static int Control( vout_thread_t *p_vout, int i_query, va_list args )
{
bool b_arg;
unsigned int i_width, i_height;
switch( i_query )
......@@ -3124,44 +2733,12 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args )
if( !i_width ) i_width = p_vout->i_window_width;
if( !i_height ) i_height = p_vout->i_window_height;
if( p_vout->p_sys->p_win->owner_window )
{
return vout_window_SetSize( p_vout->p_sys->p_win->owner_window,
i_width, i_height);
}
else
{
#ifdef MODULE_NAME_IS_xvmc
xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
#endif
/* Update dimensions */
XResizeWindow( p_vout->p_sys->p_display,
p_vout->p_sys->p_win->base_window,
i_width, i_height );
#ifdef MODULE_NAME_IS_xvmc
xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
#endif
return VLC_SUCCESS;
}
return vout_window_SetSize( p_vout->p_sys->window.owner_window,
i_width, i_height);
case VOUT_SET_STAY_ON_TOP:
b_arg = (bool) va_arg( args, int );
if( p_vout->p_sys->p_win->owner_window )
{
return vout_window_SetOnTop( p_vout->p_sys->p_win->owner_window, b_arg );
}
else
{
#ifdef MODULE_NAME_IS_xvmc
xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
#endif
WindowOnTop( p_vout, b_arg );
#ifdef MODULE_NAME_IS_xvmc
xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
#endif
return VLC_SUCCESS;
}
return vout_window_SetOnTop( p_vout->p_sys->window.owner_window,
va_arg( args, int ) );
default:
return VLC_EGENERIC;
......@@ -3301,34 +2878,3 @@ static int ConvertKey( int i_key )
return 0;
}
/*****************************************************************************
* WindowOnTop: Switches the "always on top" state of the video window.
*****************************************************************************/
static int WindowOnTop( vout_thread_t *p_vout, bool b_on_top )
{
XClientMessageEvent event;
memset( &event, 0, sizeof( XClientMessageEvent ) );
event.type = ClientMessage;
event.message_type = p_vout->p_sys->net_wm_state;
event.display = p_vout->p_sys->p_display;
event.window = p_vout->p_sys->p_win->base_window;
event.format = 32;
event.data.l[ 0 ] = b_on_top; /* set property */
if( p_vout->p_sys->b_net_wm_state_stays_on_top )
event.data.l[ 1 ] = p_vout->p_sys->net_wm_state_stays_on_top;
else if( p_vout->p_sys->b_net_wm_state_above )
/* use _NET_WM_STATE_ABOVE if window manager
* doesn't handle _NET_WM_STATE_STAYS_ON_TOP */
event.data.l[ 1 ] = p_vout->p_sys->net_wm_state_above;
else
return VLC_EGENERIC;
XSendEvent( p_vout->p_sys->p_display,
DefaultRootWindow( p_vout->p_sys->p_display ),
False, SubstructureRedirectMask,
(XEvent*)&event );
return VLC_SUCCESS;
}
......@@ -214,12 +214,8 @@ struct vout_sys_t
Visual * p_visual; /* visual pointer */
int i_screen; /* screen number */
/* Our current window */
x11_window_t * p_win;
/* Our two windows */
x11_window_t original_window;
x11_window_t fullscreen_window;
/* Our window */
x11_window_t window;
/* key and mouse event handling */
int i_vout_event; /* 1(Fullsupport), 2(FullscreenOnly), 3(none) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment