2001-04-15 22:31:58 +02:00
2001-03-03 22:47:37 +01:00
# include <stdio.h>
# include <stdlib.h>
2002-10-29 21:27:47 +01:00
# include <math.h>
2002-06-13 00:57:58 +02:00
# include <inttypes.h>
2001-04-15 20:35:17 +02:00
2001-04-15 22:31:58 +02:00
# include "config.h"
2002-05-06 17:48:07 +02:00
# include "mp_msg.h"
2002-06-13 00:57:58 +02:00
# include "x11_common.h"
2001-04-15 22:31:58 +02:00
# ifdef X11_FULLSCREEN
# include <string.h>
2001-03-03 22:47:37 +01:00
# include <unistd.h>
# include <sys/mman.h>
# include "video_out.h"
2001-04-10 02:00:04 +02:00
# include <X11/Xmd.h>
2001-03-03 22:47:37 +01:00
# include <X11/Xlib.h>
# include <X11/Xutil.h>
# include <X11/Xatom.h>
2001-07-19 20:47:22 +02:00
# ifdef HAVE_XDPMS
2001-04-15 22:31:58 +02:00
# include <X11/extensions/dpms.h>
2001-07-19 20:47:22 +02:00
# endif
2001-04-15 22:31:58 +02:00
2001-10-10 03:48:54 +02:00
# ifdef HAVE_XINERAMA
# include <X11/extensions/Xinerama.h>
# endif
2001-08-28 19:52:20 +02:00
2002-01-31 01:37:27 +01:00
# ifdef HAVE_XF86VM
# include <X11/extensions/xf86vmode.h>
# endif
2002-02-11 12:44:50 +01:00
# include "../input/input.h"
# include "../input/mouse.h"
2002-02-21 23:48:47 +01:00
# ifdef HAVE_NEW_GUI
# include "../Gui/interface.h"
2002-05-08 18:41:44 +02:00
# include "../mplayer.h"
2002-02-21 23:48:47 +01:00
# endif
2002-05-06 17:05:07 +02:00
# define vo_wm_Unknown 0
# define vo_wm_NetWM 1
# define vo_wm_KDE 2
# define vo_wm_IceWM 3
# define vo_wm_WMakerStyle 4
2001-08-28 19:52:20 +02:00
2002-05-27 13:19:56 +02:00
int ice_layer = 12 ;
2002-06-04 22:12:34 +02:00
int stop_xscreensaver = 0 ;
2002-05-27 13:19:56 +02:00
2001-04-10 02:00:04 +02:00
static int dpms_disabled = 0 ;
static int timeout_save = 0 ;
2002-06-04 22:12:34 +02:00
static int xscreensaver_was_running = 0 ;
2001-04-10 02:00:04 +02:00
2001-06-01 00:32:58 +02:00
char * mDisplayName = NULL ;
2002-05-18 01:51:37 +02:00
Display * mDisplay = NULL ;
2001-06-01 00:32:58 +02:00
Window mRootWin ;
int mScreen ;
int mLocalDisplay ;
2001-12-28 14:24:27 +01:00
/* output window id */
int WinID = - 1 ;
2002-05-03 22:57:13 +02:00
int vo_mouse_autohide = 0 ;
2002-05-14 13:41:02 +02:00
int vo_wm_type = - 1 ;
2001-04-13 02:54:05 +02:00
2002-09-18 03:22:03 +02:00
static int vo_old_x = 0 ;
static int vo_old_y = 0 ;
static int vo_old_width = 0 ;
static int vo_old_height = 0 ;
2002-01-06 22:07:20 +01:00
# ifdef HAVE_XINERAMA
int xinerama_screen = 0 ;
int xinerama_x = 0 ;
int xinerama_y = 0 ;
# endif
2002-01-31 01:37:27 +01:00
# ifdef HAVE_XF86VM
XF86VidModeModeInfo * * vidmodes = NULL ;
2002-03-07 15:04:15 +01:00
XF86VidModeModeLine modeline ;
2002-01-31 01:37:27 +01:00
# endif
2001-04-13 02:54:05 +02:00
void vo_hidecursor ( Display * disp , Window win )
{
2001-04-16 01:22:01 +02:00
Cursor no_ptr ;
Pixmap bm_no ;
XColor black , dummy ;
Colormap colormap ;
static unsigned char bm_no_data [ ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2002-01-02 20:14:05 +01:00
if ( WinID = = 0 ) return ; // do not hide, if we're playing at rootwin
2001-04-16 01:22:01 +02:00
colormap = DefaultColormap ( disp , DefaultScreen ( disp ) ) ;
XAllocNamedColor ( disp , colormap , " black " , & black , & dummy ) ;
bm_no = XCreateBitmapFromData ( disp , win , bm_no_data , 8 , 8 ) ;
no_ptr = XCreatePixmapCursor ( disp , bm_no , bm_no , & black , & black , 0 , 0 ) ;
XDefineCursor ( disp , win , no_ptr ) ;
2002-04-16 19:41:29 +02:00
XFreeCursor ( disp , no_ptr ) ;
2001-04-13 02:54:05 +02:00
}
2002-04-16 19:41:29 +02:00
void vo_showcursor ( Display * disp , Window win )
2002-05-03 22:57:13 +02:00
{
if ( WinID = = 0 ) return ;
XDefineCursor ( disp , win , 0 ) ;
}
2001-04-13 02:54:05 +02:00
2002-05-13 22:45:42 +02:00
static int x11_errorhandler ( Display * display , XErrorEvent * event )
2002-02-17 13:34:29 +01:00
{
# define MSGLEN 60
char msg [ MSGLEN ] ;
2002-02-22 20:36:21 +01:00
XGetErrorText ( display , event - > error_code , ( char * ) & msg , MSGLEN ) ;
2002-02-17 13:34:29 +01:00
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_ERR , " X11 error: %s \n " , msg ) ;
2002-02-17 13:34:29 +01:00
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_V , " Type: %x, display: %x, resourceid: %x, serial: %x \n " ,
2002-02-17 13:34:29 +01:00
event - > type , event - > display , event - > resourceid , event - > serial ) ;
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_V , " Error code: %x, request code: %x, minor code: %x \n " ,
2002-02-17 13:34:29 +01:00
event - > error_code , event - > request_code , event - > minor_code ) ;
2002-05-15 01:44:35 +02:00
abort ( ) ;
//exit_player("X11 error");
2002-02-17 13:34:29 +01:00
# undef MSGLEN
}
2001-08-28 19:52:20 +02:00
2002-05-11 19:21:32 +02:00
int vo_wm_string_test ( char * name )
{
if ( ! strncmp ( name , " _ICEWM_TRAY " , 11 ) )
{ mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] Detected wm is IceWM. \n " ) ; return vo_wm_IceWM ; }
if ( ! strncmp ( name , " _KDE_ " , 5 ) )
{ mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] Detected wm is KDE. \n " ) ; return vo_wm_KDE ; }
if ( ! strncmp ( name , " KWM_WIN_DESKTOP " , 15 ) )
{ mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] Detected wm is WindowMaker style. \n " ) ; return vo_wm_WMakerStyle ; }
// fprintf(stderr,"[ws] PropertyNotify ( 0x%x ) %s ( 0x%x )\n",win,name,xev.xproperty.atom );
return vo_wm_Unknown ;
}
2002-05-07 15:31:29 +02:00
int vo_wm_detect ( void )
{
Atom type ;
Window win ;
XEvent xev ;
int c = 0 ;
int wm = vo_wm_Unknown ;
int format ;
unsigned long nitems , bytesafter ;
unsigned char * args = NULL ;
2002-05-11 16:57:41 +02:00
char * name = NULL ;
if ( WinID > = 0 ) return vo_wm_Unknown ;
2002-05-07 15:31:29 +02:00
# if 1
// --- netwm
type = XInternAtom ( mDisplay , " _NET_SUPPORTED " , False ) ;
2002-05-23 17:40:08 +02:00
if ( Success = = XGetWindowProperty ( mDisplay , mRootWin , type , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytesafter , & args ) & & nitems > 0 )
2002-05-07 15:31:29 +02:00
{
2002-05-11 16:57:41 +02:00
mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] Detected wm is of class NetWM. \n " ) ;
2002-05-07 15:31:29 +02:00
XFree ( args ) ;
return vo_wm_NetWM ;
}
# endif
// --- other wm
mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] Create window for WM detect ... \n " ) ;
win = XCreateSimpleWindow ( mDisplay , mRootWin , vo_screenwidth , vo_screenheight , 1 , 1 , 0 , 0 , 0 ) ;
XSelectInput ( mDisplay , win , PropertyChangeMask | StructureNotifyMask ) ;
XMapWindow ( mDisplay , win ) ;
XMoveWindow ( mDisplay , win , vo_screenwidth , vo_screenheight ) ;
do
{
XCheckWindowEvent ( mDisplay , win , PropertyChangeMask | StructureNotifyMask , & xev ) ;
if ( xev . type = = PropertyNotify )
{
2002-05-11 16:57:41 +02:00
name = XGetAtomName ( mDisplay , xev . xproperty . atom ) ;
2002-05-07 15:31:29 +02:00
if ( ! name ) break ;
2002-05-11 19:21:32 +02:00
wm = vo_wm_string_test ( name ) ;
if ( wm ! = vo_wm_Unknown ) break ;
2002-05-11 16:57:41 +02:00
XFree ( name ) ; name = NULL ;
2002-05-07 15:31:29 +02:00
}
} while ( c + + < 25 ) ;
2002-05-11 16:57:41 +02:00
if ( name ) XFree ( name ) ;
2002-05-14 13:41:02 +02:00
XUnmapWindow ( mDisplay , win ) ;
2002-05-07 15:31:29 +02:00
XDestroyWindow ( mDisplay , win ) ;
# ifdef MP_DEBUG
if ( wm = = vo_wm_Unknown ) mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] Unknown wm type... \n " ) ;
# endif
return wm ;
}
2001-03-03 22:47:37 +01:00
int vo_init ( void )
{
2001-06-01 00:32:58 +02:00
// int mScreen;
2001-08-28 19:52:20 +02:00
int depth , bpp ;
2001-06-17 03:22:09 +02:00
unsigned int mask ;
2001-06-01 00:32:58 +02:00
// char * DisplayName = ":0.0";
// Display * mDisplay;
2001-08-28 19:52:20 +02:00
XImage * mXImage = NULL ;
2001-06-01 00:32:58 +02:00
// Window mRootWin;
2001-08-28 19:52:20 +02:00
XWindowAttributes attribs ;
2002-02-23 02:38:06 +01:00
char * dispName ;
2001-03-03 22:47:37 +01:00
if ( vo_depthonscreen ) return 1 ; // already called
2002-02-22 20:36:21 +01:00
XSetErrorHandler ( x11_errorhandler ) ;
#if 0
2001-06-01 00:32:58 +02:00
if ( ! mDisplayName )
if ( ! ( mDisplayName = getenv ( " DISPLAY " ) ) )
mDisplayName = strdup ( " :0.0 " ) ;
2002-02-22 20:36:21 +01:00
# else
2002-02-23 02:38:06 +01:00
dispName = XDisplayName ( mDisplayName ) ;
2002-02-22 20:36:21 +01:00
# endif
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_V , " X11 opening display: %s \n " , dispName ) ;
2001-06-01 00:32:58 +02:00
2002-02-23 02:38:06 +01:00
mDisplay = XOpenDisplay ( dispName ) ;
2001-03-03 22:47:37 +01:00
if ( ! mDisplay )
{
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_ERR , " vo: couldn't open the X11 display (%s)! \n " , dispName ) ;
2001-03-03 22:47:37 +01:00
return 0 ;
}
mScreen = DefaultScreen ( mDisplay ) ; // Screen ID.
mRootWin = RootWindow ( mDisplay , mScreen ) ; // Root window ID.
2001-10-10 03:48:54 +02:00
# ifdef HAVE_XINERAMA
if ( XineramaIsActive ( mDisplay ) )
{
XineramaScreenInfo * screens ;
int num_screens ;
2002-01-05 09:49:46 +01:00
2001-10-10 03:48:54 +02:00
screens = XineramaQueryScreens ( mDisplay , & num_screens ) ;
2002-01-06 22:07:20 +01:00
if ( xinerama_screen > = num_screens ) xinerama_screen = 0 ;
2001-12-11 17:45:25 +01:00
if ( ! vo_screenwidth )
2002-01-06 22:07:20 +01:00
vo_screenwidth = screens [ xinerama_screen ] . width ;
2001-12-11 17:45:25 +01:00
if ( ! vo_screenheight )
2002-01-06 22:07:20 +01:00
vo_screenheight = screens [ xinerama_screen ] . height ;
xinerama_x = screens [ xinerama_screen ] . x_org ;
xinerama_y = screens [ xinerama_screen ] . y_org ;
2002-01-05 09:49:46 +01:00
XFree ( screens ) ;
2001-10-10 03:48:54 +02:00
}
else
2002-03-07 15:04:15 +01:00
# endif
# ifdef HAVE_XF86VM
{
int clock ;
XF86VidModeGetModeLine ( mDisplay , mScreen , & clock , & modeline ) ;
if ( ! vo_screenwidth ) vo_screenwidth = modeline . hdisplay ;
if ( ! vo_screenheight ) vo_screenheight = modeline . vdisplay ;
}
2001-10-10 03:48:54 +02:00
# endif
{
2001-10-22 16:19:48 +02:00
if ( ! vo_screenwidth )
vo_screenwidth = DisplayWidth ( mDisplay , mScreen ) ;
if ( ! vo_screenheight )
vo_screenheight = DisplayHeight ( mDisplay , mScreen ) ;
2001-10-10 03:48:54 +02:00
}
2001-08-28 19:52:20 +02:00
// get color depth (from root window, or the best visual):
2001-03-03 22:47:37 +01:00
XGetWindowAttributes ( mDisplay , mRootWin , & attribs ) ;
2001-08-28 19:52:20 +02:00
depth = attribs . depth ;
if ( depth ! = 15 & & depth ! = 16 & & depth ! = 24 & & depth ! = 32 ) {
Visual * visual ;
depth = vo_find_depth_from_visuals ( mDisplay , mScreen , & visual ) ;
if ( depth ! = - 1 )
mXImage = XCreateImage ( mDisplay , visual , depth , ZPixmap ,
0 , NULL , 1 , 1 , 8 , 1 ) ;
} else
2002-09-03 20:10:42 +02:00
mXImage = XGetImage ( mDisplay , mRootWin , 0 , 0 , 1 , 1 , AllPlanes , ZPixmap ) ;
2001-08-28 19:52:20 +02:00
vo_depthonscreen = depth ; // display depth on screen
// get bits/pixel from XImage structure:
if ( mXImage = = NULL ) {
mask = 0 ;
} else {
/*
* for the depth = = 24 case , the XImage structures might use
* 24 or 32 bits of data per pixel . The global variable
* vo_depthonscreen stores the amount of data per pixel in the
* XImage structure !
*
* Maybe we should rename vo_depthonscreen to ( or add ) vo_bpp ?
*/
2001-03-03 22:47:37 +01:00
bpp = mXImage - > bits_per_pixel ;
2001-06-17 03:22:09 +02:00
if ( ( vo_depthonscreen + 7 ) / 8 ! = ( bpp + 7 ) / 8 ) vo_depthonscreen = bpp ; // by A'rpi
mask = mXImage - > red_mask | mXImage - > green_mask | mXImage - > blue_mask ;
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_V , " vo: X11 color mask: %X (R:%lX G:%lX B:%lX) \n " ,
2001-08-28 19:52:20 +02:00
mask , mXImage - > red_mask , mXImage - > green_mask , mXImage - > blue_mask ) ;
2002-01-15 22:30:45 +01:00
XDestroyImage ( mXImage ) ;
2001-08-28 19:52:20 +02:00
}
if ( ( ( vo_depthonscreen + 7 ) / 8 ) = = 2 ) {
if ( mask = = 0x7FFF ) vo_depthonscreen = 15 ; else
if ( mask = = 0xFFFF ) vo_depthonscreen = 16 ;
}
2001-06-01 00:32:58 +02:00
// XCloseDisplay( mDisplay );
2001-08-06 02:22:44 +02:00
/* slightly improved local display detection AST */
2002-02-23 02:38:06 +01:00
if ( strncmp ( dispName , " unix: " , 5 ) = = 0 )
dispName + = 4 ;
else if ( strncmp ( dispName , " localhost: " , 10 ) = = 0 )
dispName + = 9 ;
2002-09-23 23:17:30 +02:00
if ( * dispName = = ' : ' & & atoi ( dispName + 1 ) < 10 ) mLocalDisplay = 1 ; else mLocalDisplay = 0 ;
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_INFO , " vo: X11 running at %dx%d with depth %d and %d bpp ( \" %s \" => %s display) \n " ,
2001-08-28 19:52:20 +02:00
vo_screenwidth , vo_screenheight ,
depth , vo_depthonscreen ,
2002-02-23 02:38:06 +01:00
dispName , mLocalDisplay ? " local " : " remote " ) ;
2002-05-06 17:05:07 +02:00
2002-05-07 15:31:29 +02:00
vo_wm_type = vo_wm_detect ( ) ;
2002-05-06 17:05:07 +02:00
2002-08-28 17:55:58 +02:00
saver_off ( mDisplay ) ;
2001-03-03 22:47:37 +01:00
return 1 ;
}
2002-05-08 18:41:44 +02:00
void vo_uninit ( void )
{
2002-05-13 22:45:42 +02:00
if ( ! mDisplay )
{
mp_msg ( MSGT_VO , MSGL_V , " vo: x11 uninit called but X11 not inited.. \n " ) ;
return ;
}
// if( !vo_depthonscreen ) return;
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_V , " vo: uninit ... \n " ) ;
2002-05-08 22:24:35 +02:00
XSetErrorHandler ( NULL ) ;
2002-05-08 18:41:44 +02:00
XCloseDisplay ( mDisplay ) ;
2002-05-08 22:24:35 +02:00
vo_depthonscreen = 0 ;
2002-05-18 01:51:37 +02:00
mDisplay = NULL ;
2002-05-08 18:41:44 +02:00
}
2002-01-31 12:04:41 +01:00
2001-03-03 22:47:37 +01:00
# include "../linux/keycodes.h"
# include "wskeys.h"
extern void mplayer_put_key ( int code ) ;
void vo_x11_putkey ( int key ) {
switch ( key )
{
case wsLeft : mplayer_put_key ( KEY_LEFT ) ; break ;
case wsRight : mplayer_put_key ( KEY_RIGHT ) ; break ;
case wsUp : mplayer_put_key ( KEY_UP ) ; break ;
case wsDown : mplayer_put_key ( KEY_DOWN ) ; break ;
case wsSpace : mplayer_put_key ( ' ' ) ; break ;
case wsEscape : mplayer_put_key ( KEY_ESC ) ; break ;
case wsEnter : mplayer_put_key ( KEY_ENTER ) ; break ;
2001-04-27 00:10:25 +02:00
case wsPageUp : mplayer_put_key ( KEY_PAGE_UP ) ; break ;
case wsPageDown : mplayer_put_key ( KEY_PAGE_DOWN ) ; break ;
2001-03-03 22:47:37 +01:00
case wsq :
case wsQ : mplayer_put_key ( ' q ' ) ; break ;
case wsp :
case wsP : mplayer_put_key ( ' p ' ) ; break ;
case wsMinus :
case wsGrayMinus : mplayer_put_key ( ' - ' ) ; break ;
case wsPlus :
case wsGrayPlus : mplayer_put_key ( ' + ' ) ; break ;
2001-04-16 02:49:32 +02:00
case wsGrayMul :
case wsMul : mplayer_put_key ( ' * ' ) ; break ;
case wsGrayDiv :
case wsDiv : mplayer_put_key ( ' / ' ) ; break ;
2001-12-14 18:37:45 +01:00
case wsLess : mplayer_put_key ( ' < ' ) ; break ;
case wsMore : mplayer_put_key ( ' > ' ) ; break ;
2001-04-18 22:48:15 +02:00
case wsm :
case wsM : mplayer_put_key ( ' m ' ) ; break ;
2001-04-27 17:41:39 +02:00
case wso :
case wsO : mplayer_put_key ( ' o ' ) ; break ;
2001-08-13 13:08:18 +02:00
default : if ( ( key > = ' a ' & & key < = ' z ' ) | | ( key > = ' A ' & & key < = ' Z ' ) | |
( key > = ' 0 ' & & key < = ' 9 ' ) ) mplayer_put_key ( key ) ;
2001-03-03 22:47:37 +01:00
}
2001-04-12 02:05:41 +02:00
2001-03-03 22:47:37 +01:00
}
// ----- Motif header: -------
2001-06-27 10:50:03 +02:00
# define MWM_HINTS_FUNCTIONS (1L << 0)
# define MWM_HINTS_DECORATIONS (1L << 1)
# define MWM_HINTS_INPUT_MODE (1L << 2)
# define MWM_HINTS_STATUS (1L << 3)
# define MWM_FUNC_ALL (1L << 0)
# define MWM_FUNC_RESIZE (1L << 1)
# define MWM_FUNC_MOVE (1L << 2)
# define MWM_FUNC_MINIMIZE (1L << 3)
# define MWM_FUNC_MAXIMIZE (1L << 4)
# define MWM_FUNC_CLOSE (1L << 5)
# define MWM_DECOR_ALL (1L << 0)
# define MWM_DECOR_BORDER (1L << 1)
# define MWM_DECOR_RESIZEH (1L << 2)
# define MWM_DECOR_TITLE (1L << 3)
# define MWM_DECOR_MENU (1L << 4)
# define MWM_DECOR_MINIMIZE (1L << 5)
# define MWM_DECOR_MAXIMIZE (1L << 6)
# define MWM_INPUT_MODELESS 0
# define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
# define MWM_INPUT_SYSTEM_MODAL 2
# define MWM_INPUT_FULL_APPLICATION_MODAL 3
# define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
# define MWM_TEAROFF_WINDOW (1L<<0)
2001-03-03 22:47:37 +01:00
typedef struct
{
long flags ;
long functions ;
long decorations ;
long input_mode ;
2001-06-27 10:50:03 +02:00
long state ;
2001-03-03 22:47:37 +01:00
} MotifWmHints ;
extern MotifWmHints vo_MotifWmHints ;
extern Atom vo_MotifHints ;
extern int vo_depthonscreen ;
extern int vo_screenwidth ;
extern int vo_screenheight ;
static MotifWmHints vo_MotifWmHints ;
static Atom vo_MotifHints = None ;
2001-07-04 01:23:55 +02:00
// Note: always d==0 !
2001-03-03 22:47:37 +01:00
void vo_x11_decoration ( Display * vo_Display , Window w , int d )
{
2001-07-04 01:23:55 +02:00
2002-05-03 22:57:13 +02:00
if ( ! WinID ) return ;
2001-07-04 01:23:55 +02:00
if ( vo_fsmode & 1 ) {
XSetWindowAttributes attr ;
2002-05-05 17:33:50 +02:00
attr . override_redirect = ( ! d ) ? True : False ;
2001-07-04 01:23:55 +02:00
XChangeWindowAttributes ( vo_Display , w , CWOverrideRedirect , & attr ) ;
2002-01-31 12:15:54 +01:00
// XMapWindow(vo_Display, w);
2001-07-04 01:23:55 +02:00
}
2001-07-29 18:40:32 +02:00
if ( vo_fsmode & 8 ) {
XSetTransientForHint ( vo_Display , w , RootWindow ( vo_Display , mScreen ) ) ;
}
2001-03-03 22:47:37 +01:00
vo_MotifHints = XInternAtom ( vo_Display , " _MOTIF_WM_HINTS " , 0 ) ;
if ( vo_MotifHints ! = None )
{
2001-06-27 10:50:03 +02:00
memset ( & vo_MotifWmHints , 0 , sizeof ( MotifWmHints ) ) ;
vo_MotifWmHints . flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS ;
2002-03-08 21:14:08 +01:00
if ( d )
{
2002-05-12 18:01:08 +02:00
vo_MotifWmHints . functions = MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE ;
2002-03-08 21:14:08 +01:00
d = MWM_DECOR_ALL ;
}
#if 0
2001-07-04 01:23:55 +02:00
vo_MotifWmHints . decorations = d | ( ( vo_fsmode & 2 ) ? 0 : MWM_DECOR_MENU ) ;
2002-03-08 21:14:08 +01:00
# else
vo_MotifWmHints . decorations = d | ( ( vo_fsmode & 2 ) ? MWM_DECOR_MENU : 0 ) ;
# endif
2001-03-03 22:47:37 +01:00
XChangeProperty ( vo_Display , w , vo_MotifHints , vo_MotifHints , 32 ,
2001-07-04 01:23:55 +02:00
PropModeReplace , ( unsigned char * ) & vo_MotifWmHints , ( vo_fsmode & 4 ) ? 4 : 5 ) ;
2001-03-03 22:47:37 +01:00
}
}
2001-06-17 03:22:09 +02:00
void vo_x11_classhint ( Display * display , Window window , char * name ) {
XClassHint wmClass ;
2002-06-13 00:57:58 +02:00
pid_t pid = getpid ( ) ;
2001-06-17 03:22:09 +02:00
wmClass . res_name = name ;
wmClass . res_class = " MPlayer " ;
XSetClassHint ( display , window , & wmClass ) ;
2002-06-13 00:57:58 +02:00
XChangeProperty ( display , window , XInternAtom ( display , " _NET_WM_PID " , False ) , XA_CARDINAL , 32 , PropModeReplace , ( unsigned char * ) & pid , 1 ) ;
2001-06-17 03:22:09 +02:00
}
2002-03-08 21:14:08 +01:00
Window vo_window = None ;
2002-05-15 01:44:35 +02:00
GC vo_gc = NULL ;
2002-03-08 21:14:08 +01:00
XSizeHints vo_hint ;
2001-05-08 14:17:03 +02:00
2002-02-21 22:11:01 +01:00
# ifdef HAVE_NEW_GUI
2001-08-28 01:56:44 +02:00
void vo_setwindow ( Window w , GC g ) {
vo_window = w ; vo_gc = g ;
2001-08-29 17:09:19 +02:00
}
2001-05-08 14:17:03 +02:00
# endif
2002-05-15 01:44:35 +02:00
void vo_x11_uninit ( )
2002-01-31 12:15:54 +01:00
{
2002-08-28 17:55:58 +02:00
saver_on ( mDisplay ) ;
2002-05-15 01:44:35 +02:00
if ( vo_window ! = None ) vo_showcursor ( mDisplay , vo_window ) ;
2002-02-17 13:34:29 +01:00
2002-01-31 12:15:54 +01:00
# ifdef HAVE_NEW_GUI
/* destroy window only if it's not controlled by GUI */
2002-05-08 18:41:44 +02:00
if ( ! use_gui )
2002-01-31 12:15:54 +01:00
# endif
{
2002-05-15 01:44:35 +02:00
if ( vo_gc ) {
XSetBackground ( mDisplay , vo_gc , 0 ) ;
2002-10-17 00:53:18 +02:00
XFreeGC ( mDisplay , vo_gc ) ;
2002-05-15 01:44:35 +02:00
vo_gc = NULL ;
}
if ( vo_window ! = None ) {
XClearWindow ( mDisplay , vo_window ) ;
if ( WinID < 0 ) {
2002-05-24 23:56:58 +02:00
XEvent xev ;
2002-05-15 01:44:35 +02:00
XUnmapWindow ( mDisplay , vo_window ) ;
XDestroyWindow ( mDisplay , vo_window ) ;
2002-05-24 23:56:58 +02:00
do { XNextEvent ( mDisplay , & xev ) ; } while ( xev . type ! = DestroyNotify | | xev . xdestroywindow . event ! = vo_window ) ;
2002-05-15 01:44:35 +02:00
}
vo_window = None ;
}
2002-05-08 18:41:44 +02:00
vo_fs = 0 ;
2002-09-18 03:22:03 +02:00
vo_old_width = vo_old_height = 0 ;
2002-01-31 12:15:54 +01:00
}
}
2002-04-16 19:41:29 +02:00
int vo_mouse_timer_const = 30 ;
static int vo_mouse_counter = 30 ;
2001-03-03 22:47:37 +01:00
int vo_x11_check_events ( Display * mydisplay ) {
int ret = 0 ;
XEvent Event ;
char buf [ 100 ] ;
KeySym keySym ;
2001-06-05 20:40:44 +02:00
static XComposeStatus stat ;
2002-04-16 19:41:29 +02:00
2001-03-03 22:47:37 +01:00
// unsigned long vo_KeyTable[512];
2002-05-03 22:57:13 +02:00
if ( ( vo_mouse_autohide ) & & ( - - vo_mouse_counter = = 0 ) ) vo_hidecursor ( mydisplay , vo_window ) ;
2002-05-15 01:44:35 +02:00
2002-02-21 22:11:01 +01:00
while ( XPending ( mydisplay ) )
{
XNextEvent ( mydisplay , & Event ) ;
2002-02-21 23:48:47 +01:00
# ifdef HAVE_NEW_GUI
2002-03-13 11:59:20 +01:00
if ( use_gui )
{
guiGetEvent ( 0 , ( char * ) & Event ) ;
if ( vo_window ! = Event . xany . window ) continue ;
}
2002-02-21 23:48:47 +01:00
# endif
2002-05-15 01:44:35 +02:00
// printf("\rEvent.type=%X \n",Event.type);
2002-02-21 22:11:01 +01:00
switch ( Event . type )
{
case Expose :
ret | = VO_EVENT_EXPOSE ;
break ;
case ConfigureNotify :
2002-09-18 03:22:03 +02:00
// if (!vo_fs && (Event.xconfigure.width == vo_screenwidth || Event.xconfigure.height == vo_screenheight)) break;
// if (vo_fs && Event.xconfigure.width != vo_screenwidth && Event.xconfigure.height != vo_screenheight) break;
2002-02-21 22:11:01 +01:00
vo_dwidth = Event . xconfigure . width ;
vo_dheight = Event . xconfigure . height ;
2002-02-22 20:36:21 +01:00
#if 0
/* when resizing, x and y are zero :( */
vo_dx = Event . xconfigure . x ;
vo_dy = Event . xconfigure . y ;
# else
{
Window root ;
int foo ;
2002-05-20 06:00:25 +02:00
Window win ;
2002-02-22 20:36:21 +01:00
XGetGeometry ( mydisplay , vo_window , & root , & foo , & foo ,
& foo /*width*/ , & foo /*height*/ , & foo , & foo ) ;
XTranslateCoordinates ( mydisplay , vo_window , root , 0 , 0 ,
2002-05-20 06:00:25 +02:00
& vo_dx , & vo_dy , & win ) ;
2002-02-22 20:36:21 +01:00
}
# endif
2002-02-21 22:11:01 +01:00
ret | = VO_EVENT_RESIZE ;
break ;
case KeyPress :
2002-03-07 12:57:33 +01:00
{
int key ;
XLookupString ( & Event . xkey , buf , sizeof ( buf ) , & keySym , & stat ) ;
key = ( ( keySym & 0xff00 ) ! = 0 ? ( ( keySym & 0x00ff ) + 256 ) : ( keySym ) ) ;
# ifdef HAVE_NEW_GUI
if ( ( use_gui ) & & ( key = = wsEnter ) ) break ;
# endif
vo_x11_putkey ( key ) ;
ret | = VO_EVENT_KEYPRESS ;
}
2002-02-21 22:11:01 +01:00
break ;
2002-04-16 19:41:29 +02:00
case MotionNotify :
2002-05-03 22:57:13 +02:00
if ( vo_mouse_autohide ) { vo_showcursor ( mydisplay , vo_window ) ; vo_mouse_counter = vo_mouse_timer_const ; }
2002-04-16 19:41:29 +02:00
break ;
2002-02-21 22:11:01 +01:00
case ButtonPress :
2002-05-03 22:57:13 +02:00
if ( vo_mouse_autohide ) { vo_showcursor ( mydisplay , vo_window ) ; vo_mouse_counter = vo_mouse_timer_const ; }
2002-02-21 22:11:01 +01:00
// Ignore mouse whell press event
2002-04-17 14:26:05 +02:00
if ( Event . xbutton . button > 3 ) {
mplayer_put_key ( MOUSE_BTN0 + Event . xbutton . button - 1 ) ;
break ;
}
2002-03-13 13:11:21 +01:00
# ifdef HAVE_NEW_GUI
// Ignor mouse button 1 - 3 under gui
if ( use_gui & & ( Event . xbutton . button > = 1 ) & & ( Event . xbutton . button < = 3 ) ) break ;
# endif
2002-02-21 22:11:01 +01:00
mplayer_put_key ( ( MOUSE_BTN0 + Event . xbutton . button - 1 ) | MP_KEY_DOWN ) ;
break ;
case ButtonRelease :
2002-05-03 22:57:13 +02:00
if ( vo_mouse_autohide ) { vo_showcursor ( mydisplay , vo_window ) ; vo_mouse_counter = vo_mouse_timer_const ; }
2002-03-13 13:11:21 +01:00
# ifdef HAVE_NEW_GUI
// Ignor mouse button 1 - 3 under gui
if ( use_gui & & ( Event . xbutton . button > = 1 ) & & ( Event . xbutton . button < = 3 ) ) break ;
# endif
2002-02-21 22:11:01 +01:00
mplayer_put_key ( MOUSE_BTN0 + Event . xbutton . button - 1 ) ;
break ;
2002-04-25 23:52:47 +02:00
case PropertyNotify :
2002-04-30 00:00:50 +02:00
{
char * name = XGetAtomName ( mydisplay , Event . xproperty . atom ) ;
2002-05-11 19:21:32 +02:00
int wm = vo_wm_Unknown ;
2002-04-30 00:00:50 +02:00
if ( ! name ) break ;
2002-05-06 17:05:07 +02:00
2002-05-11 19:21:32 +02:00
wm = vo_wm_string_test ( name ) ;
if ( wm ! = vo_wm_Unknown ) vo_wm_type = wm ;
// fprintf(stderr,"[ws] PropertyNotify ( 0x%x ) %s ( 0x%x )\n",vo_window,name,Event.xproperty.atom );
2002-04-30 00:00:50 +02:00
XFree ( name ) ;
}
2002-04-25 23:52:47 +02:00
break ;
2001-05-08 14:17:03 +02:00
}
2002-02-21 22:11:01 +01:00
}
2001-03-03 22:47:37 +01:00
return ret ;
}
2002-04-25 23:52:47 +02:00
void vo_x11_sizehint ( int x , int y , int width , int height , int max )
2002-03-08 21:14:08 +01:00
{
2002-05-11 19:21:32 +02:00
vo_hint . flags = PPosition | PSize | PWinGravity ;
2002-03-08 21:14:08 +01:00
vo_hint . x = x ; vo_hint . y = y ; vo_hint . width = width ; vo_hint . height = height ;
2002-04-25 23:52:47 +02:00
if ( max )
{
vo_hint . max_width = width ; vo_hint . max_height = height ;
vo_hint . flags | = PMaxSize ;
} else { vo_hint . max_width = 0 ; vo_hint . max_height = 0 ; }
2002-03-08 21:14:08 +01:00
vo_hint . win_gravity = StaticGravity ;
XSetWMNormalHints ( mDisplay , vo_window , & vo_hint ) ;
}
2002-05-06 17:05:07 +02:00
# define WIN_LAYER_ONBOTTOM 2
# define WIN_LAYER_NORMAL 4
# define WIN_LAYER_ONTOP 6
void vo_x11_setlayer ( int layer )
{
Atom type ;
int format ;
unsigned long nitems , bytesafter ;
2002-10-16 15:31:38 +02:00
Atom * args = NULL ;
2002-05-06 17:05:07 +02:00
2002-05-09 19:28:09 +02:00
if ( WinID > = 0 ) return ;
if ( vo_wm_type = = vo_wm_IceWM )
{
2002-05-27 13:19:56 +02:00
XClientMessageEvent xev ;
memset ( & xev , 0 , sizeof ( xev ) ) ;
xev . type = ClientMessage ;
xev . window = vo_window ;
xev . message_type = XInternAtom ( mDisplay , " _WIN_LAYER " , False ) ;
xev . format = 32 ;
xev . data . l [ 0 ] = layer ? ice_layer : 4 ; // if not fullscreen, stay on layer "Normal"
xev . data . l [ 1 ] = CurrentTime ;
mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] IceWM style stay on top ( layer %d ). \n " , xev . data . l [ 0 ] ) ;
XSendEvent ( mDisplay , mRootWin , False , SubstructureNotifyMask , ( XEvent * ) & xev ) ;
2002-05-09 19:28:09 +02:00
return ;
}
2002-05-06 17:05:07 +02:00
type = XInternAtom ( mDisplay , " _NET_SUPPORTED " , False ) ;
2002-10-16 15:31:38 +02:00
if ( Success = = XGetWindowProperty ( mDisplay , mRootWin , type , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytesafter , ( unsigned char * * ) ( & args ) ) & & nitems > 0 )
2002-05-06 17:05:07 +02:00
{
XEvent e ;
2002-10-01 16:37:01 +02:00
int i ;
2002-05-06 17:05:07 +02:00
mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] NET style stay on top ( layer %d ). \n " , layer ) ;
2002-05-09 19:28:09 +02:00
memset ( & e , 0 , sizeof ( e ) ) ;
2002-05-06 17:05:07 +02:00
e . xclient . type = ClientMessage ;
e . xclient . message_type = XInternAtom ( mDisplay , " _NET_WM_STATE " , False ) ;
e . xclient . display = mDisplay ;
e . xclient . window = vo_window ;
e . xclient . format = 32 ;
e . xclient . data . l [ 0 ] = layer ;
2002-10-01 16:37:01 +02:00
2002-09-29 06:18:53 +02:00
e . xclient . data . l [ 1 ] = XInternAtom ( mDisplay , " _NET_WM_STATE_STAYS_ON_TOP " , False ) ;
2002-10-01 16:37:01 +02:00
type = XInternAtom ( mDisplay , " _NET_WM_STATE_FULLSCREEN " , False ) ;
for ( i = 0 ; i < nitems ; i + + )
if ( args [ i ] = = type ) { e . xclient . data . l [ 1 ] = XInternAtom ( mDisplay , " _NET_WM_STATE_FULLSCREEN " , False ) ; break ; }
2002-05-06 17:05:07 +02:00
XSendEvent ( mDisplay , mRootWin , False , SubstructureRedirectMask , & e ) ;
XFree ( args ) ;
return ;
}
type = XInternAtom ( mDisplay , " _WIN_SUPPORTING_WM_CHECK " , False ) ;
2002-10-16 15:31:38 +02:00
if ( Success = = XGetWindowProperty ( mDisplay , mRootWin , type , 0 , 16384 , False , AnyPropertyType , & type , & format , & nitems , & bytesafter , ( unsigned char * * ) ( & args ) ) & & nitems > 0 )
2002-05-06 17:05:07 +02:00
{
XClientMessageEvent xev ;
mp_dbg ( MSGT_VO , MSGL_STATUS , " [x11] Gnome style stay on top ( layer %d ). \n " , layer ) ;
memset ( & xev , 0 , sizeof ( xev ) ) ;
xev . type = ClientMessage ;
xev . window = vo_window ;
xev . message_type = XInternAtom ( mDisplay , " _WIN_LAYER " , False ) ;
xev . format = 32 ;
switch ( layer )
{
case - 1 : xev . data . l [ 0 ] = WIN_LAYER_ONBOTTOM ; break ;
case 0 : xev . data . l [ 0 ] = WIN_LAYER_NORMAL ; break ;
case 1 : xev . data . l [ 0 ] = WIN_LAYER_ONTOP ; break ;
}
XSendEvent ( mDisplay , mRootWin , False , SubstructureNotifyMask , ( XEvent * ) & xev ) ;
if ( layer ) XRaiseWindow ( mDisplay , vo_window ) ;
XFree ( args ) ;
return ;
}
}
2002-03-07 18:50:25 +01:00
void vo_x11_fullscreen ( void )
{
2002-09-18 03:22:03 +02:00
int x , y , w , h ;
2002-05-01 11:29:06 +02:00
2002-05-09 19:28:09 +02:00
if ( WinID > = 0 ) return ;
2002-09-18 03:22:03 +02:00
if ( vo_fs ) {
// fs->win
if ( vo_dwidth ! = vo_screenwidth & & vo_dheight ! = vo_screenheight ) return ;
vo_fs = VO_FALSE ;
x = vo_old_x ; y = vo_old_y ; w = vo_old_width ; h = vo_old_height ;
} else {
// win->fs
if ( vo_old_width & &
( vo_dwidth = = vo_screenwidth & & vo_dwidth ! = vo_old_width ) & &
( vo_dheight = = vo_screenheight & & vo_dheight ! = vo_old_height ) ) return ;
vo_fs = VO_TRUE ;
vo_old_x = vo_dx ; vo_old_y = vo_dy ; vo_old_width = vo_dwidth ; vo_old_height = vo_dheight ;
x = 0 ; y = 0 ; w = vo_screenwidth ; h = vo_screenheight ;
}
2002-05-06 17:05:07 +02:00
2002-05-05 17:33:50 +02:00
vo_x11_decoration ( mDisplay , vo_window , ( vo_fs ) ? 0 : 1 ) ;
2002-05-11 16:57:41 +02:00
vo_x11_sizehint ( x , y , w , h , 0 ) ;
2002-05-06 17:05:07 +02:00
vo_x11_setlayer ( vo_fs ) ;
2002-05-13 00:16:31 +02:00
if ( vo_wm_type = = vo_wm_Unknown & & ! ( vo_fsmode & 16 ) )
2002-09-29 00:37:20 +02:00
// XUnmapWindow( mDisplay,vo_window ); // required for MWM
XWithdrawWindow ( mDisplay , vo_window , mScreen ) ;
2002-05-06 17:05:07 +02:00
XMoveResizeWindow ( mDisplay , vo_window , x , y , w , h ) ;
2002-06-08 22:50:40 +02:00
# ifdef HAVE_XINERAMA
vo_x11_xinerama_move ( mDisplay , vo_window ) ;
# endif
2002-04-25 23:52:47 +02:00
XMapRaised ( mDisplay , vo_window ) ;
XRaiseWindow ( mDisplay , vo_window ) ;
XFlush ( mDisplay ) ;
2002-03-07 18:50:25 +01:00
}
2001-04-10 02:00:04 +02:00
void saver_on ( Display * mDisplay ) {
2001-07-19 20:47:22 +02:00
# ifdef HAVE_XDPMS
2001-04-10 02:00:04 +02:00
int nothing ;
if ( dpms_disabled )
{
2001-04-16 01:22:01 +02:00
if ( DPMSQueryExtension ( mDisplay , & nothing , & nothing ) )
{
2001-05-09 22:15:37 +02:00
if ( ! DPMSEnable ( mDisplay ) ) { // restoring power saving settings
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_WARN , " DPMS not available? \n " ) ;
2001-05-09 22:15:37 +02:00
} else {
// DPMS does not seem to be enabled unless we call DPMSInfo
BOOL onoff ;
CARD16 state ;
DPMSInfo ( mDisplay , & state , & onoff ) ;
if ( onoff ) {
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_INFO , " Successfully enabled DPMS \n " ) ;
2001-05-09 22:15:37 +02:00
} else {
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_WARN , " Could not enable DPMS \n " ) ;
2001-05-09 22:15:37 +02:00
}
}
2001-04-16 01:22:01 +02:00
}
2002-10-06 20:21:13 +02:00
dpms_disabled = 0 ;
2001-04-10 02:00:04 +02:00
}
2001-07-19 20:47:22 +02:00
# endif
2001-04-10 02:00:04 +02:00
if ( timeout_save )
{
2001-04-16 01:22:01 +02:00
int dummy , interval , prefer_blank , allow_exp ;
XGetScreenSaver ( mDisplay , & dummy , & interval , & prefer_blank , & allow_exp ) ;
XSetScreenSaver ( mDisplay , timeout_save , interval , prefer_blank , allow_exp ) ;
XGetScreenSaver ( mDisplay , & timeout_save , & interval , & prefer_blank , & allow_exp ) ;
2002-10-06 20:21:13 +02:00
timeout_save = 0 ;
2001-04-10 02:00:04 +02:00
}
2002-06-04 22:12:34 +02:00
if ( xscreensaver_was_running & & stop_xscreensaver )
system ( " xscreensaver -no-splash & " ) ;
2001-04-10 02:00:04 +02:00
}
void saver_off ( Display * mDisplay ) {
2001-07-19 20:47:22 +02:00
int interval , prefer_blank , allow_exp ;
# ifdef HAVE_XDPMS
int nothing ;
2001-04-10 02:00:04 +02:00
if ( DPMSQueryExtension ( mDisplay , & nothing , & nothing ) )
{
2001-04-16 01:22:01 +02:00
BOOL onoff ;
CARD16 state ;
DPMSInfo ( mDisplay , & state , & onoff ) ;
if ( onoff )
{
2001-05-09 22:15:37 +02:00
Status stat ;
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_INFO , " Disabling DPMS \n " ) ;
2001-04-16 01:22:01 +02:00
dpms_disabled = 1 ;
2001-05-09 22:15:37 +02:00
stat = DPMSDisable ( mDisplay ) ; // monitor powersave off
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_V , " DPMSDisable stat: %d \n " , stat ) ;
2001-04-16 01:22:01 +02:00
}
2001-04-10 02:00:04 +02:00
}
2001-07-19 20:47:22 +02:00
# endif
2001-04-10 02:00:04 +02:00
XGetScreenSaver ( mDisplay , & timeout_save , & interval , & prefer_blank , & allow_exp ) ;
if ( timeout_save )
2001-04-16 01:22:01 +02:00
XSetScreenSaver ( mDisplay , 0 , interval , prefer_blank , allow_exp ) ;
2002-06-04 22:12:34 +02:00
xscreensaver_was_running = stop_xscreensaver & & ! system ( " xscreensaver-command -exit " ) ;
2001-04-16 01:22:01 +02:00
// turning off screensaver
2001-04-10 04:29:38 +02:00
}
2001-04-15 22:31:58 +02:00
2002-08-09 19:43:49 +02:00
static XErrorHandler old_handler = NULL ;
static int selectinput_err = 0 ;
static int x11_selectinput_errorhandler ( Display * display , XErrorEvent * event )
{
if ( event - > error_code = = BadAccess ) {
selectinput_err = 1 ;
mp_msg ( MSGT_VO , MSGL_ERR , " X11 error : BadAccess during XSelectInput Call \n " ) ;
mp_msg ( MSGT_VO , MSGL_ERR , " X11 error : The 'ButtonPressMask' mask of specified window has probably already used by another appication(see man XSelectInput) \n " ) ;
/* If you think mplayer should shutdown with this error, comments out following line */
return 0 ;
}
if ( old_handler ! = NULL ) old_handler ( display , event ) ;
else x11_errorhandler ( display , event ) ;
return 0 ;
}
2002-01-05 09:49:46 +01:00
2002-08-09 19:43:49 +02:00
void vo_x11_selectinput_witherr ( Display * display , Window w , long event_mask )
{
XSync ( display , False ) ;
old_handler = XSetErrorHandler ( x11_selectinput_errorhandler ) ;
selectinput_err = 0 ;
XSelectInput ( display , w , event_mask ) ;
XSync ( display , False ) ;
XSetErrorHandler ( old_handler ) ;
if ( selectinput_err ) {
mp_msg ( MSGT_VO , MSGL_ERR , " X11 error : Mplayer discards mouse control and retry XSelectInput... \n " ) ;
XSelectInput ( display , w , event_mask & ( ~ ( ButtonPressMask | ButtonReleaseMask | PointerMotionMask ) ) ) ;
}
}
2002-01-05 09:49:46 +01:00
# ifdef HAVE_XINERAMA
void vo_x11_xinerama_move ( Display * dsp , Window w )
{
if ( XineramaIsActive ( dsp ) )
{
2002-01-06 22:07:20 +01:00
/* printf("XXXX Xinerama screen: x: %hd y: %hd\n",xinerama_x,xinerama_y); */
XMoveWindow ( dsp , w , xinerama_x , xinerama_y ) ;
2002-01-05 09:49:46 +01:00
}
}
# endif
2002-01-31 01:37:27 +01:00
# ifdef HAVE_XF86VM
void vo_vm_switch ( uint32_t X , uint32_t Y , int * modeline_width , int * modeline_height )
{
unsigned int vm_event , vm_error ;
unsigned int vm_ver , vm_rev ;
int i , j , have_vm = 0 ;
int modecount ;
if ( XF86VidModeQueryExtension ( mDisplay , & vm_event , & vm_error ) ) {
XF86VidModeQueryVersion ( mDisplay , & vm_ver , & vm_rev ) ;
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_V , " XF86VidMode Extension v%i.%i \n " , vm_ver , vm_rev ) ;
2002-01-31 01:37:27 +01:00
have_vm = 1 ;
} else
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_WARN , " XF86VidMode Extenstion not available. \n " ) ;
2002-01-31 01:37:27 +01:00
if ( have_vm ) {
if ( vidmodes = = NULL )
XF86VidModeGetAllModeLines ( mDisplay , mScreen , & modecount , & vidmodes ) ;
j = 0 ;
* modeline_width = vidmodes [ 0 ] - > hdisplay ;
* modeline_height = vidmodes [ 0 ] - > vdisplay ;
for ( i = 1 ; i < modecount ; i + + )
if ( ( vidmodes [ i ] - > hdisplay > = X ) & & ( vidmodes [ i ] - > vdisplay > = Y ) )
2002-04-09 15:18:45 +02:00
if ( ( vidmodes [ i ] - > hdisplay < = * modeline_width ) & & ( vidmodes [ i ] - > vdisplay < = * modeline_height ) )
2002-01-31 01:37:27 +01:00
{
* modeline_width = vidmodes [ i ] - > hdisplay ;
* modeline_height = vidmodes [ i ] - > vdisplay ;
j = i ;
}
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_INFO , " XF86VM: Selected video mode %dx%d for image size %dx%d. \n " , * modeline_width , * modeline_height , X , Y ) ;
2002-01-31 01:37:27 +01:00
XF86VidModeLockModeSwitch ( mDisplay , mScreen , 0 ) ;
XF86VidModeSwitchToMode ( mDisplay , mScreen , vidmodes [ j ] ) ;
XF86VidModeSwitchToMode ( mDisplay , mScreen , vidmodes [ j ] ) ;
X = ( vo_screenwidth - * modeline_width ) / 2 ;
Y = ( vo_screenheight - * modeline_height ) / 2 ;
XF86VidModeSetViewPort ( mDisplay , mScreen , X , Y ) ;
}
}
void vo_vm_close ( Display * dpy )
{
# ifdef HAVE_NEW_GUI
2002-03-10 09:16:07 +01:00
if ( vidmodes ! = NULL & & vo_window ! = None )
2002-01-31 01:37:27 +01:00
# else
if ( vidmodes ! = NULL )
# endif
2002-03-10 09:16:07 +01:00
{
int i , modecount ;
int screen ; screen = DefaultScreen ( dpy ) ;
free ( vidmodes ) ; vidmodes = NULL ;
XF86VidModeGetAllModeLines ( mDisplay , mScreen , & modecount , & vidmodes ) ;
for ( i = 0 ; i < modecount ; i + + )
if ( ( vidmodes [ i ] - > hdisplay = = vo_screenwidth ) & & ( vidmodes [ i ] - > vdisplay = = vo_screenheight ) )
{
2002-06-04 01:23:03 +02:00
mp_msg ( MSGT_VO , MSGL_INFO , " \n Returning to original mode %dx%d \n " , vo_screenwidth , vo_screenheight ) ;
2002-03-10 09:16:07 +01:00
break ;
}
XF86VidModeSwitchToMode ( dpy , screen , vidmodes [ i ] ) ;
XF86VidModeSwitchToMode ( dpy , screen , vidmodes [ i ] ) ;
free ( vidmodes ) ;
}
2002-01-31 01:37:27 +01:00
}
# endif
2002-09-03 20:10:42 +02:00
# endif /* X11_FULLSCREEN */
/*
* Scan the available visuals on this Display / Screen . Try to find
* the ' best ' available TrueColor visual that has a decent color
* depth ( at least 15 bit ) . If there are multiple visuals with depth
* > = 15 bit , we prefer visuals with a smaller color depth .
*/
int vo_find_depth_from_visuals ( Display * dpy , int screen , Visual * * visual_return )
{
XVisualInfo visual_tmpl ;
XVisualInfo * visuals ;
int nvisuals , i ;
int bestvisual = - 1 ;
int bestvisual_depth = - 1 ;
visual_tmpl . screen = screen ;
visual_tmpl . class = TrueColor ;
visuals = XGetVisualInfo ( dpy ,
VisualScreenMask | VisualClassMask , & visual_tmpl ,
& nvisuals ) ;
if ( visuals ! = NULL ) {
for ( i = 0 ; i < nvisuals ; i + + ) {
mp_msg ( MSGT_VO , MSGL_V , " vo: X11 truecolor visual %#x, depth %d, R:%lX G:%lX B:%lX \n " ,
visuals [ i ] . visualid , visuals [ i ] . depth ,
visuals [ i ] . red_mask , visuals [ i ] . green_mask ,
visuals [ i ] . blue_mask ) ;
/*
* save the visual index and it ' s depth , if this is the first
* truecolor visul , or a visual that is ' preferred ' over the
* previous ' best ' visual
*/
if ( bestvisual_depth = = - 1
| | ( visuals [ i ] . depth > = 15
& & ( visuals [ i ] . depth < bestvisual_depth
| | bestvisual_depth < 15 ) ) ) {
bestvisual = i ;
bestvisual_depth = visuals [ i ] . depth ;
}
}
if ( bestvisual ! = - 1 & & visual_return ! = NULL )
* visual_return = visuals [ bestvisual ] . visual ;
XFree ( visuals ) ;
}
return bestvisual_depth ;
}
2002-10-29 21:27:47 +01:00
static Colormap cmap = None ;
static XColor cols [ 256 ] ;
static int cm_size , red_mask , green_mask , blue_mask ;
Colormap vo_x11_create_colormap ( XVisualInfo * vinfo )
{
unsigned k , r , g , b , ru , gu , bu , m , rv , gv , bv , rvu , gvu , bvu ;
if ( vinfo - > class ! = DirectColor )
return XCreateColormap ( mDisplay , mRootWin , vinfo - > visual , AllocNone ) ;
/* can this function get called twice or more? */
if ( cmap ) return cmap ;
cm_size = vinfo - > colormap_size ;
red_mask = vinfo - > red_mask ;
green_mask = vinfo - > green_mask ;
blue_mask = vinfo - > blue_mask ;
ru = ( red_mask & ( red_mask - 1 ) ) ^ red_mask ;
gu = ( green_mask & ( green_mask - 1 ) ) ^ green_mask ;
bu = ( blue_mask & ( blue_mask - 1 ) ) ^ blue_mask ;
rvu = 65536ull * ru / ( red_mask + ru ) ;
gvu = 65536ull * gu / ( green_mask + gu ) ;
bvu = 65536ull * bu / ( blue_mask + bu ) ;
r = g = b = 0 ;
rv = gv = bv = 0 ;
m = DoRed | DoGreen | DoBlue ;
for ( k = 0 ; k < cm_size ; k + + ) {
int t ;
cols [ k ] . pixel = r | g | b ;
cols [ k ] . red = rv ;
cols [ k ] . green = gv ;
cols [ k ] . blue = bv ;
cols [ k ] . flags = m ;
t = ( r + ru ) & red_mask ; if ( t < r ) m & = ~ DoRed ; r = t ;
t = ( g + gu ) & green_mask ; if ( t < g ) m & = ~ DoGreen ; g = t ;
t = ( b + bu ) & blue_mask ; if ( t < b ) m & = ~ DoBlue ; b = t ;
rv + = rvu ;
gv + = gvu ;
bv + = bvu ;
}
cmap = XCreateColormap ( mDisplay , mRootWin , vinfo - > visual , AllocAll ) ;
XStoreColors ( mDisplay , cmap , cols , cm_size ) ;
return cmap ;
}
/*
* Via colormaps / gamma ramps we can do gamma , brightness , contrast ,
* hue and red / green / blue intensity , but we cannot do saturation .
* Currently only gamma , brightness and contrast are implemented .
* Is there sufficient interest for hue and / or red / green / blue intensity ?
*/
/* these values have range [-100,100] and are initially 0 */
static int vo_gamma = 0 ;
static int vo_brightness = 0 ;
static int vo_contrast = 0 ;
uint32_t vo_x11_set_equalizer ( char * name , int value )
{
float gamma , brightness , contrast ;
float rf , gf , bf ;
int k ;
/*
* IMPLEMENTME : consider using XF86VidModeSetGammaRamp in the case
* of TrueColor - ed window but be careful :
* unlike the colormaps , which are private for the X client
* who created them and thus automatically destroyed on client
* disconnect , this gamma ramp is a system - wide ( X - server - wide )
* setting and _must_ be restored before the process exit .
* Unforunately when the process crashes ( or get killed
* for some reason ) it is impossible to restore the setting ,
* and such behaviour could be rather annoying for the users .
*/
if ( cmap = = None ) return VO_NOTAVAIL ;
if ( ! strcasecmp ( name , " brightness " ) ) vo_brightness = value ;
else if ( ! strcasecmp ( name , " contrast " ) ) vo_contrast = value ;
else if ( ! strcasecmp ( name , " gamma " ) ) vo_gamma = value ;
else return VO_NOTIMPL ;
brightness = 0.01 * vo_brightness ;
contrast = tan ( 0.0095 * ( vo_contrast + 100 ) * M_PI / 4 ) ;
gamma = pow ( 2 , - 0.02 * vo_gamma ) ;
rf = ( float ) ( ( red_mask & ( red_mask - 1 ) ) ^ red_mask ) / red_mask ;
gf = ( float ) ( ( green_mask & ( green_mask - 1 ) ) ^ green_mask ) / green_mask ;
bf = ( float ) ( ( blue_mask & ( blue_mask - 1 ) ) ^ blue_mask ) / blue_mask ;
/* now recalculate the colormap using the newly set value */
for ( k = 0 ; k < cm_size ; k + + ) {
float s ;
s = pow ( rf * k , gamma ) ;
s = ( s - 0.5 ) * contrast + 0.5 ;
s + = brightness ;
if ( s < 0 ) s = 0 ;
if ( s > 1 ) s = 1 ;
cols [ k ] . red = ( unsigned short ) ( s * 65535 ) ;
s = pow ( gf * k , gamma ) ;
s = ( s - 0.5 ) * contrast + 0.5 ;
s + = brightness ;
if ( s < 0 ) s = 0 ;
if ( s > 1 ) s = 1 ;
cols [ k ] . green = ( unsigned short ) ( s * 65535 ) ;
s = pow ( bf * k , gamma ) ;
s = ( s - 0.5 ) * contrast + 0.5 ;
s + = brightness ;
if ( s < 0 ) s = 0 ;
if ( s > 1 ) s = 1 ;
cols [ k ] . blue = ( unsigned short ) ( s * 65535 ) ;
}
XStoreColors ( mDisplay , cmap , cols , cm_size ) ;
XFlush ( mDisplay ) ;
return VO_TRUE ;
}
uint32_t vo_x11_get_equalizer ( char * name , int * value )
{
if ( cmap = = None ) return VO_NOTAVAIL ;
if ( ! strcasecmp ( name , " brightness " ) ) * value = vo_brightness ;
else if ( ! strcasecmp ( name , " contrast " ) ) * value = vo_contrast ;
else if ( ! strcasecmp ( name , " gamma " ) ) * value = vo_gamma ;
else return VO_NOTIMPL ;
}