History

Merge branch 'master' of https://github.com/highfidelity/hifi into temp1

Sam Gateau committed 11 years ago

Commit ace6dc42 parents 48fca4c 6378009134 files · +4645 −95061Browse files

Showing the changes to interface/src/Application.cpp (1 of 134 files). Show all

Unified · Split

interface/src/Application.cpp+69−51
@@ -23,6 +23,7 @@ · 22 unmodified lines
23// include this before QGLWidget, which includes an earlier version of OpenGL23// include this before QGLWidget, which includes an earlier version of OpenGL
24#include "InterfaceConfig.h"24#include "InterfaceConfig.h"
25 25
26#include <QAbstractNativeEventFilter>
26#include <QActionGroup>27#include <QActionGroup>
27#include <QColorDialog>28#include <QColorDialog>
28#include <QDesktopWidget>29#include <QDesktopWidget>
@@ -81,13 +82,15 @@ · 52 unmodified lines
81#include <UUID.h>82#include <UUID.h>
82 83
83#include "Application.h"84#include "Application.h"
84#include "Audio.h"85#include "AudioClient.h"
85#include "InterfaceVersion.h"86#include "InterfaceVersion.h"
86#include "LODManager.h"87#include "LODManager.h"
87#include "Menu.h"88#include "Menu.h"
88#include "ModelUploader.h"89#include "ModelUploader.h"
89#include "Util.h"90#include "Util.h"
90 91
92#include "avatar/AvatarManager.h"
93
91#include "audio/AudioToolBox.h"94#include "audio/AudioToolBox.h"
92#include "audio/AudioIOStatsRenderer.h"95#include "audio/AudioIOStatsRenderer.h"
93#include "audio/AudioScope.h"96#include "audio/AudioScope.h"
@@ -127,8 +130,6 @@ · 33 unmodified lines
127#include "ui/StandAloneJSConsole.h"130#include "ui/StandAloneJSConsole.h"
128#include "ui/Stats.h"131#include "ui/Stats.h"
129 132
130
131
132using namespace std;133using namespace std;
133 134
134// Starfield information135// Starfield information
@@ -144,6 +145,37 @@ const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::D · 9 unmodified lines
144 145
145const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";146const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";
146 147
148#ifdef Q_OS_WIN
149class MyNativeEventFilter : public QAbstractNativeEventFilter {
150public:
151 static MyNativeEventFilter& getInstance() {
152 static MyNativeEventFilter staticInstance;
153 return staticInstance;
154 }
155
156 bool nativeEventFilter(const QByteArray &eventType, void* msg, long* result) Q_DECL_OVERRIDE {
157 if (eventType == "windows_generic_MSG") {
158 MSG* message = (MSG*)msg;
159 if (message->message == UWM_IDENTIFY_INSTANCES) {
160 *result = UWM_IDENTIFY_INSTANCES;
161 return true;
162 }
163 if (message->message == WM_SHOWWINDOW) {
164 Application::getInstance()->getWindow()->showNormal();
165 }
166 if (message->message == WM_COPYDATA) {
167 COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)(message->lParam);
168 QUrl url = QUrl((const char*)(pcds->lpData));
169 if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
170 DependencyManager::get<AddressManager>()->handleLookupString(url.toString());
171 }
172 }
173 }
174 return false;
175 }
176};
177#endif
178
147void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {179void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
148 QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message);180 QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message);
149 181
@@ -163,6 +195,7 @@ bool setupEssentials(int& argc, char** argv) { · 13 unmodified lines
163 QCoreApplication::setApplicationVersion(BUILD_VERSION);195 QCoreApplication::setApplicationVersion(BUILD_VERSION);
164 196
165 DependencyManager::registerInheritance<LimitedNodeList, NodeList>();197 DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
198 DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>();
166 199
167 // Set dependencies200 // Set dependencies
168 auto glCanvas = DependencyManager::set<GLCanvas>();201 auto glCanvas = DependencyManager::set<GLCanvas>();
@@ -171,7 +204,7 @@ bool setupEssentials(int& argc, char** argv) { · 2 unmodified lines
171 auto geometryCache = DependencyManager::set<GeometryCache>();204 auto geometryCache = DependencyManager::set<GeometryCache>();
172 auto glowEffect = DependencyManager::set<GlowEffect>();205 auto glowEffect = DependencyManager::set<GlowEffect>();
173 auto faceshift = DependencyManager::set<Faceshift>();206 auto faceshift = DependencyManager::set<Faceshift>();
174 auto audio = DependencyManager::set<Audio>();207 auto audio = DependencyManager::set<AudioClient>();
175 auto audioScope = DependencyManager::set<AudioScope>();208 auto audioScope = DependencyManager::set<AudioScope>();
176 auto audioIOStatsRenderer = DependencyManager::set<AudioIOStatsRenderer>();209 auto audioIOStatsRenderer = DependencyManager::set<AudioIOStatsRenderer>();
177 auto deferredLightingEffect = DependencyManager::set<DeferredLightingEffect>();210 auto deferredLightingEffect = DependencyManager::set<DeferredLightingEffect>();
@@ -182,6 +215,7 @@ bool setupEssentials(int& argc, char** argv) { · 4 unmodified lines
182 auto ddeFaceTracker = DependencyManager::set<DdeFaceTracker>();215 auto ddeFaceTracker = DependencyManager::set<DdeFaceTracker>();
183 auto modelBlender = DependencyManager::set<ModelBlender>();216 auto modelBlender = DependencyManager::set<ModelBlender>();
184 auto audioToolBox = DependencyManager::set<AudioToolBox>();217 auto audioToolBox = DependencyManager::set<AudioToolBox>();
218 auto avatarManager = DependencyManager::set<AvatarManager>();
185 auto lodManager = DependencyManager::set<LODManager>();219 auto lodManager = DependencyManager::set<LODManager>();
186 auto jsConsole = DependencyManager::set<StandAloneJSConsole>();220 auto jsConsole = DependencyManager::set<StandAloneJSConsole>();
187 auto dialogsManager = DependencyManager::set<DialogsManager>();221 auto dialogsManager = DependencyManager::set<DialogsManager>();
@@ -242,9 +276,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 54 unmodified lines
242 _aboutToQuit(false),276 _aboutToQuit(false),
243 _notifiedPacketVersionMismatchThisDomain(false)277 _notifiedPacketVersionMismatchThisDomain(false)
244{278{
279#ifdef Q_OS_WIN
280 installNativeEventFilter(&MyNativeEventFilter::getInstance());
281#endif
282
245 _logger = new FileLogger(this); // After setting organization name in order to get correct directory283 _logger = new FileLogger(this); // After setting organization name in order to get correct directory
246 qInstallMessageHandler(messageHandler);284 qInstallMessageHandler(messageHandler);
247 285
248 QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "styles/Inconsolata.otf");286 QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "styles/Inconsolata.otf");
249 _window->setWindowTitle("Interface");287 _window->setWindowTitle("Interface");
250 288
@@ -253,7 +291,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 2 unmodified lines
253 auto glCanvas = DependencyManager::get<GLCanvas>();291 auto glCanvas = DependencyManager::get<GLCanvas>();
254 auto nodeList = DependencyManager::get<NodeList>();292 auto nodeList = DependencyManager::get<NodeList>();
255 293
256 _myAvatar = _avatarManager.getMyAvatar();294 _myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
257 295
258 _applicationStartupTime = startup_time;296 _applicationStartupTime = startup_time;
259 297
@@ -284,9 +322,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 24 unmodified lines
284 QThread* audioThread = new QThread(this);322 QThread* audioThread = new QThread(this);
285 audioThread->setObjectName("Audio Thread");323 audioThread->setObjectName("Audio Thread");
286 324
287 auto audioIO = DependencyManager::get<Audio>();325 auto audioIO = DependencyManager::get<AudioClient>();
326
327 audioIO->setPositionGetter(getPositionForAudio);
328 audioIO->setOrientationGetter(getOrientationForAudio);
329
288 audioIO->moveToThread(audioThread);330 audioIO->moveToThread(audioThread);
289 connect(audioThread, &QThread::started, audioIO.data(), &Audio::start);331 connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start);
290 connect(audioIO.data(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));332 connect(audioIO.data(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
291 333
292 audioThread->start();334 audioThread->start();
@@ -330,9 +372,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 37 unmodified lines
330 auto dialogsManager = DependencyManager::get<DialogsManager>();372 auto dialogsManager = DependencyManager::get<DialogsManager>();
331 connect(&accountManager, &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog);373 connect(&accountManager, &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog);
332 connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);374 connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
333
334 // once we have a profile in account manager make sure we generate a new keypair
335 connect(&accountManager, &AccountManager::profileChanged, &accountManager, &AccountManager::generateNewKeypair);
336 375
337 // set the account manager's root URL and trigger a login request if we don't have the access token376 // set the account manager's root URL and trigger a login request if we don't have the access token
338 accountManager.setAuthURL(DEFAULT_NODE_AUTH_URL);377 accountManager.setAuthURL(DEFAULT_NODE_AUTH_URL);
@@ -497,7 +536,7 @@ Application::~Application() { · 158 unmodified lines
497 // kill any audio injectors that are still around536 // kill any audio injectors that are still around
498 AudioScriptingInterface::getInstance().stopAllInjectors();537 AudioScriptingInterface::getInstance().stopAllInjectors();
499 538
500 auto audioIO = DependencyManager::get<Audio>();539 auto audioIO = DependencyManager::get<AudioClient>();
501 540
502 // stop the audio process541 // stop the audio process
503 QMetaObject::invokeMethod(audioIO.data(), "stop", Qt::BlockingQueuedConnection);542 QMetaObject::invokeMethod(audioIO.data(), "stop", Qt::BlockingQueuedConnection);
@@ -706,7 +745,7 @@ void Application::runTests() { · 202 unmodified lines
706void Application::audioMuteToggled() {745void Application::audioMuteToggled() {
707 QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteAudio);746 QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteAudio);
708 Q_CHECK_PTR(muteAction);747 Q_CHECK_PTR(muteAction);
709 muteAction->setChecked(DependencyManager::get<Audio>()->isMuted());748 muteAction->setChecked(DependencyManager::get<AudioClient>()->isMuted());
710}749}
711 750
712void Application::aboutApp() {751void Application::aboutApp() {
@@ -1566,13 +1605,16 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa · 853 unmodified lines
1566}1605}
1567 1606
1568void Application::loadSettings() {1607void Application::loadSettings() {
1569 DependencyManager::get<Audio>()->loadSettings();1608
1609 DependencyManager::get<AudioClient>()->loadSettings();
1610
1570 Menu::getInstance()->loadSettings();1611 Menu::getInstance()->loadSettings();
1571 _myAvatar->loadData();1612 _myAvatar->loadData();
1572}1613}
1573 1614
1574void Application::saveSettings() {1615void Application::saveSettings() {
1575 DependencyManager::get<Audio>()->saveSettings();1616 DependencyManager::get<AudioClient>()->saveSettings();
1617
1576 Menu::getInstance()->saveSettings();1618 Menu::getInstance()->saveSettings();
1577 _myAvatar->saveData();1619 _myAvatar->saveData();
1578}1620}
@@ -1606,7 +1648,7 @@ void Application::init() { · 27 unmodified lines
1606 DependencyManager::get<AmbientOcclusionEffect>()->init(this);1648 DependencyManager::get<AmbientOcclusionEffect>()->init(this);
1607 1649
1608 // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager1650 // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager
1609 _avatarManager.init();1651 DependencyManager::get<AvatarManager>()->init();
1610 _myCamera.setMode(CAMERA_MODE_FIRST_PERSON);1652 _myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
1611 1653
1612 _mirrorCamera.setMode(CAMERA_MODE_MIRROR);1654 _mirrorCamera.setMode(CAMERA_MODE_MIRROR);
@@ -1985,7 +2027,7 @@ void Application::update(float deltaTime) { · 372 unmodified lines
1985 2027
1986 updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...2028 updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
1987 2029
1988 _avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...2030 DependencyManager::get<AvatarManager>()->updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...
1989 2031
1990 updateMetavoxels(deltaTime); // update metavoxels2032 updateMetavoxels(deltaTime); // update metavoxels
1991 updateCamera(deltaTime); // handle various camera tweaks like off axis projection2033 updateCamera(deltaTime); // handle various camera tweaks like off axis projection
@@ -2012,7 +2054,7 @@ void Application::update(float deltaTime) { · 20 unmodified lines
2012 {2054 {
2013 PerformanceTimer perfTimer("myAvatar");2055 PerformanceTimer perfTimer("myAvatar");
2014 updateMyAvatarLookAtPosition();2056 updateMyAvatarLookAtPosition();
2015 updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes2057 DependencyManager::get<AvatarManager>()->updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
2016 }2058 }
2017 2059
2018 {2060 {
@@ -2069,31 +2111,11 @@ void Application::update(float deltaTime) { · 50 unmodified lines
2069 if (sinceLastNack > TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS) {2111 if (sinceLastNack > TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS) {
2070 _lastSendDownstreamAudioStats = now;2112 _lastSendDownstreamAudioStats = now;
2071 2113
2072 QMetaObject::invokeMethod(DependencyManager::get<Audio>().data(), "sendDownstreamAudioStatsPacket", Qt::QueuedConnection);2114 QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "sendDownstreamAudioStatsPacket", Qt::QueuedConnection);
2073 }2115 }
2074 }2116 }
2075}2117}
2076 2118
2077void Application::updateMyAvatar(float deltaTime) {
2078 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
2079 PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()");
2080
2081 _myAvatar->update(deltaTime);
2082
2083 quint64 now = usecTimestampNow();
2084 quint64 dt = now - _lastSendAvatarDataTime;
2085
2086 if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS) {
2087 // send head/hand data to the avatar mixer and voxel server
2088 PerformanceTimer perfTimer("send");
2089 QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarData);
2090 packet.append(_myAvatar->toByteArray());
2091 controlledBroadcastToNodes(packet, NodeSet() << NodeType::AvatarMixer);
2092
2093 _lastSendAvatarDataTime = now;
2094 }
2095}
2096
2097int Application::sendNackPackets() {2119int Application::sendNackPackets() {
2098 2120
2099 if (Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {2121 if (Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
@@ -2533,7 +2555,7 @@ void Application::updateShadowMap() { · 433 unmodified lines
2533 2555
2534 {2556 {
2535 PerformanceTimer perfTimer("avatarManager");2557 PerformanceTimer perfTimer("avatarManager");
2536 _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE);2558 DependencyManager::get<AvatarManager>()->renderAvatars(Avatar::SHADOW_RENDER_MODE);
2537 }2559 }
2538 2560
2539 {2561 {
@@ -2789,7 +2811,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs · 249 unmodified lines
2789 bool mirrorMode = (theCamera.getMode() == CAMERA_MODE_MIRROR);2811 bool mirrorMode = (theCamera.getMode() == CAMERA_MODE_MIRROR);
2790 {2812 {
2791 PerformanceTimer perfTimer("avatars");2813 PerformanceTimer perfTimer("avatars");
2792 _avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE,2814 DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE,
2793 false, selfAvatarOnly); 2815 false, selfAvatarOnly);
2794 }2816 }
2795 2817
@@ -2804,7 +2826,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs · 8 unmodified lines
2804 2826
2805 {2827 {
2806 PerformanceTimer perfTimer("avatarsPostLighting");2828 PerformanceTimer perfTimer("avatarsPostLighting");
2807 _avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE,2829 DependencyManager::get<AvatarManager>()->renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE,
2808 true, selfAvatarOnly); 2830 true, selfAvatarOnly);
2809 }2831 }
2810 2832
@@ -3068,7 +3090,7 @@ void Application::resetSensors() { · 257 unmodified lines
3068 3090
3069 _myAvatar->reset();3091 _myAvatar->reset();
3070 3092
3071 QMetaObject::invokeMethod(DependencyManager::get<Audio>().data(), "reset", Qt::QueuedConnection);3093 QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "reset", Qt::QueuedConnection);
3072}3094}
3073 3095
3074static void setShortcutsEnabled(QWidget* widget, bool enabled) {3096static void setShortcutsEnabled(QWidget* widget, bool enabled) {
@@ -3208,7 +3230,7 @@ void Application::nodeKilled(SharedNodePointer node) { · 133 unmodified lines
3208 _entityEditSender.nodeKilled(node);3230 _entityEditSender.nodeKilled(node);
3209 3231
3210 if (node->getType() == NodeType::AudioMixer) {3232 if (node->getType() == NodeType::AudioMixer) {
3211 QMetaObject::invokeMethod(DependencyManager::get<Audio>().data(), "audioMixerKilled");3233 QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "audioMixerKilled");
3212 }3234 }
3213 3235
3214 if (node->getType() == NodeType::EntityServer) {3236 if (node->getType() == NodeType::EntityServer) {
@@ -3251,7 +3273,7 @@ void Application::nodeKilled(SharedNodePointer node) { · 36 unmodified lines
3251 3273
3252 } else if (node->getType() == NodeType::AvatarMixer) {3274 } else if (node->getType() == NodeType::AvatarMixer) {
3253 // our avatar mixer has gone away - clear the hash of avatars3275 // our avatar mixer has gone away - clear the hash of avatars
3254 _avatarManager.clearOtherAvatars();3276 DependencyManager::get<AvatarManager>()->clearOtherAvatars();
3255 }3277 }
3256}3278}
3257 3279
@@ -3400,7 +3422,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 142 unmodified lines
3400 3422
3401 // hook our avatar and avatar hash map object into this script engine3423 // hook our avatar and avatar hash map object into this script engine
3402 scriptEngine->setAvatarData(_myAvatar, "MyAvatar"); // leave it as a MyAvatar class to expose thrust features3424 scriptEngine->setAvatarData(_myAvatar, "MyAvatar"); // leave it as a MyAvatar class to expose thrust features
3403 scriptEngine->setAvatarHashMap(&_avatarManager, "AvatarList");3425 scriptEngine->setAvatarHashMap(DependencyManager::get<AvatarManager>().data(), "AvatarList");
3404 3426
3405 scriptEngine->registerGlobalObject("Camera", &_myCamera);3427 scriptEngine->registerGlobalObject("Camera", &_myCamera);
3406 3428
@@ -3441,7 +3463,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 34 unmodified lines
3441 scriptEngine->registerGlobalObject("GlobalServices", GlobalServicesScriptingInterface::getInstance());3463 scriptEngine->registerGlobalObject("GlobalServices", GlobalServicesScriptingInterface::getInstance());
3442 qScriptRegisterMetaType(scriptEngine, DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue);3464 qScriptRegisterMetaType(scriptEngine, DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue);
3443 3465
3444 scriptEngine->registerGlobalObject("AvatarManager", &_avatarManager);3466 scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get<AvatarManager>().data());
3445 3467
3446 scriptEngine->registerGlobalObject("Joysticks", &JoystickScriptingInterface::getInstance());3468 scriptEngine->registerGlobalObject("Joysticks", &JoystickScriptingInterface::getInstance());
3447 qScriptRegisterMetaType(scriptEngine, joystickToScriptValue, joystickFromScriptValue);3469 qScriptRegisterMetaType(scriptEngine, joystickToScriptValue, joystickFromScriptValue);
@@ -3741,10 +3763,6 @@ void Application::toggleLogDialog() { · 293 unmodified lines
3741 }3763 }
3742}3764}
3743 3765
3744void Application::initAvatarAndViewFrustum() {
3745 updateMyAvatar(0.0f);
3746}
3747
3748void Application::checkVersion() {3766void Application::checkVersion() {
3749 QNetworkRequest latestVersionRequest((QUrl(CHECK_VERSION_URL)));3767 QNetworkRequest latestVersionRequest((QUrl(CHECK_VERSION_URL)));
3750 latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);3768 latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t