core/hid: Fully implement native mouse

This commit is contained in:
german77
2021-11-14 14:09:29 -06:00
committed by Narr the Reg
parent bca299e8e0
commit 654d76e79e
21 changed files with 323 additions and 1039 deletions

View File

@ -90,9 +90,6 @@ add_executable(yuzu
configuration/configure_motion_touch.cpp
configuration/configure_motion_touch.h
configuration/configure_motion_touch.ui
configuration/configure_mouse_advanced.cpp
configuration/configure_mouse_advanced.h
configuration/configure_mouse_advanced.ui
configuration/configure_per_game.cpp
configuration/configure_per_game.h
configuration/configure_per_game.ui

View File

@ -746,6 +746,12 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
input_subsystem->GetMouse()->ReleaseButton(button);
}
void GRenderWindow::wheelEvent(QWheelEvent* event) {
const int x = event->delta();
const int y = 0;
input_subsystem->GetMouse()->MouseWheelChange(x, y);
}
void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints();
for (const auto& touch_point : touch_points) {

View File

@ -173,6 +173,7 @@ public:
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
bool event(QEvent* event) override;

View File

@ -60,11 +60,6 @@ const std::array<int, 2> Config::default_stick_mod = {
0,
};
const std::array<int, Settings::NativeMouseButton::NumMouseButtons> Config::default_mouse_buttons =
{
Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal,
};
// This shouldn't have anything except static initializers (no functions). So
// QKeySequence(...).toString() is NOT ALLOWED HERE.
// This must be in alphabetical order according to action name as it must have the same order as
@ -348,22 +343,6 @@ void Config::ReadKeyboardValues() {
void Config::ReadMouseValues() {
ReadBasicSetting(Settings::values.mouse_enabled);
for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
const std::string default_param =
InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
auto& mouse_buttons = Settings::values.mouse_buttons[i];
mouse_buttons = qt_config
->value(QStringLiteral("mouse_") +
QString::fromUtf8(Settings::NativeMouseButton::mapping[i]),
QString::fromStdString(default_param))
.toString()
.toStdString();
if (mouse_buttons.empty()) {
mouse_buttons = default_param;
}
}
}
void Config::ReadTouchscreenValues() {
@ -947,15 +926,6 @@ void Config::SaveDebugValues() {
void Config::SaveMouseValues() {
WriteBasicSetting(Settings::values.mouse_enabled);
for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
const std::string default_param =
InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]);
WriteSetting(QStringLiteral("mouse_") +
QString::fromStdString(Settings::NativeMouseButton::mapping[i]),
QString::fromStdString(Settings::values.mouse_buttons[i]),
QString::fromStdString(default_param));
}
}
void Config::SaveTouchscreenValues() {

View File

@ -24,7 +24,6 @@
#include "yuzu/configuration/configure_input_advanced.h"
#include "yuzu/configuration/configure_input_player.h"
#include "yuzu/configuration/configure_motion_touch.h"
#include "yuzu/configuration/configure_mouse_advanced.h"
#include "yuzu/configuration/configure_touchscreen_advanced.h"
#include "yuzu/configuration/configure_vibration.h"
#include "yuzu/configuration/input_profiles.h"
@ -157,9 +156,6 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
CallConfigureDialog<ConfigureDebugController>(
*this, input_subsystem, profiles.get(), hid_core, is_powered_on);
});
connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] {
CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem);
});
connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog,
[this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); });
connect(advanced, &ConfigureInputAdvanced::CallMotionTouchConfigDialog,

View File

@ -82,7 +82,6 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
connect(ui->debug_configure, &QPushButton::clicked, this,
[this] { CallDebugControllerDialog(); });
connect(ui->mouse_advanced, &QPushButton::clicked, this, [this] { CallMouseConfigDialog(); });
connect(ui->touchscreen_advanced, &QPushButton::clicked, this,
[this] { CallTouchscreenConfigDialog(); });
connect(ui->buttonMotionTouch, &QPushButton::clicked, this,
@ -178,7 +177,6 @@ void ConfigureInputAdvanced::RetranslateUI() {
}
void ConfigureInputAdvanced::UpdateUIEnabled() {
ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked());
ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
}

View File

@ -2528,11 +2528,11 @@
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="gridGroupBox_3">
<widget class="QGroupBox" name="emulatedDevicesGroupBox">
<property name="title">
<string>Other</string>
<string>Emulated Devices</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<layout class="QGridLayout" name="emulatedDevicesGridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="keyboard_enabled">
<property name="minimumSize">
@ -2547,7 +2547,7 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="emulate_analog_keyboard">
<widget class="QCheckBox" name="mouse_enabled">
<property name="minimumSize">
<size>
<width>0</width>
@ -2555,53 +2555,18 @@
</size>
</property>
<property name="text">
<string>Emulate Analog with Keyboard Input</string>
<string>Mouse</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="mouse_panning">
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<widget class="QCheckBox" name="touchscreen_enabled">
<property name="text">
<string>Enable mouse panning</string>
<string>Touchscreen</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="mouse_panning_sensitivity">
<property name="toolTip">
<string>Mouse sensitivity</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QPushButton" name="touchscreen_advanced">
<property name="text">
<string>Advanced</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1">
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -2617,80 +2582,117 @@
</property>
</spacer>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="mouse_advanced">
<property name="text">
<string>Advanced</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="touchscreen_enabled">
<property name="text">
<string>Touchscreen</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="touchscreen_advanced">
<property name="text">
<string>Advanced</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="mouse_enabled">
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Mouse</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="motion_touch">
<property name="text">
<string>Motion / Touch</string>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QPushButton" name="buttonMotionTouch">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="debug_enabled">
<property name="text">
<string>Debug Controller</string>
</property>
</widget>
</item>
<item row="7" column="2">
<item row="3" column="2">
<widget class="QPushButton" name="debug_configure">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QCheckBox" name="enable_raw_input">
<property name="toolTip">
<string>Requires restarting yuzu</string>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Enable XInput 8 player support (disables web applet)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="otherGroupBox">
<property name="title">
<string>Other</string>
</property>
<layout class="QGridLayout" name="OtherGridLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="emulate_analog_keyboard">
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Emulate Analog with Keyboard Input</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="enable_raw_input">
<property name="toolTip">
<string>Requires restarting yuzu</string>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Enable XInput 8 player support (disables web applet)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="mouse_panning">
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Enable mouse panning</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="mouse_panning_sensitivity">
<property name="toolTip">
<string>Mouse sensitivity</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="motion_touch">
<property name="text">
<string>Motion / Touch</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="buttonMotionTouch">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View File

@ -1,247 +0,0 @@
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <memory>
#include <QKeyEvent>
#include <QMenu>
#include <QTimer>
#include "common/assert.h"
#include "common/param_package.h"
#include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h"
#include "input_common/main.h"
#include "ui_configure_mouse_advanced.h"
#include "yuzu/bootmanager.h"
#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_mouse_advanced.h"
static QString GetKeyName(int key_code) {
switch (key_code) {
case Qt::LeftButton:
return QObject::tr("Click 0");
case Qt::RightButton:
return QObject::tr("Click 1");
case Qt::MiddleButton:
return QObject::tr("Click 2");
case Qt::BackButton:
return QObject::tr("Click 3");
case Qt::ForwardButton:
return QObject::tr("Click 4");
case Qt::Key_Shift:
return QObject::tr("Shift");
case Qt::Key_Control:
return QObject::tr("Ctrl");
case Qt::Key_Alt:
return QObject::tr("Alt");
case Qt::Key_Meta:
return {};
default:
return QKeySequence(key_code).toString();
}
}
static QString ButtonToText(const Common::ParamPackage& param) {
if (!param.Has("engine")) {
return QObject::tr("[not set]");
}
if (param.Get("engine", "") == "keyboard") {
return GetKeyName(param.Get("code", 0));
}
if (param.Get("engine", "") == "sdl") {
if (param.Has("hat")) {
const QString hat_str = QString::fromStdString(param.Get("hat", ""));
const QString direction_str = QString::fromStdString(param.Get("direction", ""));
return QObject::tr("Hat %1 %2").arg(hat_str, direction_str);
}
if (param.Has("axis")) {
const QString axis_str = QString::fromStdString(param.Get("axis", ""));
const QString direction_str = QString::fromStdString(param.Get("direction", ""));
return QObject::tr("Axis %1%2").arg(axis_str, direction_str);
}
if (param.Has("button")) {
const QString button_str = QString::fromStdString(param.Get("button", ""));
return QObject::tr("Button %1").arg(button_str);
}
return {};
}
return QObject::tr("[unknown]");
}
ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent,
InputCommon::InputSubsystem* input_subsystem_)
: QDialog(parent),
ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), input_subsystem{input_subsystem_},
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
ui->setupUi(this);
setFocusPolicy(Qt::ClickFocus);
button_map = {
ui->left_button, ui->right_button, ui->middle_button, ui->forward_button, ui->back_button,
};
for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) {
auto* const button = button_map[button_id];
if (button == nullptr) {
continue;
}
button->setContextMenuPolicy(Qt::CustomContextMenu);
connect(button, &QPushButton::clicked, [=, this] {
HandleClick(
button_map[button_id],
[=, this](const Common::ParamPackage& params) {
buttons_param[button_id] = params;
},
InputCommon::Polling::InputType::Button);
});
connect(button, &QPushButton::customContextMenuRequested,
[=, this](const QPoint& menu_location) {
QMenu context_menu;
context_menu.addAction(tr("Clear"), [&] {
buttons_param[button_id].Clear();
button_map[button_id]->setText(tr("[not set]"));
});
context_menu.addAction(tr("Restore Default"), [&] {
buttons_param[button_id] =
Common::ParamPackage{InputCommon::GenerateKeyboardParam(
Config::default_mouse_buttons[button_id])};
button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
});
context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
});
}
connect(ui->buttonClearAll, &QPushButton::clicked, [this] { ClearAll(); });
connect(ui->buttonRestoreDefaults, &QPushButton::clicked, [this] { RestoreDefaults(); });
timeout_timer->setSingleShot(true);
connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
connect(poll_timer.get(), &QTimer::timeout, [this] {
const auto& params = input_subsystem->GetNextInput();
if (params.Has("engine")) {
SetPollingResult(params, false);
return;
}
});
LoadConfiguration();
resize(0, 0);
}
ConfigureMouseAdvanced::~ConfigureMouseAdvanced() = default;
void ConfigureMouseAdvanced::ApplyConfiguration() {
std::transform(buttons_param.begin(), buttons_param.end(),
Settings::values.mouse_buttons.begin(),
[](const Common::ParamPackage& param) { return param.Serialize(); });
}
void ConfigureMouseAdvanced::LoadConfiguration() {
std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(),
buttons_param.begin(),
[](const std::string& str) { return Common::ParamPackage(str); });
UpdateButtonLabels();
}
void ConfigureMouseAdvanced::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
}
QDialog::changeEvent(event);
}
void ConfigureMouseAdvanced::RetranslateUI() {
ui->retranslateUi(this);
}
void ConfigureMouseAdvanced::RestoreDefaults() {
for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) {
buttons_param[button_id] = Common::ParamPackage{
InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])};
}
UpdateButtonLabels();
}
void ConfigureMouseAdvanced::ClearAll() {
for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) {
const auto* const button = button_map[i];
if (button != nullptr && button->isEnabled()) {
buttons_param[i].Clear();
}
}
UpdateButtonLabels();
}
void ConfigureMouseAdvanced::UpdateButtonLabels() {
for (int button = 0; button < Settings::NativeMouseButton::NumMouseButtons; button++) {
button_map[button]->setText(ButtonToText(buttons_param[button]));
}
}
void ConfigureMouseAdvanced::HandleClick(
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
InputCommon::Polling::InputType type) {
button->setText(tr("[press key]"));
button->setFocus();
input_setter = new_input_setter;
input_subsystem->BeginMapping(type);
QWidget::grabMouse();
QWidget::grabKeyboard();
timeout_timer->start(2500); // Cancel after 2.5 seconds
poll_timer->start(50); // Check for new inputs every 50ms
}
void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) {
timeout_timer->stop();
poll_timer->stop();
input_subsystem->StopMapping();
QWidget::releaseMouse();
QWidget::releaseKeyboard();
if (!abort) {
(*input_setter)(params);
}
UpdateButtonLabels();
input_setter = std::nullopt;
}
void ConfigureMouseAdvanced::mousePressEvent(QMouseEvent* event) {
if (!input_setter || !event) {
return;
}
const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
}
void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) {
if (!input_setter || !event) {
return;
}
if (event->key() != Qt::Key_Escape) {
input_subsystem->GetKeyboard()->PressKey(event->key());
}
}

