committed by
Narr the Reg
21 changed files with 323 additions and 1039 deletions
-
1src/common/settings.h
-
15src/common/settings_input.h
-
11src/core/hid/emulated_console.cpp
-
124src/core/hid/emulated_devices.cpp
-
56src/core/hid/emulated_devices.h
-
21src/core/hid/input_converter.cpp
-
9src/core/hid/input_converter.h
-
9src/core/hle/service/hid/controllers/mouse.cpp
-
31src/input_common/drivers/mouse.cpp
-
7src/input_common/drivers/mouse.h
-
3src/yuzu/CMakeLists.txt
-
6src/yuzu/bootmanager.cpp
-
1src/yuzu/bootmanager.h
-
30src/yuzu/configuration/config.cpp
-
4src/yuzu/configuration/configure_input.cpp
-
2src/yuzu/configuration/configure_input_advanced.cpp
-
204src/yuzu/configuration/configure_input_advanced.ui
-
247src/yuzu/configuration/configure_mouse_advanced.cpp
-
72src/yuzu/configuration/configure_mouse_advanced.h
-
335src/yuzu/configuration/configure_mouse_advanced.ui
-
174src/yuzu_cmd/config.cpp
@ -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()); |
|||
} |
|||
} |
|||
@ -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; |
|||
}; |
|||
@ -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> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue