Improve QDaemon, QForegroundViewer and settings menu

This commit is contained in:
XorTroll 2019-11-01 21:22:45 +01:00
parent 07963745e3
commit 590fb2350f
13 changed files with 97 additions and 74 deletions

View file

@ -13,9 +13,10 @@ namespace ui
PU_SMART_CTOR(SettingsMenuLayout)
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos);
void Reload();
void PushSettingItem(std::string name, std::string value_display, u32 id);
void PushSettingItem(std::string name, std::string value_display, int id);
void setting_Click(u32 id);
private:
pu::ui::elm::TextBlock::Ref infoText;
pu::ui::elm::Menu::Ref settingsMenu;
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -38,9 +38,16 @@ namespace ui
{
this->SetBackgroundImage(cfg::ProcessedThemeResource(theme, "ui/Background.png"));
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
this->infoText = pu::ui::elm::TextBlock::New(0, 100, "Browse and/or edit settings here.");
this->infoText->SetColor(textclr);
this->infoText->SetHorizontalAlign(pu::ui::elm::HorizontalAlign::Center);
qapp->ApplyConfigForElement("settings_menu", "info_text", this->infoText);
this->Add(this->infoText);
this->settingsMenu = pu::ui::elm::Menu::New(200, 160, 880, menubgclr, 100, 4);
this->settingsMenu->SetOnFocusColor(menufocusclr);
qapp->ApplyConfigForElement("settings_menu", "settings_menu_item", this->settingsMenu);
@ -55,15 +62,19 @@ namespace ui
char consolename[SET_MAX_NICKNAME_SIZE] = {};
setsysGetDeviceNickname(consolename);
this->PushSettingItem("Console nickname", EncodeForSettings<std::string>(consolename), 0);
TimeLocationName loc = {};
timeGetDeviceLocationName(&loc);
this->PushSettingItem("Console timezone location", EncodeForSettings<std::string>(loc.name), -1);
this->PushSettingItem("PC viewer USB enabled", EncodeForSettings(config.viewer_usb_enabled), 1);
this->PushSettingItem("Homebrew-as-application 'flog' takeover enabled", EncodeForSettings(config.system_title_override_enabled), 2);
}
void SettingsMenuLayout::PushSettingItem(std::string name, std::string value_display, u32 id)
void SettingsMenuLayout::PushSettingItem(std::string name, std::string value_display, int id)
{
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
auto itm = pu::ui::elm::MenuItem::New(name + ": " + value_display);
itm->AddOnClick(std::bind(&SettingsMenuLayout::setting_Click, this, id));
itm->SetIcon(cfg::ProcessedThemeResource(theme, "ui/Setting" + std::string((id < 0) ? "No" : "") + "Editable.png"));
itm->SetColor(textclr);
this->settingsMenu->AddItem(itm);
}

View file

@ -49,7 +49,7 @@
this.groupBox1.Size = new System.Drawing.Size(200, 58);
this.groupBox1.TabIndex = 1;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Available screenshots";
this.groupBox1.Text = "Available screenshot stack";
//
// ScreenshotList
//
@ -83,7 +83,7 @@
this.groupBox2.Size = new System.Drawing.Size(200, 56);
this.groupBox2.TabIndex = 3;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Image format";
this.groupBox2.Text = "Image save format";
//
// FormatList
//
@ -99,17 +99,17 @@
//
// SaveButton
//
this.SaveButton.Location = new System.Drawing.Point(12, 229);
this.SaveButton.Location = new System.Drawing.Point(12, 270);
this.SaveButton.Name = "SaveButton";
this.SaveButton.Size = new System.Drawing.Size(153, 55);
this.SaveButton.Size = new System.Drawing.Size(221, 44);
this.SaveButton.TabIndex = 4;
this.SaveButton.Text = "Save";
this.SaveButton.Text = "Save as...";
this.SaveButton.UseVisualStyleBackColor = true;
this.SaveButton.Click += new System.EventHandler(this.SaveButton_Click);
//
// RefreshButton
//
this.RefreshButton.Location = new System.Drawing.Point(12, 153);
this.RefreshButton.Location = new System.Drawing.Point(12, 185);
this.RefreshButton.Name = "RefreshButton";
this.RefreshButton.Size = new System.Drawing.Size(172, 29);
this.RefreshButton.TabIndex = 5;
@ -119,9 +119,9 @@
//
// ClipboardButton
//
this.ClipboardButton.Location = new System.Drawing.Point(13, 189);
this.ClipboardButton.Location = new System.Drawing.Point(12, 220);
this.ClipboardButton.Name = "ClipboardButton";
this.ClipboardButton.Size = new System.Drawing.Size(171, 29);
this.ClipboardButton.Size = new System.Drawing.Size(221, 44);
this.ClipboardButton.TabIndex = 6;
this.ClipboardButton.Text = "Copy to clipboard";
this.ClipboardButton.UseVisualStyleBackColor = true;
@ -131,7 +131,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 333);
this.ClientSize = new System.Drawing.Size(784, 331);
this.Controls.Add(this.ClipboardButton);
this.Controls.Add(this.RefreshButton);
this.Controls.Add(this.SaveButton);

View file

@ -98,7 +98,6 @@ namespace QForegroundViewer
private void ClipboardButton_Click(object sender, EventArgs e)
{
Clipboard.SetImage(ScreenshotBox.Image);
MessageBox.Show("Selected screenshot copied to clipboard.");
}
}
}

View file

@ -20,6 +20,7 @@ namespace QForegroundViewer
main = Main;
IncrementNumeric.Increment = 0.1m;
IncrementNumeric.Minimum = 0.1m;
IncrementNumeric.Value = 1.0m;
}
private void AboutButton_Click(object sender, EventArgs e)

View file

@ -39,7 +39,7 @@
this.CaptureBox.Location = new System.Drawing.Point(0, 0);
this.CaptureBox.Margin = new System.Windows.Forms.Padding(0);
this.CaptureBox.Name = "CaptureBox";
this.CaptureBox.Size = new System.Drawing.Size(624, 321);
this.CaptureBox.Size = new System.Drawing.Size(1280, 720);
this.CaptureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.CaptureBox.TabIndex = 0;
this.CaptureBox.TabStop = false;
@ -48,7 +48,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(624, 321);
this.ClientSize = new System.Drawing.Size(1280, 720);
this.Controls.Add(this.CaptureBox);
this.Name = "ViewerMainForm";
this.Text = "uLaunch - Foreground display viewer";

View file

@ -60,6 +60,16 @@ namespace QForegroundViewer
base.OnClosing(e);
}
protected override void OnShown(EventArgs e)
{
if(USB == null)
{
MessageBox.Show("Unable to connect to uLaunch via USB-C cable.", "Unable to connect");
Environment.Exit(Environment.ExitCode);
}
base.OnShown(e);
}
public void USBThreadMain()
{
while(RefreshCapture());
@ -67,11 +77,6 @@ namespace QForegroundViewer
public bool RefreshCapture()
{
if(USB == null)
{
MessageBox.Show("Unable to connect to uLaunch via USB-C cable.", "Unable to connect");
Environment.Exit(Environment.ExitCode);
}
try
{
USB.ReadPipe(0x81, CaptureBlocks[0], CaptureBlocks[0].Length, out _, IntPtr.Zero);

View file

@ -61,15 +61,15 @@ This is the amount of features uLaunch contains, compared to the original HOME m
- **User password** support! (up to 15 characters)
> Note: some classic HOME menu functionality (eShop, friends...) isn't implemented here. This reimplementation is mainly homebrew-orienteed, so it will lack some classic functionality.
> Note: some classic HOME menu functionality (eShop, friends...) isn't (and probably won't be) implemented here. This reimplementation is mainly homebrew-orienteed, so it will lack some classic functionality which isn't specially worth it to reverse and implement.
## Disclaimer
### Homebrew as applications
### Homebrew-as-application 'flog' takeover
uLaunch launches homebrew present (added) to main menu as an application, taking advantage of **flog**'s built-in application title, which was stubbed but not removed, thus it's content can be overriden via LayeredFS and launched.
uLaunch launches homebrew present (added) to main menu as an application, taking advantage of the system's '**flog**' built-in application title, which was stubbed but not removed, thus it's content can be overriden via LayeredFS and launched.
Since launching this title should be impossible, it might involve ban risk, so **use it at your own risk**. uLaunch **warns on launching titles this way**.
Since launching this title should be impossible, it might involve ban risk. uLaunch has this option **disabled by default**, so enable and use it **use it at your own risk**.
## Project and subprojects
@ -79,13 +79,7 @@ uLaunch is split, as mentioned above, into several sub-projects:
> This sub-project replaces qlaunch, aka title 0100000000001000.
This is the technically actual qlaunch reimplementation. However, to avoid memory issues it does not use any kind of UI (except console for development debug, which is removed for releases), and thus it uses 8MB of heap, while official HOME menu uses 56MB.
Instead, it uses [QMenu custom library applet](#qmenu-libraryappletqmenu) (launches and communicates with it) in order to display a proper menu UI.
But, if all the functionality is handled by QMenu, why is this daemon process necessary? Well, mainly since the system applet process has a lot of unique code it's the only one who can use, specially, related to title launching, focus managing...
**TL;DR**: this is a simple daemon process which stays communicated with QMenu to perform tasks it is asked to so, specially with code it is the only one that can access.
This is the technically actual qlaunch reimplementation. In fact, it is used as a back-end for the project, which just does what the actual menu (QMenu) tells it to do. This had to be like that, since qlaunch is the only one who can access certain essential functionality like title launching, so QMenu needs to access it, so it communicates with this back-end to execute it and to obtain its outcome.
### QMenu (LibraryAppletQMenu)

View file

@ -37,46 +37,6 @@ void CommonSleepHandle()
appletStartSleepSequence(true);
}
void HandleGeneralChannel()
{
AppletStorage sams_st;
auto rc = appletPopFromGeneralChannel(&sams_st);
if(R_SUCCEEDED(rc))
{
os::SystemAppletMessage sams = {};
rc = appletStorageRead(&sams_st, 0, &sams, sizeof(os::SystemAppletMessage));
appletStorageClose(&sams_st);
if(R_SUCCEEDED(rc))
{
if(sams.magic == os::SAMSMagic)
{
os::GeneralChannelMessage msg = (os::GeneralChannelMessage)sams.message;
switch(msg)
{
case os::GeneralChannelMessage::Shutdown:
{
appletStartShutdownSequence();
break;
}
case os::GeneralChannelMessage::Reboot:
{
appletStartRebootSequence();
break;
}
case os::GeneralChannelMessage::Sleep:
{
appletStartSleepSequence(true);
break;
}
default:
break;
}
}
}
}
svcSleepThread(100000000L);
}
void HandleHomeButton()
{
bool used_to_reopen_menu = false;
@ -102,6 +62,51 @@ void HandleHomeButton()
}
}
void HandleGeneralChannel()
{
AppletStorage sams_st;
auto rc = appletPopFromGeneralChannel(&sams_st);
if(R_SUCCEEDED(rc))
{
os::SystemAppletMessage sams = {};
rc = appletStorageRead(&sams_st, 0, &sams, sizeof(os::SystemAppletMessage));
appletStorageClose(&sams_st);
if(R_SUCCEEDED(rc))
{
if(sams.magic == os::SAMSMagic)
{
os::GeneralChannelMessage msg = (os::GeneralChannelMessage)sams.message;
switch(msg)
{
case os::GeneralChannelMessage::HomeButton: // Usually this doesn't happen, HOME is detected by applet messages...?
{
HandleHomeButton();
break;
}
case os::GeneralChannelMessage::Shutdown:
{
appletStartShutdownSequence();
break;
}
case os::GeneralChannelMessage::Reboot:
{
appletStartRebootSequence();
break;
}
case os::GeneralChannelMessage::Sleep:
{
appletStartSleepSequence(true);
break;
}
default: // We don't have anything special to do for the rest
break;
}
}
}
}
svcSleepThread(100000000L);
}
void HandleAppletMessage()
{
u32 nmsg = 0;
@ -359,7 +364,7 @@ namespace qdaemon
{
app_buf = new u8[RawRGBAScreenBufferSize]();
db::Mount();
db::Mount(); // Keep qlaunch's savedata always mounted to avoid others to access it.
fs::CreateDirectory(Q_BASE_DB_DIR);
fs::CreateDirectory(Q_BASE_SD_DIR);
fs::CreateDirectory(Q_ENTRIES_PATH);
@ -430,6 +435,8 @@ namespace qdaemon
void DaemonServiceMain(void *arg)
{
// TODO: restrict service access to QMenu?
static auto server = WaitableManager(2);
server.AddWaitable(new ServiceServer<ipc::IDaemonService>(AM_QDAEMON_SERVICE_NAME, 0x10));
server.Process();
@ -469,6 +476,7 @@ namespace qdaemon
}
}
// QDaemon handles basic qlaunch functionality and serves as a back-end for uLaunch, communicating with QMenu front-end when neccessary.
int main()
{
qdaemon::Initialize();

View file

@ -153,6 +153,12 @@ Can be customized via files in `/ui`.
- `ui/Banner{type}.png` -> Different 1280x135 PNG banners for menu item types (BannerFolder, BannerHomebrew or BannerInstalled)
## Settings menu
- `ui/SettingEditable.png` -> 100x100 PNG for settings which can be edited.
- `ui/SettingNoEditable.png` -> 100x100 PNG for settings which cannot be edited (thus can only be seen).
### Top menu
The top menu is the small bar shown at the top of the main menu, whose background and icons are customizable.
@ -161,6 +167,4 @@ All the menu icons ({...}Icon.png) are 50x50 icons, except battery ones (Battery
- `ui/TopMenu.png` -> Background of menu (1220x85 PNG)
- Icons in top menu (50x50 PNGs): ConnectionIcon, NoConnectionIcon, SettingsIcon, ThemesIcon, WebIcon
> *TODO: more menu icons*
- Icons in top menu (50x50 PNGs): ConnectionIcon, NoConnectionIcon, SettingsIcon, ThemesIcon, WebIcon