From 5c9abf7f9f02a3b675072b2725c2814d1c1ee239 Mon Sep 17 00:00:00 2001 From: diego Date: Mon, 23 Apr 2007 07:42:42 +0000 Subject: Gui --> gui git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@23095 b3059339-0415-0410-9bf9-f77b7e298cf2 --- gui/wm/ws.c | 1272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gui/wm/ws.h | 262 +++++++++++ gui/wm/wskeys.h | 165 +++++++ gui/wm/wsmkeys.h | 64 +++ gui/wm/wsxdnd.c | 242 +++++++++++ gui/wm/wsxdnd.h | 53 +++ 6 files changed, 2058 insertions(+) create mode 100644 gui/wm/ws.c create mode 100644 gui/wm/ws.h create mode 100644 gui/wm/wskeys.h create mode 100644 gui/wm/wsmkeys.h create mode 100644 gui/wm/wsxdnd.c create mode 100644 gui/wm/wsxdnd.h (limited to 'gui/wm') 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#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 +#ifdef HAVE_XSHAPE +#include +#endif + +#ifdef HAVE_XINERAMA +#include +#endif + +#ifdef HAVE_XF86VM +#include +#endif + +#include +#include + +#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;iWindowID == 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: + if ( win->wsCursor != None ) + { + XFreeCursor( wsDisplay,win->wsCursor ); + win->wsCursor=None; + } + XDefineCursor( wsDisplay,win->WindowID,0 ); + break; + case wsHideMouseCursor: + win->wsCursor=XCreatePixmapCursor( wsDisplay,win->wsCursorPixmap,win->wsCursorPixmap,&win->wsColor,&win->wsColor,0,0 ); + XDefineCursor( wsDisplay,win->WindowID,win->wsCursor ); + break; + } + XFlush( wsDisplay ); +} + +int wsGetDepthOnScreen( void ) +{ + int depth; + XImage * mXImage; + Visual * visual; + + if( (depth = vo_find_depth_from_visuals( wsDisplay,wsScreen,&visual )) > 0 ) + { + mXImage = XCreateImage( wsDisplay,visual,depth,ZPixmap,0,NULL, + 1,1,32,0 ); + wsDepthOnScreen = mXImage->bits_per_pixel; + wsRedMask=mXImage->red_mask; + wsGreenMask=mXImage->green_mask; + wsBlueMask=mXImage->blue_mask; + XDestroyImage( mXImage ); + } + else + { + int bpp,ibpp; + XWindowAttributes attribs; + + mXImage=XGetImage( wsDisplay,wsRootWin,0,0,1,1,AllPlanes,ZPixmap ); + bpp=mXImage->bits_per_pixel; + + XGetWindowAttributes( wsDisplay,wsRootWin,&attribs ); + ibpp=attribs.depth; + mXImage=XGetImage( wsDisplay,wsRootWin,0,0,1,1,AllPlanes,ZPixmap ); + bpp=mXImage->bits_per_pixel; + if ( ( ibpp + 7 ) / 8 != ( bpp + 7 ) / 8 ) ibpp=bpp; + wsDepthOnScreen=ibpp; + wsRedMask=mXImage->red_mask; + wsGreenMask=mXImage->green_mask; + wsBlueMask=mXImage->blue_mask; + XDestroyImage( mXImage ); + } + return wsDepthOnScreen; +} + +void wsXDone( void ) +{ + XCloseDisplay( wsDisplay ); +} + +void wsVisibleWindow( wsTWindow * win,int show ) +{ + switch( show ) + { + case wsShowWindow: XMapRaised( wsDisplay,win->WindowID ); break; + case wsHideWindow: XUnmapWindow( wsDisplay,win->WindowID ); break; + } + XFlush( wsDisplay ); +} + +void wsDestroyImage( wsTWindow * win ) +{ + if ( win->xImage ) + { + XDestroyImage( win->xImage ); + if ( wsUseXShm ) + { + XShmDetach( wsDisplay,&win->Shminfo ); + shmdt( win->Shminfo.shmaddr ); + } + } + win->xImage=NULL; +} + +void wsCreateImage( wsTWindow * win,int Width,int Height ) +{ + int CompletionType = -1; + if ( wsUseXShm ) + { + CompletionType=XShmGetEventBase( wsDisplay ) + ShmCompletion; + win->xImage=XShmCreateImage( wsDisplay,win->VisualInfo.visual, + win->VisualInfo.depth,ZPixmap,NULL,&win->Shminfo,Width,Height ); + if ( win->xImage == NULL ) + { + mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_ShmError ); + exit( 0 ); + } + win->Shminfo.shmid=shmget( IPC_PRIVATE,win->xImage->bytes_per_line * win->xImage->height,IPC_CREAT|0777 ); + if ( win->Shminfo.shmid < 0 ) + { + XDestroyImage( win->xImage ); + mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_ShmError ); + exit( 0 ); + } + win->Shminfo.shmaddr=(char *)shmat( win->Shminfo.shmid,0,0 ); + + if ( win->Shminfo.shmaddr == ((char *) -1) ) + { + XDestroyImage( win->xImage ); + if ( win->Shminfo.shmaddr != ((char *) -1) ) shmdt( win->Shminfo.shmaddr ); + mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_ShmError ); + exit( 0 ); + } + win->xImage->data=win->Shminfo.shmaddr; + win->Shminfo.readOnly=0; + XShmAttach( wsDisplay,&win->Shminfo ); + shmctl( win->Shminfo.shmid,IPC_RMID,0 ); + } + else + { + win->xImage=XCreateImage( wsDisplay,win->VisualInfo.visual,win->VisualInfo.depth, + ZPixmap,0,0,Width,Height, + (wsDepthOnScreen == 3) ? 32 : wsDepthOnScreen, + 0 ); + if ( ( win->xImage->data=malloc( win->xImage->bytes_per_line * win->xImage->height ) ) == NULL ) + { + mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_NotEnoughMemoryDrawBuffer ); + exit( 0 ); + } + } + win->ImageData=(unsigned char *)win->xImage->data; + win->ImageDataw=(unsigned short int *)win->xImage->data; + win->ImageDatadw=(unsigned int *)win->xImage->data; +} + +void wsResizeImage( wsTWindow * win,int Width,int Height ) +{ wsDestroyImage( win ); wsCreateImage( win,Width,Height ); } + +int wsGetOutMask( void ) +{ + if ( ( wsDepthOnScreen == 32 )&&( wsRedMask == 0xff0000 )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0x0000ff ) ) return wsRGB32; + if ( ( wsDepthOnScreen == 32 )&&( wsRedMask == 0x0000ff )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0xff0000 ) ) return wsBGR32; + if ( ( wsDepthOnScreen == 24 )&&( wsRedMask == 0xff0000 )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0x0000ff ) ) return wsRGB24; + if ( ( wsDepthOnScreen == 24 )&&( wsRedMask == 0x0000ff )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0xff0000 ) ) return wsBGR24; + if ( ( wsDepthOnScreen == 16 )&&( wsRedMask == 0xf800 )&&( wsGreenMask == 0x7e0 )&&( wsBlueMask == 0x1f ) ) return wsRGB16; + if ( ( wsDepthOnScreen == 16 )&&( wsRedMask == 0x1f )&&( wsGreenMask == 0x7e0 )&&( wsBlueMask == 0xf800 ) ) return wsBGR16; + if ( ( wsDepthOnScreen == 15 )&&( wsRedMask == 0x7c00 )&&( wsGreenMask == 0x3e0 )&&( wsBlueMask == 0x1f ) ) return wsRGB15; + if ( ( wsDepthOnScreen == 15 )&&( wsRedMask == 0x1f )&&( wsGreenMask == 0x3e0 )&&( wsBlueMask == 0x7c00 ) ) return wsBGR15; + return 0; +} + +void wsSetTitle( wsTWindow * win,char * name ) +{ XStoreName( wsDisplay,win->WindowID,name ); } + +void wsSetMousePosition( wsTWindow * win,int x, int y ) +{ XWarpPointer( wsDisplay,wsRootWin,win->WindowID,0,0,0,0,x,y ); } + +#ifdef ENABLE_DPMS +static int dpms_disabled=0; +static int timeout_save=0; + +void wsScreenSaverOn( Display *mDisplay ) +{ + int nothing; +#ifdef HAVE_XDPMS + if ( dpms_disabled ) + { + if ( DPMSQueryExtension( mDisplay,¬hing,¬hing ) ) + { + if ( !DPMSEnable( mDisplay ) ) mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_WS_DpmsUnavailable ); // restoring power saving settings + else + { + // DPMS does not seem to be enabled unless we call DPMSInfo + BOOL onoff; + CARD16 state; + DPMSInfo( mDisplay,&state,&onoff ); + if ( onoff ) mp_msg( MSGT_GPLAYER,MSGL_V,"Successfully enabled DPMS.\n" ); + else mp_msg( MSGT_GPLAYER,MSGL_STATUS,MSGTR_WS_DpmsNotEnabled ); + } + } + } +#endif + if ( timeout_save ) + { + 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 ); + } +} + +void wsScreenSaverOff( Display * mDisplay ) +{ + int interval,prefer_blank,allow_exp,nothing; +#ifdef HAVE_XDPMS + if ( DPMSQueryExtension( mDisplay,¬hing,¬hing ) ) + { + BOOL onoff; + CARD16 state; + DPMSInfo( mDisplay,&state,&onoff ); + if ( onoff ) + { + Status stat; + mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"Disabling DPMS.\n" ); + dpms_disabled=1; + stat=DPMSDisable( mDisplay ); // monitor powersave off + mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"stat: %d.\n",stat ); + } + } +#endif + XGetScreenSaver( mDisplay,&timeout_save,&interval,&prefer_blank,&allow_exp ); + if ( timeout_save ) XSetScreenSaver( mDisplay,0,interval,prefer_blank,allow_exp ); // turning off screensaver +} +#endif + +void wsSetShape( wsTWindow * win,char * data ) +{ +#ifdef HAVE_XSHAPE + if ( !wsUseXShape ) return; + if ( data ) + { + win->Mask=XCreateBitmapFromData( wsDisplay,win->WindowID,data,win->Width,win->Height ); + XShapeCombineMask( wsDisplay,win->WindowID,ShapeBounding,0,0,win->Mask,ShapeSet ); + XFreePixmap( wsDisplay,win->Mask ); + } + else XShapeCombineMask( wsDisplay,win->WindowID,ShapeBounding,0,0,None,ShapeSet ); +#endif +} + +void wsSetIcon( Display * dsp,Window win,Pixmap icon,Pixmap mask ) +{ + XWMHints * wm; + long data[2]; + Atom iconatom; + + wm=XGetWMHints( dsp,win ); + if ( !wm ) wm=XAllocWMHints(); + + wm->icon_pixmap=icon; + wm->icon_mask=mask; + wm->flags|=IconPixmapHint | IconMaskHint; + + XSetWMHints( dsp,win,wm ); + + data[0]=icon; + data[1]=mask; + iconatom=XInternAtom( dsp,"KWM_WIN_ICON",0 ); + XChangeProperty( dsp,win,iconatom,iconatom,32,PropModeReplace,(unsigned char *)data,2 ); + + XFree( wm ); +} + +#include "wsmkeys.h" diff --git a/gui/wm/ws.h b/gui/wm/ws.h new file mode 100644 index 0000000000..17ad5a512a --- /dev/null +++ b/gui/wm/ws.h @@ -0,0 +1,262 @@ + +// ---------------------------------------------------------------------------------------------- +// AutoSpace Window System for Linux/Win32 v0.61 +// Writed by pontscho / fresh!mindworkz +// ---------------------------------------------------------------------------------------------- + +#ifndef __MY_WS +#define __MY_WS + +#include +#include +#include +#include +#include +#ifdef HAVE_XDPMS +#include +#endif + +#define wsKeyReleased 0 +#define wsKeyPressed 1 + +#define wsShift (1L<<0) +#define wsLock (1L<<1) +#define wsCtrl (1L<<2) +#define wsAlt (1L<<3) + +#define wsPLMouseButton 1 +#define wsPMMouseButton 2 +#define wsPRMouseButton 3 +#define wsP4MouseButton 4 +#define wsP5MouseButton 5 +#define wsRLMouseButton (1 + 128) +#define wsRMMouseButton (2 + 128) +#define wsRRMouseButton (3 + 128) +#define wsR4MouseButton (4 + 128) +#define wsR5MouseButton (5 + 128) +#define wsEnterWindow 253 +#define wsLeaveWindow 254 +#define wsMoveMouse 255 + +#define wsShowMouseCursor 1 +#define wsMouse 1 +#define wsHideMouseCursor 0 +#define wsNoMouse 0 +#define wsHandleMouseButton 2 +#define wsHandleMouseMove 4 + +#define wsHideFrame 0 +#define wsNoFrame 0 +#define wsShowFrame 1 +#define wsFrame 1 +#define wsMaxSize 2 +#define wsMinSize 4 +#define wsShowWindow 8 +#define wsHideWindow 16 +#define wsOverredirect 32 + +#define wsNoBorder 0 + +#define wsSysName "AutoSpace Window System LiTe" + +#define wsRGB32 1 +#define wsBGR32 2 +#define wsRGB24 3 +#define wsBGR24 4 +#define wsRGB16 5 +#define wsBGR16 6 +#define wsRGB15 7 +#define wsBGR15 8 + +#define wsWindowVisible 1 +#define wsWindowPartialVisible 2 +#define wsWindowNotVisible 4 +#define wsWindowMapped 8 +#define wsWindowUnmapped 16 +#define wsWindowFocusIn 32 +#define wsWindowFocusOut 64 +#define wsWindowExpose 128 +#define wsWindowRolled 256 +#define wsWindowClosed 512 + +#define wsNone 0 +#define wsMapped 1 +#define wsFocused 2 +#define wsVisible 3 +#define wsNotVisible 4 +#define wsPVisible 5 +#define wsRolled 6 + +#define wsWMUnknown 0 +#define wsWMNetWM 1 +#define wsWMKDE 2 +#define wsWMIceWM 3 +#define wsWMWMaker 4 + +typedef void (*wsTReDraw)( void ); +typedef void (*wsTReSize)( unsigned int X,unsigned int Y,unsigned int width,unsigned int height ); +typedef void (*wsTIdle)( void ); +typedef void (*wsTKeyHandler)( int KeyCode,int Type,int Key ); +typedef void (*wsTMouseHandler)( int Button,int X,int Y,int RX,int RY ); +typedef void (*wsTDNDHandler)( int num,char ** str ); + +typedef struct +{ + Window WindowID; + Window Parent; + int X,Y,Width,Height; + int OldX,OldY,OldWidth,OldHeight; + int MaxX,MaxY; + int isFullScreen; + int BorderWidth; + int Property; + unsigned char * bImage; + XImage * xImage; + Pixmap Mask; + int Decorations; + + int State; + int Visible; + int Mapped; + int Focused; + int Rolled; + + wsTReDraw ReDraw; + wsTReSize ReSize; + wsTIdle Idle; + wsTKeyHandler KeyHandler; + wsTMouseHandler MouseHandler; + wsTDNDHandler DandDHandler; + + int Alt; + int Shift; + int Control; + int NumLock; + int CapsLock; +// --- Misc ------------------------------------------------------------------------------------- + + Atom AtomDeleteWindow; + Atom AtomTakeFocus; + Atom AtomRolle; + Atom AtomProtocols; + Atom AtomsProtocols[3]; + Atom AtomLeaderClient; + Atom AtomRemote; + Atom AtomWMSizeHint; + Atom AtomWMNormalHint; + + XShmSegmentInfo Shminfo; + unsigned char * ImageData; + unsigned short int * ImageDataw; + unsigned int * ImageDatadw; + GC wGC; + XGCValues wGCV; + unsigned long WindowMask; + XVisualInfo VisualInfo; + XSetWindowAttributes WindowAttrib; + XSizeHints SizeHint; + XWMHints WMHints; + + XFontStruct * Font; + int FontHeight; + + Cursor wsCursor; + char wsCursorData[1]; + Pixmap wsCursorPixmap; + int wsMouseEventType; + XColor wsColor; +} wsTWindow; + +extern int wsMaxX; +extern int wsMaxY; +extern int wsOrgX; +extern int wsOrgY; + +extern Display * wsDisplay; +extern int wsScreen; +extern Window wsRootWin; +extern int wsLayer; + +extern unsigned char * wsImageData; + +extern XEvent wsEvent; + +extern int wsDepthOnScreen; +extern int wsRedMask; +extern int wsGreenMask; +extern int wsBlueMask; + +extern int wsUseXShm; +extern int wsUseDGA; + +// ---------------------------------------------------------------------------------------------- +// wsKeyTable +// ---------------------------------------------------------------------------------------------- +extern unsigned long wsKeyTable[512]; + +extern void wsXDone( void ); +extern void wsXInit( void* disp ); + +extern int wsGetDepthOnScreen( void ); + +extern void wsDoExit( void ); +extern void wsMainLoop( void ); +extern Bool wsEvents( Display * display,XEvent * Event,XPointer arg ); +extern void wsHandleEvents( void ); + +// ---------------------------------------------------------------------------------------------- +// wsCrateWindow: create a new window on the screen. +// X,Y : window position +// wX,hY : window size +// bW : window frame size +// cV : mouse cursor visible +// D : "decoration", visible titlebar, etc ... +// ---------------------------------------------------------------------------------------------- +extern void wsCreateWindow( wsTWindow * win,int X,int Y,int wX,int hY,int bW,int cV,unsigned char D,char * label ); +extern void wsDestroyWindow( wsTWindow * win ); +extern void wsMoveWindow( wsTWindow * win,int b,int x, int y ); +extern void wsResizeWindow( wsTWindow * win,int sx, int sy ); +extern void wsIconify( wsTWindow win ); +extern void wsMoveTopWindow( Display * wsDisplay,Window win ); +extern void wsSetBackground( wsTWindow * win,int color ); +extern void wsSetForegroundRGB( wsTWindow * win,int r,int g,int b ); +extern void wsSetBackgroundRGB( wsTWindow * win,int r,int g,int b ); +#define wsClearWindow( win ) XClearWindow( wsDisplay,win.WindowID ) +extern void wsSetTitle( wsTWindow * win,char * name ); +extern void wsVisibleWindow( wsTWindow * win,int show ); +extern void wsWindowDecoration( wsTWindow * win,long d ); +extern void wsSetLayer( Display * wsDisplay,Window win, int layer ); +extern void wsFullScreen( wsTWindow * win ); +extern void wsPostRedisplay( wsTWindow * win ); +extern void wsSetShape( wsTWindow * win,char * data ); +extern void wsSetIcon( Display * dsp,Window win,Pixmap icon,Pixmap mask ); + +// ---------------------------------------------------------------------------------------------- +// Draw string at x,y with fc ( foreground color ) and bc ( background color ). +// ---------------------------------------------------------------------------------------------- +extern void wsDrawString( wsTWindow win,int x,int y,char * str,int fc,int bc ); +extern int wsTextWidth( wsTWindow win,char * str ); + +// ---------------------------------------------------------------------------------------------- +// Show / hide mouse cursor. +// ---------------------------------------------------------------------------------------------- +extern void wsVisibleMouse( wsTWindow * win,int m ); +extern void wsSetMousePosition( wsTWindow * win,int x, int y ); + +// ---------------------------------------------------------------------------------------------- +// Image handling +// ---------------------------------------------------------------------------------------------- +extern void wsCreateImage( wsTWindow * win,int Width,int Height ); +extern void wsConvert( wsTWindow * win,unsigned char * Image,unsigned int Size ); +extern void wsPutImage( wsTWindow * win ); +extern void wsResizeImage( wsTWindow * win,int Width,int Height ); +extern void wsDestroyImage( wsTWindow * win ); +extern int wsGetOutMask( void ); + +extern void wsScreenSaverOn( Display *mDisplay ); +extern void wsScreenSaverOff( Display * mDisplay ); + +#define wgIsRect( X,Y,tX,tY,bX,bY ) ( ( (X) > (tX) )&&( (Y) > (tY) )&&( (X) < (bX) )&&( (Y) < (bY) ) ) + +#endif + diff --git a/gui/wm/wskeys.h b/gui/wm/wskeys.h new file mode 100644 index 0000000000..830aecbc39 --- /dev/null +++ b/gui/wm/wskeys.h @@ -0,0 +1,165 @@ + +#ifndef _MY_WSKEY +#define _MY_WSKEY + +#define wsKeyNone -1 + +#define wsosbrackets '[' +#define wscsbrackets ']' + +#define wsq 'q' +#define wsa 'a' +#define wsz 'z' +#define wsw 'w' +#define wss 's' +#define wsx 'x' +#define wse 'e' +#define wsd 'd' +#define wsr 'r' +#define wsf 'f' +#define wsv 'v' +#define wst 't' +#define wsg 'g' +#define wsb 'b' +#define wsy 'y' +#define wsh 'h' +#define wsn 'n' +#define wsu 'u' +#define wsj 'j' +#define wsm 'm' +#define wsi 'i' +#define wsk 'k' +#define wso 'o' +#define wsl 'l' +#define wsp 'p' +#define wsc 'c' + +#define wsQ 'Q' +#define wsA 'A' +#define wsZ 'Z' +#define wsW 'W' +#define wsS 'S' +#define wsX 'X' +#define wsE 'E' +#define wsD 'D' +#define wsR 'R' +#define wsF 'F' +#define wsV 'V' +#define wsT 'T' +#define wsG 'G' +#define wsB 'B' +#define wsY 'Y' +#define wsH 'H' +#define wsN 'N' +#define wsU 'U' +#define wsJ 'J' +#define wsM 'M' +#define wsI 'I' +#define wsK 'K' +#define wsO 'O' +#define wsL 'L' +#define wsP 'P' +#define wsC 'C' + +#define ws0 '0' +#define ws1 '1' +#define ws2 '2' +#define ws3 '3' +#define ws4 '4' +#define ws5 '5' +#define ws6 '6' +#define ws7 '7' +#define ws8 '8' +#define ws9 '9' + +#define wsSpace ' ' +#define wsMinus '-' +#define wsPlus '+' +#define wsMul '*' +#define wsDiv '/' +#define wsLess '<' +#define wsMore '>' + +#define wsUp 0x52 + 256 +#define wsDown 0x54 + 256 +#define wsLeft 0x51 + 256 +#define wsRight 0x53 + 256 +#define wsLeftCtrl 0xe3 + 256 +#define wsRightCtrl 0xe4 + 256 +#define wsLeftAlt 0xe9 + 256 +#define wsRightAlt 0x7e + 256 +#define wsLeftShift 0xe1 + 256 +#define wsRightShift 0xe2 + 256 +#define wsEnter 0x0d + 256 +#define wsBackSpace 0x08 + 256 +#define wsCapsLock 0xe5 + 256 +#define wsTab 0x09 + 256 +#define wsF1 0xbe + 256 +#define wsF2 0xbf + 256 +#define wsF3 0xc0 + 256 +#define wsF4 0xc1 + 256 +#define wsF5 0xc2 + 256 +#define wsF6 0xc3 + 256 +#define wsF7 0xc4 + 256 +#define wsF8 0xc5 + 256 +#define wsF9 0xc6 + 256 +#define wsF10 0xc7 + 256 +#define wsF11 0xc8 + 256 +#define wsF12 0xc9 + 256 +#define wsInsert 0x63 + 256 +#define wsDelete 0xff + 256 +#define wsHome 0x50 + 256 +#define wsEnd 0x57 + 256 +#define wsPageUp 0x55 + 256 +#define wsPageDown 0x56 + 256 +#define wsNumLock 0x7f + 256 +#define wsEscape 0x1b + 256 +#define wsGrayEnter 0x8d + 256 +#define wsGrayPlus 0xab + 256 +#define wsGrayMinus 0xad + 256 +#define wsGrayMul 0xaa + 256 +#define wsGrayDiv 0xaf + 256 + +#define wsGrayInsert 0xb0 + 256 +#define wsGrayDelete 0xae + 256 +#define wsGrayEnd 0xb1 + 256 +#define wsGrayDown 0xb2 + 256 +#define wsGrayPageDown 0xb3 + 256 +#define wsGrayLeft 0xb4 + 256 +#define wsGray5 0xb5 + 256 +#define wsGrayRight 0xb6 + 256 +#define wsGrayHome 0xb7 + 256 +#define wsGrayUp 0xb8 + 256 +#define wsGrayPageUp 0xb9 + 256 + +//Keys for multimedia keyboard + +#define wsXF86LowerVolume 0x11 + 256 +#define wsXF86RaiseVolume 0x13 + 256 +#define wsXF86Mute 0x12 + 256 +#define wsXF86Play 0x14 + 256 +#define wsXF86Stop 0x15 + 256 +#define wsXF86Prev 0x16 + 256 +#define wsXF86Next 0x17 + 256 +#define wsXF86Media 0x32 + 256 + +#define wsXFMMPrev 0x98 +#define wsXFMMStop 0xb1 +#define wsXFMMPlay 0x95 +#define wsXFMMNext 0x93 +#define wsXFMMVolUp 0xad +#define wsXFMMVolDown 0xa6 +#define wsXFMMMute 0x99 + +#define wsKeyNumber 130 + +typedef struct +{ + int code; + const char * name; +} TwsKeyNames; + +extern TwsKeyNames wsKeyNames[ wsKeyNumber ]; + +#endif + diff --git a/gui/wm/wsmkeys.h b/gui/wm/wsmkeys.h new file mode 100644 index 0000000000..6fadb18428 --- /dev/null +++ b/gui/wm/wsmkeys.h @@ -0,0 +1,64 @@ + +#include "wskeys.h" + +TwsKeyNames wsKeyNames[ wsKeyNumber ] = + { + { wsq, "q" }, { wsa, "a" }, { wsz, "z" }, { wsw, "w" }, { wss, "s" }, { wsx, "x" }, + { wse, "e" }, { wsd, "d" }, { wsr, "r" }, { wsf, "f" }, { wsv, "v" }, { wst, "t" }, + { wsg, "g" }, { wsb, "b" }, { wsy, "y" }, { wsh, "h" }, { wsn, "n" }, { wsu, "u" }, + { wsj, "j" }, { wsm, "m" }, { wsi, "i" }, { wsk, "k" }, { wso, "o" }, { wsl, "l" }, + { wsp, "p" }, { wsc, "c" }, + + { wsQ, "Q" }, { wsA, "A" }, { wsZ, "Z" }, { wsW, "W" }, { wsS, "S" }, { wsX, "X" }, + { wsE, "E" }, { wsD, "D" }, { wsR, "R" }, { wsF, "F" }, { wsV, "V" }, { wsT, "T" }, + { wsG, "G" }, { wsB, "B" }, { wsY, "Y" }, { wsH, "H" }, { wsN, "N" }, { wsU, "U" }, + { wsJ, "J" }, { wsM, "M" }, { wsI, "I" }, { wsK, "K" }, { wsO, "O" }, { wsL, "L" }, + { wsP, "P" }, { wsC, "C" }, + + { wsUp, "Up" }, { wsDown, "Down" }, { wsLeft, "Left" }, + { wsRight, "Right" }, { wsPageUp, "PageUp" }, { wsPageDown, "PageDown" }, + + { wsLeftCtrl, "LeftCtrl" }, { wsRightCtrl, "RightCtrl" }, { wsLeftAlt, "LeftAlt" }, + { wsRightAlt, "RightAlt" }, { wsLeftShift, "LeftShift" }, { wsRightShift, "RightShift" }, + + + { wsBackSpace, "BackSpace" }, + { wsCapsLock, "CapsLock" }, + { wsNumLock, "NumLock" }, + + { wsF1, "F1" }, { wsF2, "F2" }, { wsF3, "F3" }, { wsF4, "F4" }, { wsF5, "F5" }, + { wsF6, "F6" }, { wsF7, "F7" }, { wsF8, "F8" }, { wsF9, "F9" }, { wsF10, "F10" }, + { wsF11, "F11" }, { wsF12, "F12" }, + + { wsEnter, "Enter" }, { wsTab, "Tab" }, { wsSpace, "Space" }, + { wsInsert, "Insert" }, { wsDelete, "Delete" }, { wsHome, "Home" }, + { wsEnd, "End" }, { wsEscape, "Escape" }, + + { wsosbrackets, "[" }, { wscsbrackets, "]" }, + { wsMore, "<" }, { wsLess, ">" }, + { wsMinus, "-" }, { wsPlus, "+" }, + { wsMul, "*" }, { wsDiv, "/" }, + + { ws0, "0" }, { ws1, "1" }, { ws2, "2" }, { ws3, "3" }, { ws4, "4" }, + { ws5, "5" }, { ws6, "6" }, { ws7, "7" }, { ws8, "8" }, { ws9, "9" }, + + { wsGrayEnter, "GrayEnter" }, { wsGrayPlus, "GrayPlus" }, + { wsGrayMinus, "GrayMinus" }, { wsGrayMul, "GrayMul" }, + { wsGrayDiv, "GrayDiv" }, { wsGrayInsert, "GrayInsert" }, + { wsGrayDelete, "GrayDelete" }, { wsGrayEnd, "GrayEnd" }, + { wsGrayDown, "GrayDown" }, { wsGrayPageDown, "GrayPageDown" }, + { wsGrayLeft, "GrayLeft" }, { wsGray5, "Gray5" }, + { wsGrayRight, "GrayRight" }, { wsGrayHome, "GrayHome" }, + { wsGrayUp, "GrayUp" }, { wsGrayPageUp, "GrayPageUp" }, + + { wsXF86LowerVolume, "XF86LowerVolume" }, + { wsXF86RaiseVolume, "XF86RaiseVolume" }, + { wsXF86Mute, "XF86Mute" }, + { wsXF86Play, "XF86Play" }, + { wsXF86Stop, "XF86Stop" }, + { wsXF86Prev, "XF86Prev" }, + { wsXF86Next, "XF86Next" }, + { wsXF86Media, "XF86Media" }, + + { wsKeyNone, "None" } + }; diff --git a/gui/wm/wsxdnd.c b/gui/wm/wsxdnd.c new file mode 100644 index 0000000000..5fa1c91744 --- /dev/null +++ b/gui/wm/wsxdnd.c @@ -0,0 +1,242 @@ +/* Took WindowMaker implementation and adopted for MPlayer */ + + +#include +#include "ws.h" +#include "wsxdnd.h" + +#include +#include +#include + +#include + +#include "../mp_msg.h" +#include "../help_mp.h" + +#define XDND_VERSION 3L + +Atom _XA_XdndAware; +Atom _XA_XdndEnter; +Atom _XA_XdndLeave; +Atom _XA_XdndDrop; +Atom _XA_XdndPosition; +Atom _XA_XdndStatus; +Atom _XA_XdndActionCopy; +Atom _XA_XdndSelection; +Atom _XA_XdndFinished; +Atom _XA_XdndTypeList; + +Atom atom_support; + +void wsXDNDInitialize(void) +{ + + _XA_XdndAware = XInternAtom(wsDisplay, "XdndAware", False); + _XA_XdndEnter = XInternAtom(wsDisplay, "XdndEnter", False); + _XA_XdndLeave = XInternAtom(wsDisplay, "XdndLeave", False); + _XA_XdndDrop = XInternAtom(wsDisplay, "XdndDrop", False); + _XA_XdndPosition = XInternAtom(wsDisplay, "XdndPosition", False); + _XA_XdndStatus = XInternAtom(wsDisplay, "XdndStatus", False); + _XA_XdndActionCopy = XInternAtom(wsDisplay, "XdndActionCopy", False); + _XA_XdndSelection = XInternAtom(wsDisplay, "XdndSelection", False); + _XA_XdndFinished = XInternAtom(wsDisplay, "XdndFinished", False); + _XA_XdndTypeList = XInternAtom(wsDisplay, "XdndTypeList", False); +} + +void wsXDNDMakeAwareness(wsTWindow* window) { + long int xdnd_version = XDND_VERSION; + XChangeProperty (wsDisplay, window->WindowID, _XA_XdndAware, XA_ATOM, + 32, PropModeAppend, (char *)&xdnd_version, 1); +} + +void wsXDNDClearAwareness(wsTWindow* window) { + XDeleteProperty (wsDisplay, window->WindowID, _XA_XdndAware); +} + +#define MAX_DND_FILES 64 +Bool +wsXDNDProcessSelection(wsTWindow* wnd, XEvent *event) +{ + Atom ret_type; + int ret_format; + unsigned long ret_items; + unsigned long remain_byte; + char * delme; + XEvent xevent; + + Window selowner = XGetSelectionOwner(wsDisplay,_XA_XdndSelection); + + XGetWindowProperty(wsDisplay, event->xselection.requestor, + event->xselection.property, + 0, 65536, True, atom_support, &ret_type, &ret_format, + &ret_items, &remain_byte, (unsigned char **)&delme); + + /*send finished*/ + memset (&xevent, 0, sizeof(xevent)); + xevent.xany.type = ClientMessage; + xevent.xany.display = wsDisplay; + xevent.xclient.window = selowner; + xevent.xclient.message_type = _XA_XdndFinished; + xevent.xclient.format = 32; + XDND_FINISHED_TARGET_WIN(&xevent) = wnd->WindowID; + XSendEvent(wsDisplay, selowner, 0, 0, &xevent); + + if (!delme){ + mp_msg( MSGT_GPLAYER,MSGL_WARN,MSGTR_WS_DDNothing ); + return False; + } + + { + /* Handle dropped files */ + char * retain = delme; + char * files[MAX_DND_FILES]; + int num = 0; + + while(retain < delme + ret_items) { + if (!strncmp(retain,"file:",5)) { + /* add more 2 chars while removing 5 is harmless */ + retain+=5; + } + + /* add the "retain" to the list */ + files[num++]=retain; + + + /* now check for special characters */ + { + int newone = 0; + while(retain < (delme + ret_items)){ + if(*retain == '\r' || *retain == '\n'){ + *retain=0; + newone = 1; + } else { + if (newone) + break; + } + retain++; + } + } + + if (num >= MAX_DND_FILES) + break; + } + + /* Handle the files */ + if(wnd->DandDHandler){ + wnd->DandDHandler(num,files); + } + } + + free(delme); + return True; +} + +Bool +wsXDNDProcessClientMessage(wsTWindow* wnd, XClientMessageEvent *event) +{ + /* test */ + /*{ + char * name = XGetAtomName(wsDisplay, event->message_type); + printf("Got %s\n",name); + XFree(name); + }*/ + + if (event->message_type == _XA_XdndEnter) { + Atom ok = XInternAtom(wsDisplay, "text/uri-list", False); + atom_support = None; + if ((event->data.l[1] & 1) == 0){ + int index; + for(index = 0; index <= 2 ; index++){ + if (event->data.l[2+index] == ok) { + atom_support = ok; + } + } + if (atom_support == None) { + mp_msg( MSGT_GPLAYER,MSGL_WARN,MSGTR_WS_NotAFile ); + } + } else { + /* need to check the whole list here */ + unsigned long ret_left = 1; + int offset = 0; + Atom* ret_buff; + Atom ret_type; + int ret_format; + unsigned long ret_items; + + /* while there is data left...*/ + while(ret_left && atom_support == None){ + XGetWindowProperty(wsDisplay,event->data.l[0],_XA_XdndTypeList, + offset,256,False,XA_ATOM,&ret_type, + &ret_format,&ret_items,&ret_left, + (unsigned char**)&ret_buff); + + /* sanity checks...*/ + if(ret_buff == NULL || ret_type != XA_ATOM || ret_format != 8*sizeof(Atom)){ + XFree(ret_buff); + break; + } + /* now chek what we've got */ + { + int i; + for(i=0; imessage_type == _XA_XdndLeave) { + return True; + } + + if (event->message_type == _XA_XdndDrop) { + if (event->data.l[0] != XGetSelectionOwner(wsDisplay, _XA_XdndSelection)){ + puts("Wierd selection owner... QT?"); + } + if (atom_support != None) { + XConvertSelection(wsDisplay, _XA_XdndSelection, atom_support, + _XA_XdndSelection, event->window, + CurrentTime); + } + return True; + } + + if (event->message_type == _XA_XdndPosition) { + Window srcwin = event->data.l[0]; + if (atom_support == None){ + return True; + } + + /* send response */ + { + XEvent xevent; + memset (&xevent, 0, sizeof(xevent)); + xevent.xany.type = ClientMessage; + xevent.xany.display = wsDisplay; + xevent.xclient.window = srcwin; + xevent.xclient.message_type = _XA_XdndStatus; + xevent.xclient.format = 32; + + XDND_STATUS_TARGET_WIN (&xevent) = event->window; + XDND_STATUS_WILL_ACCEPT_SET (&xevent, True); + XDND_STATUS_WANT_POSITION_SET(&xevent, True); + /* actually need smth real here */ + XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768); + XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy; + + XSendEvent(wsDisplay, srcwin, 0, 0, &xevent); + } + return True; + } + + return False; +} diff --git a/gui/wm/wsxdnd.h b/gui/wm/wsxdnd.h new file mode 100644 index 0000000000..7fe3c3fd77 --- /dev/null +++ b/gui/wm/wsxdnd.h @@ -0,0 +1,53 @@ + +#ifndef _XDND_H_ +#define _XDND_H_ + + +void wsXDNDInitialize(void); +Bool wsXDNDProcessSelection(wsTWindow* wnd,XEvent *event); +Bool wsXDNDProcessClientMessage(wsTWindow* wnd, XClientMessageEvent *event); +void wsXDNDMakeAwareness(wsTWindow* window); +void wsXDNDClearAwareness(wsTWindow* window); + +/* header was ripped from xdnd's example on its page */ + +#define XDND_THREE 3 +#define XDND_ENTER_SOURCE_WIN(e) ((e)->xclient.data.l[0]) +#define XDND_ENTER_THREE_TYPES(e) (((e)->xclient.data.l[1] & 0x1UL) == 0) +#define XDND_ENTER_THREE_TYPES_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x1UL) | (((b) == 0) ? 0 : 0x1UL) +#define XDND_ENTER_VERSION(e) ((e)->xclient.data.l[1] >> 24) +#define XDND_ENTER_VERSION_SET(e,v) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~(0xFF << 24)) | ((v) << 24) +#define XDND_ENTER_TYPE(e,i) ((e)->xclient.data.l[2 + (i)]) /* i => (0, 1, 2) */ + +/* XdndPosition */ +#define XDND_POSITION_SOURCE_WIN(e) ((e)->xclient.data.l[0]) +#define XDND_POSITION_ROOT_X(e) ((e)->xclient.data.l[2] >> 16) +#define XDND_POSITION_ROOT_Y(e) ((e)->xclient.data.l[2] & 0xFFFFUL) +#define XDND_POSITION_ROOT_SET(e,x,y) (e)->xclient.data.l[2] = ((x) << 16) | ((y) & 0xFFFFUL) +#define XDND_POSITION_TIME(e) ((e)->xclient.data.l[3]) +#define XDND_POSITION_ACTION(e) ((e)->xclient.data.l[4]) + +/* XdndStatus */ +#define XDND_STATUS_TARGET_WIN(e) ((e)->xclient.data.l[0]) +#define XDND_STATUS_WILL_ACCEPT(e) ((e)->xclient.data.l[1] & 0x1L) +#define XDND_STATUS_WILL_ACCEPT_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x1UL) | (((b) == 0) ? 0 : 0x1UL) +#define XDND_STATUS_WANT_POSITION(e) ((e)->xclient.data.l[1] & 0x2UL) +#define XDND_STATUS_WANT_POSITION_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x2UL) | (((b) == 0) ? 0 : 0x2UL) +#define XDND_STATUS_RECT_X(e) ((e)->xclient.data.l[2] >> 16) +#define XDND_STATUS_RECT_Y(e) ((e)->xclient.data.l[2] & 0xFFFFL) +#define XDND_STATUS_RECT_WIDTH(e) ((e)->xclient.data.l[3] >> 16) +#define XDND_STATUS_RECT_HEIGHT(e) ((e)->xclient.data.l[3] & 0xFFFFL) +#define XDND_STATUS_RECT_SET(e,x,y,w,h) {(e)->xclient.data.l[2] = ((x) << 16) | ((y) & 0xFFFFUL); (e)->xclient.data.l[3] = ((w) << 16) | ((h) & 0xFFFFUL); } +#define XDND_STATUS_ACTION(e) ((e)->xclient.data.l[4]) + +/* XdndLeave */ +#define XDND_LEAVE_SOURCE_WIN(e) ((e)->xclient.data.l[0]) + +/* XdndDrop */ +#define XDND_DROP_SOURCE_WIN(e) ((e)->xclient.data.l[0]) +#define XDND_DROP_TIME(e) ((e)->xclient.data.l[2]) + +/* XdndFinished */ +#define XDND_FINISHED_TARGET_WIN(e) ((e)->xclient.data.l[0]) + +#endif -- cgit v1.2.3