#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <inttypes.h>
#include "config.h"
#include "mp_msg.h"
#include "x11_common.h"
#ifdef X11_FULLSCREEN
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>
#include "video_out.h"
#include "help_mp.h"
#include <X11/Xmd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#ifdef HAVE_XDPMS
#include <X11/extensions/dpms.h>
#endif
#ifdef HAVE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#ifdef HAVE_XF86VM
#include <X11/extensions/xf86vmode.h>
#include <X11/XF86keysym.h>
#endif
#ifdef HAVE_XV
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
#endif
#include "../input/input.h"
#include "../input/mouse.h"
#ifdef HAVE_NEW_GUI
#include "../Gui/interface.h"
#include "../mplayer.h"
#endif
#define WIN_LAYER_ONBOTTOM 2
#define WIN_LAYER_NORMAL 4
#define WIN_LAYER_ONTOP 6
#define WIN_LAYER_ABOVE_DOCK 10
int fs_layer=WIN_LAYER_ABOVE_DOCK;
int orig_layer=0;
int stop_xscreensaver=0;
static int dpms_disabled=0;
static int timeout_save=0;
static int kdescreensaver_was_running=0;
char* mDisplayName=NULL;
Display* mDisplay=NULL;
Window mRootWin;
int mScreen;
int mLocalDisplay;
/* output window id */
int WinID=-1;
int vo_mouse_autohide = 0;
int vo_wm_type = 0;
int vo_fs_type = 0;
char** vo_fstype_list;
/* if equal to 1 means that WM is a metacity (broken as hell) */
int metacity_hack = 0;
Atom XA_NET_SUPPORTED;
Atom XA_NET_WM_STATE;
Atom XA_NET_WM_STATE_FULLSCREEN;
Atom XA_NET_WM_STATE_ABOVE;
Atom XA_NET_WM_STATE_STAYS_ON_TOP;
Atom XA_NET_WM_STATE_BELOW;
Atom XA_NET_WM_PID;
Atom XA_WIN_PROTOCOLS;
Atom XA_WIN_LAYER;
Atom XA_WIN_HINTS;
Atom XA_BLACKBOX_PID;
#define XA_INIT(x) XA##x = XInternAtom(mDisplay, #x, False)
static int vo_old_x = 0;
static int vo_old_y = 0;
static int vo_old_width = 0;
static int vo_old_height = 0;
int vo_x11_keepaspect = 1;
#ifdef HAVE_XINERAMA
int xinerama_screen = 0;
int xinerama_x = 0;
int xinerama_y = 0;
#endif
#ifdef HAVE_XF86VM
XF86VidModeModeInfo **vidmodes=NULL;
XF86VidModeModeLine modeline;
#endif
int vo_x11_get_fs_type( int supported );
void vo_hidecursor ( Display *disp , Window win )
{
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 };
if(WinID==0) return; // do not hide, if we're playing at rootwin
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);
XFreeCursor( disp,no_ptr );
if (bm_no != None)
XFreePixmap(disp, bm_no);
}
void vo_showcursor( Display *disp, Window win )
{
if ( WinID==0 ) return;
XDefineCursor( disp,win,0 );
}
static int x11_errorhandler(Display *display, XErrorEvent *event)
{
#define MSGLEN 60
char msg[MSGLEN];
XGetErrorText(display, event->error_code, (char *)&msg, MSGLEN);
mp_msg(MSGT_VO,MSGL_ERR,"X11 error: %s\n", msg);
mp_msg(MSGT_VO,MSGL_V,"Type: %x, display: %x, resourceid: %x, serial: %x\n",
event->type, event->display, event->resourceid, event->serial);
mp_msg(MSGT_VO,MSGL_V,"Error code: %x, request code: %x, minor code: %x\n",
event->error_code, event->request_code, event->minor_code);
abort();
//exit_player("X11 error");
#undef MSGLEN
}
void fstype_help(void)
{
mp_msg(MSGT_VO, MSGL_INFO, MSGTR_AvailableFsType);
mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "none", "don't set fullscreen window layer");
mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "layer", "use _WIN_LAYER hint with default layer");
mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "layer=<0..15>", "use _WIN_LAYER hint with a given layer number");
mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "above", "use _NETWM_STATE_ABOVE hint if available");
mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "below", "use _NETWM_STATE_BELOW hint if vailable");
mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "fullscreen", "use _NETWM_STATE_FULLSCREEN hint if availale");
mp_msg(MSGT_VO, MSGL_INFO, " %-15s %s\n", "stays_on_top", "use _NETWM_STATE_STAYS_ON_TOP hint if available");
}
int net_wm_support_state_test( Atom atom )
{
#define NET_WM_STATE_TEST(x) { if (atom == XA_NET_WM_STATE_##x) { mp_msg( MSGT_VO,MSGL_V, "[x11] Detected wm supports " #x " state.\n" ); return vo_wm_##x; } }
NET_WM_STATE_TEST(FULLSCREEN);
NET_WM_STATE_TEST(ABOVE);
NET_WM_STATE_TEST(STAYS_ON_TOP);
NET_WM_STATE_TEST(BELOW);
return 0;
}
int x11_get_property(Atom type, Atom **args, unsigned long *nitems)
{
int format;
unsigned long bytesafter;
return (Success == XGetWindowProperty( mDisplay,mRootWin,type,0,16384,
False,AnyPropertyType,&type,&format,nitems,&bytesafter,
(unsigned char **) args ) && *nitems > 0 );
}
int vo_wm_detect( void )
{
int i;
int wm = 0;
unsigned long nitems;
Atom * args = NULL;
if ( WinID >= 0 ) return 0;
// -- supports layers
if (x11_get_property(XA_WIN_PROTOCOLS, &args, &nitems))
{
mp_msg( MSGT_VO,MSGL_V,"[x11] Detected wm supports layers.\n" );
for (i = 0; i < nitems; i++)
{
if ( args[i] == XA_WIN_LAYER) {
wm |= vo_wm_LAYER;
metacity_hack |= 1;
} else
// metacity is the only manager I know which reports support only for _WIN_LAYER
// hint in _WIN_PROTOCOLS (what's more support for it is broken)
metacity_hack |= 2;
}
XFree( args );
if (wm && (metacity_hack == 1))
{
// metacity reports that it supports layers, but it is not really truth :-)
wm ^= vo_wm_LAYER;
mp_msg( MSGT_VO,MSGL_V,"[x11] Using workaround for Metacity bugs.\n" );
}
}
// --- netwm
if (x11_get_property(XA_NET_SUPPORTED, &args, &nitems))
{
mp_msg( MSGT_VO,MSGL_V,"[x11] Detected wm supports NetWM.\n" );
for (i = 0; i < nitems; i++)
wm |= net_wm_support_state_test (args[i]);
XFree( args );
// ugly hack for broken OpenBox _NET_WM_STATE_FULLSCREEN support
// (in their implementation it only changes internal state of window, nothing more!!!)
if (wm & vo_wm_FULLSCREEN)
{
if (x11_get_property(XA_BLACKBOX_PID, &args, &nitems))
{
mp_msg( MSGT_VO,MSGL_V,"[x11] Detected wm is a broken OpenBox.\n" );
wm ^= vo_wm_FULLSCREEN;
}
XFree (args);
}
}
if ( wm == 0 ) mp_msg( MSGT_VO,MSGL_V,"[x11] Unknown wm type...\n" );
return wm;
}
void vo_init_atoms( void )
{
XA_INIT
|