Move drop files event to she library

This commit is contained in:
David Capello 2014-03-20 07:31:19 -03:00
parent be6b98995e
commit 1212906d5a
10 changed files with 114 additions and 225 deletions

View File

@ -105,7 +105,6 @@ add_library(app-lib
document_location.cpp
document_undo.cpp
documents.cpp
drop_files.cpp
file/ase_format.cpp
file/bmp_format.cpp
file/file.cpp

View File

@ -32,7 +32,6 @@
#include "app/document_exporter.h"
#include "app/document_location.h"
#include "app/document_observer.h"
#include "app/drop_files.h"
#include "app/file/file.h"
#include "app/file/file_formats_manager.h"
#include "app/file_system.h"
@ -235,9 +234,6 @@ int App::run()
// Run the GUI
if (isGui()) {
// Support to drop files from Windows explorer
install_drop_files();
#ifdef ENABLE_UPDATER
// Launch the thread to check for updates.
app::CheckUpdateThreadLauncher checkUpdate;
@ -253,9 +249,6 @@ int App::run()
// Run the GUI main message loop
gui_run();
// Uninstall support to drop files
uninstall_drop_files();
// Destroy all documents in the UIContext.
const Documents& docs = m_modules->m_ui_context.getDocuments();
while (!docs.empty())

View File

@ -1,163 +0,0 @@
/* Aseprite
* Copyright (C) 2001-2013 David Capello
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/app.h"
#include "app/ui/main_window.h"
#include "base/mutex.h"
#include "base/scoped_lock.h"
#include "app/commands/commands.h"
#include "app/commands/params.h"
#include "ui/manager.h"
#include "ui/window.h"
#include "app/ui_context.h"
#include <allegro.h>
#include <vector>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#if defined STRICT || defined __GNUC__
typedef WNDPROC wndproc_t;
#else
typedef FARPROC wndproc_t;
#endif
#endif
namespace app {
#ifdef ALLEGRO_WINDOWS
static wndproc_t base_wnd_proc = NULL;
static std::vector<base::string>* dropped_files;
static base::mutex* dropped_files_mutex = NULL;
static void subclass_hwnd();
static void unsubclass_hwnd();
static LRESULT CALLBACK ase_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
void install_drop_files()
{
dropped_files = new std::vector<base::string>();
dropped_files_mutex = new base::mutex();
subclass_hwnd();
}
void uninstall_drop_files()
{
unsubclass_hwnd();
delete dropped_files_mutex;
dropped_files_mutex = NULL;
delete dropped_files;
}
void check_for_dropped_files()
{
if (!base_wnd_proc) // drop-files hook not installed
return;
// If the main window is not the current foreground one. We discard
// the drop-files event.
if (ui::Manager::getDefault()->getForegroundWindow() != App::instance()->getMainWindow())
return;
base::scoped_lock lock(*dropped_files_mutex);
if (!dropped_files->empty()) {
std::vector<base::string> files = *dropped_files;
dropped_files->clear();
// open all files
Command* cmd_open_file =
CommandsModule::instance()->getCommandByName(CommandId::OpenFile);
Params params;
for (std::vector<base::string>::iterator
it = files.begin(); it != files.end(); ++it) {
params.set("filename", it->c_str());
UIContext::instance()->executeCommand(cmd_open_file, &params);
}
}
}
static void subclass_hwnd()
{
HWND hwnd = win_get_window();
// add the WS_EX_ACCEPTFILES
SetWindowLong(hwnd, GWL_EXSTYLE,
GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_ACCEPTFILES);
// set the GWL_WNDPROC to globalWndProc
base_wnd_proc = (wndproc_t)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ase_wnd_proc);
}
static void unsubclass_hwnd()
{
HWND hwnd = win_get_window();
// restore the old wndproc
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)base_wnd_proc);
base_wnd_proc = NULL;
}
static LRESULT CALLBACK ase_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg) {
case WM_DROPFILES:
{
base::scoped_lock lock(*dropped_files_mutex);
HDROP hdrop = (HDROP)(wparam);
int index, count, length;
count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
for (index=0; index<count; ++index) {
length = DragQueryFile(hdrop, index, NULL, 0);
if (length > 0) {
TCHAR* lpstr = new TCHAR[length+1];
DragQueryFile(hdrop, index, lpstr, length+1);
dropped_files->push_back(base::to_utf8(lpstr));
delete[] lpstr;
}
}
DragFinish(hdrop);
}
break;
}
return ::CallWindowProc(base_wnd_proc, hwnd, msg, wparam, lparam);
}
#else
void install_drop_files() { }
void uninstall_drop_files() { }
void check_for_dropped_files() { }
#endif
} // namespace app

View File

@ -1,31 +0,0 @@
/* Aseprite
* Copyright (C) 2001-2013 David Capello
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef APP_DROP_FILES_H_INCLUDED
#define APP_DROP_FILES_H_INCLUDED
namespace app {
void install_drop_files();
void uninstall_drop_files();
void check_for_dropped_files();
} // namespace app
#endif

View File

@ -25,7 +25,6 @@
#include "app/commands/commands.h"
#include "app/commands/params.h"
#include "app/console.h"
#include "app/drop_files.h"
#include "app/ini_file.h"
#include "app/modules/editors.h"
#include "app/modules/gfx.h"
@ -741,11 +740,30 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
}
break;
case kDropFilesMessage:
{
// If the main window is not the current foreground one. We
// discard the drop-files event.
if (getForegroundWindow() != App::instance()->getMainWindow())
break;
const DropFilesMessage::Files& files = static_cast<DropFilesMessage*>(msg)->files();
// Open all files
Command* cmd_open_file =
CommandsModule::instance()->getCommandByName(CommandId::OpenFile);
Params params;
for (DropFilesMessage::Files::const_iterator
it = files.begin(); it != files.end(); ++it) {
params.set("filename", it->c_str());
UIContext::instance()->executeCommand(cmd_open_file, &params);
}
}
break;
case kQueueProcessingMessage:
gui_feedback();
// Open dropped files
check_for_dropped_files();
break;
case kKeyDownMessage: {

View File

@ -7,21 +7,31 @@
#ifndef SHE_EVENT_H_INCLUDED
#define SHE_EVENT_H_INCLUDED
#include <string>
#include <vector>
namespace she {
class Event {
public:
enum Type {
None,
DropFiles,
};
typedef std::vector<std::string> Files;
Event() : m_type(None) { }
int type() const { return m_type; }
void setType(Type type) { m_type = type; }
const Files& files() const { return m_files; }
void setFiles(const Files& files) { m_files = files; }
private:
Type m_type;
Files m_files;
};
} // namespace she

View File

@ -10,6 +10,9 @@
#include "she.h"
#include "base/compiler_specific.h"
#include "base/string.h"
#include <allegro.h>
#include <allegro/internal/aintern.h>
@ -163,19 +166,48 @@ private:
#if WIN32
namespace {
Display* g_display = NULL;
Display* unique_display = NULL;
wndproc_t base_wndproc = NULL;
static LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
// TODO
// switch (msg) {
// }
switch (msg) {
case WM_DROPFILES:
{
HDROP hdrop = (HDROP)(wparam);
Event::Files files;
int count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
for (int index=0; index<count; ++index) {
int length = DragQueryFile(hdrop, index, NULL, 0);
if (length > 0) {
std::vector<TCHAR> str(length+1);
DragQueryFile(hdrop, index, &str[0], str.size());
files.push_back(base::to_utf8(&str[0]));
}
}
DragFinish(hdrop);
Event ev;
ev.setType(Event::DropFiles);
ev.setFiles(files);
static_cast<Alleg4EventQueue*>(unique_display->getEventQueue())
->queueEvent(ev);
}
break;
}
return ::CallWindowProc(base_wndproc, hwnd, msg, wparam, lparam);
}
void subclass_hwnd(HWND hwnd)
{
// Add the WS_EX_ACCEPTFILES
SetWindowLong(hwnd, GWL_EXSTYLE,
GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_ACCEPTFILES);
base_wndproc = (wndproc_t)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc);
}
@ -193,6 +225,8 @@ public:
Alleg4Display(int width, int height, int scale)
: m_surface(NULL)
, m_scale(0) {
unique_display = this;
if (install_mouse() < 0) throw DisplayCreationException(allegro_error);
if (install_keyboard() < 0) throw DisplayCreationException(allegro_error);
@ -240,29 +274,31 @@ public:
m_surface->dispose();
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
unique_display = NULL;
}
void dispose() {
void dispose() OVERRIDE {
delete this;
}
int width() const {
int width() const OVERRIDE {
return SCREEN_W;
}
int height() const {
int height() const OVERRIDE {
return SCREEN_H;
}
int originalWidth() const {
int originalWidth() const OVERRIDE {
return original_width > 0 ? original_width: width();
}
int originalHeight() const {
int originalHeight() const OVERRIDE {
return original_height > 0 ? original_height: height();
}
void setScale(int scale) {
void setScale(int scale) OVERRIDE {
ASSERT(scale >= 1);
if (m_scale == scale)
@ -276,11 +312,11 @@ public:
m_surface = newSurface;
}
NotDisposableSurface* getSurface() {
NotDisposableSurface* getSurface() OVERRIDE {
return static_cast<NotDisposableSurface*>(m_surface);
}
bool flip() {
bool flip() OVERRIDE {
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
if (display_flags & DISPLAY_FLAG_WINDOW_RESIZE) {
display_flags ^= DISPLAY_FLAG_WINDOW_RESIZE;
@ -307,13 +343,13 @@ public:
return true;
}
void maximize() {
void maximize() OVERRIDE {
#ifdef WIN32
::ShowWindow(win_get_window(), SW_MAXIMIZE);
#endif
}
bool isMaximized() const {
bool isMaximized() const OVERRIDE {
#ifdef WIN32
return (::GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false);
#else
@ -321,11 +357,11 @@ public:
#endif
}
EventQueue* getEventQueue() {
EventQueue* getEventQueue() OVERRIDE {
return m_queue;
}
void* nativeHandle() {
void* nativeHandle() OVERRIDE {
#ifdef WIN32
return reinterpret_cast<void*>(win_get_window());
#else

View File

@ -460,9 +460,17 @@ bool Manager::generateMessages()
if (sheEvent.type() == she::Event::None)
break;
// TODO
// switch (sheEvent.type()) {
// }
switch (sheEvent.type()) {
case she::Event::DropFiles:
{
Message* msg = new DropFilesMessage(sheEvent.files());
msg->addRecipient(this);
enqueueMessage(msg);
}
break;
}
}
// Generate messages for timers

View File

@ -16,6 +16,9 @@
#include "ui/mouse_buttons.h"
#include "ui/widgets_list.h"
#include <string>
#include <vector>
namespace ui {
class Timer;
@ -128,6 +131,21 @@ namespace ui {
Timer* m_timer; // Timer handle
};
class DropFilesMessage : public Message
{
public:
typedef std::vector<std::string> Files;
DropFilesMessage(const Files& files)
: Message(kDropFilesMessage), m_files(files) {
}
const Files& files() const { return m_files; }
private:
Files m_files;
};
} // namespace ui
#endif

View File

@ -17,6 +17,7 @@ namespace ui {
kCloseAppMessage, // The user wants to close the entire application.
kPaintMessage, // Widget needs be repainted.
kTimerMessage, // A timer timeout.
kDropFilesMessage, // Drop files in the manager.
kWinMoveMessage, // Window movement.
kQueueProcessingMessage, // Only sent to manager which indicate
// the last message in the queue.