Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions modules/gui/skins2/macosx/macosx_dragdrop.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*****************************************************************************
* macosx_dragdrop.hpp
*****************************************************************************
* Copyright (C) 2024 the VideoLAN team
*
* Authors: VLC contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/

#ifndef MACOSX_DRAGDROP_HPP
#define MACOSX_DRAGDROP_HPP

#include "../src/skin_common.hpp"
#include "../src/generic_window.hpp"

#ifdef __OBJC__
@class NSWindow;
@class VLCDropView;
#else
typedef void NSWindow;
typedef void VLCDropView;
#endif

/// macOS drag and drop handler
class MacOSXDragDrop: public SkinObject
{
public:
MacOSXDragDrop( intf_thread_t *pIntf, NSWindow *pWindow,
bool playOnDrop, GenericWindow *pWin );
virtual ~MacOSXDragDrop();

/// Handle dropped files
void handleDrop( const char **files, int count );

/// Check if files should play immediately
bool getPlayOnDrop() const { return m_playOnDrop; }

/// Get the associated GenericWindow
GenericWindow *getWindow() const { return m_pWin; }

private:
/// Window
NSWindow *m_pWindow;
/// Drop view
VLCDropView *m_pDropView;
/// Should dropped files play immediately
bool m_playOnDrop;
/// Associated generic window
GenericWindow *m_pWin;
};

