mirror of
https://github.com/mpv-player/mpv
synced 2025-01-01 04:36:24 +01:00
add xdnd support (from Gregory Kovriga <gkovriga@techunix.technion.ac.il>) and fix -subdelay bug
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6968 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
0f7ec7d885
commit
418dbef6ef
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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 @@ 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 );
|
||||
|
@ -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 );
|
||||
|
||||
}
|
||||
|
@ -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 );
|
||||
|
13
Gui/wm/ws.c
13
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 );
|
||||
|
@ -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;
|
||||
|
205
Gui/wm/wsxdnd.c
Normal file
205
Gui/wm/wsxdnd.c
Normal file
@ -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;
|
||||
}
|
53
Gui/wm/wsxdnd.h
Normal file
53
Gui/wm/wsxdnd.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user