mirror of
https://github.com/XorTroll/uLaunch
synced 2024-11-26 13:50:25 +00:00
Improve QDaemon, QForegroundViewer and settings menu
This commit is contained in:
parent
07963745e3
commit
590fb2350f
13 changed files with 97 additions and 74 deletions
|
@ -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;
|
||||
};
|
||||
}
|
BIN
LibraryAppletQMenu/RomFs/default/ui/SettingEditable.png
Normal file
BIN
LibraryAppletQMenu/RomFs/default/ui/SettingEditable.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
LibraryAppletQMenu/RomFs/default/ui/SettingNoEditable.png
Normal file
BIN
LibraryAppletQMenu/RomFs/default/ui/SettingNoEditable.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
BIN
LibraryAppletQMenu/RomFs/default/ui/Suspended.png
Normal file
BIN
LibraryAppletQMenu/RomFs/default/ui/Suspended.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
16
README.md
16
README.md
|
@ -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)
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
10
Themes.md
10
Themes.md
|
@ -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
|
Loading…
Reference in a new issue