[aseprite] 203/308: Open files from Windows Explorer using DDE so we re-use the running instance
Tobias Hansen
thansen at moszumanska.debian.org
Tue Mar 8 02:45:11 UTC 2016
This is an automated email from the git hooks/post-receive script.
thansen pushed a commit to branch master
in repository aseprite.
commit 210ffc090e7b446d9e6e6e8bb7a83edae8ee41ef
Author: David Capello <davidcapello at gmail.com>
Date: Thu Feb 4 13:07:36 2016 -0300
Open files from Windows Explorer using DDE so we re-use the running instance
Fix #477
---
src/she/CMakeLists.txt | 5 +-
src/she/LICENSE.txt | 2 +-
src/she/alleg4/alleg_display.cpp | 17 +++-
src/she/skia/skia_window_win.cpp | 10 +-
src/she/win/window.h | 7 +-
src/she/win/window_dde.cpp | 205 +++++++++++++++++++++++++++++++++++++++
src/she/win/window_dde.h | 19 ++++
7 files changed, 259 insertions(+), 6 deletions(-)
diff --git a/src/she/CMakeLists.txt b/src/she/CMakeLists.txt
index 313f168..d0f7285 100644
--- a/src/she/CMakeLists.txt
+++ b/src/she/CMakeLists.txt
@@ -1,5 +1,5 @@
# SHE
-# Copyright (C) 2012-2015 David Capello
+# Copyright (C) 2012-2016 David Capello
set(SHE_SOURCES)
@@ -143,7 +143,8 @@ if(USE_SKIA_BACKEND)
if(WIN32)
list(APPEND SHE_SOURCES
skia/skia_window_win.cpp
- win/vk.cpp)
+ win/vk.cpp
+ win/window_dde.cpp)
endif()
if(APPLE)
diff --git a/src/she/LICENSE.txt b/src/she/LICENSE.txt
index 1021a19..65642aa 100644
--- a/src/she/LICENSE.txt
+++ b/src/she/LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2012-2013 David Capello
+Copyright (c) 2012-2016 David Capello
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/src/she/alleg4/alleg_display.cpp b/src/she/alleg4/alleg_display.cpp
index e4f6614..61bbb53 100644
--- a/src/she/alleg4/alleg_display.cpp
+++ b/src/she/alleg4/alleg_display.cpp
@@ -1,5 +1,5 @@
// SHE library
-// Copyright (C) 2012-2015 David Capello
+// Copyright (C) 2012-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -82,6 +82,21 @@ bool capture_mouse = false;
static LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
+ // Don't process DDE messages here because we cannot get the first
+ // DDE message correctly. The problem is that the message pump
+ // starts before we can subclass the Allegro HWND, so we don't have
+ // enough time to inject the code to process this kind of message.
+ //
+ // For more info see "Once you go input-idle, your application is
+ // deemed ready to receive DDE messages":
+ // https://blogs.msdn.microsoft.com/oldnewthing/20140620-00/?p=693
+ //
+ // Anyway a possible solution would be to avoid processing the
+ // message loop until we subclass the HWND. I've tested this and it
+ // doesn't work, maybe because the message pump on Allegro 4 isn't
+ // in the main thread, I really don't know. But it just crash the
+ // whole system (Windows 10).
+
switch (msg) {
case WM_DROPFILES: {
diff --git a/src/she/skia/skia_window_win.cpp b/src/she/skia/skia_window_win.cpp
index a7ea988..f5df7fa 100644
--- a/src/she/skia/skia_window_win.cpp
+++ b/src/she/skia/skia_window_win.cpp
@@ -1,5 +1,5 @@
// SHE library
-// Copyright (C) 2012-2015 David Capello
+// Copyright (C) 2012-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -22,6 +22,14 @@
#endif
+#ifdef _WIN32
+
+ #include <windows.h>
+ #include "she/win/window_dde.h" // Include this one time to
+
+#endif
+
+
namespace she {
SkiaWindow::SkiaWindow(EventQueue* queue, SkiaDisplay* display,
diff --git a/src/she/win/window.h b/src/she/win/window.h
index d8eaf21..dce9a01 100644
--- a/src/she/win/window.h
+++ b/src/she/win/window.h
@@ -1,5 +1,5 @@
// SHE library
-// Copyright (C) 2012-2015 David Capello
+// Copyright (C) 2012-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -18,6 +18,7 @@
#include "she/event.h"
#include "she/keys.h"
#include "she/native_cursor.h"
+#include "she/win/window_dde.h"
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
@@ -554,6 +555,10 @@ namespace she {
}
+ LRESULT result = FALSE;
+ if (handle_dde_messages(m_hwnd, msg, wparam, lparam, result))
+ return result;
+
return DefWindowProc(m_hwnd, msg, wparam, lparam);
}
diff --git a/src/she/win/window_dde.cpp b/src/she/win/window_dde.cpp
new file mode 100644
index 0000000..12baa42
--- /dev/null
+++ b/src/she/win/window_dde.cpp
@@ -0,0 +1,205 @@
+// SHE library
+// Copyright (C) 2016 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "she/win/window_dde.h"
+
+#include "base/string.h"
+#include "she/event.h"
+#include "she/event_queue.h"
+
+#include <string>
+#include <vector>
+
+namespace she {
+
+namespace {
+
+std::string get_atom_string(ATOM atom, bool isUnicode)
+{
+ std::string result;
+ if (!atom)
+ return result;
+
+ if (isUnicode) {
+ std::vector<WCHAR> buf(256, 0);
+ GlobalGetAtomNameW(atom, &buf[0], buf.size());
+ result = base::to_utf8(std::wstring(&buf[0]));
+ }
+ else {
+ std::vector<char> buf;
+ UINT chars = GlobalGetAtomNameA(atom, &buf[0], buf.size());
+ result = &buf[0];
+ }
+
+ return result;
+}
+
+// Converts a DDE command string (e.g. "[open(filename)]") into she events.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms648995.aspx
+bool parse_dde_command(const std::string& cmd)
+{
+ bool result = false;
+
+ for (size_t i=0; i<cmd.size(); ) {
+ if (cmd[i] == '[') {
+ size_t j = ++i;
+
+ for (; j<cmd.size(); ++j) {
+ if (cmd[j] == '(')
+ break;
+ }
+
+ std::string cmdName = cmd.substr(i, j-i);
+ std::vector<std::string> cmdParams;
+
+ for (i=j+1; i<cmd.size(); ) {
+ if (cmd[i] == ')') {
+ j = i+1;
+ break;
+ }
+ else if (cmd[i] == '"') {
+ std::string cmdParam;
+ for (j=++i; j<cmd.size(); ++j) {
+ if (cmd[j] == '"')
+ break;
+ else
+ cmdParam.push_back(cmd[j]);
+ }
+ cmdParams.push_back(cmdParam);
+ i = j+1;
+ }
+ else {
+ std::string cmdParam;
+ for (j=i; j<cmd.size(); ++j) {
+ if (cmd[j] == ',' || cmd[j] == ')')
+ break;
+ else
+ cmdParam.push_back(cmd[j]);
+ }
+ cmdParams.push_back(cmdParam);
+ i = j;
+ }
+ }
+
+ if (cmdName == "open" && !cmdParams.empty()) {
+ // Send a message to open the file as if it were dropped into the window.
+ Event ev;
+ ev.setType(Event::DropFiles);
+ ev.setFiles(cmdParams);
+ she::queue_event(ev);
+
+ result = true;
+ }
+
+ i = j;
+ }
+ else
+ ++i;
+ }
+
+ return result;
+}
+
+union DdeackContainer {
+ WORD value;
+ DDEACK ddeack;
+};
+
+} // anonymous namespace
+
+bool handle_dde_messages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LRESULT& result)
+{
+ switch (msg) {
+
+ case WM_DDE_INITIATE: {
+ HWND clienthwnd = (HWND)wparam;
+ UINT appAtom = 0, topicAtom = 0;
+ if (!UnpackDDElParam(msg, lparam,
+ &appAtom,
+ &topicAtom))
+ return false;
+
+ bool useUnicode = (IsWindowUnicode(clienthwnd) ? true: false);
+ std::string app = get_atom_string((ATOM)appAtom, useUnicode);
+ std::string topic = get_atom_string((ATOM)topicAtom, useUnicode);
+ FreeDDElParam(msg, lparam);
+
+ if (app != PACKAGE) {
+ return false;
+ }
+
+ // We have to create new atoms for this WM_DDE_ACK, we cannot
+ // reuse them according to MSDN:
+ //
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms648996(v=vs.85).aspx
+ //
+ // Anyway it looks like Windows returns the same ATOM number.
+ ATOM newApp = (useUnicode ? GlobalAddAtomW(base::from_utf8(app).c_str()):
+ GlobalAddAtomA(app.c_str()));
+ ATOM newTopic = (useUnicode ? GlobalAddAtomW(base::from_utf8(topic).c_str()):
+ GlobalAddAtomA(topic.c_str()));
+
+ if (newApp && newTopic) {
+ SendMessage(clienthwnd,
+ WM_DDE_ACK,
+ (WPARAM)hwnd,
+ PackDDElParam(WM_DDE_ACK, newApp, newTopic));
+ }
+
+ if (newApp) GlobalDeleteAtom(newApp);
+ if (newTopic) GlobalDeleteAtom(newTopic);
+
+ result = 0;
+ return true;
+ }
+
+ case WM_DDE_EXECUTE: {
+ HWND clienthwnd = (HWND)wparam;
+ bool useUnicode = (IsWindowUnicode(clienthwnd) ? true: false);
+ LPCVOID cmdPtr = (LPCVOID)GlobalLock((HGLOBAL)lparam);
+ std::string cmd;
+
+ if (useUnicode)
+ cmd = base::to_utf8((const WCHAR*)cmdPtr);
+ else
+ cmd = (const CHAR*)cmdPtr;
+
+ GlobalUnlock((HGLOBAL)lparam);
+
+ DdeackContainer ddeack;
+ ddeack.value = 0;
+ ddeack.ddeack.fAck = 1;
+
+ PostMessage(clienthwnd, WM_DDE_ACK,
+ (WPARAM)hwnd,
+ ReuseDDElParam(lparam, msg, WM_DDE_ACK,
+ (UINT_PTR)ddeack.value,
+ (UINT_PTR)lparam));
+
+ if (parse_dde_command(cmd))
+ SetForegroundWindow(hwnd);
+
+ result = 0;
+ return true;
+ }
+
+ case WM_DDE_TERMINATE: {
+ HWND clienthwnd = (HWND)wparam;
+ PostMessage(clienthwnd, WM_DDE_TERMINATE, (WPARAM)hwnd, lparam);
+ result = 0;
+ return true;
+ }
+
+ }
+
+ return false;
+}
+
+} // namespace she
diff --git a/src/she/win/window_dde.h b/src/she/win/window_dde.h
new file mode 100644
index 0000000..1551eff
--- /dev/null
+++ b/src/she/win/window_dde.h
@@ -0,0 +1,19 @@
+// SHE library
+// Copyright (C) 2016 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifndef SHE_WIN_WINDOW_DDE_H_INCLUDED
+#define SHE_WIN_WINDOW_DDE_H_INCLUDED
+#pragma once
+
+#include <windows.h>
+
+namespace she {
+
+bool handle_dde_messages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LRESULT& result);
+
+} // namespace she
+
+#endif
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git
More information about the Pkg-games-commits
mailing list