From a4251277618cd97bed4a96acbca7fd217118f421 Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Wed, 27 Apr 2022 15:13:30 +0200 Subject: [PATCH 01/10] WIP --- src/FSFileView.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/src/FSFileView.c b/src/FSFileView.c index 51533d5..1dd026d 100644 --- a/src/FSFileView.c +++ b/src/FSFileView.c @@ -808,6 +808,9 @@ handleShelfButtonDrag(XEvent* ev, void* clientData) FSFileIcon* fileIcon = (FSFileIcon*)clientData; FileInfo* fileInfo = FSGetFileButtonFileInfo(fileIcon->btn); + wwarning("DRAG HANDLER"); + // WMIsDraggingFromView(ev->) + if (!DragStarted) return; @@ -880,6 +883,65 @@ FSReorganiseShelf(FSFileView* fView) } } +// typedef struct W_DragSourceProcs { +// WMArray* (*dropDataTypes)(WMView* self); +// WMDragOperationType (*wantedDropOperation)(WMView* self); +// WMArray* (*askedOperations)(WMView* self); +// Bool (*acceptDropOperation)(WMView* self, WMDragOperationType operation); +// void (*beganDrag)(WMView* self, WMPoint* point); +// void (*endedDrag)(WMView* self, WMPoint* point, Bool deposited); +// WMData* (*fetchDragData)(WMView* self, char* type); +// /*Bool (*ignoreModifierKeysWhileDragging)(WMView *view);*/ +// } WMDragSourceProcs; + +void BeganDrag(WMView* self, WMPoint* point) +{ + wwarning("Began drag"); +} + +void EndedDrag(WMView* self, WMPoint* point, Bool deposited) +{ + wwarning("Ended drag, deposited: %s", deposited ? "YES" : "NO"); +} + +void FetchDragData(WMView* self, char* type) +{ + wwarning("Somebody requested drag data of type %s", type); +} + +static WMArray* dataTypes = NULL; + +WMArray* DropDataTypes(WMView* self) +{ + wwarning("supported data types requested"); + if (!dataTypes) { + dataTypes = WMCreateArray(1); + WMSetInArray(dataTypes, 0, &("text/uri-list")); + } + return dataTypes; +} + +WMDragOperationType WantedDropOperation(WMView* self) +{ + return WDOperationCopy; +} + +WMDragSourceProcs* CreateDragSourceProcs(FileInfo* fileInfo, FSFileIcon* fileIcon) +{ + wwarning("Creating drag source procs for %s%s", fileInfo->path, fileInfo->name); + + WMDragSourceProcs* r = wmalloc(sizeof(WMDragSourceProcs)); + // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation + r->askedOperations = NULL; + r->beganDrag = BeganDrag; + r->dropDataTypes = DropDataTypes; + r->endedDrag = EndedDrag; + r->fetchDragData = FetchDragData; + r->wantedDropOperation = WantedDropOperation; + + return r; +} + /* * FSAddFileViewShelfItem: * Create a fileIcon, add it to FileView->fileIcons @@ -909,8 +971,15 @@ FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo) WMMapWidget(fileIcon->btn); /* Drag'n'Drop */ - DndRegisterDropWidget(fileIcon->btn, handleShelfButtonDrop, fileIcon); - DndRegisterDragWidget(fileIcon->btn, handleShelfButtonDrag, fileIcon); + // DndRegisterDropWidget(fileIcon->btn, handleShelfButtonDrop, fileIcon); + // DndRegisterDragWidget(fileIcon->btn, handleShelfButtonDrag, fileIcon); + + WMPixmap* dragImg = FSCreateBlurredPixmapFromFile(WMWidgetScreen(fileIcon->btn), fileInfo->imgName); + WMDragSourceProcs* procs = CreateDragSourceProcs(fileInfo, fileIcon); + CreateDragSourceProcs(fileInfo, fileIcon); + WMSetViewDraggable(W_VIEW(fileIcon->btn), procs, dragImg); + WMReleasePixmap(dragImg); + wfree(procs); /* Add the new Btn to the fileIcon linked list */ if (fView->fileIcons == NULL) From 846327483dfc0a493f940adc265205867e2a5054 Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Wed, 27 Apr 2022 17:16:01 +0200 Subject: [PATCH 02/10] Basic dragging working --- src/FSFileView.c | 27 ++++++++++++++++++++------- src/FSFileView.h | 1 + src/FSPathView.c | 13 +++++++++++-- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/FSFileView.c b/src/FSFileView.c index 1dd026d..2751e51 100644 --- a/src/FSFileView.c +++ b/src/FSFileView.c @@ -904,9 +904,19 @@ void EndedDrag(WMView* self, WMPoint* point, Bool deposited) wwarning("Ended drag, deposited: %s", deposited ? "YES" : "NO"); } -void FetchDragData(WMView* self, char* type) +WMData* FetchDragData(WMView* self, char* type) { wwarning("Somebody requested drag data of type %s", type); + WMWidget*btn = WMWidgetOfView(self); + FileInfo* fileInfo = FSGetFileButtonFileInfo(btn); + + // TODO + char buf[1024+1]; + snprintf(buf, 1024, "file://%s%s\r\n", fileInfo->path, fileInfo->name); + + wwarning(buf); + + return WMCreateDataWithBytes(buf, strlen(buf)); } static WMArray* dataTypes = NULL; @@ -921,16 +931,20 @@ WMArray* DropDataTypes(WMView* self) return dataTypes; } +Bool AcceptDropOperation(WMView *self, WMDragOperationType operation) { + return True; +} + WMDragOperationType WantedDropOperation(WMView* self) { return WDOperationCopy; } -WMDragSourceProcs* CreateDragSourceProcs(FileInfo* fileInfo, FSFileIcon* fileIcon) +WMDragSourceProcs* CreateDragSourceProcs() { - wwarning("Creating drag source procs for %s%s", fileInfo->path, fileInfo->name); - - WMDragSourceProcs* r = wmalloc(sizeof(WMDragSourceProcs)); + WMDragSourceProcs *r = wmalloc(sizeof(WMDragSourceProcs)); + memset(r, 0, sizeof(WMDragSourceProcs)); + r->acceptDropOperation = AcceptDropOperation; // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation r->askedOperations = NULL; r->beganDrag = BeganDrag; @@ -975,8 +989,7 @@ FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo) // DndRegisterDragWidget(fileIcon->btn, handleShelfButtonDrag, fileIcon); WMPixmap* dragImg = FSCreateBlurredPixmapFromFile(WMWidgetScreen(fileIcon->btn), fileInfo->imgName); - WMDragSourceProcs* procs = CreateDragSourceProcs(fileInfo, fileIcon); - CreateDragSourceProcs(fileInfo, fileIcon); + WMDragSourceProcs* procs = CreateDragSourceProcs(fileInfo); WMSetViewDraggable(W_VIEW(fileIcon->btn), procs, dragImg); WMReleasePixmap(dragImg); wfree(procs); diff --git a/src/FSFileView.h b/src/FSFileView.h index 64918e3..202cea8 100644 --- a/src/FSFileView.h +++ b/src/FSFileView.h @@ -63,5 +63,6 @@ void FSSetFileViewFilter(FSFileView* fView, char* filter); char* FSGetFileViewFilter(FSFileView* fView); void FSSetFileViewPath(FSFileView* fileView, char* path); void FSSetFileViewMode(FSFileView* fView, FSFileViewType mode); +WMDragSourceProcs* CreateDragSourceProcs(); #endif diff --git a/src/FSPathView.c b/src/FSPathView.c index 81238b3..2144f10 100644 --- a/src/FSPathView.c +++ b/src/FSPathView.c @@ -3,6 +3,7 @@ #include /* for : double rint (double) */ #include "FSFileButton.h" +#include "FSFileView.h" #include "FSPathView.h" #include "FSUtils.h" #include "FSViewer.h" @@ -702,8 +703,8 @@ int FSAddPathViewColumn(FSPathView* pvPtr) FSSetFileButtonAction(list, btnCallback, pvPtr); FSSetFileButtonDoubleAction(list, btnDoubleCallback, pvPtr); /* Drag'n'Drop */ - DndRegisterDropWidget(list, handlePVButtonDrop, list); - DndRegisterDragWidget(list, handlePVButtonDrag, list); + // DndRegisterDropWidget(list, handlePVButtonDrop, list); + // DndRegisterDragWidget(list, handlePVButtonDrag, list); WMHangData(list, pvPtr); pvPtr->columns[index] = list; @@ -822,6 +823,14 @@ void FSSetPathViewColumnContents(FSPathView* pvPtr, int column, if (backlight) FSSetFileButtonSelected(pvPtr->columns[column], 1); FSSetFileButtonSelected(pvPtr->columns[column - 1], 0); + + FSFileButton *btn = pvPtr->columns[column]; + FileInfo *fileInfo = FSGetFileInfo(FSGetFileButtonPathname(btn)); + WMPixmap* dragImg = FSCreateBlurredPixmapFromFile(WMWidgetScreen(btn), fileInfo->imgName); + WMDragSourceProcs* procs = CreateDragSourceProcs(); + WMSetViewDraggable(W_VIEW(btn), procs, dragImg); + WMReleasePixmap(dragImg); + wfree(procs); } } From ae00ce5be82a300babefcc7da02654119440e014 Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Thu, 28 Apr 2022 14:04:30 +0200 Subject: [PATCH 03/10] Dropping onto shelf working. --- src/DnD.c | 466 +++++++++++++++++---------------------------- src/DnD.h | 35 +--- src/FSFileButton.c | 5 + src/FSFileButton.h | 2 +- src/FSFileView.c | 266 ++++++++------------------ src/FSFileView.h | 6 +- src/FSPathView.c | 107 ++++------- src/FSUtils.c | 70 +++---- src/FSUtils.h | 2 +- 9 files changed, 345 insertions(+), 614 deletions(-) diff --git a/src/DnD.c b/src/DnD.c index 79c408a..e4c8ebc 100644 --- a/src/DnD.c +++ b/src/DnD.c @@ -1,20 +1,3 @@ -/* - Copyright (C) 1996 César Crusius - Copyright (C) 1999 Igor Roboul - WINGs adaptation - - This file is part of the DND Library. This library is free - software; you can redistribute it and/or modify it under the terms of - the GNU Library General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. This library is distributed in the hope - that it will be useful, but WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the GNU Library General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free Software - Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - */ - #include #include #include @@ -23,339 +6,240 @@ #include #include "DnD.h" +#include "FSFileButton.h" +#include "FSFileView.h" +#include "files.h" -/* #define DEBUG */ -/* Local variables */ - -static Display* dpy; /* current display */ -static XButtonEvent StartEvent; /* event that started the drag */ -static int DragPrecision; /* minimum dx,dy to start drag */ -static int Dragging; /* Drag state flag */ -static int DataOK; /* Non-zero if data registered */ -static Atom DndProtocol; /* ClientMessage identifier */ -static Atom DndSelection; /* For the data transfers */ -static Atom WM_STATE; /* Needed for icon stuff */ -static Window Target; /* Drop window */ -static WMWindow* MainWindow; /* Main window of application */ -static int DataType; /* Current drag data type */ -static int RootFlag; /* Non-zero if dropped on root */ -static WMEventProc* OtherDrop; /* Handler for non-registered widgets*/ -static XColor Black, White; /* For the cursors */ - -int DragStarted; - -static void DndDispatchEvent(XEvent* event, void* data); -static void slideView(WMView* view, int srcX, int srcY, int dstX, int dstY); - -/* Initialize Drag'n'Drop */ -void DndInitialize(WMWidget* w) +void BeganDrag(WMView* self, WMPoint* point) { - int screen, i; + wwarning("Began drag"); +} - dpy = (W_VIEW(w))->screen->display; +void EndedDrag(WMView* self, WMPoint* point, Bool deposited) +{ + if (deposited) { + // Ok, successful drag. Receiver will take care. + return; + } - DndProtocol = XInternAtom(dpy, "DndProtocol", False); - DndSelection = XInternAtom(dpy, "DndSelection", False); + FSFileButton* btn = (FSFileButton*)WMWidgetOfView(self); + if (WMWidgetClass(btn) != FileButtonWidgetClass()) { + return; + } - WMCreateEventHandler(W_VIEW(w), ClientMessageMask, - DndDispatchEvent, W_VIEW(w)); + // TODO: We (wrongly) assume this is a shelf FSFileButton + // that has its FSFileView attached. For FilePath's + // buttons, this is not true. + FSFileView* fView = (FSFileView*)WMGetHangedData(btn); + if (!fView) { + return; + } - MainWindow = (WMWindow*)((W_VIEW(w))->window); - OtherDrop = NULL; - Dragging = 0; - DragPrecision = 20; - DragStarted = 0; + FSFileViewRemoveFileButtonFromShelf(fView, btn); } -void DndRegisterOtherDrop(WMEventProc* handler) +WMData* FetchDragData(WMView* self, char* type) { - OtherDrop = handler; + wwarning("Somebody requested drag data of type %s", type); + + if (!self) { + return NULL; + } + + WMWidget* btn = WMWidgetOfView(self); + if (!btn) { + return NULL; + } + + FileInfo* fileInfo = FSGetFileButtonFileInfo(btn); + if (!fileInfo) { + return NULL; + } + + // TODO + char buf[2048 + 1]; + memset((void*)buf, 0, 2048 + 1); + snprintf(buf, 2048, "file://%s%s\r\n", fileInfo->path, fileInfo->name); + + wwarning(buf); + + return WMCreateDataWithBytes(buf, strlen(buf)); } -/* Update target widget info */ -static void -DndUpdateTargetProc(XEvent* event, void* data) +static WMArray* dataTypes = NULL; +WMArray* SupportedDataTypes() { - if (event->type == EnterNotify) - Target = event->xany.window; - else - Target = 0; + if (!dataTypes) { + dataTypes = WMCreateArray(1); + WMSetInArray(dataTypes, 0, &("text/uri-list")); + } + return dataTypes; } -/* Register widget as drop target */ -void DndRegisterDropWidget(WMWidget* w, WMEventProc* handler, void* data) +WMArray* DropDataTypes(WMView* self) { - WMCreateEventHandler(W_VIEW(w), EnterWindowMask | LeaveWindowMask, - DndUpdateTargetProc, data); - WMCreateEventHandler(W_VIEW(w), ClientMessageMask, handler, data); + wwarning("supported data types requested"); + return SupportedDataTypes(); } -/* Initializes the drag and rop structures. Binded to ButtonPress event - in registered drag widgets */ -static void -DndStartAction(XEvent* event, void* data) +Bool AcceptDropOperation(WMView* self, WMDragOperationType operation) { - if (event->type == ButtonRelease) { - DragStarted = 0; - return; - } - StartEvent = *((XButtonEvent*)event); - Dragging = 0; - DataOK = 0; - DragStarted = !DragStarted; -#ifdef DEBUG - fprintf(stderr, "Initializing DnD variables...\n"); - fprintf(stderr, "Root 0x%x Window 0x%x Subwindow 0x%x\n", - StartEvent.root, StartEvent.window, StartEvent.subwindow); -#endif + return True; } -/* Register widget as drag source */ -void DndRegisterDragWidget(WMWidget* w, WMEventProc* handler, void* data) +WMDragOperationType WantedDropOperation(WMView* self) { - WMCreateEventHandler(W_VIEW(w), ButtonPressMask | ButtonReleaseMask, DndStartAction, data); - WMCreateEventHandler(W_VIEW(w), ButtonMotionMask, handler, data); + return WDOperationCopy; } -/* Dispatch Drop events */ -/* Send Drop message to real drop target */ -static void -DndDispatchEvent(XEvent* event, void* data) +WMDragSourceProcs* CreateDragSourceProcs() { - if ((event->type != ClientMessage) || (event->xclient.message_type != DndProtocol)) - return; - - if (!Target && OtherDrop) /* Drop on non-registered widget */ - OtherDrop(event, data); - - if (WMWidgetXID(data) == Target) - return; + WMDragSourceProcs* r = wmalloc(sizeof(WMDragSourceProcs)); + memset((void*)r, 0, sizeof(WMDragSourceProcs)); + r->acceptDropOperation = AcceptDropOperation; + // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation + r->askedOperations = NULL; + r->beganDrag = BeganDrag; + r->dropDataTypes = DropDataTypes; + r->endedDrag = EndedDrag; + r->fetchDragData = FetchDragData; + r->wantedDropOperation = WantedDropOperation; + + return r; +} - event->xclient.window = Target; - XSendEvent(dpy, Target, False, NoEventMask, event); +void PrepareForDragOperation(WMView* self) +{ + wwarning("DROPZONE: Prepare for drag"); } -void DndGetData(unsigned char** Data, unsigned long* Size) +WMArray* RequiredDataTypes(WMView* self, WMDragOperationType request, + WMArray* sourceDataTypes) { - Window root = DefaultRootWindow(dpy); - - Atom ActualType; - int ActualFormat; - unsigned long RemainingBytes; - - XGetWindowProperty(dpy, root, DndSelection, - 0L, 1000000L, - False, AnyPropertyType, - &ActualType, &ActualFormat, - Size, &RemainingBytes, - Data); + wwarning("DROPZONE: supported data types requested"); + return SupportedDataTypes(); } -int DndDataType(XEvent* ev) +WMDragOperationType AllowedDropOperation(WMView* self, + WMDragOperationType request, + WMArray* sourceDataTypes) { - int Type; - - if (ev->xclient.message_type != DndProtocol) - return DndNotDnd; - Type = (int)(ev->xclient.data.l[0]); - if (Type >= DndEND) - Type = DndUnknown; - return Type; + wwarning("DROPZONE: allowed op %d? We'll answer with %d", request, WDOperationLink); + + return WDOperationLink; } -unsigned int -DndDragButtons(XEvent* event) +Bool InspectDropData(WMView* self, WMArray* dropData) { - if (event->xclient.message_type != DndProtocol) - return 0; - return (unsigned int)(event->xclient.data.l[1]); + wwarning("DROPZONE: Inspecting drop data"); + return True; } -void DndSetData(int Type, unsigned char* Data, unsigned long Size) +WMData* FirstNonNullDataItem(WMArray* array) { - Window root = DefaultRootWindow(dpy); - int AuxSize; + WMArrayIterator iter = 0; + WMData* data; - if (DataOK) - return; + WM_ITERATE_ARRAY(array, data, iter) + { + if (data) { + return data; + } + }; - /* Set the data type */ - DataType = Type >= DndEND ? 0 : Type; + return NULL; +} - /* Set the data */ - AuxSize = Size > INT_MAX ? INT_MAX : (int)Size; - XChangeProperty(dpy, root, DndSelection, XA_STRING, 8, - PropModeReplace, Data, AuxSize); +int Index(WMData* data, char ch) +{ + char* bytes = WMDataBytes(data); + unsigned int len = WMGetDataLength(data); - for (Size -= (unsigned long)AuxSize; Size; Size -= (unsigned long)AuxSize) { - Data += AuxSize; - AuxSize = Size > INT_MAX ? INT_MAX : (int)Size; - XChangeProperty(dpy, root, DndSelection, XA_STRING, 8, - PropModeAppend, Data, AuxSize); + for (int i = 0; i < len; i++) { + if (*(bytes + i) == ch) { + return i; + } } - /* Everything is now ok */ - DataOK = 1; + return -1; } -/* Handle dragging. This function must be called - from application drag handler */ -int DndHandleDragging(WMWidget* w, XEvent* event, WMPixmap* pixmap) +char* FirstPath(WMData* data) { - WMSize size; - WMView* dragView; - WMScreen* scr = WMWidgetScreen(w); - Display* dpy = WMScreenDisplay(scr); - /* WMPixmap *pixmap = NULL; */ - XEvent Event; - Window DispatchWindow; - Window root = DefaultRootWindow(dpy); - - if (!DragStarted) - return 0; - if (Dragging) { -#ifdef DEBUG - fprintf(stderr, "Dragging...\n"); -#endif - return 0; - } - if (abs(StartEvent.x_root - event->xmotion.x_root) < DragPrecision && abs(StartEvent.y_root - event->xmotion.y_root) < DragPrecision) { - return 0; + char* bytes = WMDataBytes(data); + unsigned int len = WMGetDataLength(data); + + if (len < 7) { + return NULL; } -#ifdef DEBUG - fprintf(stderr, "StartEvent.x_root=%d\nevent->xmotion.x_root=%d\n", - StartEvent.x_root, event->xmotion.x_root); -#endif - - dragView = W_CreateTopView(scr); - dragView->attribFlags |= CWOverrideRedirect | CWSaveUnder; - dragView->attribs.event_mask = StructureNotifyMask; - dragView->attribs.override_redirect = True; - dragView->attribs.save_under = True; - - size = WMGetPixmapSize(pixmap); - W_ResizeView(dragView, size.width, size.height); - - W_MoveView(dragView, event->xmotion.x_root - 8, event->xmotion.y_root - 8); - - W_RealizeView(dragView); - - W_MapView(dragView); - - XSetWindowBackgroundPixmap(dpy, dragView->window, WMGetPixmapXID(pixmap)); - XClearWindow(dpy, dragView->window); - XUngrabPointer(dpy, CurrentTime); - XGrabPointer(dpy, root, False, - ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeSync, GrabModeAsync, root, - None, - CurrentTime); - /* XGrabPointer(dpy,root,False, */ - /* ButtonMotionMask|ButtonPressMask|ButtonReleaseMask, */ - /* GrabModeSync,GrabModeAsync,root, */ - /* DndCursor[DataType].CursorID, */ - /* CurrentTime); */ - - /* XGrabPointer(dpy, dragView->window, True, */ - /* ButtonMotionMask|ButtonReleaseMask|EnterWindowMask, */ - /* GrabModeSync, GrabModeAsync, */ - /* scr->rootWin, scr->defaultCursor, CurrentTime); */ - - Dragging = 1; - RootFlag = 0; - while (Dragging) { - XAllowEvents(dpy, SyncPointer, CurrentTime); - WMNextEvent(dpy, &Event); - /* XNextEvent(dpy, &Event); */ - switch (Event.type) { - case ButtonRelease: - if (Event.xbutton.subwindow) - RootFlag = 0; - else { - RootFlag = 1; - slideView(dragView, - Event.xbutton.x_root, Event.xbutton.y_root, - event->xmotion.x_root, event->xmotion.y_root); - } - Dragging = 0; - break; - case MotionNotify: - W_MoveView(dragView, - Event.xmotion.x_root + 1, Event.xmotion.y_root + 1); - break; + if (strncmp(bytes, "file://", 7) != 0) { + return NULL; + } - default: - WMHandleEvent(&Event); + int pos = Index(data, '\r'); + if (pos < 7) { + if ((pos = Index(data, '\r')) < 7) { + return NULL; } } - DataOK = 0; - XUngrabPointer(dpy, CurrentTime); - W_DestroyView(dragView); -#ifdef DEBUG - fprintf(stderr, "Root flag : %d\n", RootFlag); -#endif - XSendEvent(dpy, Event.xbutton.window, True, NoEventMask, &Event); - - if (!RootFlag) { - Target = XmuClientWindow(dpy, Event.xbutton.subwindow); - if (Target == Event.xbutton.subwindow) - DispatchWindow = Target; - else - DispatchWindow = PointerWindow; - - /* - * For the moment, we do not process drops onto the root - * window. - */ - /* } */ - /* else */ - /* Target=DispatchWindow=(Window)MainWindow; */ - - Event.xclient.type = ClientMessage; - Event.xclient.display = dpy; - Event.xclient.message_type = DndProtocol; - Event.xclient.format = 32; - Event.xclient.window = Target; - Event.xclient.data.l[0] = DataType; - Event.xclient.data.l[1] = (long)event->xbutton.state; - Event.xclient.data.l[2] = (long)w; - Event.xclient.data.l[3] = 0; - Event.xclient.data.l[4] = 0; - - XSendEvent(dpy, DispatchWindow, True, NoEventMask, &Event); -#ifdef DEBUG - fprintf(stderr, "ClientMessage sent to 0x%x(0x%x).\n", - DispatchWindow, Target); -#endif - } - DragStarted = 0; - return 1; + char* r = (char*)wmalloc(pos - 7 + 1); + strncpy(r, bytes + 7, pos - 7); + r[pos - 7] = '\0'; + return r; } -static void -slideView(WMView* view, int srcX, int srcY, int dstX, int dstY) +void PerformDragOperation(WMView* self, WMArray* dropData, WMArray* operations, WMPoint* dropLocation) { - double x, y, dx, dy; - int i; + wwarning("DROPZONE: Performing drop operation"); - srcX -= 8; - srcY -= 8; - dstX -= 8; - dstY -= 8; + WMWidget* widget = WMWidgetOfView(self); + FSFileView* fView = WMGetHangedData(widget); - x = srcX; - y = srcY; + if (!fView) { + return; + } - dx = (double)(dstX - srcX) / 20.0; - dy = (double)(dstY - srcY) / 20.0; + // Dropped onto the free space of the shelf + if (WMWidgetClass(widget) == WC_Frame) { + WMData* data = FirstNonNullDataItem(dropData); + if (!data) { + return; + } - for (i = 0; i < 20; i++) { - W_MoveView(view, x, y); - XFlush(view->screen->display); + // TODO: Iterate through all paths + char* d = FirstPath(data); + if (!d) { + return; + } - x += dx; - y += dy; + FileInfo* fileInfo = FSGetFileInfo(d); + if (fileInfo) { + if (FSAddFileViewShelfItemIntoProplist(fView, fileInfo)) { + FSAddFileViewShelfItem(fView, fileInfo); + } + } + wfree(d); } } + +void ConcludeDragOperation(WMView* self) +{ + wwarning("DROPZONE: Conclude drag"); +} + +WMDragDestinationProcs* CreateDragDestinationProcs() +{ + WMDragDestinationProcs* r = wmalloc(sizeof(WMDragDestinationProcs)); + memset((void*)r, 0, sizeof(WMDragDestinationProcs)); + + r->prepareForDragOperation = PrepareForDragOperation; + r->requiredDataTypes = RequiredDataTypes; + r->allowedOperation = AllowedDropOperation; + r->inspectDropData = InspectDropData; + r->performDragOperation = PerformDragOperation; + r->concludeDragOperation = ConcludeDragOperation; + + return r; +} \ No newline at end of file diff --git a/src/DnD.h b/src/DnD.h index 097c3f5..fa27a00 100644 --- a/src/DnD.h +++ b/src/DnD.h @@ -1,35 +1,10 @@ -#ifndef WINGs_DND -#define WINGs_DND +#ifndef _DND_H_ +#define _DND_H_ #include -void DndInitialize(WMWidget* w); - -void DndRegisterDropWidget(WMWidget* w, WMEventProc* handler, void* data); -void DndRegisterDrop(WMEventProc* handler); - -void DndGetData(unsigned char** Data, unsigned long* Size); -void DndSetData(int Type, unsigned char* Data, unsigned long Size); - -int DndDataType(XEvent* event); -unsigned int DndDragButtons(XEvent* event); - -int DndHandleDragging(WMWidget* w, XEvent* event, WMPixmap* pixmap); - -void DndRegisterDragWidget(WMWidget* w, WMEventProc* handler, void* data); - -#define DndNotDnd -1 -#define DndUnknown 0 -#define DndRawData 1 -#define DndFile 2 -#define DndFiles 3 -#define DndText 4 -#define DndDir 5 -#define DndLink 6 -#define DndExe 7 - -#define DndEND 8 - -extern int DragStarted; +WMDragSourceProcs* CreateDragSourceProcs(); +WMDragDestinationProcs* CreateDragDestinationProcs(); +WMArray* SupportedDataTypes(); #endif diff --git a/src/FSFileButton.c b/src/FSFileButton.c index 5a240da..05bf3c1 100644 --- a/src/FSFileButton.c +++ b/src/FSFileButton.c @@ -125,6 +125,11 @@ InitFSFileButton(WMScreen* scr) return fileButtonWidgetClass; } +W_Class FileButtonWidgetClass() +{ + return fileButtonWidgetClass; +} + /* * Function to create the Widget */ diff --git a/src/FSFileButton.h b/src/FSFileButton.h index d0a9b29..9a8a8c4 100644 --- a/src/FSFileButton.h +++ b/src/FSFileButton.h @@ -20,7 +20,7 @@ void FSSetFileButtonDoubleAction(FSFileButton* bPtr, void* doubleClientData); void FSGroupFileButtons(FSFileButton* bPtr, FSFileButton* newMember); void FSClearFileButton(FSFileButton* bPtr); - +W_Class FileButtonWidgetClass(); W_Class InitFSFileButton(WMScreen*); typedef struct FSFileIcon { diff --git a/src/FSFileView.c b/src/FSFileView.c index 2751e51..54cf704 100644 --- a/src/FSFileView.c +++ b/src/FSFileView.c @@ -42,17 +42,12 @@ #define COLUMN_PADDING 4 // only used for increment calc here, needs to go static void notificationObserver(void* self, WMNotification* notif); -static void FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo); static void handleShelfButtonActions(WMWidget* self, void* data); static void handleShelfEventActions(XEvent* event, void* data); -static void FSAddFileViewItemIntoShelf(FSViewer* fView); -static void FSRemoveFileViewItemFromShelf(FSFileView* fView, - FSFileIcon* fileIcon); +static void FSRemoveFileViewItemFromShelf(FSFileView* fView, FSFileIcon* fileIcon); static void FSSetupFileViewShelfItems(FSFileView* fView); static void FSReorganiseShelf(FSFileView* fView); static void handleScrollViewDoubleClick(WMWidget* self, void* clientData); -static Bool FSAddFileViewShelfItemIntoProplist(FSFileView* fView, - FileInfo* fileInfo); static void handleShelfDrop(XEvent* ev, void* clientData); static void handleBtnDrop(XEvent* ev, void* clientData); static void handleBtnDrag(XEvent* ev, void* clientData); @@ -340,9 +335,6 @@ FSCreateFileView(FSViewer* fsViewer, char* path, Bool primary) /* Initialise the FileButton Widget */ InitFSFileButton(fView->scr); - /* Initialize drag'n'drop */ - DndInitialize(fView->fileView); - // fView->fileBrowserF = WMCreateFrame(fView->fileView); // WMSetViewNotifySizeChanges(WMWidgetView(fView->fileBrowserF), True); // WMSetFrameRelief(fView->fileBrowserF, WRFlat); @@ -454,7 +446,9 @@ FSCreateFileView(FSViewer* fsViewer, char* path, Bool primary) (void*)fView); /* Drag'n'Drop handles */ - DndRegisterDropWidget(fView->shelfF, handleShelfDrop, fView); + WMHangData(fView->shelfF, (void*)fView); + WMRegisterViewForDraggedTypes(W_VIEW(fView->shelfF), SupportedDataTypes()); + WMSetViewDragDestinationProcs(W_VIEW(fView->shelfF), CreateDragDestinationProcs()); WMMapSubwidgets(fView->fileView); WMMapWidget(fView->shelfF); @@ -673,11 +667,11 @@ handleShelfDrop(XEvent* ev, void* clientData) unsigned long Size; unsigned int Type; - Type = DndDataType(ev); - if ((Type != DndFile) && (Type != DndDir) && (Type != DndLink) && (Type != DndExe)) { - return; - } - DndGetData(&data, &Size); + // Type = DndDataType(ev); + // if ((Type != DndFile) && (Type != DndDir) && (Type != DndLink) && (Type != DndExe)) { + // return; + // } + // DndGetData(&data, &Size); fileInfo = FSGetFileInfo(data); if (fileInfo) { @@ -757,79 +751,45 @@ handleShelfButtonDrop(XEvent* ev, void* clientData) FileInfo* dest = FSGetFileButtonFileInfo(fileIcon->btn); FSFileView* fView = WMGetHangedData(fileIcon->btn); - Type = DndDataType(ev); - if ((Type != DndFile) && (Type != DndFiles) && (Type != DndExe) && (Type != DndDir) && (Type != DndLink)) { - return; - } + // Type = DndDataType(ev); + // if ((Type != DndFile) && (Type != DndFiles) && (Type != DndExe) && (Type != DndDir) && (Type != DndLink)) { + // return; + // } - Keys = DndDragButtons(ev); + // Keys = DndDragButtons(ev); - DndGetData(&data, &Size); + // DndGetData(&data, &Size); if (!data) return; - if (Type != DndFiles) { - char* srcPath = NULL; - char* destPath = NULL; - - src = FSGetFileInfo(data); - - srcPath = GetPathnameFromPathName(src->path, src->name); - destPath = GetPathnameFromPathName(dest->path, dest->name); - - if (strcmp(srcPath, destPath) != 0) { - if (Keys & ShiftMask) /* Copy */ - { - wwarning("%s %d", __FILE__, __LINE__); - FSCopy(src, dest); - } else { - /* FSFileIcon *fileIcon = NULL; */ - - FSMove(src, dest); - /* fileIcon = FSFindFileIconWithFileInfo(fView, src); */ - /* if(fileIcon) */ - /* FSRemoveFileViewItemFromShelf(fView, fileIcon); */ - } - } - if (srcPath) - free(srcPath); - if (destPath) - free(destPath); - } -} - -/* Drag handle for Shelf icon */ -static void -handleShelfButtonDrag(XEvent* ev, void* clientData) -{ - int type; - char* path = NULL; - WMPixmap* pixmap = NULL; - FSFileIcon* fileIcon = (FSFileIcon*)clientData; - FileInfo* fileInfo = FSGetFileButtonFileInfo(fileIcon->btn); - - wwarning("DRAG HANDLER"); - // WMIsDraggingFromView(ev->) - - if (!DragStarted) - return; - - if (!fileInfo) - return; - - path = GetPathnameFromPathName(fileInfo->path, fileInfo->name); - type = FSGetDNDType(fileInfo); - - DndSetData(type, path, (unsigned long)(strlen(path) + 1)); - - pixmap = FSCreateBlurredPixmapFromFile(WMWidgetScreen(fileIcon->btn), - fileInfo->imgName); - DndHandleDragging(fileIcon->btn, ev, pixmap); - - if (path) - free(path); - if (pixmap) - WMReleasePixmap(pixmap); + // if (Type != DndFiles) { + // char* srcPath = NULL; + // char* destPath = NULL; + + // src = FSGetFileInfo(data); + + // srcPath = GetPathnameFromPathName(src->path, src->name); + // destPath = GetPathnameFromPathName(dest->path, dest->name); + + // if (strcmp(srcPath, destPath) != 0) { + // if (Keys & ShiftMask) /* Copy */ + // { + // wwarning("%s %d", __FILE__, __LINE__); + // FSCopy(src, dest); + // } else { + // /* FSFileIcon *fileIcon = NULL; */ + + // FSMove(src, dest); + // /* fileIcon = FSFindFileIconWithFileInfo(fView, src); */ + // /* if(fileIcon) */ + // /* FSRemoveFileViewItemFromShelf(fView, fileIcon); */ + // } + // } + // if (srcPath) + // free(srcPath); + // if (destPath) + // free(destPath); + // } } /* @@ -883,86 +843,12 @@ FSReorganiseShelf(FSFileView* fView) } } -// typedef struct W_DragSourceProcs { -// WMArray* (*dropDataTypes)(WMView* self); -// WMDragOperationType (*wantedDropOperation)(WMView* self); -// WMArray* (*askedOperations)(WMView* self); -// Bool (*acceptDropOperation)(WMView* self, WMDragOperationType operation); -// void (*beganDrag)(WMView* self, WMPoint* point); -// void (*endedDrag)(WMView* self, WMPoint* point, Bool deposited); -// WMData* (*fetchDragData)(WMView* self, char* type); -// /*Bool (*ignoreModifierKeysWhileDragging)(WMView *view);*/ -// } WMDragSourceProcs; - -void BeganDrag(WMView* self, WMPoint* point) -{ - wwarning("Began drag"); -} - -void EndedDrag(WMView* self, WMPoint* point, Bool deposited) -{ - wwarning("Ended drag, deposited: %s", deposited ? "YES" : "NO"); -} - -WMData* FetchDragData(WMView* self, char* type) -{ - wwarning("Somebody requested drag data of type %s", type); - WMWidget*btn = WMWidgetOfView(self); - FileInfo* fileInfo = FSGetFileButtonFileInfo(btn); - - // TODO - char buf[1024+1]; - snprintf(buf, 1024, "file://%s%s\r\n", fileInfo->path, fileInfo->name); - - wwarning(buf); - - return WMCreateDataWithBytes(buf, strlen(buf)); -} - -static WMArray* dataTypes = NULL; - -WMArray* DropDataTypes(WMView* self) -{ - wwarning("supported data types requested"); - if (!dataTypes) { - dataTypes = WMCreateArray(1); - WMSetInArray(dataTypes, 0, &("text/uri-list")); - } - return dataTypes; -} - -Bool AcceptDropOperation(WMView *self, WMDragOperationType operation) { - return True; -} - -WMDragOperationType WantedDropOperation(WMView* self) -{ - return WDOperationCopy; -} - -WMDragSourceProcs* CreateDragSourceProcs() -{ - WMDragSourceProcs *r = wmalloc(sizeof(WMDragSourceProcs)); - memset(r, 0, sizeof(WMDragSourceProcs)); - r->acceptDropOperation = AcceptDropOperation; - // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation - r->askedOperations = NULL; - r->beganDrag = BeganDrag; - r->dropDataTypes = DropDataTypes; - r->endedDrag = EndedDrag; - r->fetchDragData = FetchDragData; - r->wantedDropOperation = WantedDropOperation; - - return r; -} - /* * FSAddFileViewShelfItem: * Create a fileIcon, add it to FileView->fileIcons * and add it to the shelf after the last fileIcon */ -static void -FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo) +void FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo) { char* pathname; FSFileIcon* fileIcon; @@ -977,6 +863,7 @@ FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo) /* Create a FileButton */ fileIcon->btn = FSCreateFileButton(fView->shelfF); + assert(WMWidgetClass(fileIcon->btn) == FileButtonWidgetClass()); pathname = GetPathnameFromPathName(fileInfo->path, fileInfo->name); FSSetFileButtonPathname(fileIcon->btn, pathname, 0); FSSetFileButtonAction(fileIcon->btn, handleShelfButtonActions, fView); @@ -985,15 +872,14 @@ FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo) WMMapWidget(fileIcon->btn); /* Drag'n'Drop */ - // DndRegisterDropWidget(fileIcon->btn, handleShelfButtonDrop, fileIcon); - // DndRegisterDragWidget(fileIcon->btn, handleShelfButtonDrag, fileIcon); - WMPixmap* dragImg = FSCreateBlurredPixmapFromFile(WMWidgetScreen(fileIcon->btn), fileInfo->imgName); WMDragSourceProcs* procs = CreateDragSourceProcs(fileInfo); - WMSetViewDraggable(W_VIEW(fileIcon->btn), procs, dragImg); + WMSetViewDraggable(WMWidgetView(fileIcon->btn), procs, dragImg); WMReleasePixmap(dragImg); wfree(procs); + // TODO: Implement handleShelfButtonDrop for XDND, too. + /* Add the new Btn to the fileIcon linked list */ if (fView->fileIcons == NULL) fView->fileIcons @@ -1024,8 +910,7 @@ FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo) * Add the selected path to the shelf and * update the SHELF entry in the user defaults DB */ -static void -FSAddFileViewItemIntoShelf(FSViewer* fsViewer) +void FSAddFileViewItemIntoShelf(FSViewer* fsViewer) { FSFileView* fView = NULL; FileInfo* fileInfo = NULL; @@ -1052,8 +937,7 @@ FSAddFileViewItemIntoShelf(FSViewer* fsViewer) * entered return False, if the fileInfo is already in there * return true. */ -static Bool -FSAddFileViewShelfItemIntoProplist(FSFileView* fView, FileInfo* fileInfo) +Bool FSAddFileViewShelfItemIntoProplist(FSFileView* fView, FileInfo* fileInfo) { Bool notFound; char* pathname = NULL; @@ -1091,36 +975,49 @@ FSAddFileViewShelfItemIntoProplist(FSFileView* fView, FileInfo* fileInfo) return notFound; } +void FSFileViewRemoveFileButtonFromShelf(FSFileView* fView, FSFileButton* btn) +{ + FSFileIcon* tmp = fView->fileIcons; + + for (FSFileIcon* tmp = fView->fileIcons; + tmp != NULL; + tmp = tmp->next) { + if (tmp->btn == btn) { + FSRemoveFileViewItemFromShelf(fView, tmp); + return; + } + } + + return; +} + /* * Remove the fileIcon from the shelf and the proplist entry */ static void FSRemoveFileViewItemFromShelf(FSFileView* fView, FSFileIcon* fileIcon) { - char* pathname = NULL; WMPropList* key = NULL; WMPropList* val = NULL; WMPropList* array = NULL; - FileInfo* fileInfo = NULL; FSFileIcon* tmp = fView->fileIcons; - if (fileIcon == NULL) + if (fileIcon == NULL) { return; - /* - The following code is needed to remove the btn to - prevent a seg fault when the btn widget is destroyed - and the calling function exits. The procedure is as follows: - a) unmap the btn and remove it from the list - b) Remove the shelf item from the proplist entry - c) Reorganise the shelf with the updated list. - d) Set dirtyFileIcon so that it will be removed on the next - reorganise shelf call or when the FileViewer is destroyed. - - To check that it seg faults at the end of this function insert - WMWidgetDestroy(fileIcon->btn); - */ - /* Required by dirtyIcon...*/ + } + + FileInfo* fileInfo = FSGetFileButtonFileInfo(fileIcon->btn); + char* pathname = GetPathnameFromPathName(fileInfo->path, fileInfo->name); + + // We cannot destroy the widget right away, as there might be + // more events lined up for its view, so we free the resources + // next time to not leak it. + if (fView->dirtyFileIcon) { + WMDestroyWidget(fView->dirtyFileIcon->btn); + fView->dirtyFileIcon = NULL; + } WMUnmapWidget(fileIcon->btn); + if (tmp != fileIcon) { while (tmp->next != fileIcon) tmp = tmp->next; @@ -1130,10 +1027,7 @@ FSRemoveFileViewItemFromShelf(FSFileView* fView, FSFileIcon* fileIcon) fView->fileIcons = tmp; } fView->fileIconCnt--; - /*...dirtyIcon*/ - fileInfo = FSGetFileButtonFileInfo(fileIcon->btn); - pathname = GetPathnameFromPathName(fileInfo->path, fileInfo->name); val = WMCreatePLString(pathname); array = FSGetUDObjectForKey(defaultsDB, "SHELF"); diff --git a/src/FSFileView.h b/src/FSFileView.h index 202cea8..36f82aa 100644 --- a/src/FSFileView.h +++ b/src/FSFileView.h @@ -63,6 +63,8 @@ void FSSetFileViewFilter(FSFileView* fView, char* filter); char* FSGetFileViewFilter(FSFileView* fView); void FSSetFileViewPath(FSFileView* fileView, char* path); void FSSetFileViewMode(FSFileView* fView, FSFileViewType mode); -WMDragSourceProcs* CreateDragSourceProcs(); - +void FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo); +void FSAddFileViewItemIntoShelf(FSViewer* fsViewer); +Bool FSAddFileViewShelfItemIntoProplist(FSFileView* fView, FileInfo* fileInfo); +void FSFileViewRemoveFileButtonFromShelf(FSFileView* fView, FSFileButton* btn); #endif diff --git a/src/FSPathView.c b/src/FSPathView.c index 2144f10..ccde62a 100644 --- a/src/FSPathView.c +++ b/src/FSPathView.c @@ -824,8 +824,8 @@ void FSSetPathViewColumnContents(FSPathView* pvPtr, int column, FSSetFileButtonSelected(pvPtr->columns[column], 1); FSSetFileButtonSelected(pvPtr->columns[column - 1], 0); - FSFileButton *btn = pvPtr->columns[column]; - FileInfo *fileInfo = FSGetFileInfo(FSGetFileButtonPathname(btn)); + FSFileButton* btn = pvPtr->columns[column]; + FileInfo* fileInfo = FSGetFileInfo(FSGetFileButtonPathname(btn)); WMPixmap* dragImg = FSCreateBlurredPixmapFromFile(WMWidgetScreen(btn), fileInfo->imgName); WMDragSourceProcs* procs = CreateDragSourceProcs(); WMSetViewDraggable(W_VIEW(btn), procs, dragImg); @@ -845,77 +845,48 @@ handlePVButtonDrop(XEvent* ev, void* clientData) FSFileButton* btn = (FSFileButton*)clientData; FSPathView* pvPtr = WMGetHangedData(btn); - Type = DndDataType(ev); - if ((Type != DndFile) && (Type != DndFiles) && (Type != DndExe) && (Type != DndDir) && (Type != DndLink)) { - return; - } + // Type = DndDataType(ev); + // if ((Type != DndFile) && (Type != DndFiles) && (Type != DndExe) && (Type != DndDir) && (Type != DndLink)) { + // return; + // } - Keys = DndDragButtons(ev); + // Keys = DndDragButtons(ev); - DndGetData(&data, &Size); + // DndGetData(&data, &Size); if (!data) return; - if (Type != DndFiles) { - char* srcPath = NULL; - char* destPath = NULL; - - src = FSGetFileInfo(data); - dest = FSGetFileInfo(FSGetFileButtonPathname(btn)); - - srcPath = GetPathnameFromPathName(src->path, src->name); - destPath = GetPathnameFromPathName(dest->path, dest->name); - - if (strcmp(srcPath, destPath) != 0) { - if (Keys & ShiftMask) /* Copy */ - { - FSCopy(src, dest); - /* insertIntoColumn(bPtr, destPath, src->name); */ - } else { - FSMove(src, dest); - /* removeFromColumn(bPtr, src->path); */ - /* insertIntoColumn(bPtr, destPath, src->name); */ - /* Check if it was on the shelf??? */ - /* fileIcon = FSFindFileIconWithFileInfo(fView, src); */ - /* if(fileIcon) */ - /* FSRemoveFileViewItemFromShelf(fView, fileIcon); */ - } - } - - if (srcPath) - free(srcPath); - if (destPath) - free(destPath); - } -} - -/* Drag handle for Shelf icon */ -static void -handlePVButtonDrag(XEvent* ev, void* clientData) -{ - int type; - char* path = NULL; - WMPixmap* pixmap = NULL; - FileInfo* fileInfo = NULL; - FSFileButton* btn = (FSFileButton*)clientData; - - if (!DragStarted) - return; - - path = FSGetFileButtonPathname(btn); - fileInfo = FSGetFileInfo(path); - type = FSGetDNDType(fileInfo); - - DndSetData(type, path, (unsigned long)(strlen(path) + 1)); - - pixmap = FSCreateBlurredPixmapFromFile(WMWidgetScreen(btn), - fileInfo->imgName); - DndHandleDragging(btn, ev, pixmap); - - if (pixmap) - WMReleasePixmap(pixmap); - if (path) - free(path); + // if (Type != DndFiles) { + // char* srcPath = NULL; + // char* destPath = NULL; + + // src = FSGetFileInfo(data); + // dest = FSGetFileInfo(FSGetFileButtonPathname(btn)); + + // srcPath = GetPathnameFromPathName(src->path, src->name); + // destPath = GetPathnameFromPathName(dest->path, dest->name); + + // if (strcmp(srcPath, destPath) != 0) { + // if (Keys & ShiftMask) /* Copy */ + // { + // FSCopy(src, dest); + // /* insertIntoColumn(bPtr, destPath, src->name); */ + // } else { + // FSMove(src, dest); + // /* removeFromColumn(bPtr, src->path); */ + // /* insertIntoColumn(bPtr, destPath, src->name); */ + // /* Check if it was on the shelf??? */ + // /* fileIcon = FSFindFileIconWithFileInfo(fView, src); */ + // /* if(fileIcon) */ + // /* FSRemoveFileViewItemFromShelf(fView, fileIcon); */ + // } + // } + + // if (srcPath) + // free(srcPath); + // if (destPath) + // free(destPath); + // } } short FSGetPathViewLastClicked(FSPathView* pvPtr) diff --git a/src/FSUtils.c b/src/FSUtils.c index 4ca771b..25092ba 100644 --- a/src/FSUtils.c +++ b/src/FSUtils.c @@ -1082,41 +1082,41 @@ void FSSetBusyCursor(WMWidget* w, Bool state) XUndefineCursor(dpy, wnd); } -int FSGetDNDType(FileInfo* fileInfo) -{ - int type = DndFile; - char buf[MAX_LEN]; - char* pathname = NULL; - - if (fileInfo == NULL) - return 0; - - switch (fileInfo->fileType) { - case S_LINK: - type = DndLink; - break; - case DIRECTORY: - case ROOT: - case HOME: - type = DndDir; - break; - default: - pathname = GetPathnameFromPathName(fileInfo->path, - fileInfo->name); - magic_get_type(pathname, buf); - if (strcmp("EXEC", buf) == 0) - type = DndExe; - else if (strcmp("ascii", buf) == 0) - type = DndFile; - else if (strcmp("ascii", buf) == 0) - type = DndText; - else - type = DndFile; - break; - } - - return type; -} +// int FSGetDNDType(FileInfo* fileInfo) +// { +// int type = DndFile; +// char buf[MAX_LEN]; +// char* pathname = NULL; + +// if (fileInfo == NULL) +// return 0; + +// switch (fileInfo->fileType) { +// case S_LINK: +// type = DndLink; +// break; +// case DIRECTORY: +// case ROOT: +// case HOME: +// type = DndDir; +// break; +// default: +// pathname = GetPathnameFromPathName(fileInfo->path, +// fileInfo->name); +// magic_get_type(pathname, buf); +// if (strcmp("EXEC", buf) == 0) +// type = DndExe; +// else if (strcmp("ascii", buf) == 0) +// type = DndFile; +// else if (strcmp("ascii", buf) == 0) +// type = DndText; +// else +// type = DndFile; +// break; +// } + +// return type; +// } int FSExecCommand(char* path, char* execStr) { diff --git a/src/FSUtils.h b/src/FSUtils.h index 63bcae3..90d9d22 100644 --- a/src/FSUtils.h +++ b/src/FSUtils.h @@ -34,7 +34,7 @@ char* FSParseExecString(char* pathname, char* txt, ...); void FSUnsetCursor(WMWidget* w); void FSSetCursor(WMWidget* w, char* type, char* name); void FSSetBusyCursor(WMWidget* w, Bool state); -int FSGetDNDType(FileInfo* fileInfo); +// int FSGetDNDType(FileInfo* fileInfo); int FSExecCommand(char* path, char* execStr); Bool FSImageTypeIsSupported(char* imgType); From e1cd1035ec750561defc59ad1e4065c36976453b Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Thu, 28 Apr 2022 22:05:41 +0200 Subject: [PATCH 04/10] Support adding multiple files to the shelf --- src/DnD.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/DnD.c b/src/DnD.c index e4c8ebc..1f162ab 100644 --- a/src/DnD.c +++ b/src/DnD.c @@ -150,24 +150,24 @@ WMData* FirstNonNullDataItem(WMArray* array) return NULL; } -int Index(WMData* data, char ch) +int Index(WMData* data, char ch, int startPos) { char* bytes = WMDataBytes(data); unsigned int len = WMGetDataLength(data); - for (int i = 0; i < len; i++) { + for (int i = startPos; i < len; i++) { if (*(bytes + i) == ch) { - return i; + return i - startPos; } } return -1; } -char* FirstPath(WMData* data) +char* FindNextPath(WMData* data, int* startPos) { - char* bytes = WMDataBytes(data); - unsigned int len = WMGetDataLength(data); + char* bytes = WMDataBytes(data) + *startPos; + unsigned int len = WMGetDataLength(data) - *startPos; if (len < 7) { return NULL; @@ -177,9 +177,9 @@ char* FirstPath(WMData* data) return NULL; } - int pos = Index(data, '\r'); + int pos = Index(data, '\r', *startPos); if (pos < 7) { - if ((pos = Index(data, '\r')) < 7) { + if ((pos = Index(data, '\n', *startPos)) < 7) { return NULL; } } @@ -187,6 +187,18 @@ char* FirstPath(WMData* data) char* r = (char*)wmalloc(pos - 7 + 1); strncpy(r, bytes + 7, pos - 7); r[pos - 7] = '\0'; + + int next = pos + 1; + for (int i = next; i < len; i++) { + if (*(bytes + i) == '\r' || *(bytes + i) == '\n') { + continue; + } + + next = i; + break; + } + *startPos += next; + return r; } @@ -208,19 +220,18 @@ void PerformDragOperation(WMView* self, WMArray* dropData, WMArray* operations, return; } - // TODO: Iterate through all paths - char* d = FirstPath(data); - if (!d) { - return; - } + int pos = 0; + char* d = NULL; - FileInfo* fileInfo = FSGetFileInfo(d); - if (fileInfo) { - if (FSAddFileViewShelfItemIntoProplist(fView, fileInfo)) { - FSAddFileViewShelfItem(fView, fileInfo); + while ((d = FindNextPath(data, &pos)) != NULL) { + FileInfo* fileInfo = FSGetFileInfo(d); + if (fileInfo) { + if (FSAddFileViewShelfItemIntoProplist(fView, fileInfo)) { + FSAddFileViewShelfItem(fView, fileInfo); + } } + wfree(d); } - wfree(d); } } From c18e01ad399c68f04b183ef35476dab3cbf556f6 Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Thu, 28 Apr 2022 22:30:25 +0200 Subject: [PATCH 05/10] Fix dragging from pathview. --- src/DnD.h | 5 +- src/FSFileView.c | 8 +-- src/FSPathView.c | 7 +- src/{DnD.c => dnddest.c} | 110 +++---------------------------- src/dndsource.c | 136 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+), 113 deletions(-) rename src/{DnD.c => dnddest.c} (59%) create mode 100644 src/dndsource.c diff --git a/src/DnD.h b/src/DnD.h index fa27a00..6bcb95d 100644 --- a/src/DnD.h +++ b/src/DnD.h @@ -3,8 +3,9 @@ #include -WMDragSourceProcs* CreateDragSourceProcs(); -WMDragDestinationProcs* CreateDragDestinationProcs(); +WMDragDestinationProcs* ShelfDragDestinationProcs(); WMArray* SupportedDataTypes(); +WMDragSourceProcs* FileViewDragSourceProcs(); +WMDragSourceProcs* PathViewDragSourceProcs(); #endif diff --git a/src/FSFileView.c b/src/FSFileView.c index 54cf704..cac3ae1 100644 --- a/src/FSFileView.c +++ b/src/FSFileView.c @@ -11,13 +11,13 @@ #include #include -#include "DnD.h" #include "FSFileButton.h" #include "FSFileView.h" #include "FSMenu.h" #include "FSUtils.h" #include "FSViewer.h" #include "df.h" +#include "dnd.h" #include "filebrowser.h" #include "files.h" #include "windowmanager.h" @@ -448,7 +448,7 @@ FSCreateFileView(FSViewer* fsViewer, char* path, Bool primary) /* Drag'n'Drop handles */ WMHangData(fView->shelfF, (void*)fView); WMRegisterViewForDraggedTypes(W_VIEW(fView->shelfF), SupportedDataTypes()); - WMSetViewDragDestinationProcs(W_VIEW(fView->shelfF), CreateDragDestinationProcs()); + WMSetViewDragDestinationProcs(W_VIEW(fView->shelfF), ShelfDragDestinationProcs()); WMMapSubwidgets(fView->fileView); WMMapWidget(fView->shelfF); @@ -873,10 +873,8 @@ void FSAddFileViewShelfItem(FSFileView* fView, FileInfo* fileInfo) /* Drag'n'Drop */ WMPixmap* dragImg = FSCreateBlurredPixmapFromFile(WMWidgetScreen(fileIcon->btn), fileInfo->imgName); - WMDragSourceProcs* procs = CreateDragSourceProcs(fileInfo); - WMSetViewDraggable(WMWidgetView(fileIcon->btn), procs, dragImg); + WMSetViewDraggable(WMWidgetView(fileIcon->btn), FileViewDragSourceProcs(fileInfo), dragImg); WMReleasePixmap(dragImg); - wfree(procs); // TODO: Implement handleShelfButtonDrop for XDND, too. diff --git a/src/FSPathView.c b/src/FSPathView.c index ccde62a..d445e6c 100644 --- a/src/FSPathView.c +++ b/src/FSPathView.c @@ -7,10 +7,9 @@ #include "FSPathView.h" #include "FSUtils.h" #include "FSViewer.h" +#include "dnd.h" #include "files.h" -#include "DnD.h" - #include "xpm/arrow.xpm" /* typedef struct PVIcon */ @@ -827,10 +826,8 @@ void FSSetPathViewColumnContents(FSPathView* pvPtr, int column, FSFileButton* btn = pvPtr->columns[column]; FileInfo* fileInfo = FSGetFileInfo(FSGetFileButtonPathname(btn)); WMPixmap* dragImg = FSCreateBlurredPixmapFromFile(WMWidgetScreen(btn), fileInfo->imgName); - WMDragSourceProcs* procs = CreateDragSourceProcs(); - WMSetViewDraggable(W_VIEW(btn), procs, dragImg); + WMSetViewDraggable(W_VIEW(btn), PathViewDragSourceProcs(), dragImg); WMReleasePixmap(dragImg); - wfree(procs); } } diff --git a/src/DnD.c b/src/dnddest.c similarity index 59% rename from src/DnD.c rename to src/dnddest.c index 1f162ab..88ea489 100644 --- a/src/DnD.c +++ b/src/dnddest.c @@ -5,109 +5,11 @@ #include #include -#include "DnD.h" #include "FSFileButton.h" #include "FSFileView.h" +#include "dnd.h" #include "files.h" -void BeganDrag(WMView* self, WMPoint* point) -{ - wwarning("Began drag"); -} - -void EndedDrag(WMView* self, WMPoint* point, Bool deposited) -{ - if (deposited) { - // Ok, successful drag. Receiver will take care. - return; - } - - FSFileButton* btn = (FSFileButton*)WMWidgetOfView(self); - if (WMWidgetClass(btn) != FileButtonWidgetClass()) { - return; - } - - // TODO: We (wrongly) assume this is a shelf FSFileButton - // that has its FSFileView attached. For FilePath's - // buttons, this is not true. - FSFileView* fView = (FSFileView*)WMGetHangedData(btn); - if (!fView) { - return; - } - - FSFileViewRemoveFileButtonFromShelf(fView, btn); -} - -WMData* FetchDragData(WMView* self, char* type) -{ - wwarning("Somebody requested drag data of type %s", type); - - if (!self) { - return NULL; - } - - WMWidget* btn = WMWidgetOfView(self); - if (!btn) { - return NULL; - } - - FileInfo* fileInfo = FSGetFileButtonFileInfo(btn); - if (!fileInfo) { - return NULL; - } - - // TODO - char buf[2048 + 1]; - memset((void*)buf, 0, 2048 + 1); - snprintf(buf, 2048, "file://%s%s\r\n", fileInfo->path, fileInfo->name); - - wwarning(buf); - - return WMCreateDataWithBytes(buf, strlen(buf)); -} - -static WMArray* dataTypes = NULL; -WMArray* SupportedDataTypes() -{ - if (!dataTypes) { - dataTypes = WMCreateArray(1); - WMSetInArray(dataTypes, 0, &("text/uri-list")); - } - return dataTypes; -} - -WMArray* DropDataTypes(WMView* self) -{ - wwarning("supported data types requested"); - return SupportedDataTypes(); -} - -Bool AcceptDropOperation(WMView* self, WMDragOperationType operation) -{ - return True; -} - -WMDragOperationType WantedDropOperation(WMView* self) -{ - return WDOperationCopy; -} - -WMDragSourceProcs* CreateDragSourceProcs() -{ - WMDragSourceProcs* r = wmalloc(sizeof(WMDragSourceProcs)); - memset((void*)r, 0, sizeof(WMDragSourceProcs)); - r->acceptDropOperation = AcceptDropOperation; - // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation - r->askedOperations = NULL; - r->beganDrag = BeganDrag; - r->dropDataTypes = DropDataTypes; - r->endedDrag = EndedDrag; - r->fetchDragData = FetchDragData; - r->wantedDropOperation = WantedDropOperation; - - return r; -} - void PrepareForDragOperation(WMView* self) { wwarning("DROPZONE: Prepare for drag"); @@ -240,8 +142,14 @@ void ConcludeDragOperation(WMView* self) wwarning("DROPZONE: Conclude drag"); } -WMDragDestinationProcs* CreateDragDestinationProcs() +static WMDragDestinationProcs* shelfDragDestinationProcs = NULL; + +WMDragDestinationProcs* ShelfDragDestinationProcs() { + if (shelfDragDestinationProcs) { + return shelfDragDestinationProcs; + } + WMDragDestinationProcs* r = wmalloc(sizeof(WMDragDestinationProcs)); memset((void*)r, 0, sizeof(WMDragDestinationProcs)); @@ -252,5 +160,5 @@ WMDragDestinationProcs* CreateDragDestinationProcs() r->performDragOperation = PerformDragOperation; r->concludeDragOperation = ConcludeDragOperation; - return r; + return (shelfDragDestinationProcs = r); } \ No newline at end of file diff --git a/src/dndsource.c b/src/dndsource.c new file mode 100644 index 0000000..29d86bf --- /dev/null +++ b/src/dndsource.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include + +#include "FSFileButton.h" +#include "FSFileView.h" +#include "dnd.h" +#include "files.h" + +void BeganDrag(WMView* self, WMPoint* point) +{ + wwarning("Began drag"); +} + +void EndedFileViewDrag(WMView* self, WMPoint* point, Bool deposited) +{ + if (deposited) { + // Ok, successful drag. Receiver will take care. + return; + } + + FSFileButton* btn = (FSFileButton*)WMWidgetOfView(self); + if (WMWidgetClass(btn) != FileButtonWidgetClass()) { + return; + } + + // TODO: We (wrongly) assume this is a shelf FSFileButton + // that has its FSFileView attached. For FilePath's + // buttons, this is not true. + FSFileView* fView = (FSFileView*)WMGetHangedData(btn); + if (!fView) { + return; + } + + FSFileViewRemoveFileButtonFromShelf(fView, btn); +} + +WMData* FetchDragData(WMView* self, char* type) +{ + wwarning("Somebody requested drag data of type %s", type); + + if (!self) { + return NULL; + } + + WMWidget* btn = WMWidgetOfView(self); + if (!btn) { + return NULL; + } + + FileInfo* fileInfo = FSGetFileButtonFileInfo(btn); + if (!fileInfo) { + return NULL; + } + + // TODO + char buf[2048 + 1]; + memset((void*)buf, 0, 2048 + 1); + snprintf(buf, 2048, "file://%s%s\r\n", fileInfo->path, fileInfo->name); + + wwarning(buf); + + return WMCreateDataWithBytes(buf, strlen(buf)); +} + +static WMArray* dataTypes = NULL; +WMArray* SupportedDataTypes() +{ + if (!dataTypes) { + dataTypes = WMCreateArray(1); + WMSetInArray(dataTypes, 0, &("text/uri-list")); + } + return dataTypes; +} + +WMArray* DropDataTypes(WMView* self) +{ + wwarning("supported data types requested"); + return SupportedDataTypes(); +} + +Bool AcceptDropOperation(WMView* self, WMDragOperationType operation) +{ + return True; +} + +WMDragOperationType WantedDropOperation(WMView* self) +{ + return WDOperationCopy; +} + +static WMDragSourceProcs* pathViewDragSourceProcs = NULL; +static WMDragSourceProcs* fileViewDragSourceProcs = NULL; + +WMDragSourceProcs* PathViewDragSourceProcs() +{ + if (pathViewDragSourceProcs) { + return pathViewDragSourceProcs; + } + + WMDragSourceProcs* r = wmalloc(sizeof(WMDragSourceProcs)); + memset((void*)r, 0, sizeof(WMDragSourceProcs)); + r->acceptDropOperation = AcceptDropOperation; + // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation + r->askedOperations = NULL; + r->beganDrag = NULL; + r->dropDataTypes = DropDataTypes; + r->endedDrag = NULL; + r->fetchDragData = FetchDragData; + r->wantedDropOperation = WantedDropOperation; + + return (pathViewDragSourceProcs = r); +} + +WMDragSourceProcs* FileViewDragSourceProcs() +{ + if (fileViewDragSourceProcs) { + return fileViewDragSourceProcs; + } + + WMDragSourceProcs* r = wmalloc(sizeof(WMDragSourceProcs)); + memset((void*)r, 0, sizeof(WMDragSourceProcs)); + r->acceptDropOperation = AcceptDropOperation; + // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation + r->askedOperations = NULL; + r->beganDrag = NULL; + r->dropDataTypes = DropDataTypes; + r->endedDrag = EndedFileViewDrag; + r->fetchDragData = FetchDragData; + r->wantedDropOperation = WantedDropOperation; + + return (fileViewDragSourceProcs = r); +} \ No newline at end of file From faa982cebd5e4bd771fb88d819cac6eaef2c338c Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Fri, 29 Apr 2022 07:51:52 +0200 Subject: [PATCH 06/10] Quality. --- src/FSFileBrowser.c | 2 +- src/FSFileButton.c | 2 +- src/FSMCList.c | 2 +- src/FSUtils.c | 2 +- src/dnddest.c | 4 ++-- src/dndsource.c | 27 ++++++++++++++++----------- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/FSFileBrowser.c b/src/FSFileBrowser.c index b16a0e2..7c7e68b 100644 --- a/src/FSFileBrowser.c +++ b/src/FSFileBrowser.c @@ -6,12 +6,12 @@ #include "files.h" /* #include "FSFileButton.h" */ -#include "DnD.h" #include "FSBrowser.h" #include "FSMCList.h" #include "FSPathView.h" #include "FSUtils.h" #include "FSViewer.h" +#include "dnd.h" #include "filebrowser.h" #define LIST_WIDTH 170 diff --git a/src/FSFileButton.c b/src/FSFileButton.c index 05bf3c1..e24e031 100644 --- a/src/FSFileButton.c +++ b/src/FSFileButton.c @@ -11,10 +11,10 @@ #include #include -#include "DnD.h" #include "FSFileButton.h" #include "FSUtils.h" #include "FSViewer.h" +#include "dnd.h" #include "files.h" /* diff --git a/src/FSMCList.c b/src/FSMCList.c index 1c0b8fd..41e3303 100644 --- a/src/FSMCList.c +++ b/src/FSMCList.c @@ -7,11 +7,11 @@ #include #include -#include "DnD.h" #include "FSBrowser.h" #include "FSMCList.h" #include "FSUtils.h" #include "FSViewer.h" +#include "dnd.h" #include "files.h" #include "xpm/list_dir.xpm" #include "xpm/list_file.xpm" diff --git a/src/FSUtils.c b/src/FSUtils.c index 25092ba..2a7c578 100644 --- a/src/FSUtils.c +++ b/src/FSUtils.c @@ -53,12 +53,12 @@ typedef unsigned long ulong; #endif /*__SunOS__*/ /* #include "config.h" */ -#include "DnD.h" #include "FSFileButton.h" #include "FSFileView.h" #include "FSPanel.h" #include "FSUtils.h" #include "FSViewer.h" +#include "dnd.h" #include "filebrowser.h" #include "files.h" #include "misc.h" diff --git a/src/dnddest.c b/src/dnddest.c index 88ea489..a512d51 100644 --- a/src/dnddest.c +++ b/src/dnddest.c @@ -54,7 +54,7 @@ WMData* FirstNonNullDataItem(WMArray* array) int Index(WMData* data, char ch, int startPos) { - char* bytes = WMDataBytes(data); + const char* bytes = WMDataBytes(data); unsigned int len = WMGetDataLength(data); for (int i = startPos; i < len; i++) { @@ -68,7 +68,7 @@ int Index(WMData* data, char ch, int startPos) char* FindNextPath(WMData* data, int* startPos) { - char* bytes = WMDataBytes(data) + *startPos; + const char* bytes = WMDataBytes(data) + *startPos; unsigned int len = WMGetDataLength(data) - *startPos; if (len < 7) { diff --git a/src/dndsource.c b/src/dndsource.c index 29d86bf..e64fb12 100644 --- a/src/dndsource.c +++ b/src/dndsource.c @@ -27,9 +27,6 @@ void EndedFileViewDrag(WMView* self, WMPoint* point, Bool deposited) return; } - // TODO: We (wrongly) assume this is a shelf FSFileButton - // that has its FSFileView attached. For FilePath's - // buttons, this is not true. FSFileView* fView = (FSFileView*)WMGetHangedData(btn); if (!fView) { return; @@ -40,7 +37,7 @@ void EndedFileViewDrag(WMView* self, WMPoint* point, Bool deposited) WMData* FetchDragData(WMView* self, char* type) { - wwarning("Somebody requested drag data of type %s", type); + wwarning("data type %s requested", type); if (!self) { return NULL; @@ -51,19 +48,27 @@ WMData* FetchDragData(WMView* self, char* type) return NULL; } + if (WMWidgetClass(btn) != FileButtonWidgetClass()) { + return NULL; + } + FileInfo* fileInfo = FSGetFileButtonFileInfo(btn); if (!fileInfo) { return NULL; } - // TODO - char buf[2048 + 1]; - memset((void*)buf, 0, 2048 + 1); - snprintf(buf, 2048, "file://%s%s\r\n", fileInfo->path, fileInfo->name); - - wwarning(buf); + const int pathLen = strlen(fileInfo->path); + const int nameLen = strlen(fileInfo->name); + char* buf = (char*)malloc(7 + pathLen + nameLen + 2 + 1); + if (!buf) { + return NULL; + } + strncpy(buf, "file://", 7); + strncpy(buf + 7, fileInfo->path, pathLen); + strncpy(buf + 7 + pathLen, fileInfo->name, nameLen); + strncpy(buf + 7 + pathLen + nameLen, "\r\n", 2); - return WMCreateDataWithBytes(buf, strlen(buf)); + return WMCreateDataWithBytesNoCopy(buf, strlen(buf), wfree); } static WMArray* dataTypes = NULL; From 717f3ac4ca755a16d02dcae7f6a4f3868f9b6594 Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Fri, 29 Apr 2022 07:55:27 +0200 Subject: [PATCH 07/10] Make dnd.h renaming explicit --- src/{DnD.h => dnd.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{DnD.h => dnd.h} (100%) diff --git a/src/DnD.h b/src/dnd.h similarity index 100% rename from src/DnD.h rename to src/dnd.h From 6ecd941655b00de922151d286e6e67da1b3fb356 Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Fri, 29 Apr 2022 08:27:15 +0200 Subject: [PATCH 08/10] No need to use heap for drag procs. --- src/dndsource.c | 61 +++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/src/dndsource.c b/src/dndsource.c index e64fb12..36158eb 100644 --- a/src/dndsource.c +++ b/src/dndsource.c @@ -97,45 +97,32 @@ WMDragOperationType WantedDropOperation(WMView* self) return WDOperationCopy; } -static WMDragSourceProcs* pathViewDragSourceProcs = NULL; -static WMDragSourceProcs* fileViewDragSourceProcs = NULL; +static WMDragSourceProcs fileViewDragSourceProcs = { + .acceptDropOperation = AcceptDropOperation, + .askedOperations = NULL, + .beganDrag = NULL, + .dropDataTypes = DropDataTypes, + .endedDrag = EndedFileViewDrag, + .fetchDragData = FetchDragData, + .wantedDropOperation = WantedDropOperation, +}; -WMDragSourceProcs* PathViewDragSourceProcs() +WMDragSourceProcs* FileViewDragSourceProcs() { - if (pathViewDragSourceProcs) { - return pathViewDragSourceProcs; - } - - WMDragSourceProcs* r = wmalloc(sizeof(WMDragSourceProcs)); - memset((void*)r, 0, sizeof(WMDragSourceProcs)); - r->acceptDropOperation = AcceptDropOperation; - // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation - r->askedOperations = NULL; - r->beganDrag = NULL; - r->dropDataTypes = DropDataTypes; - r->endedDrag = NULL; - r->fetchDragData = FetchDragData; - r->wantedDropOperation = WantedDropOperation; - - return (pathViewDragSourceProcs = r); + return &fileViewDragSourceProcs; } -WMDragSourceProcs* FileViewDragSourceProcs() -{ - if (fileViewDragSourceProcs) { - return fileViewDragSourceProcs; - } +static WMDragSourceProcs pathViewDragSourceProcs = { + .acceptDropOperation = AcceptDropOperation, + .askedOperations = NULL, + .beganDrag = NULL, + .dropDataTypes = DropDataTypes, + .endedDrag = NULL, + .fetchDragData = FetchDragData, + .wantedDropOperation = WantedDropOperation, +}; - WMDragSourceProcs* r = wmalloc(sizeof(WMDragSourceProcs)); - memset((void*)r, 0, sizeof(WMDragSourceProcs)); - r->acceptDropOperation = AcceptDropOperation; - // Can be NULL if we don't return WDOAskedOperations in wantedDropOperation - r->askedOperations = NULL; - r->beganDrag = NULL; - r->dropDataTypes = DropDataTypes; - r->endedDrag = EndedFileViewDrag; - r->fetchDragData = FetchDragData; - r->wantedDropOperation = WantedDropOperation; - - return (fileViewDragSourceProcs = r); -} \ No newline at end of file +WMDragSourceProcs* PathViewDragSourceProcs() +{ + return &pathViewDragSourceProcs; +} From 06f494b81d7dced557e21bcab5138387b22f277f Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Thu, 5 Dec 2024 07:23:11 +0100 Subject: [PATCH 09/10] Don't drop shelf items on unsuccessful drag --- src/dnddest.c | 15 ++++++++------- src/dndsource.c | 10 +++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/dnddest.c b/src/dnddest.c index a512d51..d0fa9f0 100644 --- a/src/dnddest.c +++ b/src/dnddest.c @@ -12,13 +12,13 @@ void PrepareForDragOperation(WMView* self) { - wwarning("DROPZONE: Prepare for drag"); + //wwarning("DROPZONE: Prepare for drag"); } WMArray* RequiredDataTypes(WMView* self, WMDragOperationType request, WMArray* sourceDataTypes) { - wwarning("DROPZONE: supported data types requested"); + //wwarning("DROPZONE: supported data types requested"); return SupportedDataTypes(); } @@ -26,14 +26,14 @@ WMDragOperationType AllowedDropOperation(WMView* self, WMDragOperationType request, WMArray* sourceDataTypes) { - wwarning("DROPZONE: allowed op %d? We'll answer with %d", request, WDOperationLink); + //wwarning("DROPZONE: allowed op %d? We'll answer with %d", request, WDOperationLink); return WDOperationLink; } Bool InspectDropData(WMView* self, WMArray* dropData) { - wwarning("DROPZONE: Inspecting drop data"); + //wwarning("DROPZONE: Inspecting drop data"); return True; } @@ -106,7 +106,7 @@ char* FindNextPath(WMData* data, int* startPos) void PerformDragOperation(WMView* self, WMArray* dropData, WMArray* operations, WMPoint* dropLocation) { - wwarning("DROPZONE: Performing drop operation"); + //wwarning("DROPZONE: Performing drop operation"); WMWidget* widget = WMWidgetOfView(self); FSFileView* fView = WMGetHangedData(widget); @@ -126,6 +126,7 @@ void PerformDragOperation(WMView* self, WMArray* dropData, WMArray* operations, char* d = NULL; while ((d = FindNextPath(data, &pos)) != NULL) { + //wwarning("Path sent by drag source: '%s'", d); FileInfo* fileInfo = FSGetFileInfo(d); if (fileInfo) { if (FSAddFileViewShelfItemIntoProplist(fView, fileInfo)) { @@ -139,7 +140,7 @@ void PerformDragOperation(WMView* self, WMArray* dropData, WMArray* operations, void ConcludeDragOperation(WMView* self) { - wwarning("DROPZONE: Conclude drag"); + //wwarning("DROPZONE: Conclude drag"); } static WMDragDestinationProcs* shelfDragDestinationProcs = NULL; @@ -161,4 +162,4 @@ WMDragDestinationProcs* ShelfDragDestinationProcs() r->concludeDragOperation = ConcludeDragOperation; return (shelfDragDestinationProcs = r); -} \ No newline at end of file +} diff --git a/src/dndsource.c b/src/dndsource.c index 36158eb..46dd0d7 100644 --- a/src/dndsource.c +++ b/src/dndsource.c @@ -12,7 +12,7 @@ void BeganDrag(WMView* self, WMPoint* point) { - wwarning("Began drag"); + //wwarning("Began drag"); } void EndedFileViewDrag(WMView* self, WMPoint* point, Bool deposited) @@ -32,12 +32,12 @@ void EndedFileViewDrag(WMView* self, WMPoint* point, Bool deposited) return; } - FSFileViewRemoveFileButtonFromShelf(fView, btn); + //FSFileViewRemoveFileButtonFromShelf(fView, btn); } WMData* FetchDragData(WMView* self, char* type) { - wwarning("data type %s requested", type); + //wwarning("data type %s requested", type); if (!self) { return NULL; @@ -83,7 +83,7 @@ WMArray* SupportedDataTypes() WMArray* DropDataTypes(WMView* self) { - wwarning("supported data types requested"); + //wwarning("supported data types requested"); return SupportedDataTypes(); } @@ -115,7 +115,7 @@ WMDragSourceProcs* FileViewDragSourceProcs() static WMDragSourceProcs pathViewDragSourceProcs = { .acceptDropOperation = AcceptDropOperation, .askedOperations = NULL, - .beganDrag = NULL, + .beganDrag = BeganDrag, .dropDataTypes = DropDataTypes, .endedDrag = NULL, .fetchDragData = FetchDragData, From 3b5a73d062d841556070d40977f056f053a297ed Mon Sep 17 00:00:00 2001 From: Robert Lillack Date: Thu, 5 Dec 2024 07:35:25 +0100 Subject: [PATCH 10/10] Fix crash when dragging out. --- src/dndsource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dndsource.c b/src/dndsource.c index 46dd0d7..184da6d 100644 --- a/src/dndsource.c +++ b/src/dndsource.c @@ -66,7 +66,7 @@ WMData* FetchDragData(WMView* self, char* type) strncpy(buf, "file://", 7); strncpy(buf + 7, fileInfo->path, pathLen); strncpy(buf + 7 + pathLen, fileInfo->name, nameLen); - strncpy(buf + 7 + pathLen + nameLen, "\r\n", 2); + strncpy(buf + 7 + pathLen + nameLen, "\r\n", 3); return WMCreateDataWithBytesNoCopy(buf, strlen(buf), wfree); }