simplify ApplicationInstance states

This commit is contained in:
nakst 2021-08-18 02:20:27 +01:00
parent 3180b16221
commit f7954b3e99
5 changed files with 221 additions and 198 deletions

View File

@ -658,11 +658,13 @@ const EsApplicationStartupInformation *EsInstanceGetStartupInformation(EsInstanc
return instance->startupInformation; return instance->startupInformation;
} }
void EsInstanceDestroy(EsInstance *_instance) { void EsInstanceDestroy(EsInstance *instance) {
UndoManagerDestroy(_instance->undoManager); EsInstance *inspector = ((APIInstance *) instance->_private)->attachedInspector;
EsAssert(_instance->window->instance == _instance); if (inspector) EsInstanceDestroy(inspector);
_instance->window->destroyInstanceAfterClose = true; UndoManagerDestroy(instance->undoManager);
EsElementDestroy(_instance->window); EsAssert(instance->window->instance == instance);
instance->window->destroyInstanceAfterClose = true;
EsElementDestroy(instance->window);
} }
EsInstance *InstanceFromWindowID(uint64_t id) { EsInstance *InstanceFromWindowID(uint64_t id) {

View File

@ -29,7 +29,6 @@
// - Print screen. // - Print screen.
// TODO Only let File Manager read the file_type sections of the system configuration. // TODO Only let File Manager read the file_type sections of the system configuration.
// TODO Maybe extend tab hitbox to top of window when maximised? Might need a visual change too.
// TODO Restarting Desktop if it crashes. // TODO Restarting Desktop if it crashes.
// TODO Make sure applications can't delete |Fonts: and |Themes:. // TODO Make sure applications can't delete |Fonts: and |Themes:.
@ -41,12 +40,14 @@
#define APPLICATION_PERMISSION_RUN_TEMPORARY_APPLICATION (1 << 3) #define APPLICATION_PERMISSION_RUN_TEMPORARY_APPLICATION (1 << 3)
#define APPLICATION_PERMISSION_SHUTDOWN (1 << 4) #define APPLICATION_PERMISSION_SHUTDOWN (1 << 4)
#define APPLICATION_ID_DESKTOP_BLANK_TAB ((int64_t) 0x8000000000000000L) #define APPLICATION_ID_DESKTOP_BLANK_TAB (-1)
#define APPLICATION_ID_DESKTOP_SETTINGS (-2)
#define APPLICATION_ID_DESKTOP_CRASHED (-3)
#define CRASHED_TAB_FATAL_ERROR (1) #define CRASHED_TAB_FATAL_ERROR (0)
#define CRASHED_TAB_PROGRAM_NOT_FOUND (2) #define CRASHED_TAB_PROGRAM_NOT_FOUND (1)
#define CRASHED_TAB_INVALID_EXECUTABLE (3) #define CRASHED_TAB_INVALID_EXECUTABLE (2)
#define CRASHED_TAB_NOT_RESPONDING (4) #define CRASHED_TAB_NOT_RESPONDING (3)
#define INSTALLATION_STATE_NONE (0) #define INSTALLATION_STATE_NONE (0)
#define INSTALLATION_STATE_INSTALLER (1) #define INSTALLATION_STATE_INSTALLER (1)
@ -66,6 +67,7 @@ struct ReorderList : EsElement {
struct WindowTab : ReorderItem { struct WindowTab : ReorderItem {
struct ContainerWindow *container; struct ContainerWindow *container;
struct ApplicationInstance *applicationInstance; struct ApplicationInstance *applicationInstance;
struct ApplicationInstance *notRespondingInstance;
EsButton *closeButton; EsButton *closeButton;
}; };
@ -100,13 +102,14 @@ struct OpenDocument {
char *temporarySavePath; char *temporarySavePath;
size_t temporarySavePathBytes; size_t temporarySavePathBytes;
EsHandle readHandle; EsHandle readHandle;
uint64_t id; EsObjectID id;
uint64_t currentWriter; EsObjectID currentWriter;
}; };
struct InstalledApplication { struct InstalledApplication {
char *cName; char *cName;
char *cExecutable; char *cExecutable;
void (*createInstance)(EsMessage *); // For applications provided by Desktop.
int64_t id; int64_t id;
uint32_t iconID; uint32_t iconID;
bool hidden, useSingleProcess, temporary; bool hidden, useSingleProcess, temporary;
@ -121,24 +124,24 @@ struct CrashedTabInstance : EsInstance {
struct BlankTabInstance : EsInstance { struct BlankTabInstance : EsInstance {
}; };
struct ApplicationInstance { struct SettingsInstance : EsInstance {
WindowTab *tab; };
EsInstance *localInstance;
InstalledApplication *application;
uint64_t documentID;
struct ApplicationInstance {
// User interface.
WindowTab *tab; // nullptr for notRespondingInstance.
EsObjectID embeddedWindowID;
EsHandle embeddedWindowHandle;
// Currently loaded application.
InstalledApplication *application;
EsObjectID documentID, processID;
EsHandle processHandle;
// Tab information.
char title[128]; char title[128];
size_t titleBytes; size_t titleBytes;
uint32_t iconID; uint32_t iconID;
uint64_t processID;
EsHandle processHandle;
uint64_t embeddedWindowID;
EsHandle embeddedWindowHandle;
bool notResponding;
EsHandle restoreEmbeddedWindowHandle;
uint64_t restoreEmbeddedWindowID;
}; };
const EsStyle styleNewTabContent = { const EsStyle styleNewTabContent = {
@ -164,8 +167,8 @@ struct {
Array<ContainerWindow *> allContainerWindows; Array<ContainerWindow *> allContainerWindows;
Array<EsMessageDevice> connectedDevices; Array<EsMessageDevice> connectedDevices;
InstalledApplication *fileManager; InstalledApplication *fileManager;
uint64_t currentDocumentID; EsObjectID currentDocumentID;
HashStore<uint64_t, OpenDocument> openDocuments; HashStore<EsObjectID, OpenDocument> openDocuments;
TaskBar taskBar; TaskBar taskBar;
EsWindow *wallpaperWindow; EsWindow *wallpaperWindow;
bool shutdownWindowOpen; bool shutdownWindowOpen;
@ -174,11 +177,11 @@ struct {
} desktop; } desktop;
int TaskBarButtonMessage(EsElement *element, EsMessage *message); int TaskBarButtonMessage(EsElement *element, EsMessage *message);
ApplicationInstance *ApplicationInstanceCreate(int64_t id, EsApplicationStartupInformation *startupInformation, ContainerWindow *container); ApplicationInstance *ApplicationInstanceCreate(int64_t id, EsApplicationStartupInformation *startupInformation, ContainerWindow *container, bool hidden = false);
void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInformation *startupInformation, ApplicationInstance *instance); void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInformation *startupInformation, ApplicationInstance *instance);
void ApplicationInstanceClose(ApplicationInstance *instance); void ApplicationInstanceClose(ApplicationInstance *instance);
ApplicationInstance *ApplicationInstanceFindByWindowID(uint64_t windowID, bool remove = false); ApplicationInstance *ApplicationInstanceFindByWindowID(EsObjectID windowID, bool remove = false);
void EmbeddedWindowDestroyed(uint64_t id); void EmbeddedWindowDestroyed(EsObjectID id);
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
// Reorder lists: // Reorder lists:
@ -388,14 +391,22 @@ int ReorderListMessage(EsElement *_list, EsMessage *message) {
// Container windows: // Container windows:
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
void WindowTabActivate(WindowTab *tab) { void WindowTabClose(WindowTab *tab) {
if (tab->container->active != tab) { if (tab->notRespondingInstance) {
// The application is not responding, so force quit the process.
EsProcessTerminate(tab->applicationInstance->processHandle, 1);
} else {
ApplicationInstanceClose(tab->applicationInstance);
}
}
void WindowTabActivate(WindowTab *tab, bool force = false) {
if (tab->container->active != tab || force) {
tab->container->active = tab; tab->container->active = tab;
EsElementRelayout(tab->container->tabBand); EsElementRelayout(tab->container->tabBand);
tab->container->taskBarButton->Repaint(true); tab->container->taskBarButton->Repaint(true);
EsHandle handle = tab->notRespondingInstance ? tab->notRespondingInstance->embeddedWindowHandle : tab->applicationInstance->embeddedWindowHandle;
// EsPrint("Activating tab %d...\n", tab->tabIndex); EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, tab->window->handle, handle, 0, ES_WINDOW_PROPERTY_EMBED);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, tab->container->window->handle, (uintptr_t) tab->applicationInstance->embeddedWindowHandle, 0, ES_WINDOW_PROPERTY_EMBED);
} }
} }
@ -429,7 +440,7 @@ int ContainerWindowMessage(EsElement *element, EsMessage *message) {
} else if (ctrlOnly && scancode == ES_SCANCODE_T) { } else if (ctrlOnly && scancode == ES_SCANCODE_T) {
ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_BLANK_TAB, nullptr, container); ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_BLANK_TAB, nullptr, container);
} else if (ctrlOnly && scancode == ES_SCANCODE_W) { } else if (ctrlOnly && scancode == ES_SCANCODE_W) {
ApplicationInstanceClose(container->active->applicationInstance); WindowTabClose(container->active);
} else if (ctrlOnly && scancode == ES_SCANCODE_N) { } else if (ctrlOnly && scancode == ES_SCANCODE_N) {
ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_BLANK_TAB, nullptr, nullptr); ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_BLANK_TAB, nullptr, nullptr);
} else if (message->keyboard.modifiers == ES_MODIFIER_FLAG && scancode == ES_SCANCODE_UP_ARROW) { } else if (message->keyboard.modifiers == ES_MODIFIER_FLAG && scancode == ES_SCANCODE_UP_ARROW) {
@ -471,7 +482,12 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
WindowTabBand *band = (WindowTabBand *) tab->parent; WindowTabBand *band = (WindowTabBand *) tab->parent;
ApplicationInstance *instance = tab->applicationInstance; ApplicationInstance *instance = tab->applicationInstance;
if (message->type == ES_MSG_PRESSED_START) { if (message->type == ES_MSG_DESTROY) {
if (tab->notRespondingInstance) {
ApplicationInstanceClose(tab->notRespondingInstance);
tab->notRespondingInstance = nullptr;
}
} else if (message->type == ES_MSG_PRESSED_START) {
tab->BringToFront(); tab->BringToFront();
WindowTabActivate(tab); WindowTabActivate(tab);
} else if (message->type == ES_MSG_HIT_TEST) { } else if (message->type == ES_MSG_HIT_TEST) {
@ -510,11 +526,10 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
EsMenu *menu = EsMenuCreate(tab, ES_FLAGS_DEFAULT); EsMenu *menu = EsMenuCreate(tab, ES_FLAGS_DEFAULT);
EsMenuAddItem(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(DesktopCloseTab), [] (EsMenu *, EsGeneric context) { EsMenuAddItem(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(DesktopCloseTab), [] (EsMenu *, EsGeneric context) {
ApplicationInstanceClose(((WindowTab *) context.p)->applicationInstance); WindowTabClose((WindowTab *) context.p);
}, tab); }, tab);
if (EsKeyboardIsShiftHeld() && !instance->localInstance) { if (EsKeyboardIsShiftHeld()) {
EsAssert(instance->processHandle);
EsMenuAddSeparator(menu); EsMenuAddSeparator(menu);
EsMenuAddItem(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(DesktopInspectUI), [] (EsMenu *, EsGeneric context) { EsMenuAddItem(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(DesktopInspectUI), [] (EsMenu *, EsGeneric context) {
@ -528,7 +543,7 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
EsMenuShow(menu); EsMenuShow(menu);
} else if (message->type == ES_MSG_MOUSE_MIDDLE_UP && (element->state & UI_STATE_HOVERED)) { } else if (message->type == ES_MSG_MOUSE_MIDDLE_UP && (element->state & UI_STATE_HOVERED)) {
ApplicationInstanceClose(tab->applicationInstance); WindowTabClose(tab);
} else if (message->type == ES_MSG_REORDER_ITEM_TEST) { } else if (message->type == ES_MSG_REORDER_ITEM_TEST) {
} else { } else {
return 0; return 0;
@ -548,7 +563,7 @@ WindowTab *WindowTabCreate(ContainerWindow *container, ApplicationInstance *inst
tab->closeButton->userData = tab; tab->closeButton->userData = tab;
EsButtonOnCommand(tab->closeButton, [] (EsInstance *, EsElement *element, EsCommand *) { EsButtonOnCommand(tab->closeButton, [] (EsInstance *, EsElement *element, EsCommand *) {
ApplicationInstanceClose(((WindowTab *) element->userData.p)->applicationInstance); WindowTabClose((WindowTab *) element->userData.p);
}); });
return tab; return tab;
@ -748,15 +763,21 @@ void ShutdownModalCreate() {
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
void InstanceForceQuit(EsInstance *, EsElement *element, EsCommand *) { void InstanceForceQuit(EsInstance *, EsElement *element, EsCommand *) {
ApplicationInstance *instance = (ApplicationInstance *) element->userData.p; EsObjectID windowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0);
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i];
if (instance->tab && instance->tab->notRespondingInstance && instance->tab->notRespondingInstance->embeddedWindowID == windowID) {
EsProcessTerminate(instance->processHandle, 1); EsProcessTerminate(instance->processHandle, 1);
break;
}
}
} }
void InstanceCrashedTabCreate(int reason, ApplicationInstance *_instance) { void InstanceCrashedTabCreate(EsMessage *message) {
EsMessage m = {}; CrashedTabInstance *instance = (CrashedTabInstance *) _EsInstanceCreate(sizeof(CrashedTabInstance), message, nullptr);
m.type = ES_MSG_INSTANCE_CREATE; int32_t reason = ((APIInstance *) instance->_private)->startupInformation->data;
m.createInstance.window = EsSyscall(ES_SYSCALL_WINDOW_CREATE, ES_WINDOW_NORMAL, 0, 0, 0);
CrashedTabInstance *instance = (CrashedTabInstance *) _EsInstanceCreate(sizeof(CrashedTabInstance), &m, nullptr);
instance->window->toolbarFillMode = true; instance->window->toolbarFillMode = true;
if (reason != CRASHED_TAB_NOT_RESPONDING) EsWindowSetIcon(instance->window, ES_ICON_DIALOG_ERROR); if (reason != CRASHED_TAB_NOT_RESPONDING) EsWindowSetIcon(instance->window, ES_ICON_DIALOG_ERROR);
EsElement *toolbar = EsWindowGetToolbar(instance->window); EsElement *toolbar = EsWindowGetToolbar(instance->window);
@ -773,70 +794,68 @@ void InstanceCrashedTabCreate(int reason, ApplicationInstance *_instance) {
} else if (reason == CRASHED_TAB_NOT_RESPONDING) { } else if (reason == CRASHED_TAB_NOT_RESPONDING) {
EsTextDisplayCreate(panel, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(DesktopNotResponding)); EsTextDisplayCreate(panel, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(DesktopNotResponding));
EsButton *button = EsButtonCreate(panel, ES_CELL_H_RIGHT, ES_STYLE_PUSH_BUTTON_DANGEROUS, INTERFACE_STRING(DesktopForceQuit)); EsButton *button = EsButtonCreate(panel, ES_CELL_H_RIGHT, ES_STYLE_PUSH_BUTTON_DANGEROUS, INTERFACE_STRING(DesktopForceQuit));
button->userData = _instance;
EsButtonOnCommand(button, InstanceForceQuit); EsButtonOnCommand(button, InstanceForceQuit);
} }
_instance->embeddedWindowHandle = m.createInstance.window;
_instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, m.createInstance.window, 0, 0, 0);
_instance->localInstance = instance;
} }
void InstanceBlankTabCreate(ApplicationInstance *_instance) { void InstanceBlankTabCreate(EsMessage *message) {
EsMessage m = {}; EsInstance *instance = _EsInstanceCreate(sizeof(BlankTabInstance), message, nullptr);
m.type = ES_MSG_INSTANCE_CREATE;
m.createInstance.window = EsSyscall(ES_SYSCALL_WINDOW_CREATE, ES_WINDOW_NORMAL, 0, 0, 0);
EsInstance *instance = _EsInstanceCreate(sizeof(BlankTabInstance), &m, nullptr);
EsWindowSetTitle(instance->window, INTERFACE_STRING(DesktopNewTabTitle)); EsWindowSetTitle(instance->window, INTERFACE_STRING(DesktopNewTabTitle));
EsPanel *windowBackground = EsPanelCreate(instance->window, ES_CELL_FILL, ES_STYLE_PANEL_WINDOW_BACKGROUND); EsPanel *windowBackground = EsPanelCreate(instance->window, ES_CELL_FILL, ES_STYLE_PANEL_WINDOW_BACKGROUND);
EsPanel *content = EsPanelCreate(windowBackground, ES_CELL_FILL | ES_PANEL_V_SCROLL_AUTO, &styleNewTabContent); EsPanel *content = EsPanelCreate(windowBackground, ES_CELL_FILL | ES_PANEL_V_SCROLL_AUTO, &styleNewTabContent);
EsPanel *buttonGroup;
{
// Installed applications list. // Installed applications list.
EsPanel *buttonGroup = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleButtonGroupContainer); buttonGroup = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleButtonGroupContainer);
buttonGroup->separatorStylePart = ES_STYLE_BUTTON_GROUP_SEPARATOR; buttonGroup->separatorStylePart = ES_STYLE_BUTTON_GROUP_SEPARATOR;
buttonGroup->separatorFlags = ES_CELL_H_FILL; buttonGroup->separatorFlags = ES_CELL_H_FILL;
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) { for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
InstalledApplication *application = desktop.installedApplications[i]; InstalledApplication *application = desktop.installedApplications[i];
if (application->hidden) continue;
if (application->hidden) {
continue;
}
EsButton *button = EsButtonCreate(buttonGroup, ES_CELL_H_FILL | ES_BUTTON_NOT_FOCUSABLE, ES_STYLE_BUTTON_GROUP_ITEM, application->cName); EsButton *button = EsButtonCreate(buttonGroup, ES_CELL_H_FILL | ES_BUTTON_NOT_FOCUSABLE, ES_STYLE_BUTTON_GROUP_ITEM, application->cName);
EsButtonSetIcon(button, (EsStandardIcon) application->iconID ?: ES_ICON_APPLICATION_DEFAULT_ICON);
button->userData = application; button->userData = application;
EsButtonSetIcon(button, (EsStandardIcon) application->iconID ?: ES_ICON_APPLICATION_DEFAULT_ICON);
EsButtonOnCommand(button, [] (EsInstance *, EsElement *element, EsCommand *) { EsButtonOnCommand(button, [] (EsInstance *, EsElement *element, EsCommand *) {
uint64_t tabID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0); EsObjectID tabID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0);
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(tabID); ApplicationInstance *instance = ApplicationInstanceFindByWindowID(tabID);
ApplicationInstanceStart(((InstalledApplication *) element->userData.p)->id, nullptr, instance); ApplicationInstanceStart(((InstalledApplication *) element->userData.p)->id, nullptr, instance);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, instance->tab->window->handle, (uintptr_t) instance->embeddedWindowHandle, 0, ES_WINDOW_PROPERTY_EMBED); WindowTabActivate(instance->tab, true);
EsInstanceDestroy(element->instance); EsInstanceDestroy(element->instance);
instance->localInstance = nullptr;
}); });
} }
} }
_instance->embeddedWindowHandle = m.createInstance.window; void InstanceSettingsCreate(EsMessage *message) {
_instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, m.createInstance.window, 0, 0, 0); // TODO.
_instance->localInstance = instance;
EsInstance *instance = _EsInstanceCreate(sizeof(SettingsInstance), message, nullptr);
EsWindowSetTitle(instance->window, INTERFACE_STRING(DesktopSettingsTitle));
EsWindowSetIcon(instance->window, ES_ICON_PREFERENCES_DESKTOP);
EsPanel *windowBackground = EsPanelCreate(instance->window, ES_CELL_FILL, ES_STYLE_PANEL_WINDOW_BACKGROUND);
EsPanel *content = EsPanelCreate(windowBackground, ES_CELL_FILL | ES_PANEL_V_SCROLL_AUTO, &styleNewTabContent);
EsPanel *buttonGroup;
buttonGroup = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleButtonGroupContainer);
buttonGroup->separatorStylePart = ES_STYLE_BUTTON_GROUP_SEPARATOR;
buttonGroup->separatorFlags = ES_CELL_H_FILL;
EsButton *button = EsButtonCreate(buttonGroup, ES_CELL_H_FILL | ES_BUTTON_NOT_FOCUSABLE, ES_STYLE_BUTTON_GROUP_ITEM, "Keyboard");
EsButtonSetIcon(button, ES_ICON_PREFERENCES_DESKTOP_KEYBOARD);
} }
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
// Application management: // Application management:
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
ApplicationInstance *ApplicationInstanceFindByWindowID(uint64_t windowID, bool remove) { ApplicationInstance *ApplicationInstanceFindByWindowID(EsObjectID windowID, bool remove) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) { for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i]; ApplicationInstance *instance = desktop.allApplicationInstances[i];
if (instance->embeddedWindowID == windowID || (instance->restoreEmbeddedWindowID == windowID && instance->notResponding)) { if (instance->embeddedWindowID == windowID) {
if (remove) { if (remove) {
desktop.allApplicationInstances.Delete(i); desktop.allApplicationInstances.Delete(i);
} }
@ -849,17 +868,11 @@ ApplicationInstance *ApplicationInstanceFindByWindowID(uint64_t windowID, bool r
} }
void ApplicationInstanceClose(ApplicationInstance *instance) { void ApplicationInstanceClose(ApplicationInstance *instance) {
if (!instance->processID) {
// This is a Desktop owned instance.
if (instance->localInstance) EsInstanceDestroy(instance->localInstance);
instance->localInstance = nullptr;
} else {
// TODO Force closing not responding instances. // TODO Force closing not responding instances.
EsMessage m = { ES_MSG_TAB_CLOSE_REQUEST }; EsMessage m = { ES_MSG_TAB_CLOSE_REQUEST };
m.tabOperation.id = instance->embeddedWindowID; m.tabOperation.id = instance->embeddedWindowID;
EsMessagePostRemote(instance->processHandle, &m); EsMessagePostRemote(instance->processHandle, &m);
} }
}
void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInformation *startupInformation, ApplicationInstance *instance) { void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInformation *startupInformation, ApplicationInstance *instance) {
EsApplicationStartupInformation _startupInformation = {}; EsApplicationStartupInformation _startupInformation = {};
@ -868,14 +881,15 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
startupInformation = &_startupInformation; startupInformation = &_startupInformation;
} }
if (instance->restoreEmbeddedWindowHandle) { if (instance->tab && instance->tab->notRespondingInstance) {
EsHandleClose(instance->restoreEmbeddedWindowHandle); ApplicationInstanceClose(instance->tab->notRespondingInstance);
instance->restoreEmbeddedWindowHandle = ES_INVALID_HANDLE; instance->tab->notRespondingInstance = nullptr;
} }
if (applicationID == APPLICATION_ID_DESKTOP_BLANK_TAB) { if (instance->processHandle) {
InstanceBlankTabCreate(instance); EsHandleClose(instance->processHandle);
return; instance->processID = 0;
instance->processHandle = ES_INVALID_HANDLE;
} }
InstalledApplication *application = nullptr; InstalledApplication *application = nullptr;
@ -887,7 +901,9 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
} }
if (!application) { if (!application) {
InstanceCrashedTabCreate(CRASHED_TAB_PROGRAM_NOT_FOUND, instance); EsApplicationStartupInformation s = {};
s.data = CRASHED_TAB_PROGRAM_NOT_FOUND;
ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, &s, instance);
return; return;
} }
@ -905,7 +921,9 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
EsHandle process = application->singleProcessHandle; EsHandle process = application->singleProcessHandle;
if (!application->useSingleProcess || process == ES_INVALID_HANDLE) { if (application->createInstance) {
process = ES_CURRENT_PROCESS;
} else if (!application->useSingleProcess || process == ES_INVALID_HANDLE) {
EsProcessInformation information; EsProcessInformation information;
EsProcessCreationArguments arguments = {}; EsProcessCreationArguments arguments = {};
@ -914,7 +932,9 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
ES_FILE_READ | ES_NODE_FAIL_IF_NOT_FOUND, &executableNode); ES_FILE_READ | ES_NODE_FAIL_IF_NOT_FOUND, &executableNode);
if (ES_CHECK_ERROR(error)) { if (ES_CHECK_ERROR(error)) {
InstanceCrashedTabCreate(CRASHED_TAB_INVALID_EXECUTABLE, instance); EsApplicationStartupInformation s = {};
s.data = CRASHED_TAB_INVALID_EXECUTABLE;
ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, &s, instance);
return; return;
} }
@ -984,7 +1004,9 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
process = information.handle; process = information.handle;
EsHandleClose(information.mainThread.handle); EsHandleClose(information.mainThread.handle);
} else { } else {
InstanceCrashedTabCreate(CRASHED_TAB_INVALID_EXECUTABLE, instance); EsApplicationStartupInformation s = {};
s.data = CRASHED_TAB_INVALID_EXECUTABLE;
ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, &s, instance);
return; return;
} }
} }
@ -1016,7 +1038,7 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
startupInformation->readHandle = EsSyscall(ES_SYSCALL_NODE_SHARE, startupInformation->readHandle, process, 0, 0); startupInformation->readHandle = EsSyscall(ES_SYSCALL_NODE_SHARE, startupInformation->readHandle, process, 0, 0);
} }
if (!application->useSingleProcess) { if (!application->useSingleProcess && !application->createInstance) {
startupInformation->flags |= ES_APPLICATION_STARTUP_SINGLE_INSTANCE_IN_PROCESS; startupInformation->flags |= ES_APPLICATION_STARTUP_SINGLE_INSTANCE_IN_PROCESS;
} }
@ -1029,6 +1051,10 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, 0xFF000000 | GetConstantNumber("windowFillColor"), 0, ES_WINDOW_PROPERTY_RESIZE_CLEAR_COLOR); EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, 0xFF000000 | GetConstantNumber("windowFillColor"), 0, ES_WINDOW_PROPERTY_RESIZE_CLEAR_COLOR);
instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, handle, 0, 0, 0); instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, handle, 0, 0, 0);
m.createInstance.window = EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, process, 0, ES_WINDOW_PROPERTY_EMBED_OWNER); m.createInstance.window = EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, process, 0, ES_WINDOW_PROPERTY_EMBED_OWNER);
if (application->createInstance) {
application->createInstance(&m);
} else {
EsMessagePostRemote(process, &m); EsMessagePostRemote(process, &m);
if (!application->useSingleProcess) { if (!application->useSingleProcess) {
@ -1037,16 +1063,17 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
application->openInstanceCount++; application->openInstanceCount++;
} }
} }
}
ApplicationInstance *ApplicationInstanceCreate(int64_t id, EsApplicationStartupInformation *startupInformation, ContainerWindow *container) { ApplicationInstance *ApplicationInstanceCreate(int64_t id, EsApplicationStartupInformation *startupInformation, ContainerWindow *container, bool hidden) {
ApplicationInstance *instance = (ApplicationInstance *) EsHeapAllocate(sizeof(ApplicationInstance), true); ApplicationInstance *instance = (ApplicationInstance *) EsHeapAllocate(sizeof(ApplicationInstance), true);
WindowTab *tab = WindowTabCreate(container ?: ContainerWindowCreate(), instance); WindowTab *tab = !hidden ? WindowTabCreate(container ?: ContainerWindowCreate(), instance) : nullptr;
instance->title[0] = ' '; instance->title[0] = ' ';
instance->titleBytes = 1; instance->titleBytes = 1;
desktop.allApplicationInstances.Add(instance);
instance->tab = tab; instance->tab = tab;
desktop.allApplicationInstances.Add(instance);
ApplicationInstanceStart(id, startupInformation, instance); ApplicationInstanceStart(id, startupInformation, instance);
WindowTabActivate(tab); if (!hidden) WindowTabActivate(tab);
return instance; return instance;
} }
@ -1083,27 +1110,9 @@ void ApplicationInstanceCrashed(EsMessage *message) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) { for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i]; ApplicationInstance *instance = desktop.allApplicationInstances[i];
if (instance->processID != message->crash.pid) { if (instance->processID == message->crash.pid) {
continue; ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, nullptr, instance);
} WindowTabActivate(instance->tab, true);
if (instance->notResponding) {
instance->notResponding = false;
instance->embeddedWindowHandle = instance->restoreEmbeddedWindowHandle;
instance->restoreEmbeddedWindowHandle = ES_INVALID_HANDLE;
instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, instance->embeddedWindowHandle, 0, 0, 0);
EsInstanceDestroy(instance->localInstance);
instance->localInstance = nullptr;
}
instance->processID = 0;
EsHandleClose(instance->embeddedWindowHandle);
InstanceCrashedTabCreate(CRASHED_TAB_FATAL_ERROR, instance);
ContainerWindow *container = instance->tab->container;
if (instance->tab == container->active) {
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, container->window->handle, (uintptr_t) instance->embeddedWindowHandle, 0, ES_WINDOW_PROPERTY_EMBED);
} }
} }
@ -1122,7 +1131,7 @@ void ApplicationInstanceCrashed(EsMessage *message) {
EsHandleClose(processHandle); EsHandleClose(processHandle);
} }
void ApplicationProcessTerminated(uint64_t pid) { void ApplicationProcessTerminated(EsObjectID pid) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) { for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i]; ApplicationInstance *instance = desktop.allApplicationInstances[i];
@ -1130,15 +1139,6 @@ void ApplicationProcessTerminated(uint64_t pid) {
continue; continue;
} }
if (instance->notResponding) {
instance->notResponding = false;
instance->embeddedWindowHandle = instance->restoreEmbeddedWindowHandle;
instance->restoreEmbeddedWindowHandle = ES_INVALID_HANDLE;
instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, instance->embeddedWindowHandle, 0, 0, 0);
EsInstanceDestroy(instance->localInstance);
instance->localInstance = nullptr;
}
EmbeddedWindowDestroyed(instance->embeddedWindowID); EmbeddedWindowDestroyed(instance->embeddedWindowID);
} }
@ -1160,7 +1160,7 @@ void ApplicationProcessTerminated(uint64_t pid) {
void OpenDocumentWithApplication(EsApplicationStartupInformation *startupInformation) { void OpenDocumentWithApplication(EsApplicationStartupInformation *startupInformation) {
bool foundDocument = false; bool foundDocument = false;
uint64_t documentID; EsObjectID documentID;
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) { for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
OpenDocument *document = &desktop.openDocuments[i]; OpenDocument *document = &desktop.openDocuments[i];
@ -1319,7 +1319,7 @@ void InstanceAnnouncePathMoved(ApplicationInstance *fromInstance, const uint8_t
const char *oldPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2; const char *oldPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2;
const char *newPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2 + oldPathBytes; const char *newPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2 + oldPathBytes;
uint64_t documentID = 0; EsObjectID documentID = 0;
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) { for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
OpenDocument *document = &desktop.openDocuments[i]; OpenDocument *document = &desktop.openDocuments[i];
@ -1418,6 +1418,33 @@ void ApplicationInstanceCompleteSave(ApplicationInstance *fromInstance) {
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
void ConfigurationLoad() { void ConfigurationLoad() {
// Add applications provided by Desktop.
{
InstalledApplication *application = (InstalledApplication *) EsHeapAllocate(sizeof(InstalledApplication), true);
application->id = APPLICATION_ID_DESKTOP_BLANK_TAB;
application->hidden = true;
application->createInstance = InstanceBlankTabCreate;
desktop.installedApplications.Add(application);
}
{
InstalledApplication *application = (InstalledApplication *) EsHeapAllocate(sizeof(InstalledApplication), true);
application->cName = (char *) interfaceString_DesktopSettingsApplication;
application->id = APPLICATION_ID_DESKTOP_SETTINGS;
application->iconID = ES_ICON_PREFERENCES_DESKTOP;
application->createInstance = InstanceSettingsCreate;
desktop.installedApplications.Add(application);
}
{
InstalledApplication *application = (InstalledApplication *) EsHeapAllocate(sizeof(InstalledApplication), true);
application->id = APPLICATION_ID_DESKTOP_CRASHED;
application->hidden = true;
application->createInstance = InstanceCrashedTabCreate;
desktop.installedApplications.Add(application);
}
for (uintptr_t i = 0; i < api.systemConfigurationGroups.Length(); i++) { for (uintptr_t i = 0; i < api.systemConfigurationGroups.Length(); i++) {
// Load information about installed applications. // Load information about installed applications.
@ -1569,41 +1596,33 @@ void WallpaperLoad(EsGeneric) {
void CheckForegroundWindowResponding(EsGeneric) { void CheckForegroundWindowResponding(EsGeneric) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) { for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i]; ApplicationInstance *instance = desktop.allApplicationInstances[i];
WindowTab *tab = instance->tab;
if ((~instance->tab->container->taskBarButton->customStyleState & THEME_STATE_SELECTED) if (!tab || (~tab->container->taskBarButton->customStyleState & THEME_STATE_SELECTED) || tab->container->active != instance->tab) {
|| instance->tab->container->active != instance->tab
|| !instance->processID || !instance->processHandle) {
continue; continue;
} }
EsProcessState state; EsProcessState state;
EsProcessGetState(instance->processHandle, &state); EsProcessGetState(instance->processHandle, &state);
WindowTab *tab = instance->tab;
if (state.flags & ES_PROCESS_STATE_PINGED) { if (state.flags & ES_PROCESS_STATE_PINGED) {
if (instance->notResponding) { if (tab->notRespondingInstance) {
// Tab is already in a non-responding state. // The tab is already not responding.
} else { } else {
instance->notResponding = true; // The tab has just stopped not responding.
instance->restoreEmbeddedWindowHandle = instance->embeddedWindowHandle; EsApplicationStartupInformation startupInformation = { .data = CRASHED_TAB_NOT_RESPONDING };
instance->restoreEmbeddedWindowID = instance->embeddedWindowID; tab->notRespondingInstance = ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_CRASHED,
InstanceCrashedTabCreate(CRASHED_TAB_NOT_RESPONDING, instance); &startupInformation, tab->container, true /* hidden */);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, tab->container->window->handle, instance->embeddedWindowHandle, 0, ES_WINDOW_PROPERTY_EMBED); WindowTabActivate(tab, true);
} }
} else { } else {
if (instance->notResponding) { if (tab->notRespondingInstance) {
instance->notResponding = false; // The tab has started responding.
instance->embeddedWindowHandle = instance->restoreEmbeddedWindowHandle; ApplicationInstanceClose(tab->notRespondingInstance);
instance->restoreEmbeddedWindowHandle = ES_INVALID_HANDLE; tab->notRespondingInstance = nullptr;
instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, instance->embeddedWindowHandle, 0, 0, 0); WindowTabActivate(tab, true);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, tab->container->window->handle, instance->embeddedWindowHandle, 0, ES_WINDOW_PROPERTY_EMBED);
tab->Repaint(true);
tab->container->taskBarButton->Repaint(true);
EsAssert(instance->localInstance);
EsInstanceDestroy(instance->localInstance);
instance->localInstance = nullptr;
} else { } else {
// Check if the tab is responding.
EsMessage m; EsMessage m;
EsMemoryZero(&m, sizeof(EsMessage)); EsMemoryZero(&m, sizeof(EsMessage));
m.type = ES_MSG_PING; m.type = ES_MSG_PING;
@ -1825,22 +1844,19 @@ void DesktopMessage2(EsMessage *message, uint8_t *buffer) {
} }
} }
void EmbeddedWindowDestroyed(uint64_t id) { void EmbeddedWindowDestroyed(EsObjectID id) {
// TODO Close open documents. // TODO Close open documents.
EsMenuCloseAll(); EsMenuCloseAll();
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(id, true /* remove if found */); ApplicationInstance *instance = ApplicationInstanceFindByWindowID(id, true /* remove if found */);
if (!instance) return; if (!instance) return;
ContainerWindow *container = instance->tab->container; EsHandleClose(instance->embeddedWindowHandle);
if (instance->processID && !instance->notResponding) EsHandleClose(instance->embeddedWindowHandle);
if (instance->processHandle) EsHandleClose(instance->processHandle); if (instance->processHandle) EsHandleClose(instance->processHandle);
if (instance->restoreEmbeddedWindowHandle) EsHandleClose(instance->restoreEmbeddedWindowHandle);
instance->embeddedWindowID = 0;
InstalledApplication *application = instance->application; InstalledApplication *application = instance->application;
if (application && application->singleProcessHandle && instance->processID) { if (application && application->singleProcessHandle) {
EsAssert(application->openInstanceCount); EsAssert(application->openInstanceCount);
application->openInstanceCount--; application->openInstanceCount--;
@ -1854,6 +1870,9 @@ void EmbeddedWindowDestroyed(uint64_t id) {
} }
} }
if (instance->tab) {
ContainerWindow *container = instance->tab->container;
if (container->tabBand->items.Length() == 1) { if (container->tabBand->items.Length() == 1) {
EsElementDestroy(container->window); EsElementDestroy(container->window);
EsElementDestroy(container->taskBarButton); EsElementDestroy(container->taskBarButton);
@ -1871,6 +1890,7 @@ void EmbeddedWindowDestroyed(uint64_t id) {
EsElementDestroy(instance->tab); EsElementDestroy(instance->tab);
} }
}
EsHeapFree(instance); EsHeapFree(instance);
} }

View File

@ -6664,8 +6664,6 @@ struct InspectorElementEntry {
struct InspectorWindow : EsInstance { struct InspectorWindow : EsInstance {
EsInstance *instance; EsInstance *instance;
EsWindow *window;
EsListView *elementList; EsListView *elementList;
Array<InspectorElementEntry> elements; Array<InspectorElementEntry> elements;
InspectorElementEntry hoveredElement; InspectorElementEntry hoveredElement;

View File

@ -1390,6 +1390,7 @@ struct EsApplicationStartupInformation {
STRING filePath; STRING filePath;
EsWindow *targetWindow; EsWindow *targetWindow;
uint32_t flags; uint32_t flags;
int32_t data;
EsHandle readHandle; // Internal use. EsHandle readHandle; // Internal use.
}; };

View File

@ -78,6 +78,8 @@ DEFINE_INTERFACE_STRING(DesktopNoSuchApplication, "The requested application cou
DEFINE_INTERFACE_STRING(DesktopApplicationStartupError, "The requested application could not be started. Your system may be low on resources, or the application files may have been corrupted."); DEFINE_INTERFACE_STRING(DesktopApplicationStartupError, "The requested application could not be started. Your system may be low on resources, or the application files may have been corrupted.");
DEFINE_INTERFACE_STRING(DesktopNotResponding, "The application is not responding.\nIf you choose to force quit, any unsaved data may be lost."); DEFINE_INTERFACE_STRING(DesktopNotResponding, "The application is not responding.\nIf you choose to force quit, any unsaved data may be lost.");
DEFINE_INTERFACE_STRING(DesktopConfirmShutdown, "Are you sure you want to turn off your computer? All applications will be closed."); DEFINE_INTERFACE_STRING(DesktopConfirmShutdown, "Are you sure you want to turn off your computer? All applications will be closed.");
DEFINE_INTERFACE_STRING(DesktopSettingsApplication, "Settings");
DEFINE_INTERFACE_STRING(DesktopSettingsTitle, "Settings");
// File operations. // File operations.