changeset 6967:0fa27966ac47

add xdnd support (from Gregory Kovriga <gkovriga@techunix.technion.ac.il>) and fix -subdelay bug
author pontscho
date Sun, 11 Aug 2002 13:12:38 +0000
parents 2994bd73f35d
children c8716f1c8965
files Gui/Makefile Gui/interface.c Gui/mplayer/mplayer.c Gui/mplayer/mw.h Gui/mplayer/play.c Gui/wm/ws.c Gui/wm/ws.h Gui/wm/wsxdnd.c Gui/wm/wsxdnd.h
diffstat 9 files changed, 329 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/Gui/Makefile	Sun Aug 11 10:52:22 2002 +0000
+++ b/Gui/Makefile	Sun Aug 11 13:12:38 2002 +0000
@@ -14,7 +14,7 @@
 
 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 \
--- a/Gui/interface.c	Sun Aug 11 10:52:22 2002 +0000
+++ b/Gui/interface.c	Sun Aug 11 13:12:38 2002 +0000
@@ -93,6 +93,7 @@
  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
--- a/Gui/mplayer/mplayer.c	Sun Aug 11 10:52:22 2002 +0000
+++ b/Gui/mplayer/mplayer.c	Sun Aug 11 13:12:38 2002 +0000
@@ -3,6 +3,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #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 @@
 
  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 @@
   wsNoBorder,wsShowMouseCursor|wsHandleMouseButton|wsHandleMouseMove,i,"MPlayer" ); //wsMinSize|
 
  wsSetShape( &appMPlayer.mainWindow,appMPlayer.main.Mask.Image );
+ wsXDNDMakeAwareness(&appMPlayer.mainWindow);
 
  mplMenuInit();
 
@@ -94,10 +100,12 @@
  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 );
--- a/Gui/mplayer/mw.h	Sun Aug 11 10:52:22 2002 +0000
+++ b/Gui/mplayer/mw.h	Sun Aug 11 13:12:38 2002 +0000
@@ -650,3 +650,45 @@
    }
  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 );
+
+}
--- a/Gui/mplayer/play.c	Sun Aug 11 10:52:22 2002 +0000
+++ b/Gui/mplayer/play.c	Sun Aug 11 13:12:38 2002 +0000
@@ -246,8 +246,11 @@
 
 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 );
--- a/Gui/wm/ws.c	Sun Aug 11 10:52:22 2002 +0000
+++ b/Gui/wm/ws.c	Sun Aug 11 13:12:38 2002 +0000
@@ -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 @@
   }
 }
 
+/* enable DND atoms */
+wsXDNDInitialize();
+ 
 { /* on remote display XShm will be disabled - LGB */
  char *dispname=DisplayString(wsDisplay);
  int localdisp=1;
@@ -557,7 +561,10 @@
            { 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 @@
 	}
         break;
 
+   case SelectionNotify:
+     /* Handle DandD */
+     wsXDNDProcessSelection(wsWindowList[l],Event);
+     break;
   }
  XFlush( wsDisplay );
  XSync( wsDisplay,False );
--- a/Gui/wm/ws.h	Sun Aug 11 10:52:22 2002 +0000
+++ b/Gui/wm/ws.h	Sun Aug 11 13:12:38 2002 +0000
@@ -100,7 +100,7 @@
 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 @@
  wsTIdle              Idle;
  wsTKeyHandler        KeyHandler;
  wsTMouseHandler      MouseHandler;
- wsRemoteHandler      RemoteHandler;
+ wsTDNDHandler        DandDHandler;
 
  int                  Alt;
  int                  Shift;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Gui/wm/wsxdnd.c	Sun Aug 11 13:12:38 2002 +0000
@@ -0,0 +1,205 @@
+/* Took WindowMaker implementation and adopted for MPlayer */
+
+
+#include <X11/Xlib.h>
+#include "ws.h"
+#include "wsxdnd.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xatom.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 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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Gui/wm/wsxdnd.h	Sun Aug 11 13:12:38 2002 +0000
@@ -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