From 418dbef6efa7efd9ccd76bb1925f5eeaf5008b3e Mon Sep 17 00:00:00 2001 From: pontscho Date: Sun, 11 Aug 2002 13:12:38 +0000 Subject: add xdnd support (from Gregory Kovriga ) and fix -subdelay bug git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6968 b3059339-0415-0410-9bf9-f77b7e298cf2 --- Gui/Makefile | 2 +- Gui/interface.c | 1 + Gui/mplayer/mplayer.c | 8 ++ Gui/mplayer/mw.h | 42 +++++++++++ Gui/mplayer/play.c | 7 +- Gui/wm/ws.c | 13 +++- Gui/wm/ws.h | 4 +- Gui/wm/wsxdnd.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++ Gui/wm/wsxdnd.h | 53 +++++++++++++ 9 files changed, 329 insertions(+), 6 deletions(-) create mode 100644 Gui/wm/wsxdnd.c create mode 100644 Gui/wm/wsxdnd.h diff --git a/Gui/Makefile b/Gui/Makefile index e165d63edf..6fab07f1c2 100644 --- a/Gui/Makefile +++ b/Gui/Makefile @@ -14,7 +14,7 @@ endif CFLAGS = $(OPTIMIZE) $(INCDIR) $(DEBUG) -SRCS = wm/ws.c wm/wsconv.c app.c events.c interface.c cfg.c \ +SRCS = wm/ws.c wm/wsconv.c wm/wsxdnd.c app.c events.c interface.c cfg.c \ bitmap/bitmap.c bitmap/tga/tga.c bitmap/bmp/bmp.c bitmap/png/png.c \ skin/skin.c skin/font.c skin/cut.c \ mplayer/mplayer.c mplayer/widgets.c mplayer/play.c \ diff --git a/Gui/interface.c b/Gui/interface.c index e6eba8e23b..96b594b66c 100644 --- a/Gui/interface.c +++ b/Gui/interface.c @@ -93,6 +93,7 @@ void guiInit( void ) appInit( (void*)mDisplay ); if ( plCurrent && !filename ) mplSetFileName( plCurrent->path,plCurrent->name ); + if ( sub_delay > 0.0f ) gtkSubDelay=sub_delay; #if defined( USE_OSD ) || defined( USE_SUB ) guiLoadFont(); #endif diff --git a/Gui/mplayer/mplayer.c b/Gui/mplayer/mplayer.c index 68c5a18815..90f33a82be 100644 --- a/Gui/mplayer/mplayer.c +++ b/Gui/mplayer/mplayer.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include "./mplayer.h" #include "../events.h" @@ -14,6 +17,7 @@ #include "../wm/ws.h" #include "../wm/wskeys.h" #include "../wm/widget.h" +#include "../wm/wsxdnd.h" #include "../bitmap/bitmap.h" #include "../../config.h" @@ -71,6 +75,7 @@ void mplInit( void * disp ) wsDestroyImage( &appMPlayer.subWindow ); wsCreateImage( &appMPlayer.subWindow,appMPlayer.sub.Bitmap.Width,appMPlayer.sub.Bitmap.Height ); + wsXDNDMakeAwareness(&appMPlayer.subWindow); vo_setwindow( appMPlayer.subWindow.WindowID, appMPlayer.subWindow.wGC ); @@ -82,6 +87,7 @@ void mplInit( void * disp ) wsNoBorder,wsShowMouseCursor|wsHandleMouseButton|wsHandleMouseMove,i,"MPlayer" ); //wsMinSize| wsSetShape( &appMPlayer.mainWindow,appMPlayer.main.Mask.Image ); + wsXDNDMakeAwareness(&appMPlayer.mainWindow); mplMenuInit(); @@ -94,10 +100,12 @@ void mplInit( void * disp ) appMPlayer.mainWindow.ReDraw=mplMainDraw; appMPlayer.mainWindow.MouseHandler=mplMainMouseHandle; appMPlayer.mainWindow.KeyHandler=mplMainKeyHandle; + appMPlayer.mainWindow.DandDHandler=mplDandDHandler; appMPlayer.subWindow.ReDraw=mplSubDraw; appMPlayer.subWindow.MouseHandler=mplSubMouseHandle; appMPlayer.subWindow.KeyHandler=mplMainKeyHandle; + appMPlayer.subWindow.DandDHandler=mplDandDHandler; wsSetBackgroundRGB( &appMPlayer.subWindow,appMPlayer.subR,appMPlayer.subG,appMPlayer.subB ); wsClearWindow( appMPlayer.subWindow ); diff --git a/Gui/mplayer/mw.h b/Gui/mplayer/mw.h index 3bc29c01fd..bf86bd8edd 100644 --- a/Gui/mplayer/mw.h +++ b/Gui/mplayer/mw.h @@ -650,3 +650,45 @@ void mplMainKeyHandle( int KeyCode,int Type,int Key ) } if ( msg != evNone ) mplEventHandling( msg,0 ); } + +/* this will be used to handle Drag&Drop files */ +void mplDandDHandler(int num,const char** files) +{ + struct stat buf; + int f = 0; + + if (num <= 0) + return; + + /* clear playlist */ + gtkSet(gtkDelPl,0,NULL); + + /* now fill it with new items */ + for(f=0; f < num; f++){ + char* str = files[f]; + plItem* item; + if(stat(str,&buf) == 0 && S_ISDIR(buf.st_mode) == 0) { + /* this is not a directory so try to play it */ + printf("Received D&D %s\n",str); + item = calloc(1,sizeof(plItem)); + /* FIXME: decompose file name ? */ + /* yes -- Pontscho */ + if ( strrchr( str,'/' ) ) + { + char * t = strdup( str ); + char * s = strrchr( t,'/' ); *s=0; s++; + item->name = gstrdup( s ); + item->path = gstrdup( t ); + free( t ); + } else { item->name = strdup(str); item->path = strdup(""); } + gtkSet(gtkAddPlItem,0,(void*)item); + } else { + printf("Received not a file: %s !\n",str); + } + } + + mplSetFileName( NULL,files[0] ); + if ( guiIntfStruct.Playing == 1 ) mplEventHandling( evStop,0 ); + mplEventHandling( evPlay,0 ); + +} diff --git a/Gui/mplayer/play.c b/Gui/mplayer/play.c index 2c547a44a8..1f5d71495e 100644 --- a/Gui/mplayer/play.c +++ b/Gui/mplayer/play.c @@ -246,8 +246,11 @@ void ChangeSkin( char * name ) void mplSetFileName( char * dir,char * name ) { - if ( !name || !dir ) return; - guiSetDF( guiIntfStruct.Filename,dir,name ); + if ( !name ) return; + + if ( !dir ) guiSetFilename( guiIntfStruct.Filename,name ) + else guiSetDF( guiIntfStruct.Filename,dir,name ) + guiIntfStruct.StreamType=STREAMTYPE_FILE; guiIntfStruct.FilenameChanged=1; gfree( (void **)&guiIntfStruct.AudioFile ); diff --git a/Gui/wm/ws.c b/Gui/wm/ws.c index f67a1fa108..e8128ffe7a 100644 --- a/Gui/wm/ws.c +++ b/Gui/wm/ws.c @@ -21,6 +21,7 @@ #include "../../config.h" #include "ws.h" #include "wsconv.h" +#include "wsxdnd.h" #include "../../postproc/rgb2rgb.h" #include "../../mp_msg.h" #include "../../mplayer.h" @@ -227,6 +228,9 @@ if(mDisplay){ } } +/* enable DND atoms */ +wsXDNDInitialize(); + { /* on remote display XShm will be disabled - LGB */ char *dispname=DisplayString(wsDisplay); int localdisp=1; @@ -557,7 +561,10 @@ Bool wsEvents( Display * display,XEvent * Event,XPointer arg ) { i=wsWindowFocusIn; wsWindowList[l]->Focused=wsFocused; goto expose; } if ( Event->xclient.data.l[0] == wsWindowList[l]->AtomRolle ) { mp_msg( MSGT_GPLAYER,MSGL_STATUS,"[ws] rolled.\n" ); } - } + } else { + /* try to process DND events */ + wsXDNDProcessClientMessage(wsWindowList[l],&Event->xclient); + } break; case MapNotify: i=wsWindowMapped; wsWindowList[l]->Mapped=wsMapped; goto expose; @@ -681,6 +688,10 @@ buttonreleased: } break; + case SelectionNotify: + /* Handle DandD */ + wsXDNDProcessSelection(wsWindowList[l],Event); + break; } XFlush( wsDisplay ); XSync( wsDisplay,False ); diff --git a/Gui/wm/ws.h b/Gui/wm/ws.h index 3b22de8978..332abdcbf1 100644 --- a/Gui/wm/ws.h +++ b/Gui/wm/ws.h @@ -100,7 +100,7 @@ typedef void (*wsTReSize)( unsigned int X,unsigned int Y,unsigned int width,un 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 (*wsRemoteHandler)( char * str ); +typedef void (*wsTDNDHandler)( int num,char ** str ); typedef struct { @@ -128,7 +128,7 @@ typedef struct wsTIdle Idle; wsTKeyHandler KeyHandler; wsTMouseHandler MouseHandler; - wsRemoteHandler RemoteHandler; + wsTDNDHandler DandDHandler; int Alt; int Shift; diff --git a/Gui/wm/wsxdnd.c b/Gui/wm/wsxdnd.c new file mode 100644 index 0000000000..90c2e95e97 --- /dev/null +++ b/Gui/wm/wsxdnd.c @@ -0,0 +1,205 @@ +/* Took WindowMaker implementation and adopted for MPlayer */ + + +#include +#include "ws.h" +#include "wsxdnd.h" + +#include +#include + +#include + + +#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 atom_support; + +void wsXDNDInitialize() +{ + + _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); +} + +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){ + printf("D&D: Nothing returned!\n"); + return False; + } + + { + /* Handle dropped files */ + char * retain = delme; + char * files[MAX_DND_FILES]; + int num = 0; + /* + printf("Got: %s\n",delme); + */ + 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); +} + +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) { + printf("This doesn't seem as a file...\n"); + } + } else { + /* FIXME: need something else here */ + } + return True; + } + + if (event->message_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..8d88aeacdc --- /dev/null +++ b/Gui/wm/wsxdnd.h @@ -0,0 +1,53 @@ + +#ifndef _XDND_H_ +#define _XDND_H_ + + +void wsXDNDInitialize(); +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