View File

@ -1,72 +0,0 @@
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <optional>
#include <QDialog>
class QCheckBox;
class QPushButton;
class QTimer;
namespace InputCommon {
class InputSubsystem;
}
namespace Ui {
class ConfigureMouseAdvanced;
}
class ConfigureMouseAdvanced : public QDialog {
Q_OBJECT
public:
explicit ConfigureMouseAdvanced(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_);
~ConfigureMouseAdvanced() override;
void ApplyConfiguration();
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();
/// Load configuration settings.
void LoadConfiguration();
/// Restore all buttons to their default values.
void RestoreDefaults();
/// Clear all input configuration
void ClearAll();
/// Update UI to reflect current configuration.
void UpdateButtonLabels();
/// Called when the button was pressed.
void HandleClick(QPushButton* button,
std::function<void(const Common::ParamPackage&)> new_input_setter,
InputCommon::Polling::InputType type);
/// Finish polling and configure input using the input_setter
void SetPollingResult(const Common::ParamPackage& params, bool abort);
/// Handle mouse button press events.
void mousePressEvent(QMouseEvent* event) override;
/// Handle key press events.
void keyPressEvent(QKeyEvent* event) override;
std::unique_ptr<Ui::ConfigureMouseAdvanced> ui;
InputCommon::InputSubsystem* input_subsystem;
/// This will be the the setting function when an input is awaiting configuration.
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
std::array<QPushButton*, Settings::NativeMouseButton::NumMouseButtons> button_map;
std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons> buttons_param;
std::unique_ptr<QTimer> timeout_timer;
std::unique_ptr<QTimer> poll_timer;
};

View File

@ -1,335 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureMouseAdvanced</class>
<widget class="QDialog" name="ConfigureMouseAdvanced">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>310</width>
<height>193</height>
</rect>
</property>
<property name="windowTitle">
<string>Configure Mouse</string>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
min-width: 60px;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="gridGroupBox">
<property name="title">
<string>Mouse Buttons</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="5">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Forward:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="forward_button">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_4">
<property name="minimumSize">
<size>
<width>54</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Back:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="back_button">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Left:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="left_button">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="3">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Middle:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="middle_button">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="6">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="5">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Right:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="right_button">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QPushButton" name="buttonClearAll">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonRestoreDefaults">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Defaults</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ConfigureMouseAdvanced</receiver>
<slot>accept()</slot>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ConfigureMouseAdvanced</receiver>
<slot>reject()</slot>
</connection>
</connections>
</ui>