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/wm/ws.c | 13 +++- Gui/wm/ws.h | 4 +- Gui/wm/wsxdnd.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Gui/wm/wsxdnd.h | 53 +++++++++++++++ 4 files changed, 272 insertions(+), 3 deletions(-) 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 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