mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-21 13:45:38 +00:00
(Android) Added initial touch overlay support
This commit is contained in:
parent
d50a062f5e
commit
e91512a519
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -36,6 +36,7 @@ es-de.worker.js
|
|||
# Android
|
||||
/android
|
||||
/logback.log
|
||||
es-core/src/InputOverlay.*
|
||||
es-core/src/utils/PlatformUtilAndroid.*
|
||||
|
||||
# AppImage
|
||||
|
|
|
@ -1144,6 +1144,20 @@ void GuiMenu::openInputDeviceOptions()
|
|||
}
|
||||
});
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// Whether to enable the touch overlay.
|
||||
auto inputTouchOverlay = std::make_shared<SwitchComponent>();
|
||||
inputTouchOverlay->setState(Settings::getInstance()->getBool("InputTouchOverlay"));
|
||||
s->addWithLabel("ENABLE TOUCH OVERLAY", inputTouchOverlay);
|
||||
s->addSaveFunc([inputTouchOverlay, s] {
|
||||
if (Settings::getInstance()->getBool("InputTouchOverlay") !=
|
||||
inputTouchOverlay->getState()) {
|
||||
Settings::getInstance()->setBool("InputTouchOverlay", inputTouchOverlay->getState());
|
||||
s->setNeedsSaving();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
// Whether to only accept input from the first controller.
|
||||
auto inputOnlyFirstController = std::make_shared<SwitchComponent>();
|
||||
inputOnlyFirstController->setState(
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <SDL2/SDL_timer.h>
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "InputOverlay.h"
|
||||
#include "utils/PlatformUtilAndroid.h"
|
||||
#endif
|
||||
|
||||
|
@ -890,6 +891,8 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
InputOverlay::getInstance();
|
||||
|
||||
LOG(LogDebug) << "Android API level: " << SDL_GetAndroidSDKVersion();
|
||||
Utils::Platform::Android::printDeviceInfo();
|
||||
int storageState {SDL_AndroidGetExternalStorageState()};
|
||||
|
|
|
@ -170,7 +170,9 @@ set(CORE_SOURCES
|
|||
)
|
||||
|
||||
if(ANDROID)
|
||||
set(CORE_HEADERS ${CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/src/InputOverlay.h)
|
||||
set(CORE_HEADERS ${CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/PlatformUtilAndroid.h)
|
||||
set(CORE_HEADERS ${CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/src/InputOverlay.cpp)
|
||||
set(CORE_SOURCES ${CORE_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/PlatformUtilAndroid.cpp)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
#include <vector>
|
||||
|
||||
#define DEVICE_KEYBOARD -1
|
||||
#define DEVICE_CEC -2
|
||||
#define DEVICE_TOUCH -2
|
||||
#define DEVICE_CEC -3
|
||||
|
||||
enum InputType {
|
||||
TYPE_AXIS,
|
||||
TYPE_BUTTON,
|
||||
TYPE_KEY,
|
||||
TYPE_TOUCH,
|
||||
TYPE_CEC_BUTTON,
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
#include <pugixml.hpp>
|
||||
|
||||
#define KEYBOARD_GUID_STRING "-1"
|
||||
#define CEC_GUID_STRING "-2"
|
||||
#define TOUCH_GUID_STRING "-2"
|
||||
#define CEC_GUID_STRING "-3"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -32,7 +33,12 @@ namespace
|
|||
|
||||
InputManager::InputManager() noexcept
|
||||
: mWindow {Window::getInstance()}
|
||||
#if defined(__ANDROID__)
|
||||
, mInputOverlay {InputOverlay::getInstance()}
|
||||
#endif
|
||||
, mKeyboardInputConfig {nullptr}
|
||||
, mTouchInputConfig {nullptr}
|
||||
, mCECInputConfig {nullptr}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -81,6 +87,11 @@ void InputManager::init()
|
|||
LOG(LogInfo) << "Added keyboard with default configuration";
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
mTouchInputConfig = std::make_unique<InputConfig>(DEVICE_TOUCH, "Touch", TOUCH_GUID_STRING);
|
||||
loadTouchConfig();
|
||||
#endif
|
||||
|
||||
// Load optional controller mappings. Normally the supported controllers should be compiled
|
||||
// into SDL as a header file, but if a user has a very rare controller that is not supported,
|
||||
// the bundled mapping is incorrect, or the SDL version is a bit older, it makes sense to be
|
||||
|
@ -136,6 +147,7 @@ void InputManager::deinit()
|
|||
mInputConfigs.clear();
|
||||
|
||||
mKeyboardInputConfig.reset();
|
||||
mTouchInputConfig.reset();
|
||||
mCECInputConfig.reset();
|
||||
|
||||
SDL_GameControllerEventState(SDL_DISABLE);
|
||||
|
@ -284,6 +296,11 @@ int InputManager::getNumConfiguredDevices()
|
|||
if (mKeyboardInputConfig->isConfigured())
|
||||
++num;
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
if (mTouchInputConfig->isConfigured())
|
||||
++num;
|
||||
#endif
|
||||
|
||||
if (mCECInputConfig->isConfigured())
|
||||
++num;
|
||||
|
||||
|
@ -313,8 +330,11 @@ std::string InputManager::getDeviceGUIDString(int deviceId)
|
|||
{
|
||||
if (deviceId == DEVICE_KEYBOARD)
|
||||
return KEYBOARD_GUID_STRING;
|
||||
|
||||
if (deviceId == DEVICE_CEC)
|
||||
#if defined(__ANDROID__)
|
||||
else if (deviceId == DEVICE_TOUCH)
|
||||
return TOUCH_GUID_STRING;
|
||||
#endif
|
||||
else if (deviceId == DEVICE_CEC)
|
||||
return CEC_GUID_STRING;
|
||||
|
||||
auto it = mJoysticks.find(deviceId);
|
||||
|
@ -333,6 +353,10 @@ InputConfig* InputManager::getInputConfigByDevice(int device)
|
|||
{
|
||||
if (device == DEVICE_KEYBOARD)
|
||||
return mKeyboardInputConfig.get();
|
||||
#if defined(__ANDROID__)
|
||||
else if (device == DEVICE_TOUCH)
|
||||
return mTouchInputConfig.get();
|
||||
#endif
|
||||
else if (device == DEVICE_CEC)
|
||||
return mCECInputConfig.get();
|
||||
else
|
||||
|
@ -510,6 +534,62 @@ bool InputManager::parseEvent(const SDL_Event& event)
|
|||
Input(DEVICE_KEYBOARD, TYPE_KEY, event.key.keysym.sym, 0, false));
|
||||
return true;
|
||||
}
|
||||
#if defined(__ANDROID__)
|
||||
case SDL_FINGERDOWN: {
|
||||
if (!Settings::getInstance()->getBool("InputTouchOverlay"))
|
||||
return false;
|
||||
|
||||
const int buttonID {mInputOverlay.getButtonId(
|
||||
SDL_FINGERDOWN, event.tfinger.fingerId + 1, event.tfinger.x, event.tfinger.y)};
|
||||
if (buttonID != -2) {
|
||||
mWindow->input(getInputConfigByDevice(DEVICE_TOUCH),
|
||||
Input(DEVICE_TOUCH, TYPE_TOUCH, buttonID, 1, false));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case SDL_FINGERUP: {
|
||||
if (!Settings::getInstance()->getBool("InputTouchOverlay"))
|
||||
return false;
|
||||
|
||||
const int buttonID {mInputOverlay.getButtonId(SDL_FINGERUP, event.tfinger.fingerId + 1,
|
||||
event.tfinger.x, event.tfinger.y)};
|
||||
if (buttonID != -2) {
|
||||
mWindow->input(getInputConfigByDevice(DEVICE_TOUCH),
|
||||
Input(DEVICE_TOUCH, TYPE_TOUCH, buttonID, 0, false));
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case SDL_FINGERMOTION: {
|
||||
if (!Settings::getInstance()->getBool("InputTouchOverlay"))
|
||||
return false;
|
||||
|
||||
bool releasedButton {false};
|
||||
const int buttonID {
|
||||
mInputOverlay.getButtonId(SDL_FINGERMOTION, event.tfinger.fingerId + 1,
|
||||
event.tfinger.x, event.tfinger.y, &releasedButton)};
|
||||
|
||||
if (buttonID == -2)
|
||||
return false;
|
||||
|
||||
if (releasedButton) {
|
||||
mWindow->input(getInputConfigByDevice(DEVICE_TOUCH),
|
||||
Input(DEVICE_TOUCH, TYPE_TOUCH, buttonID, 0, false));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
mWindow->input(getInputConfigByDevice(DEVICE_TOUCH),
|
||||
Input(DEVICE_TOUCH, TYPE_TOUCH, buttonID, 1, false));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
case SDL_TEXTINPUT: {
|
||||
mWindow->textInput(event.text.text);
|
||||
break;
|
||||
|
@ -646,6 +726,31 @@ void InputManager::loadDefaultControllerConfig(SDL_JoystickID deviceIndex)
|
|||
// clang-format on
|
||||
}
|
||||
|
||||
void InputManager::loadTouchConfig()
|
||||
{
|
||||
InputConfig* cfg {mTouchInputConfig.get()};
|
||||
|
||||
if (cfg->isConfigured())
|
||||
return;
|
||||
|
||||
// clang-format off
|
||||
cfg->mapInput("Up", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_DPAD_UP, 1, true));
|
||||
cfg->mapInput("Down", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_DPAD_DOWN, 1, true));
|
||||
cfg->mapInput("Left", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_DPAD_LEFT, 1, true));
|
||||
cfg->mapInput("Right", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, 1, true));
|
||||
cfg->mapInput("Start", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_START, 1, true));
|
||||
cfg->mapInput("Back", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_BACK, 1, true));
|
||||
cfg->mapInput("A", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_A, 1, true));
|
||||
cfg->mapInput("B", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_B, 1, true));
|
||||
cfg->mapInput("X", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_X, 1, true));
|
||||
cfg->mapInput("Y", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_Y, 1, true));
|
||||
cfg->mapInput("LeftShoulder", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, 1, true));
|
||||
cfg->mapInput("RightShoulder", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, 1, true));
|
||||
cfg->mapInput("LeftTrigger", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 1, true));
|
||||
cfg->mapInput("RightTrigger", Input(DEVICE_TOUCH, TYPE_TOUCH, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 1, true));
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void InputManager::addControllerByDeviceIndex(Window* window, int deviceIndex)
|
||||
{
|
||||
// Open joystick and add it to our list.
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define ES_CORE_INPUT_MANAGER_H
|
||||
|
||||
#include "CECInput.h"
|
||||
#include "InputOverlay.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_joystick.h>
|
||||
|
@ -57,12 +58,16 @@ private:
|
|||
bool loadInputConfig(InputConfig* config);
|
||||
void loadDefaultKBConfig();
|
||||
void loadDefaultControllerConfig(SDL_JoystickID deviceIndex);
|
||||
void loadTouchConfig();
|
||||
|
||||
void addControllerByDeviceIndex(Window* window, int deviceIndex);
|
||||
void removeControllerByJoystickID(Window* window, SDL_JoystickID joyID);
|
||||
|
||||
Window* mWindow;
|
||||
CECInput mCECInput;
|
||||
#if defined(__ANDROID__)
|
||||
InputOverlay& mInputOverlay;
|
||||
#endif
|
||||
|
||||
static const int DEADZONE_TRIGGERS = 18000;
|
||||
static const int DEADZONE_THUMBSTICKS = 23000;
|
||||
|
@ -73,6 +78,7 @@ private:
|
|||
std::map<SDL_JoystickID, std::unique_ptr<InputConfig>> mInputConfigs;
|
||||
|
||||
std::unique_ptr<InputConfig> mKeyboardInputConfig;
|
||||
std::unique_ptr<InputConfig> mTouchInputConfig;
|
||||
std::unique_ptr<InputConfig> mCECInputConfig;
|
||||
|
||||
std::map<std::pair<SDL_JoystickID, int>, int> mPrevAxisValues;
|
||||
|
|
|
@ -239,6 +239,9 @@ void Settings::setDefaults()
|
|||
|
||||
// Input device settings.
|
||||
mStringMap["InputControllerType"] = {"xbox", "xbox"};
|
||||
#if defined(__ANDROID__)
|
||||
mBoolMap["InputTouchOverlay"] = {true, true};
|
||||
#endif
|
||||
mBoolMap["InputOnlyFirstController"] = {false, false};
|
||||
mBoolMap["InputIgnoreKeyboard"] = {false, false};
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
#include "guis/GuiInfoPopup.h"
|
||||
#include "resources/Font.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "InputOverlay.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
|
@ -662,6 +666,11 @@ void Window::render()
|
|||
if (mRenderScreensaver)
|
||||
mScreensaver->renderScreensaver();
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
if (Settings::getInstance()->getBool("InputTouchOverlay"))
|
||||
InputOverlay::getInstance().render(mRenderer->getIdentity());
|
||||
#endif
|
||||
|
||||
if (Settings::getInstance()->getBool("DisplayGPUStatistics") && mFrameDataText) {
|
||||
mRenderer->setMatrix(mRenderer->getIdentity());
|
||||
mDefaultFonts.at(1)->renderTextCache(mFrameDataText.get());
|
||||
|
|
22
resources/graphics/overlay/button_a.svg
Normal file
22
resources/graphics/overlay/button_a.svg
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="52"
|
||||
height="52"
|
||||
version="1.1"
|
||||
viewBox="0 0 52 52"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:0.25;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.735;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers stroke fill;stop-color:#000000"
|
||||
id="path949"
|
||||
cx="26"
|
||||
cy="26"
|
||||
r="25.13261" />
|
||||
<path
|
||||
id="rect852"
|
||||
style="fill:#ffffff;fill-opacity:0.25;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.735;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill;stop-color:#000000"
|
||||
d="M 21.761353,11.664063 14.67151,40.335937 h 6.855469 L 23.10901,33.34375 h 5.761719 l 1.582031,6.992187 h 6.874997 L 30.218385,11.664063 Z m 4.238282,8.749999 1.699218,7.519531 h -3.359374 c 0.898437,-4.010417 1.451823,-6.516925 1.660156,-7.519531 z" />
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
22
resources/graphics/overlay/button_b.svg
Normal file
22
resources/graphics/overlay/button_b.svg
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="52"
|
||||
height="52"
|
||||
version="1.1"
|
||||
viewBox="0 0 52 52"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:0.25;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.735;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers stroke fill;stop-color:#000000"
|
||||
id="path949"
|
||||
cx="26"
|
||||
cy="26"
|
||||
r="25.13261" />
|
||||
<path
|
||||
id="button_b"
|
||||
d="m 17.230469,11.722656 v 28.554688 h 9.160156 c 2.552083,-0.02604 4.583333,-0.781249 6.09375,-2.265625 1.523437,-1.497395 2.285156,-3.561197 2.285156,-6.191406 0,-1.692708 -0.32552,-3.072916 -0.976562,-4.140625 -0.63802,-1.080729 -1.653646,-1.888021 -3.046875,-2.421875 1.002604,-0.377604 1.770833,-0.989584 2.304687,-1.835938 0.78125,-1.184896 1.171875,-2.604166 1.171875,-4.257812 0,-2.591146 -0.722656,-4.479167 -2.167968,-5.664063 -1.445313,-1.184896 -3.756511,-1.777344 -6.933594,-1.777344 z m 6.503906,5.292969 h 1.347656 c 0.807292,0 1.393229,0.221355 1.757813,0.664063 0.377604,0.442709 0.566406,1.171875 0.566406,2.1875 0,1.002604 -0.16276,1.757813 -0.488281,2.265625 -0.32552,0.494792 -0.872396,0.742187 -1.640625,0.742187 h -1.542969 z m 0,10.996094 h 1.699219 c 1.614583,0 2.421875,1.10026 2.421875,3.300781 0,2.408854 -0.78125,3.613281 -2.34375,3.613281 h -1.777344 z"
|
||||
style="fill:#ffffff;fill-opacity:0.25;stroke:#ffffff;stroke-width:1.735;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.998283" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
16
resources/graphics/overlay/button_dpad.svg
Normal file
16
resources/graphics/overlay/button_dpad.svg
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="52"
|
||||
height="40"
|
||||
version="1.1"
|
||||
viewBox="0 0 52 40"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<path
|
||||
id="rect6831"
|
||||
style="opacity:1;fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.74532;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill;stop-color:#000000;stop-opacity:1;fill-opacity:0.25"
|
||||
d="M 0.8722719,0.87265904 V 39.127341 H 31.564741 L 50.76394,19.999999 31.564741,0.87265904 Z" />
|
||||
</svg>
|
After Width: | Height: | Size: 664 B |
22
resources/graphics/overlay/button_x.svg
Normal file
22
resources/graphics/overlay/button_x.svg
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="52"
|
||||
height="52"
|
||||
version="1.1"
|
||||
viewBox="0 0 52 52"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:0.25;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.735;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers stroke fill;stop-color:#000000"
|
||||
id="path949"
|
||||
cx="26"
|
||||
cy="26"
|
||||
r="25.13261" />
|
||||
<path
|
||||
id="rect1405"
|
||||
style="fill:#ffffff;fill-opacity:0.25;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.735;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers stroke fill;stop-color:#000000"
|
||||
d="m 16.259727,11.722656 6.054687,13.730469 -6.523437,14.824219 h 7.070312 l 3.007813,-8.144532 3.28125,8.144532 h 7.050781 L 29.677695,25.667968 35.712852,11.722656 h -7.109375 l -2.539063,7.265625 -2.929687,-7.265625 z" />
|
||||
</svg>
|
After Width: | Height: | Size: 1,011 B |
22
resources/graphics/overlay/button_y.svg
Normal file
22
resources/graphics/overlay/button_y.svg
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="52"
|
||||
height="52"
|
||||
version="1.1"
|
||||
viewBox="0 0 52 52"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:0.25;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.735;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;paint-order:markers stroke fill;stop-color:#000000"
|
||||
id="path949"
|
||||
cx="26"
|
||||
cy="26"
|
||||
r="25.13261" />
|
||||
<path
|
||||
id="button_y"
|
||||
d="M 15.88925,11.722656 22.608,28.949219 v 11.328125 h 6.757812 V 28.753906 l 6.738281,-17.03125 h -7.109375 c -1.015625,3.072917 -2.005208,6.022136 -2.96875,8.847656 l -2.988281,-8.847656 z"
|
||||
style="fill:#ffffff;fill-opacity:0.25;stroke:#ffffff;stroke-width:1.735;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 907 B |
Loading…
Reference in a new issue