summaryrefslogtreecommitdiffstats
path: root/gui/wm/ws.c
diff options
context:
space:
mode:
Diffstat (limited to 'gui/wm/ws.c')
-rw-r--r--gui/wm/ws.c1272
1 files changed, 1272 insertions, 0 deletions
diff --git a/gui/wm/ws.c b/gui/wm/ws.c
new file mode 100644
index 0000000000..5e2e010bf3
--- /dev/null
+++ b/gui/wm/ws.c
@@ -0,0 +1,1272 @@
+
+// --------------------------------------------------------------------------
+// AutoSpace Window System for Linux/Win32 v0.85
+// Writed by pontscho/fresh!mindworkz
+// --------------------------------------------------------------------------
+
+#include <X11/Xlib.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <inttypes.h>
+
+#include "../config.h"
+#include "../libvo/x11_common.h"
+#include "../libvo/video_out.h"
+#include "ws.h"
+#include "wsxdnd.h"
+#include "../cpudetect.h"
+#include "../libswscale/swscale.h"
+#include "../libswscale/rgb2rgb.h"
+#include "../libmpcodecs/vf_scale.h"
+#include "../mp_msg.h"
+#include "../help_mp.h"
+#include "../mplayer.h"
+
+#include <X11/extensions/XShm.h>
+#ifdef HAVE_XSHAPE
+#include <X11/extensions/shape.h>
+#endif
+
+#ifdef HAVE_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+
+#ifdef HAVE_XF86VM
+#include <X11/extensions/xf86vmode.h>
+#endif
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#undef ENABLE_DPMS
+
+#ifdef HAVE_XINERAMA
+extern int xinerama_screen;
+#endif
+
+typedef struct
+{
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long input_mode;
+ unsigned long status;
+} MotifWmHints;
+
+Atom wsMotifHints;
+
+int wsMaxX = 0; // Screen width.
+int wsMaxY = 0; // Screen height.
+int wsOrgX = 0; // Screen origin x.
+int wsOrgY = 0; // Screen origin y.
+
+Display * wsDisplay;
+int wsScreen;
+Window wsRootWin;
+XEvent wsEvent;
+int wsWindowDepth;
+GC wsHGC;
+MotifWmHints wsMotifWmHints;
+Atom wsTextProperlyAtom = None;
+int wsLayer = 0;
+
+int wsDepthOnScreen = 0;
+int wsRedMask = 0;
+int wsGreenMask = 0;
+int wsBlueMask = 0;
+int wsOutMask = 0;
+
+int wsTrue = True;
+
+#define wsWLCount 5
+wsTWindow * wsWindowList[wsWLCount] = { NULL,NULL,NULL,NULL,NULL };
+
+unsigned long wsKeyTable[512];
+
+int wsUseXShm = 1;
+int wsUseXShape = 1;
+
+int XShmGetEventBase( Display* );
+inline int wsSearch( Window win );
+
+// ---
+
+#define PACK_RGB16(r,g,b,pixel) pixel=(b>>3);\
+ pixel<<=6;\
+ pixel|=(g>>2);\
+ pixel<<=5;\
+ pixel|=(r>>3)
+
+#define PACK_RGB15(r,g,b,pixel) pixel=(b>>3);\
+ pixel<<=5;\
+ pixel|=(g>>3);\
+ pixel<<=5;\
+ pixel|=(r>>3)
+
+typedef void(*wsTConvFunc)( const unsigned char * in_pixels, unsigned char * out_pixels, unsigned num_pixels );
+wsTConvFunc wsConvFunc = NULL;
+
+void rgb32torgb32( const unsigned char * src, unsigned char * dst,unsigned int src_size )
+{ memcpy( dst,src,src_size ); }
+
+// ---
+
+#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)
+
+void wsWindowDecoration( wsTWindow * win,long d )
+{
+ wsMotifHints=XInternAtom( wsDisplay,"_MOTIF_WM_HINTS",0 );
+ if ( wsMotifHints == None ) return;
+
+ memset( &wsMotifWmHints,0,sizeof( MotifWmHints ) );
+ wsMotifWmHints.flags=MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
+ if ( d )
+ {
+ wsMotifWmHints.functions=MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE;
+ wsMotifWmHints.decorations=MWM_DECOR_ALL;
+ }
+ XChangeProperty( wsDisplay,win->WindowID,wsMotifHints,wsMotifHints,32,
+ PropModeReplace,(unsigned char *)&wsMotifWmHints,5 );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Init X Window System.
+// ----------------------------------------------------------------------------------------------
+
+int wsIOErrorHandler( Display * dpy )
+{
+ fprintf( stderr,"[ws] IO error in display.\n" );
+ exit( 0 );
+}
+
+int wsErrorHandler( Display * dpy,XErrorEvent * Event )
+{
+ char type[128];
+ XGetErrorText( wsDisplay,Event->error_code,type,128 );
+ fprintf(stderr,"[ws] Error in display.\n");
+ fprintf(stderr,"[ws] Error code: %d ( %s )\n",Event->error_code,type );
+ fprintf(stderr,"[ws] Request code: %d\n",Event->request_code );
+ fprintf(stderr,"[ws] Minor code: %d\n",Event->minor_code );
+ fprintf(stderr,"[ws] Modules: %s\n",current_module?current_module:"(NULL)" );
+ exit( 0 );
+}
+
+void wsXInit( void* mDisplay )
+{
+ int eventbase;
+ int errorbase;
+
+if(mDisplay){
+ wsDisplay=mDisplay;
+} else {
+ char * DisplayName = ":0.0";
+ if ( getenv( "DISPLAY" ) ) DisplayName=getenv( "DISPLAY" );
+ wsDisplay=XOpenDisplay( DisplayName );
+ if ( !wsDisplay )
+ {
+ mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_CouldNotOpenDisplay );
+ exit( 0 );
+ }
+}
+
+/* enable DND atoms */
+wsXDNDInitialize();
+
+{ /* on remote display XShm will be disabled - LGB */
+ char *dispname=DisplayString(wsDisplay);
+ int localdisp=1;
+ if (dispname&&*dispname!=':') {
+ localdisp=0;
+ wsUseXShm=0;
+ }
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[ws] display name: %s => %s display.\n",dispname,localdisp?"local":"REMOTE");
+ if (!localdisp) mp_msg( MSGT_GPLAYER,MSGL_V,MSGTR_WS_RemoteDisplay );
+}
+
+ if ( !XShmQueryExtension( wsDisplay ) )
+ {
+ mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_WS_NoXshm );
+ wsUseXShm=0;
+ }
+#ifdef HAVE_XSHAPE
+ if ( !XShapeQueryExtension( wsDisplay,&eventbase,&errorbase ) )
+ {
+ mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_WS_NoXshape );
+ wsUseXShape=0;
+ }
+#else
+ wsUseXShape=0;
+#endif
+
+ XSynchronize( wsDisplay,True );
+
+ wsScreen=DefaultScreen( wsDisplay );
+ wsRootWin=RootWindow( wsDisplay,wsScreen );
+#ifdef HAVE_XF86VM
+ {
+ int clock;
+ XF86VidModeModeLine modeline;
+
+ XF86VidModeGetModeLine( wsDisplay,wsScreen,&clock ,&modeline );
+ wsMaxX=modeline.hdisplay;
+ wsMaxY=modeline.vdisplay;
+ }
+#endif
+ {
+ wsOrgX = wsOrgY = 0;
+ if ( !wsMaxX )
+ wsMaxX=DisplayWidth( wsDisplay,wsScreen );
+ if ( !wsMaxY )
+ wsMaxY=DisplayHeight( wsDisplay,wsScreen );
+ }
+ vo_screenwidth = wsMaxX; vo_screenheight = wsMaxY;
+ xinerama_x = wsOrgX; xinerama_y = wsOrgY;
+ update_xinerama_info();
+ wsMaxX = vo_screenwidth; wsMaxY = vo_screenheight;
+ wsOrgX = xinerama_x; wsOrgY = xinerama_y;
+
+ wsGetDepthOnScreen();
+#ifdef DEBUG
+ {
+ int minor,major,shp;
+ mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] Screen depth: %d\n",wsDepthOnScreen );
+ mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] size: %dx%d\n",wsMaxX,wsMaxY );
+#ifdef HAVE_XINERAMA
+ mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] origin: +%d+%d\n",wsOrgX,wsOrgY );
+#endif
+ mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] red mask: 0x%x\n",wsRedMask );
+ mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] green mask: 0x%x\n",wsGreenMask );
+ mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] blue mask: 0x%x\n",wsBlueMask );
+ if ( wsUseXShm )
+ {
+ XShmQueryVersion( wsDisplay,&major,&minor,&shp );
+ mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] XShm version is %d.%d\n",major,minor );
+ }
+ #ifdef HAVE_XSHAPE
+ if ( wsUseXShape )
+ {
+ XShapeQueryVersion( wsDisplay,&major,&minor );
+ mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] XShape version is %d.%d\n",major,minor );
+ }
+ #endif
+ }
+#endif
+ wsOutMask=wsGetOutMask();
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[ws] Initialized converter: " );
+ sws_rgb2rgb_init(get_sws_cpuflags());
+ switch ( wsOutMask )
+ {
+ case wsRGB32:
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb32\n" );
+ wsConvFunc=rgb32torgb32;
+ break;
+ case wsBGR32:
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr32\n" );
+ wsConvFunc=rgb32tobgr32;
+ break;
+ case wsRGB24:
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb24\n" );
+ wsConvFunc=rgb32to24;
+ break;
+ case wsBGR24:
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr24\n" );
+ wsConvFunc=rgb32tobgr24;
+ break;
+ case wsRGB16:
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb16\n" );
+ wsConvFunc=rgb32to16;
+ break;
+ case wsBGR16:
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr16\n" );
+ wsConvFunc=rgb32tobgr16;
+ break;
+ case wsRGB15:
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb15\n" );
+ wsConvFunc=rgb32to15;
+ break;
+ case wsBGR15:
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr15\n" );
+ wsConvFunc=rgb32tobgr15;
+ break;
+ }
+ XSetErrorHandler( wsErrorHandler );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Create window.
+// X,Y : window position
+// wX,wY : size of window
+// bW : border width
+// cV : visible mouse cursor on window
+// D : visible frame, title, etc.
+// sR : screen ratio
+// ----------------------------------------------------------------------------------------------
+
+XClassHint wsClassHint;
+XTextProperty wsTextProperty;
+Window LeaderWindow;
+
+void wsCreateWindow( wsTWindow * win,int X,int Y,int wX,int hY,int bW,int cV,unsigned char D,char * label )
+{
+ int depth;
+
+ win->Property=D;
+ if ( D & wsShowFrame ) win->Decorations=1;
+ wsHGC=DefaultGC( wsDisplay,wsScreen );
+// The window position and size.
+ switch ( X )
+ {
+ case -1: win->X=( wsMaxX / 2 ) - ( wX / 2 ) + wsOrgX; break;
+ case -2: win->X=wsMaxX - wX - 1 + wsOrgX; break;
+ default: win->X=X; break;
+ }
+ switch ( Y )
+ {
+ case -1: win->Y=( wsMaxY / 2 ) - ( hY / 2 ) + wsOrgY; break;
+ case -2: win->Y=wsMaxY - hY - 1 + wsOrgY; break;
+ default: win->Y=Y; break;
+ }
+ win->Width=wX;
+ win->Height=hY;
+ win->OldX=win->X;
+ win->OldY=win->Y;
+ win->OldWidth=win->Width;
+ win->OldHeight=win->Height;
+
+// Border size for window.
+ win->BorderWidth=bW;
+// Hide Mouse Cursor
+ win->wsCursor=None;
+ win->wsMouseEventType=cV;
+ win->wsCursorData[0]=0;
+ win->wsCursorPixmap=XCreateBitmapFromData( wsDisplay,wsRootWin,win->wsCursorData,1,1 );
+ if ( !(cV & wsShowMouseCursor) ) win->wsCursor=XCreatePixmapCursor( wsDisplay,win->wsCursorPixmap,win->wsCursorPixmap,&win->wsColor,&win->wsColor,0,0 );
+
+ depth = vo_find_depth_from_visuals( wsDisplay,wsScreen,NULL );
+ if ( depth < 15 )
+ {
+ mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_ColorDepthTooLow );
+ exit( 0 );
+ }
+ XMatchVisualInfo( wsDisplay,wsScreen,depth,TrueColor,&win->VisualInfo );
+
+// ---
+ win->AtomLeaderClient=XInternAtom( wsDisplay,"WM_CLIENT_LEADER",False );
+ win->AtomDeleteWindow=XInternAtom( wsDisplay,"WM_DELETE_WINDOW",False );
+ win->AtomTakeFocus=XInternAtom( wsDisplay,"WM_TAKE_FOCUS",False );
+ win->AtomRolle=XInternAtom( wsDisplay,"WM_WINDOW_ROLE",False );
+ win->AtomWMSizeHint=XInternAtom( wsDisplay,"WM_SIZE_HINT",False );
+ win->AtomWMNormalHint=XInternAtom( wsDisplay,"WM_NORMAL_HINT",False );
+ win->AtomProtocols=XInternAtom( wsDisplay,"WM_PROTOCOLS",False );
+ win->AtomsProtocols[0]=win->AtomDeleteWindow;
+ win->AtomsProtocols[1]=win->AtomTakeFocus;
+ win->AtomsProtocols[2]=win->AtomRolle;
+// ---
+
+ win->WindowAttrib.background_pixel=BlackPixel( wsDisplay,wsScreen );
+ win->WindowAttrib.border_pixel=WhitePixel( wsDisplay,wsScreen );
+ win->WindowAttrib.colormap=XCreateColormap( wsDisplay,wsRootWin,win->VisualInfo.visual,AllocNone );
+ win->WindowAttrib.event_mask=StructureNotifyMask | FocusChangeMask |
+ ExposureMask | PropertyChangeMask |
+ EnterWindowMask | LeaveWindowMask |
+ VisibilityChangeMask |
+ KeyPressMask | KeyReleaseMask;
+ if ( ( cV & wsHandleMouseButton ) ) win->WindowAttrib.event_mask|=ButtonPressMask | ButtonReleaseMask;
+ if ( ( cV & wsHandleMouseMove ) ) win->WindowAttrib.event_mask|=PointerMotionMask;
+ win->WindowAttrib.cursor=win->wsCursor;
+ win->WindowAttrib.override_redirect=False;
+ if ( D & wsOverredirect ) win->WindowAttrib.override_redirect=True;
+
+ win->WindowMask=CWBackPixel | CWBorderPixel |
+ CWColormap | CWEventMask | CWCursor |
+ CWOverrideRedirect;
+
+ win->WindowID=XCreateWindow( wsDisplay,
+ (win->Parent != 0?win->Parent:wsRootWin),
+ win->X,win->Y,win->Width,win->Height,win->BorderWidth,
+ win->VisualInfo.depth,
+ InputOutput,
+ win->VisualInfo.visual,
+ win->WindowMask,&win->WindowAttrib );
+
+ wsClassHint.res_name="MPlayer";
+
+ wsClassHint.res_class="MPlayer";
+ XSetClassHint( wsDisplay,win->WindowID,&wsClassHint );
+
+ win->SizeHint.flags=PPosition | PSize | PResizeInc | PWinGravity;// | PBaseSize;
+ win->SizeHint.x=win->X;
+ win->SizeHint.y=win->Y;
+ win->SizeHint.width=win->Width;
+ win->SizeHint.height=win->Height;
+
+ if ( D & wsMinSize )
+ {
+ win->SizeHint.flags|=PMinSize;
+ win->SizeHint.min_width=win->Width;
+ win->SizeHint.min_height=win->Height;
+ }
+ if ( D & wsMaxSize )
+ {
+ win->SizeHint.flags|=PMaxSize;
+ win->SizeHint.max_width=win->Width;
+ win->SizeHint.max_height=win->Height;
+ }
+
+ win->SizeHint.height_inc=1;
+ win->SizeHint.width_inc=1;
+ win->SizeHint.base_width=win->Width;
+ win->SizeHint.base_height=win->Height;
+ win->SizeHint.win_gravity=StaticGravity;
+ XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint );
+
+ win->WMHints.flags=InputHint | StateHint;
+ win->WMHints.input=True;
+ win->WMHints.initial_state=NormalState;
+ XSetWMHints( wsDisplay,win->WindowID,&win->WMHints );
+
+ wsWindowDecoration( win,win->Decorations );
+ XStoreName( wsDisplay,win->WindowID,label );
+ XmbSetWMProperties( wsDisplay,win->WindowID,label,label,NULL,0,NULL,NULL,NULL );
+
+ XSetWMProtocols( wsDisplay,win->WindowID,win->AtomsProtocols,3 );
+ XChangeProperty( wsDisplay,win->WindowID,
+ win->AtomLeaderClient,
+ XA_WINDOW,32,PropModeReplace,
+ (unsigned char *)&LeaderWindow,1 );
+
+ wsTextProperty.value=label;
+ wsTextProperty.encoding=XA_STRING;
+ wsTextProperty.format=8;
+ wsTextProperty.nitems=strlen( label );
+ XSetWMIconName( wsDisplay,win->WindowID,&wsTextProperty );
+
+ win->wGC=XCreateGC( wsDisplay,win->WindowID,
+ GCForeground | GCBackground,
+ &win->wGCV );
+
+ win->Visible=0;
+ win->Focused=0;
+ win->Mapped=0;
+ win->Rolled=0;
+ if ( D & wsShowWindow ) XMapWindow( wsDisplay,win->WindowID );
+
+ wsCreateImage( win,win->Width,win->Height );
+// --- End of creating --------------------------------------------------------------------------
+
+ {
+ int i;
+ for ( i=0;i < wsWLCount;i++ )
+ if ( wsWindowList[i] == NULL ) break;
+ if ( i == wsWLCount )
+ { mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_TooManyOpenWindows ); exit( 0 ); }
+ wsWindowList[i]=win;
+ }
+
+ XFlush( wsDisplay );
+ XSync( wsDisplay,False );
+
+ win->ReDraw=NULL;
+ win->ReSize=NULL;
+ win->Idle=NULL;
+ win->MouseHandler=NULL;
+ win->KeyHandler=NULL;
+ mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[ws] window is created. ( %s ).\n",label );
+}
+
+void wsDestroyWindow( wsTWindow * win )
+{
+ int l;
+ l=wsSearch( win->WindowID );
+ wsWindowList[l]=NULL;
+ if ( win->wsCursor != None )
+ {
+ XFreeCursor( wsDisplay,win->wsCursor );
+ win->wsCursor=None;
+ }
+ XFreeGC( wsDisplay,win->wGC );
+ XUnmapWindow( wsDisplay,win->WindowID );
+ wsDestroyImage( win );
+ XDestroyWindow( wsDisplay,win->WindowID );
+#if 0
+ win->ReDraw=NULL;
+ win->ReSize=NULL;
+ win->Idle=NULL;
+ win->MouseHandler=NULL;
+ win->KeyHandler=NULL;
+ win->Visible=0;
+ win->Focused=0;
+ win->Mapped=0;
+ win->Rolled=0;
+#endif
+}
+
+// ----------------------------------------------------------------------------------------------
+// Handle events.
+// ----------------------------------------------------------------------------------------------
+
+inline int wsSearch( Window win )
+{
+ int i;
+ for ( i=0;i<wsWLCount;i++ ) if ( wsWindowList[i] && wsWindowList[i]->WindowID == win ) return i;
+ return -1;
+}
+
+Bool wsEvents( Display * display,XEvent * Event,XPointer arg )
+{
+ unsigned long i = 0;
+ int l;
+ int x,y;
+ Window child_window = 0;
+
+ l=wsSearch( Event->xany.window );
+ if ( l == -1 ) return !wsTrue;
+ wsWindowList[l]->State=0;
+ switch( Event->type )
+ {
+ case ClientMessage:
+ if ( Event->xclient.message_type == wsWindowList[l]->AtomProtocols )
+ {
+ if ( (Atom)Event->xclient.data.l[0] == wsWindowList[l]->AtomDeleteWindow )
+ { i=wsWindowClosed; goto expose; }
+ if ( (Atom)Event->xclient.data.l[0] == wsWindowList[l]->AtomTakeFocus )
+ { i=wsWindowFocusIn; wsWindowList[l]->Focused=wsFocused; goto expose; }
+ if ( (Atom)Event->xclient.data.l[0] == wsWindowList[l]->AtomRolle )
+ { mp_msg( MSGT_GPLAYER,MSGL_V,"[ws] role set.\n" ); }
+ } else {
+ /* try to process DND events */
+ wsXDNDProcessClientMessage(wsWindowList[l],&Event->xclient);
+ }
+ break;
+
+ case MapNotify: i=wsWindowMapped; wsWindowList[l]->Mapped=wsMapped; goto expose;
+ case UnmapNotify: i=wsWindowUnmapped; wsWindowList[l]->Mapped=wsNone; goto expose;
+ case FocusIn:
+ if ( wsWindowList[l]->Focused == wsFocused ) break;
+ i=wsWindowFocusIn;
+ wsWindowList[l]->Focused=wsFocused;
+ goto expose;
+ case FocusOut:
+ if ( wsWindowList[l]->Focused == wsNone ) break;
+ i=wsWindowFocusOut;
+ wsWindowList[l]->Focused=wsNone;
+ goto expose;
+ case VisibilityNotify:
+ switch( Event->xvisibility.state )
+ {
+ case VisibilityUnobscured: i=wsWindowVisible; wsWindowList[l]->Visible=wsVisible; goto expose;
+ case VisibilityFullyObscured: i=wsWindowNotVisible; wsWindowList[l]->Visible=wsNotVisible; goto expose;
+ case VisibilityPartiallyObscured: i=wsWindowPartialVisible; wsWindowList[l]->Visible=wsPVisible; goto expose;
+ }
+expose:
+ wsWindowList[l]->State=i;
+ if ( wsWindowList[l]->ReDraw ) wsWindowList[l]->ReDraw();
+ break;
+
+ case Expose:
+ wsWindowList[l]->State=wsWindowExpose;
+ if ( ( wsWindowList[l]->ReDraw )&&( !Event->xexpose.count ) ) wsWindowList[l]->ReDraw();
+ break;
+
+ case ConfigureNotify:
+ XTranslateCoordinates( wsDisplay,wsWindowList[l]->WindowID,wsRootWin,0,0,&x,&y,&child_window );
+ if ( ( wsWindowList[l]->X != x )||( wsWindowList[l]->Y != y )||( wsWindowList[l]->Width != Event->xconfigure.width )||( wsWindowList[l]->Height != Event->xconfigure.height ) )
+ {
+ wsWindowList[l]->X=x; wsWindowList[l]->Y=y;
+ wsWindowList[l]->Width=Event->xconfigure.width; wsWindowList[l]->Height=Event->xconfigure.height;
+ if ( wsWindowList[l]->ReSize ) wsWindowList[l]->ReSize( wsWindowList[l]->X,wsWindowList[l]->Y,wsWindowList[l]->Width,wsWindowList[l]->Height );
+ }
+
+ wsWindowList[l]->Rolled=wsNone;
+ if ( Event->xconfigure.y < 0 )
+ { i=wsWindowRolled; wsWindowList[l]->Rolled=wsRolled; goto expose; }
+
+ break;
+
+ case KeyPress: i=wsKeyPressed; goto keypressed;
+ case KeyRelease: i=wsKeyReleased;
+keypressed:
+ wsWindowList[l]->Alt=0;
+ wsWindowList[l]->Shift=0;
+ wsWindowList[l]->NumLock=0;
+ wsWindowList[l]->Control=0;
+ wsWindowList[l]->CapsLock=0;
+ if ( Event->xkey.state & Mod1Mask ) wsWindowList[l]->Alt=1;
+ if ( Event->xkey.state & Mod2Mask ) wsWindowList[l]->NumLock=1;
+ if ( Event->xkey.state & ControlMask ) wsWindowList[l]->Control=1;
+ if ( Event->xkey.state & ShiftMask ) wsWindowList[l]->Shift=1;
+ if ( Event->xkey.state & LockMask ) wsWindowList[l]->CapsLock=1;
+#if 0
+ {
+ KeySym keySym;
+ keySym=XKeycodeToKeysym( wsDisplay,Event->xkey.keycode,0 );
+ if ( keySym != NoSymbol )
+ {
+ keySym=( (keySym&0xff00) != 0?( (keySym&0x00ff) + 256 ):( keySym ) );
+ wsKeyTable[ keySym ]=i;
+ if ( wsWindowList[l]->KeyHandler )
+ wsWindowList[l]->KeyHandler( Event->xkey.state,i,keySym );
+ }
+ }
+#else
+ {
+ int key;
+ char buf[100];
+ KeySym keySym;
+ static XComposeStatus stat;
+
+ XLookupString( &Event->xkey,buf,sizeof(buf),&keySym,&stat );
+ key=( (keySym&0xff00) != 0?( (keySym&0x00ff) + 256 ):( keySym ) );
+ wsKeyTable[ key ]=i;
+ if ( wsWindowList[l]->KeyHandler ) wsWindowList[l]->KeyHandler( Event->xkey.keycode,i,key );
+ }
+#endif
+ break;
+
+ case MotionNotify:
+ i=wsMoveMouse;
+ {
+ /* pump all motion events from the display queue:
+ this way it works faster when moving the window */
+ static XEvent e;
+ if ( Event->xmotion.state )
+ {
+ while(XCheckTypedWindowEvent(display,Event->xany.window,MotionNotify,&e)){
+ /* FIXME: need to make sure we didn't release/press the button in between...*/
+ /* FIXME: do we need some timeout here to make sure we don't spend too much time
+ removing events from the queue? */
+ Event = &e;
+ }
+ }
+ }
+ goto buttonreleased;
+ case ButtonRelease: i=Event->xbutton.button + 128; goto buttonreleased;
+ case ButtonPress: i=Event->xbutton.button; goto buttonreleased;
+ case EnterNotify: i=wsEnterWindow; goto buttonreleased;
+ case LeaveNotify: i=wsLeaveWindow;
+buttonreleased:
+ if ( wsWindowList[l]->MouseHandler )
+ wsWindowList[l]->MouseHandler( i,Event->xbutton.x,Event->xbutton.y,Event->xmotion.x_root,Event->xmotion.y_root );
+ break;
+
+ case SelectionNotify:
+ /* Handle DandD */
+ wsXDNDProcessSelection(wsWindowList[l],Event);
+ break;
+ }
+ XFlush( wsDisplay );
+ XSync( wsDisplay,False );
+ return !wsTrue;
+}
+
+Bool wsDummyEvents( Display * display,XEvent * Event,XPointer arg )
+{ return True; }
+
+void wsHandleEvents( void ){
+ // handle pending events
+ while ( XPending(wsDisplay) ){
+ XNextEvent( wsDisplay,&wsEvent );
+// printf("### X event: %d [%d]\n",wsEvent.type,delay);
+ wsEvents( wsDisplay,&wsEvent,NULL );
+ }
+}
+
+void wsMainLoop( void )
+{
+ int delay=20;
+ mp_msg( MSGT_GPLAYER,MSGL_V,"[ws] init threads: %d\n",XInitThreads() );
+ XSynchronize( wsDisplay,False );
+ XLockDisplay( wsDisplay );
+// XIfEvent( wsDisplay,&wsEvent,wsEvents,NULL );
+
+#if 1
+
+while(wsTrue){
+ // handle pending events
+ while ( XPending(wsDisplay) ){
+ XNextEvent( wsDisplay,&wsEvent );
+ wsEvents( wsDisplay,&wsEvent,NULL );
+ delay=0;
+ }
+ usleep(delay*1000); // FIXME!
+ if(delay<10*20) delay+=20; // pump up delay up to 0.2 sec (low activity)
+}
+
+#else
+
+ while( wsTrue )
+ {
+ XIfEvent( wsDisplay,&wsEvent,wsDummyEvents,NULL );
+ wsEvents( wsDisplay,&wsEvent,NULL );
+ }
+#endif
+
+ XUnlockDisplay( wsDisplay );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Move window to selected layer
+// ----------------------------------------------------------------------------------------------
+
+#define WIN_LAYER_ONBOTTOM 2
+#define WIN_LAYER_NORMAL 4
+#define WIN_LAYER_ONTOP 10
+
+void wsSetLayer( Display * wsDisplay, Window win, int layer )
+{ vo_x11_setlayer( wsDisplay,win,layer ); }
+
+// ----------------------------------------------------------------------------------------------
+// Switch to fullscreen.
+// ----------------------------------------------------------------------------------------------
+void wsFullScreen( wsTWindow * win )
+{
+ int decoration = 0;
+
+ if ( win->isFullScreen )
+ {
+ vo_x11_ewmh_fullscreen( _NET_WM_STATE_REMOVE ); // removes fullscreen state if wm supports EWMH
+ if ( ! (vo_fs_type & vo_wm_FULLSCREEN) ) // shouldn't be needed with EWMH fs
+ {
+ win->X=win->OldX;
+ win->Y=win->OldY;
+ win->Width=win->OldWidth;
+ win->Height=win->OldHeight;
+ decoration=win->Decorations;
+ }
+
+#ifdef ENABLE_DPMS
+ wsScreenSaverOn( wsDisplay );
+#endif
+
+ win->isFullScreen=False;
+ }
+ else
+ {
+ if ( ! (vo_fs_type & vo_wm_FULLSCREEN) ) // shouldn't be needed with EWMH fs
+ {
+ win->OldX=win->X; win->OldY=win->Y;
+ win->OldWidth=win->Width; win->OldHeight=win->Height;
+ vo_dx = win->X; vo_dy = win->Y;
+ vo_dwidth = win->Width; vo_dheight = win->Height;
+ vo_screenwidth = wsMaxX; vo_screenheight = wsMaxY;
+ xinerama_x = wsOrgX; xinerama_y = wsOrgY;
+ update_xinerama_info();
+ wsMaxX = vo_screenwidth; wsMaxY = vo_screenheight;
+ wsOrgX = xinerama_x; wsOrgY = xinerama_y;
+ win->X=wsOrgX; win->Y=wsOrgY;
+ win->Width=wsMaxX; win->Height=wsMaxY;
+ }
+
+ win->isFullScreen=True;
+#ifdef ENABLE_DPMS
+ wsScreenSaverOff( wsDisplay );
+#endif
+
+ vo_x11_ewmh_fullscreen( _NET_WM_STATE_ADD ); // adds fullscreen state if wm supports EWMH
+ }
+
+ if ( ! (vo_fs_type & vo_wm_FULLSCREEN) ) // shouldn't be needed with EWMH fs
+ {
+ vo_x11_decoration( wsDisplay,win->WindowID,decoration );
+ vo_x11_sizehint( win->X,win->Y,win->Width,win->Height,0 );
+ vo_x11_setlayer( wsDisplay,win->WindowID,win->isFullScreen );
+
+ if ((!(win->isFullScreen)) & vo_ontop) vo_x11_setlayer(wsDisplay, win->WindowID,1);
+
+ XMoveResizeWindow( wsDisplay,win->WindowID,win->X,win->Y,win->Width,win->Height );
+ }
+
+ if ( vo_wm_type == 0 && !(vo_fsmode&16) )
+ {
+ XWithdrawWindow( wsDisplay,win->WindowID,wsScreen );
+ }
+
+
+ XMapRaised( wsDisplay,win->WindowID );
+ XRaiseWindow( wsDisplay,win->WindowID );
+ XFlush( wsDisplay );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Redraw screen.
+// ----------------------------------------------------------------------------------------------
+void wsPostRedisplay( wsTWindow * win )
+{
+ if ( win->ReDraw )
+ {
+ win->State=wsWindowExpose;
+ win->ReDraw();
+ XFlush( wsDisplay );
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+// Do Exit.
+// ----------------------------------------------------------------------------------------------
+void wsDoExit( void )
+{ wsTrue=False; wsResizeWindow( wsWindowList[0],32,32 ); }
+
+// ----------------------------------------------------------------------------------------------
+// Put 'Image' to window.
+// ----------------------------------------------------------------------------------------------
+void wsConvert( wsTWindow * win,unsigned char * Image,unsigned int Size )
+{ if ( wsConvFunc ) wsConvFunc( Image,win->ImageData,win->xImage->width * win->xImage->height * 4 ); }
+
+void wsPutImage( wsTWindow * win )
+{
+ if ( wsUseXShm )
+ {
+ XShmPutImage( wsDisplay,win->WindowID,win->wGC,win->xImage,
+ 0,0,
+ ( win->Width - win->xImage->width ) / 2,( win->Height - win->xImage->height ) / 2,
+ win->xImage->width,win->xImage->height,0 );
+ }
+ else
+ {
+ XPutImage( wsDisplay,win->WindowID,win->wGC,win->xImage,
+ 0,0,
+ ( win->Width - win->xImage->width ) / 2,( win->Height - win->xImage->height ) / 2,
+ win->xImage->width,win->xImage->height );
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+// Move window to x, y.
+// ----------------------------------------------------------------------------------------------
+void wsMoveWindow( wsTWindow * win,int b,int x, int y )
+{
+ if ( b )
+ {
+ switch ( x )
+ {
+ case -1: win->X=( wsMaxX / 2 ) - ( win->Width / 2 ) + wsOrgX; break;
+ case -2: win->X=wsMaxX - win->Width + wsOrgX; break;
+ default: win->X=x; break;
+ }
+ switch ( y )
+ {
+ case -1: win->Y=( wsMaxY / 2 ) - ( win->Height / 2 ) + wsOrgY; break;
+ case -2: win->Y=wsMaxY - win->Height + wsOrgY; break;
+ default: win->Y=y; break;
+ }
+ }
+ else { win->X=x; win->Y=y; }
+
+ win->SizeHint.flags=PPosition | PWinGravity;
+ win->SizeHint.x=win->X;
+ win->SizeHint.y=win->Y;
+ win->SizeHint.win_gravity=StaticGravity;
+ XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint );
+
+ XMoveWindow( wsDisplay,win->WindowID,win->X,win->Y );
+ if ( win->ReSize ) win->ReSize( win->X,win->Y,win->Width,win->Height );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Resize window to sx, sy.
+// ----------------------------------------------------------------------------------------------
+void wsResizeWindow( wsTWindow * win,int sx, int sy )
+{
+ win->Width=sx;
+ win->Height=sy;
+
+ win->SizeHint.flags=PPosition | PSize | PWinGravity;// | PBaseSize;
+ win->SizeHint.x=win->X;
+ win->SizeHint.y=win->Y;
+ win->SizeHint.width=win->Width;
+ win->SizeHint.height=win->Height;
+
+ if ( win->Property & wsMinSize )
+ {
+ win->SizeHint.flags|=PMinSize;
+ win->SizeHint.min_width=win->Width;
+ win->SizeHint.min_height=win->Height;
+ }
+ if ( win->Property & wsMaxSize )
+ {
+ win->SizeHint.flags|=PMaxSize;
+ win->SizeHint.max_width=win->Width;
+ win->SizeHint.max_height=win->Height;
+ }
+
+ win->SizeHint.win_gravity=StaticGravity;
+ win->SizeHint.base_width=sx; win->SizeHint.base_height=sy;
+
+ if ( vo_wm_type == 0 ) XUnmapWindow( wsDisplay,win->WindowID );
+
+ XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint );
+ XResizeWindow( wsDisplay,win->WindowID,sx,sy );
+ XMapRaised( wsDisplay,win->WindowID );
+ if ( win->ReSize ) win->ReSize( win->X,win->Y,win->Width,win->Height );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Iconify window.
+// ----------------------------------------------------------------------------------------------
+void wsIconify( wsTWindow win )
+{ XIconifyWindow( wsDisplay,win.WindowID,0 ); }
+
+// ----------------------------------------------------------------------------------------------
+// Move top the window.
+// ----------------------------------------------------------------------------------------------
+void wsMoveTopWindow( Display * wsDisplay,Window win )
+{
+// XUnmapWindow( wsDisplay,win );
+// XMapWindow( wsDisplay,win );
+ XMapRaised( wsDisplay,win );
+ XRaiseWindow( wsDisplay,win );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Set window background to 'color'.
+// ----------------------------------------------------------------------------------------------
+void wsSetBackground( wsTWindow * win,int color )
+{ XSetWindowBackground( wsDisplay,win->WindowID,color ); }
+
+void wsSetBackgroundRGB( wsTWindow * win,int r,int g,int b )
+{
+ int color = 0;
+ switch ( wsOutMask )
+ {
+ case wsRGB32:
+ case wsRGB24: color=( r << 16 ) + ( g << 8 ) + b; break;
+ case wsBGR32:
+ case wsBGR24: color=( b << 16 ) + ( g << 8 ) + r; break;
+ case wsRGB16: PACK_RGB16( b,g,r,color ); break;
+ case wsBGR16: PACK_RGB16( r,g,b,color ); break;
+ case wsRGB15: PACK_RGB15( b,g,r,color ); break;
+ case wsBGR15: PACK_RGB15( r,g,b,color ); break;
+ }
+ XSetWindowBackground( wsDisplay,win->WindowID,color );
+}
+
+void wsSetForegroundRGB( wsTWindow * win,int r,int g,int b )
+{
+ int color = 0;
+ switch ( wsOutMask )
+ {
+ case wsRGB32:
+ case wsRGB24: color=( r << 16 ) + ( g << 8 ) + b; break;
+ case wsBGR32:
+ case wsBGR24: color=( b << 16 ) + ( g << 8 ) + r; break;
+ case wsRGB16: PACK_RGB16( b,g,r,color ); break;
+ case wsBGR16: PACK_RGB16( r,g,b,color ); break;
+ case wsRGB15: PACK_RGB15( b,g,r,color ); break;
+ case wsBGR15: PACK_RGB15( r,g,b,color ); break;
+ }
+ XSetForeground( wsDisplay,win->wGC,color );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Draw string at x,y with fc ( foreground color ) and bc ( background color ).
+// ----------------------------------------------------------------------------------------------
+void wsDrawString( wsTWindow win,int x,int y,char * str,int fc,int bc )
+{
+ XSetForeground( wsDisplay,win.wGC,bc );
+ XFillRectangle( wsDisplay,win.WindowID,win.wGC,x,y,
+ XTextWidth( win.Font,str,strlen( str ) ) + 20,
+ win.FontHeight + 2 );
+ XSetForeground( wsDisplay,win.wGC,fc );
+ XDrawString( wsDisplay,win.WindowID,win.wGC,x + 10,y + 13,str,strlen( str ) );
+}
+
+// ----------------------------------------------------------------------------------------------
+// Calculation string width.
+// ----------------------------------------------------------------------------------------------
+int wsTextWidth( wsTWindow win,char * str )
+{ return XTextWidth( win.Font,str,strlen( str ) ) + 20; }
+
+// ----------------------------------------------------------------------------------------------
+// Show / hide mouse cursor.
+// ----------------------------------------------------------------------------------------------
+void wsVisibleMouse( wsTWindow * win,int m )
+{
+ switch ( m )
+ {
+ case wsShowMouseCursor:
+