[aseprite] 65/134: Fix several issues with keyboard shortcuts customization

Tobias Hansen thansen at moszumanska.debian.org
Sat Mar 14 17:10:07 UTC 2015


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit 0b13e53c67dbb9a5ead0f58251ad455e8e988db7
Author: David Capello <davidcapello at gmail.com>
Date:   Sat Nov 15 18:31:12 2014 -0300

    Fix several issues with keyboard shortcuts customization
    
    Changes:
    * Now default action modifiers can be removed (fix #521)
    * Now action modifiers have a KeyContext (the key context depend on the
      action itself, cannot be configured by the user)
    * Fix Accelerator::check() and Accelerator::operator=() when the unicode
      char and scancode are nil (i.e. we are comparing only modifiers)
    * Convert Accelerators to a class to simplify code
    * Remove unused variables in Accelerator::check() when REPORT_KEYS is
      defined
---
 src/app/commands/cmd_keyboard_shortcuts.cpp |  17 ++-
 src/app/ui/keyboard_shortcuts.cpp           | 221 +++++++++++++++++++++-------
 src/app/ui/keyboard_shortcuts.h             |  12 +-
 src/app/ui/select_accelerator.cpp           |  12 +-
 src/app/ui/select_accelerator.h             |   4 +-
 src/ui/accelerator.cpp                      |  38 ++++-
 src/ui/accelerator.h                        |  33 ++++-
 7 files changed, 261 insertions(+), 76 deletions(-)

diff --git a/src/app/commands/cmd_keyboard_shortcuts.cpp b/src/app/commands/cmd_keyboard_shortcuts.cpp
index 25c519b..6651cf4 100644
--- a/src/app/commands/cmd_keyboard_shortcuts.cpp
+++ b/src/app/commands/cmd_keyboard_shortcuts.cpp
@@ -82,12 +82,13 @@ private:
 
   void onChangeAccel(int index) {
     Accelerator origAccel = m_key->accels()[index];
-    SelectAccelerator window(origAccel);
+    SelectAccelerator window(origAccel, m_key->keycontext());
     window.openWindowInForeground();
 
     if (window.isModified()) {
       m_key->disableAccel(origAccel);
-      m_key->add(window.accel(), KeySource::UserDefined);
+      if (!window.accel().isEmpty())
+        m_key->add(window.accel(), KeySource::UserDefined);
     }
 
     getRoot()->layout();
@@ -106,7 +107,7 @@ private:
 
   void onAddAccel() {
     ui::Accelerator accel;
-    SelectAccelerator window(accel);
+    SelectAccelerator window(accel, m_key->keycontext());
     window.openWindowInForeground();
 
     if (window.isModified()) {
@@ -359,8 +360,14 @@ private:
     fillList(this->menus(), AppMenus::instance()->getRootMenu(), 0);
     for (Key* key : *app::KeyboardShortcuts::instance()) {
       std::string text = key->triggerString();
-      if (key->keycontext() == KeyContext::Selection)
-        text += " (w/selection)";
+      switch (key->keycontext()) {
+        case KeyContext::Selection:
+          text = "Selection context: " + text;
+          break;
+        case KeyContext::MovingPixels:
+          text = "Moving pixels context: " + text;
+          break;
+      }
       KeyItem* keyItem = new KeyItem(text, key, NULL, 0);
 
       ListBox* listBox = NULL;
diff --git a/src/app/ui/keyboard_shortcuts.cpp b/src/app/ui/keyboard_shortcuts.cpp
index cb597a5..5d54719 100644
--- a/src/app/ui/keyboard_shortcuts.cpp
+++ b/src/app/ui/keyboard_shortcuts.cpp
@@ -39,8 +39,6 @@
 #include "ui/accelerator.h"
 #include "ui/message.h"
 
-#include <algorithm>
-
 #define XML_KEYBOARD_FILE_VERSION "1"
 
 namespace {
@@ -80,6 +78,13 @@ namespace {
     return shortcut;
   }
 
+  bool bool_attr_is_true(const TiXmlElement* elem, const char* attribute_name)
+  {
+    const char* value = elem->Attribute(attribute_name);
+
+    return (value != NULL) && (strcmp(value, "true") == 0);
+  }
+
   std::string get_user_friendly_string_for_keyaction(app::KeyAction action)
   {
     for (int c=0; actions[c].name; ++c) {
@@ -118,6 +123,9 @@ namespace app {
 
 using namespace ui;
 
+//////////////////////////////////////////////////////////////////////
+// Key
+
 Key::Key(Command* command, const Params* params, KeyContext keyContext)
   : m_type(KeyType::Command)
   , m_useUsers(false)
@@ -141,12 +149,38 @@ Key::Key(KeyAction action)
   , m_keycontext(KeyContext::Any)
   , m_action(action)
 {
-}
-
-void Key::setUserAccels(const Accelerators& accels)
-{
-  m_useUsers = true;
-  m_users = accels;
+  switch (action) {
+    case KeyAction::None:
+      m_keycontext = KeyContext::Any;
+      break;
+    case KeyAction::CopySelection:
+      m_keycontext = KeyContext::MovingPixels;
+      break;
+    case KeyAction::SnapToGrid:
+      m_keycontext = KeyContext::MovingPixels;
+      break;
+    case KeyAction::AngleSnap:
+      m_keycontext = KeyContext::MovingPixels;
+      break;
+    case KeyAction::MaintainAspectRatio:
+      m_keycontext = KeyContext::MovingPixels;
+      break;
+    case KeyAction::LockAxis:
+      m_keycontext = KeyContext::MovingPixels;
+      break;
+    case KeyAction::AddSelection:
+      m_keycontext = KeyContext::Selection;
+      break;
+    case KeyAction::SubtractSelection:
+      m_keycontext = KeyContext::Selection;
+      break;
+    case KeyAction::LeftMouseButton:
+      m_keycontext = KeyContext::Any;
+      break;
+    case KeyAction::RightMouseButton:
+      m_keycontext = KeyContext::Any;
+      break;
+  }
 }
 
 void Key::add(const ui::Accelerator& accel, KeySource source)
@@ -159,11 +193,16 @@ void Key::add(const ui::Accelerator& accel, KeySource source)
       m_users = m_accels;
     }
     accels = &m_users;
+  }
 
-    KeyboardShortcuts::instance()->disableAccel(accel);
+  // Remove the accelerator from other commands
+  if (source == KeySource::UserDefined) {
+    KeyboardShortcuts::instance()->disableAccel(accel, m_keycontext);
+    m_userRemoved.remove(accel);
   }
 
-  accels->push_back(accel);
+  // Add the accelerator
+  accels->add(accel);
 }
 
 bool Key::isPressed(Message* msg) const
@@ -194,7 +233,7 @@ bool Key::checkFromAllegroKeyArray()
 
 bool Key::hasAccel(const ui::Accelerator& accel) const
 {
-  return (std::find(accels().begin(), accels().end(), accel) != accels().end());
+  return accels().has(accel);
 }
 
 void Key::disableAccel(const ui::Accelerator& accel)
@@ -204,14 +243,16 @@ void Key::disableAccel(const ui::Accelerator& accel)
     m_users = m_accels;
   }
 
-  Accelerators::iterator it = std::find(m_users.begin(), m_users.end(), accel);
-  if (it != m_users.end())
-    m_users.erase(it);
+  m_users.remove(accel);
+
+  if (m_accels.has(accel))
+    m_userRemoved.add(accel);
 }
 
 void Key::reset()
 {
   m_users.clear();
+  m_userRemoved.clear();
   m_useUsers = false;
 }
 
@@ -235,6 +276,9 @@ std::string Key::triggerString() const
   return "Unknown";
 }
 
+//////////////////////////////////////////////////////////////////////
+// KeyboardShortcuts
+
 KeyboardShortcuts* KeyboardShortcuts::instance()
 {
   static KeyboardShortcuts* singleton = NULL;
@@ -270,6 +314,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
   while (xmlKey) {
     const char* command_name = xmlKey->Attribute("command");
     const char* command_key = get_shortcut(xmlKey);
+    bool removed = bool_attr_is_true(xmlKey, "removed");
 
     if (command_name && command_key) {
       Command* command = CommandsModule::instance()->getCommandByName(command_name);
@@ -303,15 +348,21 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
         // add the keyboard shortcut to the command
         Key* key = this->command(command_name, &params, keycontext);
         if (key) {
-          key->add(Accelerator(command_key), source);
-
-          // Add the shortcut to the menuitems with this
-          // command (this is only visual, the "manager_msg_proc"
-          // is the only one that process keyboard shortcuts)
-          if (key->accels().size() == 1) {
-            AppMenus::instance()->applyShortcutToMenuitemsWithCommand(
-              command, &params, key);
+          Accelerator accel(command_key);
+
+          if (!removed) {
+            key->add(accel, source);
+
+            // Add the shortcut to the menuitems with this
+            // command (this is only visual, the "manager_msg_proc"
+            // is the only one that process keyboard shortcuts)
+            if (key->accels().size() == 1) {
+              AppMenus::instance()->applyShortcutToMenuitemsWithCommand(
+                command, &params, key);
+            }
           }
+          else
+            key->disableAccel(accel);
         }
       }
     }
@@ -327,6 +378,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
   while (xmlKey) {
     const char* tool_id = xmlKey->Attribute("tool");
     const char* tool_key = get_shortcut(xmlKey);
+    bool removed = bool_attr_is_true(xmlKey, "removed");
 
     if (tool_id && tool_key) {
       tools::Tool* tool = App::instance()->getToolBox()->getToolById(tool_id);
@@ -334,8 +386,14 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
         PRINTF(" - Shortcut for tool `%s': <%s>\n", tool_id, tool_key);
 
         Key* key = this->tool(tool);
-        if (key)
-          key->add(Accelerator(tool_key), source);
+        if (key) {
+          Accelerator accel(tool_key);
+
+          if (!removed)
+            key->add(accel, source);
+          else
+            key->disableAccel(accel);
+        }
       }
     }
     xmlKey = xmlKey->NextSiblingElement();
@@ -349,14 +407,22 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
   while (xmlKey) {
     const char* tool_id = xmlKey->Attribute("tool");
     const char* tool_key = get_shortcut(xmlKey);
+    bool removed = bool_attr_is_true(xmlKey, "removed");
+
     if (tool_id && tool_key) {
       tools::Tool* tool = App::instance()->getToolBox()->getToolById(tool_id);
       if (tool) {
         PRINTF(" - Shortcut for quicktool `%s': <%s>\n", tool_id, tool_key);
 
         Key* key = this->quicktool(tool);
-        if (key)
-          key->add(Accelerator(tool_key), source);
+        if (key) {
+          Accelerator accel(tool_key);
+
+          if (!removed)
+            key->add(accel, source);
+          else
+            key->disableAccel(accel);
+        }
       }
     }
     xmlKey = xmlKey->NextSiblingElement();
@@ -370,6 +436,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
   while (xmlKey) {
     const char* tool_action = xmlKey->Attribute("action");
     const char* tool_key = get_shortcut(xmlKey);
+    bool removed = bool_attr_is_true(xmlKey, "removed");
 
     if (tool_action && tool_key) {
       PRINTF(" - Shortcut for sprite editor `%s': <%s>\n", tool_action, tool_key);
@@ -378,8 +445,14 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
 
       if (action != KeyAction::None) {
         Key* key = this->action(action);
-        if (key)
-          key->add(Accelerator(tool_key), source);
+        if (key) {
+          Accelerator accel(tool_key);
+
+          if (!removed)
+            key->add(accel, source);
+          else
+            key->disableAccel(accel);
+        }
       }
     }
     xmlKey = xmlKey->NextSiblingElement();
@@ -424,41 +497,77 @@ void KeyboardShortcuts::exportKeys(TiXmlElement& parent, KeyType type)
 {
   for (Key* key : m_keys) {
     // Save only user defined accelerators.
-    if (key->type() != type || key->userAccels().empty())
+    if (key->type() != type)
       continue;
 
-    for (const ui::Accelerator& accel : key->userAccels()) {
-      TiXmlElement elem("key");
-
-      switch (key->type()) {
-        case KeyType::Command:
-          elem.SetAttribute("command", key->command()->short_name());
-          if (key->params()) {
-            for (const auto& param : *key->params()) {
-              if (param.second.empty())
-                continue;
-
-              TiXmlElement paramElem("param");
-              paramElem.SetAttribute("name", param.first.c_str());
-              paramElem.SetAttribute("value", param.second.c_str());
-              elem.InsertEndChild(paramElem);
-            }
-          }
+    for (const ui::Accelerator& accel : key->userRemovedAccels())
+      exportAccel(parent, key, accel, true);
+
+    for (const ui::Accelerator& accel : key->userAccels())
+      exportAccel(parent, key, accel, false);
+  }
+}
+
+void KeyboardShortcuts::exportAccel(TiXmlElement& parent, Key* key, const ui::Accelerator& accel, bool removed)
+{
+  TiXmlElement elem("key");
+
+  switch (key->type()) {
+
+    case KeyType::Command: {
+      const char* keycontextStr = NULL;
+
+      elem.SetAttribute("command", key->command()->short_name());
+
+      switch (key->keycontext()) {
+        case KeyContext::Any:
+          // Without "context" attribute
           break;
-        case KeyType::Tool:
-        case KeyType::Quicktool:
-          elem.SetAttribute("tool", key->tool()->getId().c_str());
+        case KeyContext::Normal:
+          keycontextStr = "Normal";
           break;
-        case KeyType::Action:
-          elem.SetAttribute("action",
-            base::convert_to<std::string>(key->action()).c_str());
+        case KeyContext::Selection:
+          keycontextStr = "Selection";
+          break;
+        case KeyContext::MovingPixels:
+          keycontextStr = "MovingPixels";
           break;
       }
 
-      elem.SetAttribute("shortcut", accel.toString().c_str());
-      parent.InsertEndChild(elem);
+      if (keycontextStr)
+        elem.SetAttribute("context", keycontextStr);
+
+      if (key->params()) {
+        for (const auto& param : *key->params()) {
+          if (param.second.empty())
+            continue;
+
+          TiXmlElement paramElem("param");
+          paramElem.SetAttribute("name", param.first.c_str());
+          paramElem.SetAttribute("value", param.second.c_str());
+          elem.InsertEndChild(paramElem);
+        }
+      }
+      break;
     }
+
+    case KeyType::Tool:
+    case KeyType::Quicktool:
+      elem.SetAttribute("tool", key->tool()->getId().c_str());
+      break;
+
+    case KeyType::Action:
+      elem.SetAttribute("action",
+        base::convert_to<std::string>(key->action()).c_str());
+      break;
   }
+
+  elem.SetAttribute("shortcut", accel.toString().c_str());
+
+  if (removed)
+    elem.SetAttribute("removed", "true");
+
+  parent.InsertEndChild(elem);
 }
 
 void KeyboardShortcuts::reset()
@@ -531,10 +640,10 @@ Key* KeyboardShortcuts::action(KeyAction action)
   return key;
 }
 
-void KeyboardShortcuts::disableAccel(const ui::Accelerator& accel)
+void KeyboardShortcuts::disableAccel(const ui::Accelerator& accel, KeyContext keyContext)
 {
   for (Key* key : m_keys) {
-    if (key->hasAccel(accel))
+    if (key->keycontext() == keyContext && key->hasAccel(accel))
       key->disableAccel(accel);
   }
 }
diff --git a/src/app/ui/keyboard_shortcuts.h b/src/app/ui/keyboard_shortcuts.h
index 4c70986..65a61aa 100644
--- a/src/app/ui/keyboard_shortcuts.h
+++ b/src/app/ui/keyboard_shortcuts.h
@@ -44,6 +44,7 @@ namespace app {
     Any,
     Normal,
     Selection,
+    MovingPixels,
   };
 
   enum class KeySource {
@@ -83,8 +84,7 @@ namespace app {
     }
     const ui::Accelerators& origAccels() const { return m_accels; }
     const ui::Accelerators& userAccels() const { return m_users; }
-
-    void setUserAccels(const ui::Accelerators& accels);
+    const ui::Accelerators& userRemovedAccels() const { return m_userRemoved; }
 
     void add(const ui::Accelerator& accel, KeySource source);
     bool isPressed(ui::Message* msg) const;
@@ -109,8 +109,9 @@ namespace app {
 
   private:
     KeyType m_type;
-    ui::Accelerators m_accels;
-    ui::Accelerators m_users;
+    ui::Accelerators m_accels;      // Default accelerators (from gui.xml)
+    ui::Accelerators m_users;       // User-defined accelerators
+    ui::Accelerators m_userRemoved; // Default accelerators removed by user
     bool m_useUsers;
     KeyContext m_keycontext;
 
@@ -149,7 +150,7 @@ namespace app {
     Key* quicktool(tools::Tool* tool);
     Key* action(KeyAction action);
 
-    void disableAccel(const ui::Accelerator& accel);
+    void disableAccel(const ui::Accelerator& accel, KeyContext keyContext);
 
     KeyContext getCurrentKeyContext();
     bool getCommandFromKeyMessage(ui::Message* msg, Command** command, Params** params);
@@ -159,6 +160,7 @@ namespace app {
     KeyboardShortcuts();
 
     void exportKeys(TiXmlElement& parent, KeyType type);
+    void exportAccel(TiXmlElement& parent, Key* key, const ui::Accelerator& accel, bool removed);
 
     Keys m_keys;
 
diff --git a/src/app/ui/select_accelerator.cpp b/src/app/ui/select_accelerator.cpp
index e5ee3e9..046136d 100644
--- a/src/app/ui/select_accelerator.cpp
+++ b/src/app/ui/select_accelerator.cpp
@@ -63,6 +63,12 @@ protected:
             keymsg->scancode(),
             keymsg->unicodeChar() > 32 ?
               std::tolower(keymsg->unicodeChar()): 0);
+
+          // Convert the accelerator to a string, and parse it
+          // again. Just to obtain the exact accelerator we'll read
+          // when we import the gui.xml file or an .aseprite-keys file.
+          m_accel = Accelerator(m_accel.toString());
+
           updateText();
 
           AccelChange(&m_accel);
@@ -84,8 +90,9 @@ protected:
   Accelerator m_accel;
 };
 
-SelectAccelerator::SelectAccelerator(const ui::Accelerator& accel)
+SelectAccelerator::SelectAccelerator(const ui::Accelerator& accel, KeyContext keyContext)
   : m_keyField(new KeyField(accel))
+  , m_keyContext(keyContext)
   , m_accel(accel)
   , m_modified(false)
 {
@@ -170,7 +177,8 @@ void SelectAccelerator::updateAssignedTo()
   std::string res = "None";
 
   for (Key* key : *KeyboardShortcuts::instance()) {
-    if (key->hasAccel(m_accel)) {
+    if (key->keycontext() == m_keyContext &&
+        key->hasAccel(m_accel)) {
       res = key->triggerString();
       break;
     }
diff --git a/src/app/ui/select_accelerator.h b/src/app/ui/select_accelerator.h
index 475d8c2..843fb28 100644
--- a/src/app/ui/select_accelerator.h
+++ b/src/app/ui/select_accelerator.h
@@ -20,6 +20,7 @@
 #define APP_UI_SELECT_ACCELERATOR_H_INCLUDED
 #pragma once
 
+#include "app/ui/keyboard_shortcuts.h"
 #include "ui/accelerator.h"
 
 #include "generated_select_accelerator.h"
@@ -28,7 +29,7 @@ namespace app {
 
   class SelectAccelerator : public app::gen::SelectAccelerator {
   public:
-    explicit SelectAccelerator(const ui::Accelerator& accelerator);
+    SelectAccelerator(const ui::Accelerator& accelerator, KeyContext keyContext);
 
     bool isModified() const { return m_modified; }
     const ui::Accelerator& accel() const { return m_accel; }
@@ -45,6 +46,7 @@ namespace app {
     class KeyField;
 
     KeyField* m_keyField;
+    KeyContext m_keyContext;
     ui::Accelerator m_origAccel;
     ui::Accelerator m_accel;
     bool m_modified;
diff --git a/src/ui/accelerator.cpp b/src/ui/accelerator.cpp
index d5a9885..4afcbc4 100644
--- a/src/ui/accelerator.cpp
+++ b/src/ui/accelerator.cpp
@@ -19,11 +19,16 @@
 #include <string>
 #include <vector>
 
+#include <algorithm>
+
 // #define REPORT_KEYS
 #define PREPROCESS_KEYS
 
 namespace ui {
 
+//////////////////////////////////////////////////////////////////////
+// Accelerator
+
 Accelerator::Accelerator()
   : m_modifiers(kKeyNoneModifier)
   , m_scancode(kKeyNil)
@@ -197,6 +202,8 @@ bool Accelerator::operator==(const Accelerator& other) const
       return true;
     else if (m_unicodeChar != 0)
       return (std::tolower(m_unicodeChar) == std::tolower(other.m_unicodeChar));
+    else               // Only comparing modifiers, and they are equal
+      return true;
   }
 
   return false;
@@ -345,11 +352,6 @@ std::string Accelerator::toString() const
 
 bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int unicodeChar) const
 {
-#ifdef REPORT_KEYS
-  char buf[256];
-  std::string buf2;
-#endif
-
   // Preprocess the character to be compared with the accelerator
 #ifdef PREPROCESS_KEYS
   // Directly scancode
@@ -411,15 +413,18 @@ bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int unicod
 
   if ((m_modifiers == modifiers) &&
       ((m_scancode != kKeyNil && m_scancode == scancode) ||
-       (m_unicodeChar && m_unicodeChar == unicodeChar))) {
+       (m_unicodeChar && m_unicodeChar == unicodeChar) ||
+       (m_scancode == kKeyNil && scancode == kKeyNil && !m_unicodeChar && !unicodeChar))) {
 #ifdef REPORT_KEYS
     printf("true\n");
+    fflush(stdout);
 #endif
     return true;
   }
 
 #ifdef REPORT_KEYS
   printf("false\n");
+  fflush(stdout);
 #endif
   return false;
 }
@@ -439,4 +444,25 @@ bool Accelerator::checkFromAllegroKeyArray() const
           (m_modifiers == modifiers));
 }
 
+//////////////////////////////////////////////////////////////////////
+// Accelerators
+
+bool Accelerators::has(const Accelerator& accel) const
+{
+  return (std::find(begin(), end(), accel) != end());
+}
+
+void Accelerators::add(const Accelerator& accel)
+{
+  if (!has(accel))
+    m_list.push_back(accel);
+}
+
+void Accelerators::remove(const Accelerator& accel)
+{
+  auto it = std::find(begin(), end(), accel);
+  if (it != end())
+    m_list.erase(it);
+}
+
 } // namespace ui
diff --git a/src/ui/accelerator.h b/src/ui/accelerator.h
index 7014374..cecc663 100644
--- a/src/ui/accelerator.h
+++ b/src/ui/accelerator.h
@@ -43,7 +43,38 @@ namespace ui {
     int m_unicodeChar;
   };
 
-  typedef std::vector<Accelerator> Accelerators;
+  class Accelerators {
+  public:
+    typedef std::vector<Accelerator> List;
+    typedef List::iterator iterator;
+    typedef List::const_iterator const_iterator;
+
+    iterator begin() { return m_list.begin(); }
+    iterator end() { return m_list.end(); }
+    const_iterator begin() const { return m_list.begin(); }
+    const_iterator end() const { return m_list.end(); }
+
+    bool empty() const { return m_list.empty(); }
+    size_t size() const { return m_list.size(); }
+
+    const ui::Accelerator& front() const { return m_list.front(); }
+
+    const ui::Accelerator& operator[](int index) const {
+      return m_list[index];
+    }
+
+    ui::Accelerator& operator[](int index) {
+      return m_list[index];
+    }
+
+    void clear() { m_list.clear(); }
+    bool has(const Accelerator& accel) const;
+    void add(const Accelerator& accel);
+    void remove(const Accelerator& accel);
+
+  private:
+    List m_list;
+  };
 
 } // namespace ui
 

-- 
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