mirror of https://gitlab.com/nakst/essence
installer interface
This commit is contained in:
parent
485dbc59e5
commit
f53a980a65
|
@ -96,11 +96,3 @@ FileType *FolderEntryGetType(Folder *folder, FolderEntry *entry) {
|
|||
return &knownFileTypes[index ? index : KNOWN_FILE_TYPE_UNKNOWN];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t IconFromDriveType(uint8_t driveType) {
|
||||
if (driveType == ES_DRIVE_TYPE_HDD ) return ES_ICON_DRIVE_HARDDISK;
|
||||
if (driveType == ES_DRIVE_TYPE_SSD ) return ES_ICON_DRIVE_HARDDISK_SOLIDSTATE;
|
||||
if (driveType == ES_DRIVE_TYPE_CDROM ) return ES_ICON_MEDIA_OPTICAL;
|
||||
if (driveType == ES_DRIVE_TYPE_USB_MASS_STORAGE) return ES_ICON_DRIVE_REMOVABLE_MEDIA_USB;
|
||||
return ES_ICON_DRIVE_HARDDISK;
|
||||
}
|
||||
|
|
|
@ -880,7 +880,7 @@ int PlacesViewCallback(EsElement *element, EsMessage *message) {
|
|||
} else {
|
||||
Drive *drive = &drives[index - 1];
|
||||
EsBufferFormat(message->getContent.buffer, "%s", drive->information.labelBytes, drive->information.label);
|
||||
message->getContent.icon = IconFromDriveType(drive->information.driveType);
|
||||
message->getContent.icon = EsIconIDFromDriveType(drive->information.driveType);
|
||||
}
|
||||
} else if (group == PLACES_VIEW_GROUP_BOOKMARKS) {
|
||||
if (index == 0) {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <essence.h>
|
||||
|
||||
#include <shared/hash.cpp>
|
||||
#include <shared/strings.cpp>
|
||||
#include <ports/lzma/LzmaDec.c>
|
||||
|
||||
#include <shared/array.cpp>
|
||||
|
@ -15,7 +16,47 @@
|
|||
#define exit(x) EsThreadTerminate(ES_CURRENT_THREAD)
|
||||
#include <shared/esfs2.h>
|
||||
|
||||
// Assume an additional 64MB of storage capacity is needed on top of totalUncompressedBytes.
|
||||
#define PARTITION_OVERHEAD (64 * 1024 * 1024)
|
||||
|
||||
struct InstallerMetadata {
|
||||
uint64_t totalUncompressedBytes;
|
||||
};
|
||||
|
||||
const EsStyle styleRoot = {
|
||||
.metrics = {
|
||||
.mask = ES_THEME_METRICS_GAP_MAJOR | ES_THEME_METRICS_INSETS,
|
||||
.insets = ES_RECT_1(30),
|
||||
.gapMajor = 20,
|
||||
},
|
||||
};
|
||||
|
||||
const EsStyle styleDrivesSelectHint = {
|
||||
.inherit = ES_STYLE_TEXT_PARAGRAPH_SECONDARY,
|
||||
|
||||
.metrics = {
|
||||
.mask = ES_THEME_METRICS_TEXT_ALIGN | ES_THEME_METRICS_INSETS,
|
||||
.insets = ES_RECT_1(30),
|
||||
.textAlign = ES_TEXT_H_CENTER | ES_TEXT_V_CENTER | ES_TEXT_WRAP,
|
||||
},
|
||||
};
|
||||
|
||||
const EsStyle styleButtonsRow = {
|
||||
.metrics = {
|
||||
.mask = ES_THEME_METRICS_GAP_MAJOR,
|
||||
.gapMajor = 10,
|
||||
},
|
||||
};
|
||||
|
||||
InstallerMetadata *metadata;
|
||||
Array<EsMessageDevice> connectedDrives;
|
||||
EsListView *drivesList;
|
||||
EsPanel *driveInformation;
|
||||
EsObjectID selectedDriveID;
|
||||
EsButton *installButton;
|
||||
EsPanel *switcher;
|
||||
EsPanel *panelInstallOptions;
|
||||
EsPanel *panelLicenses;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
|
@ -126,6 +167,8 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
|
|||
return crc64 == actualCRC64 ? ES_SUCCESS : ES_ERROR_CORRUPT_DATA;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
void ReadBlock(uint64_t, uint64_t, void *) {
|
||||
// TODO.
|
||||
}
|
||||
|
@ -138,33 +181,213 @@ void WriteBytes(uint64_t, uint64_t, void *) {
|
|||
// TODO.
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
EsBlockDeviceInformation ConnectedDriveGetInformation(EsHandle handle) {
|
||||
EsBlockDeviceInformation information;
|
||||
EsDeviceControl(handle, ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION, 0, &information);
|
||||
|
||||
for (uintptr_t i = 0; i < information.modelBytes; i++) {
|
||||
if (information.model[i] == 0) {
|
||||
information.modelBytes = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = information.modelBytes; i > 0; i--) {
|
||||
if (information.model[i - 1] == ' ') {
|
||||
information.modelBytes--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return information;
|
||||
}
|
||||
|
||||
void ConnectedDriveAdd(EsMessageDevice device) {
|
||||
if (device.type != ES_DEVICE_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
EsBlockDeviceInformation information;
|
||||
EsDeviceControl(device.handle, ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION, 0, &information);
|
||||
EsBlockDeviceInformation information = ConnectedDriveGetInformation(device.handle);
|
||||
|
||||
if (information.nestLevel) {
|
||||
if (information.nestLevel || information.driveType == ES_DRIVE_TYPE_CDROM) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO EsObjectID might not necessarily fit in EsGeneric...
|
||||
EsListViewFixedItemInsert(drivesList, information.model, information.modelBytes, device.id);
|
||||
connectedDrives.Add(device);
|
||||
}
|
||||
|
||||
void ConnectedDriveRemove(EsMessageDevice device) {
|
||||
if (device.id == selectedDriveID) {
|
||||
EsElementDestroyContents(driveInformation);
|
||||
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL | ES_CELL_V_FILL, &styleDrivesSelectHint, INTERFACE_STRING(InstallerDriveRemoved));
|
||||
selectedDriveID = 0;
|
||||
EsElementSetDisabled(installButton, true);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < connectedDrives.Length(); i++) {
|
||||
if (connectedDrives[i].id == device.id) {
|
||||
EsListViewFixedItemRemove(drivesList, device.id);
|
||||
connectedDrives.Delete(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectedDriveSelect(uintptr_t index) {
|
||||
EsMessageDevice device = connectedDrives[index];
|
||||
if (selectedDriveID == device.id) return;
|
||||
selectedDriveID = device.id;
|
||||
EsElementSetDisabled(installButton, true);
|
||||
|
||||
EsBlockDeviceInformation information = ConnectedDriveGetInformation(device.handle);
|
||||
EsElementDestroyContents(driveInformation);
|
||||
|
||||
EsPanel *nameRow = EsPanelCreate(driveInformation, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
|
||||
EsIconDisplayCreate(nameRow, ES_FLAGS_DEFAULT, 0, EsIconIDFromDriveType(information.driveType));
|
||||
EsSpacerCreate(nameRow, ES_CELL_V_FILL, 0, 8, 0);
|
||||
EsTextDisplayCreate(nameRow, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING2, information.model, information.modelBytes);
|
||||
EsSpacerCreate(driveInformation, ES_CELL_H_FILL, 0, 0, 16);
|
||||
|
||||
EsPanel *messageRow = EsPanelCreate(driveInformation, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
|
||||
EsIconDisplay *statusIcon = EsIconDisplayCreate(messageRow, ES_CELL_V_TOP, ES_STYLE_ICON_DISPLAY_SMALL, ES_ICON_DIALOG_INFORMATION);
|
||||
EsSpacerCreate(messageRow, ES_CELL_V_FILL, 0, 8, 0);
|
||||
|
||||
// TODO Check there are no file systems already on the drive.
|
||||
|
||||
bool showCapacity = true;
|
||||
|
||||
if (information.readOnly) {
|
||||
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
|
||||
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveReadOnly));
|
||||
showCapacity = false;
|
||||
} else if (information.sectorSize * information.sectorCount < metadata->totalUncompressedBytes + PARTITION_OVERHEAD) {
|
||||
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
|
||||
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveNotEnoughSpace));
|
||||
} else {
|
||||
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveOkay));
|
||||
EsElementSetDisabled(installButton, false);
|
||||
}
|
||||
|
||||
if (showCapacity) {
|
||||
// TODO Localization.
|
||||
char buffer[128];
|
||||
size_t bytes = EsStringFormat(buffer, sizeof(buffer), "Minimum space required: %D", metadata->totalUncompressedBytes + PARTITION_OVERHEAD);
|
||||
EsSpacerCreate(driveInformation, ES_CELL_H_FILL, 0, 0, 10);
|
||||
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, buffer, bytes);
|
||||
bytes = EsStringFormat(buffer, sizeof(buffer), "Drive capacity: %D", information.sectorSize * information.sectorCount);
|
||||
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, buffer, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
int DrivesListMessage(EsElement *element, EsMessage *message) {
|
||||
if (message->type == ES_MSG_LIST_VIEW_SELECT) {
|
||||
EsGeneric deviceID;
|
||||
|
||||
if (EsListViewFixedItemGetSelected(((EsListView *) element), &deviceID)) {
|
||||
for (uintptr_t i = 0; i < connectedDrives.Length(); i++) {
|
||||
if (connectedDrives[i].id == deviceID.u) {
|
||||
ConnectedDriveSelect(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ButtonViewLicenses(EsInstance *, EsElement *, EsCommand *) {
|
||||
EsPanelSwitchTo(switcher, panelLicenses, ES_TRANSITION_FADE_IN);
|
||||
}
|
||||
|
||||
void ButtonInstallOptions(EsInstance *, EsElement *, EsCommand *) {
|
||||
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_FADE_IN);
|
||||
}
|
||||
|
||||
|
||||
void ButtonShutdown(EsInstance *, EsElement *, EsCommand *) {
|
||||
EsSystemShowShutdownDialog();
|
||||
}
|
||||
|
||||
void ButtonInstall(EsInstance *, EsElement *, EsCommand *) {
|
||||
// TODO.
|
||||
}
|
||||
|
||||
int SwitcherMessage(EsElement *, EsMessage *message) {
|
||||
if (message->type == ES_MSG_GET_WIDTH || message->type == ES_MSG_GET_HEIGHT) {
|
||||
return EsMessageSend(panelInstallOptions, message);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _start() {
|
||||
_init();
|
||||
|
||||
metadata = (InstallerMetadata *) EsFileReadAll(EsLiteral("0:/installer_metadata.dat"), nullptr);
|
||||
EsAssert(metadata);
|
||||
|
||||
{
|
||||
EsWindow *window = EsWindowCreate(_EsInstanceCreate(sizeof(EsInstance), nullptr), ES_WINDOW_PLAIN);
|
||||
EsHandle handle = EsWindowGetHandle(window);
|
||||
window->instance->window = window;
|
||||
|
||||
EsRectangle screen;
|
||||
EsSyscall(ES_SYSCALL_SCREEN_BOUNDS_GET, 0, (uintptr_t) &screen, 0, 0);
|
||||
EsSyscall(ES_SYSCALL_WINDOW_MOVE, handle, (uintptr_t) &screen, 0, 0);
|
||||
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, ES_WINDOW_SOLID_TRUE, 0, ES_WINDOW_PROPERTY_SOLID);
|
||||
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, 0, 0, ES_WINDOW_PROPERTY_FOCUSED);
|
||||
|
||||
EsPanel *sheet = EsPanelCreate(window, ES_PANEL_VERTICAL | ES_CELL_PUSH | ES_CELL_CENTER, ES_STYLE_INSTALLER_ROOT);
|
||||
switcher = EsPanelCreate(sheet, ES_CELL_H_FILL | ES_PANEL_SWITCHER);
|
||||
switcher->messageUser = SwitcherMessage;
|
||||
|
||||
{
|
||||
panelInstallOptions = EsPanelCreate(switcher, ES_CELL_H_FILL, &styleRoot);
|
||||
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_NONE);
|
||||
EsTextDisplayCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
|
||||
|
||||
EsPanel *drivesPanel = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_PANEL_INSET);
|
||||
EsPanel *drivesSplit = EsPanelCreate(drivesPanel, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
|
||||
EsPanel *drivesLeft = EsPanelCreate(drivesSplit, ES_CELL_H_FILL);
|
||||
EsTextDisplayCreate(drivesLeft, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDrivesList));
|
||||
EsSpacerCreate(drivesLeft, ES_CELL_H_FILL, 0, 0, 8);
|
||||
drivesList = EsListViewCreate(drivesLeft, ES_CELL_H_FILL | ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
|
||||
drivesList->messageUser = DrivesListMessage;
|
||||
EsElementFocus(drivesList);
|
||||
EsSpacerCreate(drivesSplit, ES_CELL_V_FILL, 0, 25, 0);
|
||||
driveInformation = EsPanelCreate(drivesSplit, ES_CELL_H_FILL | ES_CELL_V_FILL);
|
||||
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL | ES_CELL_V_FILL, &styleDrivesSelectHint, INTERFACE_STRING(InstallerDrivesSelectHint));
|
||||
|
||||
EsPanel *buttonsRow = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, &styleButtonsRow);
|
||||
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(InstallerViewLicenses)), ButtonViewLicenses);
|
||||
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopShutdownAction)), ButtonShutdown);
|
||||
EsSpacerCreate(buttonsRow, ES_CELL_H_FILL);
|
||||
installButton = EsButtonCreate(buttonsRow, ES_ELEMENT_DISABLED, 0, INTERFACE_STRING(InstallerInstall));
|
||||
EsButtonOnCommand(installButton, ButtonInstall);
|
||||
}
|
||||
|
||||
{
|
||||
panelLicenses = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
|
||||
EsTextbox *textbox = EsTextboxCreate(panelLicenses, ES_CELL_FILL | ES_TEXTBOX_MULTILINE);
|
||||
EsElementSetDisabled(textbox);
|
||||
size_t bytes;
|
||||
char *data = (char *) EsFileReadAll(EsLiteral("0:/installer_licenses.txt"), &bytes);
|
||||
EsTextboxInsert(textbox, data, bytes);
|
||||
EsHeapFree(data);
|
||||
EsButtonOnCommand(EsButtonCreate(panelLicenses, ES_CELL_H_LEFT, 0, INTERFACE_STRING(InstallerGoBack)), ButtonInstallOptions);
|
||||
}
|
||||
|
||||
// EsWindowCreate(instance, ES_WINDOW_INSPECTOR);
|
||||
}
|
||||
|
||||
EsDeviceEnumerate([] (EsMessageDevice device, EsGeneric) {
|
||||
ConnectedDriveAdd(device);
|
||||
}, 0);
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
name=Installer
|
||||
permission_all_files=1
|
||||
permission_all_devices=1
|
||||
permission_shutdown=1
|
||||
hidden=1
|
||||
is_installer=1
|
||||
|
||||
[build]
|
||||
source=apps/installer.cpp
|
||||
|
|
|
@ -168,7 +168,7 @@ void FormatPopupCreate(Instance *instance) {
|
|||
EsListView *list = EsListViewCreate(column, ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
|
||||
EsListViewFixedItemInsert(list, INTERFACE_STRING(CommonFormatPlainText), 0);
|
||||
EsListViewFixedItemInsert(list, "C/C++", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C);
|
||||
EsListViewFixedItemInsert(list, "Ini file", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI);
|
||||
EsListViewFixedItemInsert(list, "Ini", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI);
|
||||
EsListViewFixedItemSelect(list, instance->syntaxHighlightingLanguage);
|
||||
|
||||
list->messageUser = [] (EsElement *element, EsMessage *message) {
|
||||
|
|
|
@ -758,15 +758,17 @@ EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, const char *appl
|
|||
}
|
||||
}
|
||||
|
||||
apiInstance->mainWindowHandle = message->createInstance.window;
|
||||
instance->window = EsWindowCreate(instance, ES_WINDOW_NORMAL);
|
||||
EsWindowSetTitle(instance->window, nullptr, 0);
|
||||
if (message) {
|
||||
apiInstance->mainWindowHandle = message->createInstance.window;
|
||||
instance->window = EsWindowCreate(instance, ES_WINDOW_NORMAL);
|
||||
EsWindowSetTitle(instance->window, nullptr, 0);
|
||||
|
||||
if (apiInstance->startupInformation && apiInstance->startupInformation->readHandle) {
|
||||
InstanceCreateFileStore(apiInstance, apiInstance->startupInformation->readHandle);
|
||||
InstancePostOpenMessage(instance, false);
|
||||
EsWindowSetTitle(instance->window, apiInstance->startupInformation->filePath, apiInstance->startupInformation->filePathBytes);
|
||||
EsCommandSetDisabled(&apiInstance->commandShowInFileManager, false);
|
||||
if (apiInstance->startupInformation && apiInstance->startupInformation->readHandle) {
|
||||
InstanceCreateFileStore(apiInstance, apiInstance->startupInformation->readHandle);
|
||||
InstancePostOpenMessage(instance, false);
|
||||
EsWindowSetTitle(instance->window, apiInstance->startupInformation->filePath, apiInstance->startupInformation->filePathBytes);
|
||||
EsCommandSetDisabled(&apiInstance->commandShowInFileManager, false);
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
|
@ -1437,6 +1439,14 @@ double EsPerformanceTimerPop() {
|
|||
return result;
|
||||
}
|
||||
|
||||
uint32_t EsIconIDFromDriveType(uint8_t driveType) {
|
||||
if (driveType == ES_DRIVE_TYPE_HDD ) return ES_ICON_DRIVE_HARDDISK;
|
||||
if (driveType == ES_DRIVE_TYPE_SSD ) return ES_ICON_DRIVE_HARDDISK_SOLIDSTATE;
|
||||
if (driveType == ES_DRIVE_TYPE_CDROM ) return ES_ICON_MEDIA_OPTICAL;
|
||||
if (driveType == ES_DRIVE_TYPE_USB_MASS_STORAGE) return ES_ICON_DRIVE_REMOVABLE_MEDIA_USB;
|
||||
return ES_ICON_DRIVE_HARDDISK;
|
||||
}
|
||||
|
||||
uint32_t EsIconIDFromString(const char *string, ptrdiff_t stringBytes) {
|
||||
if (!string) {
|
||||
return 0;
|
||||
|
|
|
@ -177,6 +177,7 @@ struct {
|
|||
Array<ContainerWindow *> allContainerWindows;
|
||||
|
||||
InstalledApplication *fileManager;
|
||||
InstalledApplication *installer;
|
||||
|
||||
EsObjectID currentDocumentID;
|
||||
HashStore<EsObjectID, OpenDocument> openDocuments;
|
||||
|
@ -187,7 +188,7 @@ struct {
|
|||
|
||||
bool shutdownWindowOpen;
|
||||
bool setupDesktopUIComplete;
|
||||
int installationState;
|
||||
uint8_t installationState;
|
||||
|
||||
EsHandle nextClipboardFile;
|
||||
EsObjectID nextClipboardProcessID;
|
||||
|
@ -1882,6 +1883,8 @@ void ConfigurationLoadApplications() {
|
|||
|
||||
if (EsSystemConfigurationGroupReadInteger(group, EsLiteral("is_file_manager"))) {
|
||||
desktop.fileManager = application;
|
||||
} else if (EsSystemConfigurationGroupReadInteger(group, EsLiteral("is_installer"))) {
|
||||
desktop.installer = application;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2160,23 +2163,25 @@ void DesktopSetup() {
|
|||
EsButtonOnCommand(shutdownButton, [] (EsInstance *, EsElement *, EsCommand *) {
|
||||
ShutdownModalCreate();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!desktop.setupDesktopUIComplete) {
|
||||
// Launch the first application.
|
||||
// Launch the first application.
|
||||
|
||||
char *firstApplication = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("first_application"));
|
||||
char *firstApplication = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("first_application"));
|
||||
|
||||
if (firstApplication && firstApplication[0]) {
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
if (desktop.installedApplications[i]->cName && 0 == EsCRTstrcmp(desktop.installedApplications[i]->cName, firstApplication)) {
|
||||
ApplicationInstanceCreate(desktop.installedApplications[i]->id, nullptr, nullptr);
|
||||
if (firstApplication && firstApplication[0]) {
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
if (desktop.installedApplications[i]->cName && 0 == EsCRTstrcmp(desktop.installedApplications[i]->cName, firstApplication)) {
|
||||
ApplicationInstanceCreate(desktop.installedApplications[i]->id, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EsHeapFree(firstApplication);
|
||||
EsHeapFree(firstApplication);
|
||||
}
|
||||
} else if (desktop.installationState == INSTALLATION_STATE_INSTALLER) {
|
||||
if (!desktop.setupDesktopUIComplete) {
|
||||
ApplicationInstanceCreate(desktop.installer->id, nullptr, nullptr, true /* hidden */);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CHECK_FOR_NOT_RESPONDING
|
||||
|
@ -2186,37 +2191,6 @@ void DesktopSetup() {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (desktop.setupDesktopUIComplete) {
|
||||
} else if (desktop.installationState == INSTALLATION_STATE_NONE) {
|
||||
#if 0
|
||||
// Play the startup sound.
|
||||
|
||||
EsThreadCreate([] (EsGeneric) {
|
||||
size_t pathBytes;
|
||||
char *path = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("startup_sound"), &pathBytes);
|
||||
|
||||
if (path) {
|
||||
PlaySound(path, pathBytes);
|
||||
EsHeapFree(path);
|
||||
}
|
||||
}, nullptr, 0);
|
||||
#endif
|
||||
} else if (desktop.installationState == INSTALLATION_STATE_INSTALLER) {
|
||||
// Start the installer.
|
||||
|
||||
EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_PLAIN);
|
||||
|
||||
EsRectangle screen;
|
||||
EsSyscall(ES_SYSCALL_SCREEN_BOUNDS_GET, 0, (uintptr_t) &screen, 0, 0);
|
||||
EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &screen, 0, ES_WINDOW_MOVE_ALWAYS_ON_TOP);
|
||||
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, ES_WINDOW_SOLID_TRUE, 0, ES_WINDOW_PROPERTY_SOLID);
|
||||
|
||||
EsPanel *root = EsPanelCreate(window, ES_PANEL_VERTICAL | ES_CELL_PUSH | ES_CELL_CENTER, ES_STYLE_INSTALLER_ROOT);
|
||||
EsTextDisplayCreate(root, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, EsLiteral("Essence Installation"));
|
||||
|
||||
// TODO.
|
||||
}
|
||||
|
||||
desktop.setupDesktopUIComplete = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -5130,6 +5130,11 @@ EsIconDisplay *EsIconDisplayCreate(EsElement *parent, uint64_t flags, const EsSt
|
|||
return display;
|
||||
}
|
||||
|
||||
void EsIconDisplaySetIcon(EsIconDisplay *display, uint32_t iconID) {
|
||||
display->iconID = iconID;
|
||||
EsElementRepaint(display);
|
||||
}
|
||||
|
||||
// --------------------------------- Sliders.
|
||||
|
||||
struct EsSlider : EsElement {
|
||||
|
@ -5461,6 +5466,10 @@ void EsWindowSetTitle(EsWindow *window, const char *title, ptrdiff_t titleBytes)
|
|||
MessageDesktop(buffer, bytes, window->handle);
|
||||
}
|
||||
|
||||
EsHandle EsWindowGetHandle(EsWindow *window) {
|
||||
return window->handle;
|
||||
}
|
||||
|
||||
EsError EsMouseSetPosition(EsWindow *relativeWindow, int x, int y) {
|
||||
if (relativeWindow) {
|
||||
EsRectangle bounds = EsWindowGetBounds(relativeWindow);
|
||||
|
|
|
@ -2437,6 +2437,28 @@ bool EsListViewFixedItemSelect(EsListView *view, EsGeneric data) {
|
|||
return found;
|
||||
}
|
||||
|
||||
bool EsListViewFixedItemRemove(EsListView *view, EsGeneric data) {
|
||||
EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS);
|
||||
EsMessageMutexCheck();
|
||||
EsListViewIndex index;
|
||||
bool found = EsListViewFixedItemFindIndex(view, data, &index);
|
||||
|
||||
if (found) {
|
||||
EsListViewRemove(view, 0, index, 1);
|
||||
ListViewFixedItem item = view->fixedItems[index];
|
||||
|
||||
for (uintptr_t i = 0; i < item.otherColumns.Length(); i++) {
|
||||
EsHeapFree(item.otherColumns[i].string);
|
||||
}
|
||||
|
||||
EsHeapFree(item.firstColumn.string);
|
||||
item.otherColumns.Free();
|
||||
view->fixedItems.Delete(index);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool EsListViewFixedItemGetSelected(EsListView *view, EsGeneric *data) {
|
||||
EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS);
|
||||
EsMessageMutexCheck();
|
||||
|
|
|
@ -2082,6 +2082,7 @@ function void EsDrawTextLayers(EsPainter *painter, EsTextPlan *plan, EsRectangle
|
|||
function void EsDrawVectorFile(EsPainter *painter, EsRectangle bounds, const void *data, size_t dataBytes);
|
||||
|
||||
function uint32_t EsIconIDFromString(STRING string = BLANK_STRING);
|
||||
function uint32_t EsIconIDFromDriveType(uint8_t driveType);
|
||||
|
||||
function uint8_t *EsImageLoad(const void *file, size_t fileSize, uint32_t *width, uint32_t *height, int imageChannels);
|
||||
|
||||
|
@ -2335,6 +2336,7 @@ function void EsWindowSwitchToolbar(EsWindow *window, EsElement *toolbar, EsTran
|
|||
function void EsWindowSetIcon(EsWindow *window, uint32_t iconID);
|
||||
function void EsWindowSetTitle(EsWindow *window, STRING title = BLANK_STRING);
|
||||
function void EsWindowAddSizeAlternative(EsWindow *window, EsElement *small, EsElement *big, int widthThreshold, int heightThreshold); // Switch between elements when the window size goes below a threshold.
|
||||
function EsHandle EsWindowGetHandle(EsWindow *window); // For internal use only.
|
||||
|
||||
function EsMenu *EsMenuCreate(EsElement *source, uint64_t flags = ES_FLAGS_DEFAULT);
|
||||
function EsElement *EsMenuGetSource(EsMenu *menu); // TODO Public property?
|
||||
|
@ -2409,6 +2411,7 @@ function void EsPanelStartMovementAnimation(EsPanel *panel, float timeMultiplier
|
|||
// Static displays.
|
||||
|
||||
function EsIconDisplay *EsIconDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL, uint32_t iconID = 0);
|
||||
function void EsIconDisplaySetIcon(EsIconDisplay *display, uint32_t iconID);
|
||||
|
||||
function EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL);
|
||||
function void EsImageDisplayLoadBits(EsImageDisplay *display, const uint32_t *bits, size_t width, size_t height, size_t stride);
|
||||
|
@ -2466,6 +2469,7 @@ function void EsListViewRemove(EsListView *view, EsListViewIndex group, EsListVi
|
|||
function void EsListViewRemoveAll(EsListView *view, EsListViewIndex group);
|
||||
// (Fixed items.)
|
||||
function EsListViewIndex EsListViewFixedItemInsert(EsListView *view, STRING string = BLANK_STRING, EsGeneric data = ES_NULL, EsListViewIndex index = -1, uint32_t iconID = 0);
|
||||
function bool EsListViewFixedItemRemove(EsListView *view, EsGeneric data); // Returns false if the item was not found.
|
||||
function void EsListViewFixedItemAddString(EsListView *view, EsListViewIndex index, STRING string = BLANK_STRING); // For additional columns.
|
||||
function bool EsListViewFixedItemFindIndex(EsListView *view, EsGeneric data, EsListViewIndex *index); // Returns false if the item was not found.
|
||||
function bool EsListViewFixedItemSelect(EsListView *view, EsGeneric data); // Returns false if the item was not found.
|
||||
|
|
|
@ -55,6 +55,7 @@ define ES_STYLE_PANEL_DIALOG_ROOT (ES_STYLE_CAST(1311))
|
|||
define ES_STYLE_PANEL_DOCUMENT (ES_STYLE_CAST(1547))
|
||||
define ES_STYLE_PANEL_FILLED (ES_STYLE_CAST(1313))
|
||||
define ES_STYLE_PANEL_GROUP_BOX (ES_STYLE_CAST(1315))
|
||||
define ES_STYLE_PANEL_INSET (ES_STYLE_CAST(1641))
|
||||
define_private ES_STYLE_PANEL_INSPECTOR_WINDOW_CONTAINER (ES_STYLE_CAST(1317))
|
||||
define_private ES_STYLE_PANEL_INSPECTOR_WINDOW_ROOT (ES_STYLE_CAST(1319))
|
||||
define_private ES_STYLE_PANEL_MENU_COLUMN (ES_STYLE_CAST(1321))
|
||||
|
|
|
@ -46,6 +46,7 @@ struct NVMeController : KDevice {
|
|||
uint64_t maximumDataTransferBytes;
|
||||
uint32_t rtd3EntryLatencyUs;
|
||||
uint16_t maximumOutstandingCommands;
|
||||
char model[40];
|
||||
|
||||
uint8_t *adminCompletionQueue, *adminSubmissionQueue;
|
||||
uint32_t adminCompletionQueueHead, adminSubmissionQueueTail;
|
||||
|
@ -610,6 +611,7 @@ void NVMeController::Initialise() {
|
|||
maximumDataTransferBytes = identifyData[77] ? (1 << (12 + identifyData[77] + (((capabilities >> 48) & 0xF)))) : 0;
|
||||
rtd3EntryLatencyUs = *(uint32_t *) (identifyData + 88);
|
||||
maximumOutstandingCommands = *(uint16_t *) (identifyData + 514);
|
||||
EsMemoryCopy(model, &identifyData[24], sizeof(model));
|
||||
|
||||
if (rtd3EntryLatencyUs > 250 * 1000) {
|
||||
rtd3EntryLatencyUs = 250 * 1000; // Maximum shutdown delay: 250ms.
|
||||
|
@ -624,7 +626,7 @@ void NVMeController::Initialise() {
|
|||
KernelLog(LOG_INFO, "NVMe", "controller identify data", "Controller identify reported the following information: "
|
||||
"serial number - '%s', model number - '%s', firmware revision - '%s', "
|
||||
"maximum data transfer - %D, RTD3 entry latency - %dus, maximum outstanding commands - %d.\n",
|
||||
20, identifyData + 4, 40, identifyData + 24, 8, identifyData + 64,
|
||||
20, identifyData + 4, sizeof(model), model, 8, identifyData + 64,
|
||||
maximumDataTransferBytes, rtd3EntryLatencyUs, maximumOutstandingCommands);
|
||||
|
||||
if (maximumDataTransferBytes == 0 || maximumDataTransferBytes >= 2097152) {
|
||||
|
@ -788,7 +790,7 @@ void NVMeController::Initialise() {
|
|||
|
||||
bool readOnly = identifyData[4096 + 99] & (1 << 0);
|
||||
|
||||
KernelLog(LOG_INFO, "NVMe", "namespace identified", "Identifier namespace %d with sectors of size %D, and a capacity of %D.%z\n",
|
||||
KernelLog(LOG_INFO, "NVMe", "namespace identified", "Identified namespace %d with sectors of size %D, and a capacity of %D.%z\n",
|
||||
nsid, sectorBytes, capacity, readOnly ? " The namespace is read-only." : "");
|
||||
|
||||
NVMeDrive *device = (NVMeDrive *) KDeviceCreate("NVMe namespace", this, sizeof(NVMeDrive));
|
||||
|
@ -801,11 +803,15 @@ void NVMeController::Initialise() {
|
|||
device->controller = this;
|
||||
device->nsid = nsid;
|
||||
|
||||
device->maxAccessSectorCount = maximumDataTransferBytes / sectorBytes;
|
||||
device->information.sectorSize = sectorBytes;
|
||||
device->information.sectorCount = capacity / sectorBytes;
|
||||
device->maxAccessSectorCount = maximumDataTransferBytes / sectorBytes;
|
||||
device->information.readOnly = readOnly;
|
||||
device->information.driveType = ES_DRIVE_TYPE_SSD;
|
||||
|
||||
EsAssert(sizeof(device->information.model) >= sizeof(model));
|
||||
device->information.modelBytes = sizeof(model);
|
||||
EsMemoryCopy(device->information.model, model, 40);
|
||||
|
||||
device->access = [] (KBlockDeviceAccessRequest request) {
|
||||
NVMeDrive *drive = (NVMeDrive *) request.device;
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -5,6 +5,7 @@
|
|||
|
||||
#define ELLIPSIS "…"
|
||||
#define HYPHENATION_POINT "‧"
|
||||
#define SYSTEM_BRAND_SHORT "Essence"
|
||||
|
||||
// Common.
|
||||
|
||||
|
@ -52,7 +53,7 @@ DEFINE_INTERFACE_STRING(CommonDriveSSD, "SSD");
|
|||
DEFINE_INTERFACE_STRING(CommonDriveCDROM, "CD-ROM");
|
||||
DEFINE_INTERFACE_STRING(CommonDriveUSBMassStorage, "USB drive");
|
||||
|
||||
DEFINE_INTERFACE_STRING(CommonSystemBrand, "Essence Alpha v0.1");
|
||||
DEFINE_INTERFACE_STRING(CommonSystemBrand, SYSTEM_BRAND_SHORT " Alpha v0.1");
|
||||
|
||||
DEFINE_INTERFACE_STRING(CommonListViewType, "List view");
|
||||
DEFINE_INTERFACE_STRING(CommonListViewTypeThumbnails, "Thumbnails");
|
||||
|
@ -276,6 +277,19 @@ DEFINE_INTERFACE_STRING(Game2048NewGame, "New game");
|
|||
DEFINE_INTERFACE_STRING(Game2048HighScore, "High score: \aw6]%d\a]");
|
||||
DEFINE_INTERFACE_STRING(Game2048NewHighScore, "You reached a new high score!");
|
||||
|
||||
// Installer.
|
||||
|
||||
DEFINE_INTERFACE_STRING(InstallerTitle, SYSTEM_BRAND_SHORT " Installer");
|
||||
DEFINE_INTERFACE_STRING(InstallerDrivesList, "Select the drive to install on:");
|
||||
DEFINE_INTERFACE_STRING(InstallerDrivesSelectHint, "Choose a drive from the list on the left.");
|
||||
DEFINE_INTERFACE_STRING(InstallerDriveRemoved, "The drive was disconnected.");
|
||||
DEFINE_INTERFACE_STRING(InstallerDriveReadOnly, "This drive is read-only. You cannot install " SYSTEM_BRAND_SHORT " on this drive.");
|
||||
DEFINE_INTERFACE_STRING(InstallerDriveNotEnoughSpace, "This drive does not have enough space to install " SYSTEM_BRAND_SHORT ".");
|
||||
DEFINE_INTERFACE_STRING(InstallerDriveOkay, SYSTEM_BRAND_SHORT " can be installed on this drive.");
|
||||
DEFINE_INTERFACE_STRING(InstallerInstall, "Install");
|
||||
DEFINE_INTERFACE_STRING(InstallerViewLicenses, "Licenses");
|
||||
DEFINE_INTERFACE_STRING(InstallerGoBack, "Back");
|
||||
|
||||
// TODO System Monitor.
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
|
|
@ -446,3 +446,7 @@ EsBufferReadInt32Endian=444
|
|||
EsBufferWriteInt32Endian=445
|
||||
EsSystemGetOptimalWorkQueueThreadCount=446
|
||||
EsDeviceControl=447
|
||||
EsWindowGetHandle=448
|
||||
EsListViewFixedItemRemove=449
|
||||
EsIconIDFromDriveType=450
|
||||
EsIconDisplaySetIcon=451
|
||||
|
|
12
util/build.c
12
util/build.c
|
@ -1002,7 +1002,7 @@ void AddressToLine(const char *symbolFile) {
|
|||
}
|
||||
}
|
||||
|
||||
void GatherFilesForInstallerArchive(FILE *file, const char *path1, const char *path2, uint64_t *crc64) {
|
||||
void GatherFilesForInstallerArchive(FILE *file, const char *path1, const char *path2, uint64_t *crc64, uint64_t *totalUncompressedSize) {
|
||||
char path[4096], path3[4096];
|
||||
snprintf(path, sizeof(path), "%s%s", path1, path2);
|
||||
|
||||
|
@ -1021,7 +1021,7 @@ void GatherFilesForInstallerArchive(FILE *file, const char *path1, const char *p
|
|||
lstat(path, &s);
|
||||
|
||||
if (S_ISDIR(s.st_mode)) {
|
||||
GatherFilesForInstallerArchive(file, path1, path3, crc64);
|
||||
GatherFilesForInstallerArchive(file, path1, path3, crc64, totalUncompressedSize);
|
||||
} else if (S_ISREG(s.st_mode)) {
|
||||
size_t _length;
|
||||
void *data = LoadFile(path, &_length);
|
||||
|
@ -1033,6 +1033,7 @@ void GatherFilesForInstallerArchive(FILE *file, const char *path1, const char *p
|
|||
fwrite(path3, 1, pathBytes, file);
|
||||
fwrite(data, 1, length, file);
|
||||
*crc64 = CalculateCRC64(data, length, *crc64);
|
||||
*totalUncompressedSize += length;
|
||||
free(data);
|
||||
} else {
|
||||
printf("skipping: %s\n", path3);
|
||||
|
@ -1105,8 +1106,8 @@ void DoCommand(const char *l) {
|
|||
"ports/lzma/7zStream.c ports/lzma/Threads.c ports/lzma/LzFindMt.c ports/lzma/LzFind.c "
|
||||
"ports/lzma/7zFile.c ports/lzma/Alloc.c ports/lzma/CpuArch.c -pthread");
|
||||
FILE *f = fopen("bin/temp.dat", "wb");
|
||||
uint64_t crc64 = 0;
|
||||
GatherFilesForInstallerArchive(f, "root", "", &crc64);
|
||||
uint64_t crc64 = 0, uncompressed = 0;
|
||||
GatherFilesForInstallerArchive(f, "root", "", &crc64, &uncompressed);
|
||||
fwrite(&crc64, 1, sizeof(crc64), f);
|
||||
uint32_t sizeMB = ftell(f) / 1000000;
|
||||
fclose(f);
|
||||
|
@ -1116,6 +1117,9 @@ void DoCommand(const char *l) {
|
|||
lstat("bin/installer_archive.dat", &s);
|
||||
printf("Compressed to %d MB.\n", (uint32_t) (s.st_size / 1000000));
|
||||
unlink("bin/temp.dat");
|
||||
f = fopen("bin/installer_metadata.dat", "ab");
|
||||
fwrite(&uncompressed, 1, sizeof(uncompressed), f);
|
||||
fclose(f);
|
||||
} else if (0 == strcmp(l, "config")) {
|
||||
BuildUtilities();
|
||||
CallSystem("bin/config_editor");
|
||||
|
|
|
@ -305,6 +305,7 @@ Option options[] = {
|
|||
{ "Emulator.SecondaryDriveMB", OPTION_TYPE_STRING, { .s = NULL } },
|
||||
{ "General.first_application", OPTION_TYPE_STRING, { .s = NULL } },
|
||||
{ "General.wallpaper", OPTION_TYPE_STRING, { .s = NULL } },
|
||||
{ "General.installation_state", OPTION_TYPE_STRING, { .s = "0" } },
|
||||
};
|
||||
|
||||
char *previousOptionsBuffer;
|
||||
|
|
Loading…
Reference in New Issue