#endif
185 changes: 185 additions & 0 deletions modules/gui/skins2/macosx/macosx_dragdrop.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/*****************************************************************************
* macosx_dragdrop.mm
*****************************************************************************
* Copyright (C) 2024 the VideoLAN team
*
* Authors: VLC contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#import <Cocoa/Cocoa.h>

#include "macosx_dragdrop.hpp"
#include "../commands/async_queue.hpp"
#include "../commands/cmd_add_item.hpp"

#include <vlc_url.h>


/// NSView subclass that handles drag and drop
@interface VLCDropView : NSView
{
MacOSXDragDrop *m_pHandler;
}
- (instancetype)initWithFrame:(NSRect)frame handler:(MacOSXDragDrop *)handler;
@end

@implementation VLCDropView

- (instancetype)initWithFrame:(NSRect)frame handler:(MacOSXDragDrop *)handler
{
self = [super initWithFrame:frame];
if( self )
{
m_pHandler = handler;

// Register for drag types
[self registerForDraggedTypes:@[
NSPasteboardTypeFileURL,
NSPasteboardTypeURL,
NSPasteboardTypeString
]];
}
return self;
}

- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
{
return NSDragOperationCopy;
}

- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
{
NSPasteboard *pasteboard = [sender draggingPasteboard];

// Try to get file URLs
NSArray *fileURLs = [pasteboard readObjectsForClasses:@[[NSURL class]]
options:@{NSPasteboardURLReadingFileURLsOnlyKey: @YES}];

if( fileURLs && [fileURLs count] > 0 )
{
NSMutableArray *paths = [NSMutableArray array];
for( NSURL *url in fileURLs )
{
[paths addObject:[url path]];
}

// Convert to C strings
int count = (int)[paths count];
const char **files = (const char **)malloc( count * sizeof(char*) );
for( int i = 0; i < count; i++ )
{
files[i] = [[paths objectAtIndex:i] UTF8String];
}

if( m_pHandler )
{
m_pHandler->handleDrop( files, count );
}

free( files );
return YES;
}

// Try generic URLs
NSArray *urls = [pasteboard readObjectsForClasses:@[[NSURL class]] options:nil];
if( urls && [urls count] > 0 )
{
int count = (int)[urls count];
const char **files = (const char **)malloc( count * sizeof(char*) );
for( int i = 0; i < count; i++ )
{
NSURL *url = [urls objectAtIndex:i];
files[i] = [[url absoluteString] UTF8String];
}

if( m_pHandler )
{
m_pHandler->handleDrop( files, count );
}

free( files );
return YES;
}

return NO;
}

@end


MacOSXDragDrop::MacOSXDragDrop( intf_thread_t *pIntf, NSWindow *pWindow,
bool playOnDrop, GenericWindow *pWin ):
SkinObject( pIntf ), m_pWindow( pWindow ), m_pDropView( nil ),
m_playOnDrop( playOnDrop ), m_pWin( pWin )
{
@autoreleasepool {
if( m_pWindow )
{
// Create and add drop view
NSView *contentView = [m_pWindow contentView];
NSRect frame = [contentView bounds];

m_pDropView = [[VLCDropView alloc] initWithFrame:frame handler:this];
[m_pDropView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[contentView addSubview:m_pDropView positioned:NSWindowAbove relativeTo:nil];
}
}
}


MacOSXDragDrop::~MacOSXDragDrop()
{
@autoreleasepool {
if( m_pDropView )
{
[m_pDropView removeFromSuperview];
m_pDropView = nil;
}
}
}


void MacOSXDragDrop::handleDrop( const char **files, int count )
{
for( int i = 0; i < count; i++ )
{
const char *file = files[i];

// Convert path to URI if needed
char *uri = vlc_path2uri( file, NULL );
if( !uri )
{
// Might already be a URI
uri = strdup( file );
}

if( uri )
{
bool playNow = m_playOnDrop && (i == 0);

CmdAddItem *pCmd = new CmdAddItem( getIntf(), uri, playNow );
AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) );

free( uri );
}
}
}
132 changes: 132 additions & 0 deletions modules/gui/skins2/macosx/macosx_factory.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*****************************************************************************
* macosx_factory.hpp
*****************************************************************************
* Copyright (C) 2024 the VideoLAN team
*
* Authors: VLC contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/

#ifndef MACOSX_FACTORY_HPP
#define MACOSX_FACTORY_HPP

#include "../src/os_factory.hpp"
#include "../src/generic_window.hpp"
#include <map>

class MacOSXTimerLoop;

/// Class used to instantiate macOS specific objects
class MacOSXFactory: public OSFactory
{
public:
MacOSXFactory( intf_thread_t *pIntf );
virtual ~MacOSXFactory();

/// Initialization method
virtual bool init();

/// Instantiate an object OSGraphics
virtual OSGraphics *createOSGraphics( int width, int height );

/// Get the instance of the singleton OSLoop
virtual OSLoop *getOSLoop();

/// Destroy the instance of OSLoop
virtual void destroyOSLoop();

/// Instantiate an OSTimer with the given command
virtual OSTimer *createOSTimer( CmdGeneric &rCmd );

/// Minimize all the windows
virtual void minimize();

/// Restore the minimized windows
virtual void restore();

/// Add an icon in the system tray
virtual void addInTray();

/// Remove the icon from the system tray
virtual void removeFromTray();

/// Show the task in the task bar
virtual void addInTaskBar();

/// Remove the task from the task bar
virtual void removeFromTaskBar();

/// Instantiate an OSWindow object
virtual OSWindow *createOSWindow( GenericWindow &rWindow,
bool dragDrop, bool playOnDrop,
OSWindow *pParent,
GenericWindow::WindowType_t type );

/// Instantiate an object OSTooltip
virtual OSTooltip *createOSTooltip();

/// Instantiate an object OSPopup
virtual OSPopup *createOSPopup();

/// Get the directory separator
virtual const std::string &getDirSeparator() const { return m_dirSep; }

/// Get the resource path
virtual const std::list<std::string> &getResourcePath() const
{ return m_resourcePath; }

/// Get the screen size
virtual int getScreenWidth() const;
virtual int getScreenHeight() const;

/// Get Monitor Information
virtual void getMonitorInfo( OSWindow *pWindow,
int* x, int* y,
int* width, int* height ) const;
virtual void getMonitorInfo( int numScreen,
int* x, int* y,
int* width, int* height ) const;

/// Get the work area (screen area without taskbars)
virtual SkinsRect getWorkArea() const;

/// Get the position of the mouse
virtual void getMousePos( int &rXPos, int &rYPos ) const;

/// Change the cursor
virtual void changeCursor( CursorType_t type ) const;

/// Delete a directory recursively
virtual void rmDir( const std::string &rPath );

/// Get the timer loop
MacOSXTimerLoop *getTimerLoop() const { return m_pTimerLoop; }

/// Map to find the GenericWindow* associated with an NSWindow
std::map<void*, GenericWindow*> m_windowMap;

private:
/// Timer loop
MacOSXTimerLoop *m_pTimerLoop;
/// Directory separator
const std::string m_dirSep;
/// Resource path
std::list<std::string> m_resourcePath;
/// Screen dimensions
int m_screenWidth, m_screenHeight;
};

#endif
Loading