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;
}
void EsInstanceDestroy(EsInstance *_instance) {
UndoManagerDestroy(_instance->undoManager);
EsAssert(_instance->window->instance == _instance);
_instance->window->destroyInstanceAfterClose = true;
EsElementDestroy(_instance->window);
void EsInstanceDestroy(EsInstance *instance) {
EsInstance *inspector = ((APIInstance *) instance->_private)->attachedInspector;
if (inspector) EsInstanceDestroy(inspector);
UndoManagerDestroy(instance->undoManager);
EsAssert(instance->window->instance == instance);
instance->window->destroyInstanceAfterClose = true;
EsElementDestroy(instance->window);
}
EsInstance *InstanceFromWindowID(uint64_t id) {

View File

@ -29,7 +29,6 @@
// - Print screen.
// 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 Make sure applications can't delete |Fonts: and |Themes:.
@ -41,12 +40,14 @@
#define APPLICATION_PERMISSION_RUN_TEMPORARY_APPLICATION (1 << 3)
#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_PROGRAM_NOT_FOUND (2)
#define CRASHED_TAB_INVALID_EXECUTABLE (3)
#define CRASHED_TAB_NOT_RESPONDING (4)
#define CRASHED_TAB_FATAL_ERROR (0)
#define CRASHED_TAB_PROGRAM_NOT_FOUND (1)
#define CRASHED_TAB_INVALID_EXECUTABLE (2)
#define CRASHED_TAB_NOT_RESPONDING (3)
#define INSTALLATION_STATE_NONE (0)
#define INSTALLATION_STATE_INSTALLER (1)
@ -66,6 +67,7 @@ struct ReorderList : EsElement {
struct WindowTab : ReorderItem {
struct ContainerWindow *container;
struct ApplicationInstance *applicationInstance;
struct ApplicationInstance *notRespondingInstance;
EsButton *closeButton;
};
@ -100,13 +102,14 @@ struct OpenDocument {
char *temporarySavePath;
size_t temporarySavePathBytes;
EsHandle readHandle;
uint64_t id;
uint64_t currentWriter;
EsObjectID id;
EsObjectID currentWriter;
};
struct InstalledApplication {
char *cName;
char *cExecutable;
void (*createInstance)(EsMessage *); // For applications provided by Desktop.
int64_t id;
uint32_t iconID;
bool hidden, useSingleProcess, temporary;
@ -121,24 +124,24 @@ struct CrashedTabInstance : EsInstance {
struct BlankTabInstance : EsInstance {
};
struct ApplicationInstance {
WindowTab *tab;
EsInstance *localInstance;
InstalledApplication *application;
uint64_t documentID;
struct SettingsInstance : EsInstance {
};
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];
size_t titleBytes;
uint32_t iconID;
uint64_t processID;
EsHandle processHandle;
uint64_t embeddedWindowID;
EsHandle embeddedWindowHandle;
bool notResponding;
EsHandle restoreEmbeddedWindowHandle;
uint64_t restoreEmbeddedWindowID;
};
const EsStyle styleNewTabContent = {
@ -164,8 +167,8 @@ struct {
Array<ContainerWindow *> allContainerWindows;
Array<EsMessageDevice> connectedDevices;
InstalledApplication *fileManager;
uint64_t currentDocumentID;
HashStore<uint64_t, OpenDocument> openDocuments;
EsObjectID currentDocumentID;
HashStore<EsObjectID, OpenDocument> openDocuments;
TaskBar taskBar;
EsWindow *wallpaperWindow;
bool shutdownWindowOpen;
@ -174,11 +177,11 @@ struct {
} desktop;
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 ApplicationInstanceClose(ApplicationInstance *instance);
ApplicationInstance *ApplicationInstanceFindByWindowID(uint64_t windowID, bool remove = false);
void EmbeddedWindowDestroyed(uint64_t id);
ApplicationInstance *ApplicationInstanceFindByWindowID(EsObjectID windowID, bool remove = false);
void EmbeddedWindowDestroyed(EsObjectID id);
//////////////////////////////////////////////////////
// Reorder lists:
@ -388,14 +391,22 @@ int ReorderListMessage(EsElement *_list, EsMessage *message) {
// Container windows:
//////////////////////////////////////////////////////
void WindowTabActivate(WindowTab *tab) {
if (tab->container->active != tab) {
void WindowTabClose(WindowTab *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;
EsElementRelayout(tab->container->tabBand);
tab->container->taskBarButton->Repaint(true);
// EsPrint("Activating tab %d...\n", tab->tabIndex);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, tab->container->window->handle, (uintptr_t) tab->applicationInstance->embeddedWindowHandle, 0, ES_WINDOW_PROPERTY_EMBED);
EsHandle handle = tab->notRespondingInstance ? tab->notRespondingInstance->embeddedWindowHandle : tab->applicationInstance->embeddedWindowHandle;
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, tab->window->handle, handle, 0, ES_WINDOW_PROPERTY_EMBED);
}
}
@ -429,7 +440,7 @@ int ContainerWindowMessage(EsElement *element, EsMessage *message) {
} else if (ctrlOnly && scancode == ES_SCANCODE_T) {
ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_BLANK_TAB, nullptr, container);
} else if (ctrlOnly && scancode == ES_SCANCODE_W) {
ApplicationInstanceClose(container->active->applicationInstance);
WindowTabClose(container->active);
} else if (ctrlOnly && scancode == ES_SCANCODE_N) {
ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_BLANK_TAB, nullptr, nullptr);
} 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;
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();
WindowTabActivate(tab);
} 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);
EsMenuAddItem(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(DesktopCloseTab), [] (EsMenu *, EsGeneric context) {
ApplicationInstanceClose(((WindowTab *) context.p)->applicationInstance);
WindowTabClose((WindowTab *) context.p);
}, tab);
if (EsKeyboardIsShiftHeld() && !instance->localInstance) {
EsAssert(instance->processHandle);
if (EsKeyboardIsShiftHeld()) {
EsMenuAddSeparator(menu);
EsMenuAddItem(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(DesktopInspectUI), [] (EsMenu *, EsGeneric context) {
@ -528,7 +543,7 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
EsMenuShow(menu);
} 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 {
return 0;
@ -548,7 +563,7 @@ WindowTab *WindowTabCreate(ContainerWindow *container, ApplicationInstance *inst
tab->closeButton->userData = tab;
EsButtonOnCommand(tab->closeButton, [] (EsInstance *, EsElement *element, EsCommand *) {
ApplicationInstanceClose(((WindowTab *) element->userData.p)->applicationInstance);
WindowTabClose((WindowTab *) element->userData.p);
});
return tab;
@ -748,15 +763,21 @@ void ShutdownModalCreate() {
//////////////////////////////////////////////////////
void InstanceForceQuit(EsInstance *, EsElement *element, EsCommand *) {
ApplicationInstance *instance = (ApplicationInstance *) element->userData.p;
EsProcessTerminate(instance->processHandle, 1);
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);
break;
}
}
}
void InstanceCrashedTabCreate(int reason, ApplicationInstance *_instance) {
EsMessage m = {};
m.type = ES_MSG_INSTANCE_CREATE;
m.createInstance.window = EsSyscall(ES_SYSCALL_WINDOW_CREATE, ES_WINDOW_NORMAL, 0, 0, 0);
CrashedTabInstance *instance = (CrashedTabInstance *) _EsInstanceCreate(sizeof(CrashedTabInstance), &m, nullptr);
void InstanceCrashedTabCreate(EsMessage *message) {
CrashedTabInstance *instance = (CrashedTabInstance *) _EsInstanceCreate(sizeof(CrashedTabInstance), message, nullptr);
int32_t reason = ((APIInstance *) instance->_private)->startupInformation->data;
instance->window->toolbarFillMode = true;
if (reason != CRASHED_TAB_NOT_RESPONDING) EsWindowSetIcon(instance->window, ES_ICON_DIALOG_ERROR);
EsElement *toolbar = EsWindowGetToolbar(instance->window);
@ -773,70 +794,68 @@ void InstanceCrashedTabCreate(int reason, ApplicationInstance *_instance) {
} else if (reason == CRASHED_TAB_NOT_RESPONDING) {
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));
button->userData = _instance;
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) {
EsMessage m = {};
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);
void InstanceBlankTabCreate(EsMessage *message) {
EsInstance *instance = _EsInstanceCreate(sizeof(BlankTabInstance), message, nullptr);
EsWindowSetTitle(instance->window, INTERFACE_STRING(DesktopNewTabTitle));
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;
{
// 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->separatorFlags = ES_CELL_H_FILL;
buttonGroup->separatorStylePart = ES_STYLE_BUTTON_GROUP_SEPARATOR;
buttonGroup->separatorFlags = ES_CELL_H_FILL;
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
InstalledApplication *application = desktop.installedApplications[i];
if (application->hidden) continue;
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
InstalledApplication *application = desktop.installedApplications[i];
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;
if (application->hidden) {
continue;
}
EsButton *button = EsButtonCreate(buttonGroup, ES_CELL_H_FILL | ES_BUTTON_NOT_FOCUSABLE, ES_STYLE_BUTTON_GROUP_ITEM, application->cName);
button->userData = application;
EsButtonSetIcon(button, (EsStandardIcon) application->iconID ?: ES_ICON_APPLICATION_DEFAULT_ICON);
EsButtonOnCommand(button, [] (EsInstance *, EsElement *element, EsCommand *) {
uint64_t tabID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0);
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(tabID);
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);
EsInstanceDestroy(element->instance);
instance->localInstance = nullptr;
});
}
EsButtonOnCommand(button, [] (EsInstance *, EsElement *element, EsCommand *) {
EsObjectID tabID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, element->window->handle, 0, 0, 0);
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(tabID);
ApplicationInstanceStart(((InstalledApplication *) element->userData.p)->id, nullptr, instance);
WindowTabActivate(instance->tab, true);
EsInstanceDestroy(element->instance);
});
}
}
_instance->embeddedWindowHandle = m.createInstance.window;
_instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, m.createInstance.window, 0, 0, 0);
_instance->localInstance = instance;
void InstanceSettingsCreate(EsMessage *message) {
// TODO.
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:
//////////////////////////////////////////////////////
ApplicationInstance *ApplicationInstanceFindByWindowID(uint64_t windowID, bool remove) {
ApplicationInstance *ApplicationInstanceFindByWindowID(EsObjectID windowID, bool remove) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i];
if (instance->embeddedWindowID == windowID || (instance->restoreEmbeddedWindowID == windowID && instance->notResponding)) {
if (instance->embeddedWindowID == windowID) {
if (remove) {
desktop.allApplicationInstances.Delete(i);
}
@ -849,16 +868,10 @@ ApplicationInstance *ApplicationInstanceFindByWindowID(uint64_t windowID, bool r
}
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.
EsMessage m = { ES_MSG_TAB_CLOSE_REQUEST };
m.tabOperation.id = instance->embeddedWindowID;
EsMessagePostRemote(instance->processHandle, &m);
}
// TODO Force closing not responding instances.
EsMessage m = { ES_MSG_TAB_CLOSE_REQUEST };
m.tabOperation.id = instance->embeddedWindowID;
EsMessagePostRemote(instance->processHandle, &m);
}
void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInformation *startupInformation, ApplicationInstance *instance) {
@ -868,14 +881,15 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
startupInformation = &_startupInformation;
}
if (instance->restoreEmbeddedWindowHandle) {
EsHandleClose(instance->restoreEmbeddedWindowHandle);
instance->restoreEmbeddedWindowHandle = ES_INVALID_HANDLE;
if (instance->tab && instance->tab->notRespondingInstance) {
ApplicationInstanceClose(instance->tab->notRespondingInstance);
instance->tab->notRespondingInstance = nullptr;
}
if (applicationID == APPLICATION_ID_DESKTOP_BLANK_TAB) {
InstanceBlankTabCreate(instance);
return;
if (instance->processHandle) {
EsHandleClose(instance->processHandle);
instance->processID = 0;
instance->processHandle = ES_INVALID_HANDLE;
}
InstalledApplication *application = nullptr;
@ -887,7 +901,9 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
}
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;
}
@ -905,7 +921,9 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
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;
EsProcessCreationArguments arguments = {};
@ -914,7 +932,9 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
ES_FILE_READ | ES_NODE_FAIL_IF_NOT_FOUND, &executableNode);
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;
}
@ -984,7 +1004,9 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
process = information.handle;
EsHandleClose(information.mainThread.handle);
} else {
InstanceCrashedTabCreate(CRASHED_TAB_INVALID_EXECUTABLE, instance);
EsApplicationStartupInformation s = {};
s.data = CRASHED_TAB_INVALID_EXECUTABLE;
ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, &s, instance);
return;
}
}
@ -1016,7 +1038,7 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
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;
}
@ -1029,24 +1051,29 @@ void ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
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);
m.createInstance.window = EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, process, 0, ES_WINDOW_PROPERTY_EMBED_OWNER);
EsMessagePostRemote(process, &m);
if (!application->useSingleProcess) {
EsHandleClose(process);
if (application->createInstance) {
application->createInstance(&m);
} else {
application->openInstanceCount++;
EsMessagePostRemote(process, &m);
if (!application->useSingleProcess) {
EsHandleClose(process);
} else {
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);
WindowTab *tab = WindowTabCreate(container ?: ContainerWindowCreate(), instance);
WindowTab *tab = !hidden ? WindowTabCreate(container ?: ContainerWindowCreate(), instance) : nullptr;
instance->title[0] = ' ';
instance->titleBytes = 1;
desktop.allApplicationInstances.Add(instance);
instance->tab = tab;
desktop.allApplicationInstances.Add(instance);
ApplicationInstanceStart(id, startupInformation, instance);
WindowTabActivate(tab);
if (!hidden) WindowTabActivate(tab);
return instance;
}
@ -1083,27 +1110,9 @@ void ApplicationInstanceCrashed(EsMessage *message) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i];
if (instance->processID != message->crash.pid) {
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;
}
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);
if (instance->processID == message->crash.pid) {
ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, nullptr, instance);
WindowTabActivate(instance->tab, true);
}
}
@ -1122,7 +1131,7 @@ void ApplicationInstanceCrashed(EsMessage *message) {
EsHandleClose(processHandle);
}
void ApplicationProcessTerminated(uint64_t pid) {
void ApplicationProcessTerminated(EsObjectID pid) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i];
@ -1130,15 +1139,6 @@ void ApplicationProcessTerminated(uint64_t pid) {
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);
}
@ -1160,7 +1160,7 @@ void ApplicationProcessTerminated(uint64_t pid) {
void OpenDocumentWithApplication(EsApplicationStartupInformation *startupInformation) {
bool foundDocument = false;
uint64_t documentID;
EsObjectID documentID;
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); 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 *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++) {
OpenDocument *document = &desktop.openDocuments[i];
@ -1418,6 +1418,33 @@ void ApplicationInstanceCompleteSave(ApplicationInstance *fromInstance) {
//////////////////////////////////////////////////////
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++) {
// Load information about installed applications.
@ -1569,41 +1596,33 @@ void WallpaperLoad(EsGeneric) {
void CheckForegroundWindowResponding(EsGeneric) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i];
WindowTab *tab = instance->tab;
if ((~instance->tab->container->taskBarButton->customStyleState & THEME_STATE_SELECTED)
|| instance->tab->container->active != instance->tab
|| !instance->processID || !instance->processHandle) {
if (!tab || (~tab->container->taskBarButton->customStyleState & THEME_STATE_SELECTED) || tab->container->active != instance->tab) {
continue;
}
EsProcessState state;
EsProcessGetState(instance->processHandle, &state);
WindowTab *tab = instance->tab;
if (state.flags & ES_PROCESS_STATE_PINGED) {
if (instance->notResponding) {
// Tab is already in a non-responding state.
if (tab->notRespondingInstance) {
// The tab is already not responding.
} else {
instance->notResponding = true;
instance->restoreEmbeddedWindowHandle = instance->embeddedWindowHandle;
instance->restoreEmbeddedWindowID = instance->embeddedWindowID;
InstanceCrashedTabCreate(CRASHED_TAB_NOT_RESPONDING, instance);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, tab->container->window->handle, instance->embeddedWindowHandle, 0, ES_WINDOW_PROPERTY_EMBED);
// The tab has just stopped not responding.
EsApplicationStartupInformation startupInformation = { .data = CRASHED_TAB_NOT_RESPONDING };
tab->notRespondingInstance = ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_CRASHED,
&startupInformation, tab->container, true /* hidden */);
WindowTabActivate(tab, true);
}
} else {
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);
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;
if (tab->notRespondingInstance) {
// The tab has started responding.
ApplicationInstanceClose(tab->notRespondingInstance);
tab->notRespondingInstance = nullptr;
WindowTabActivate(tab, true);
} else {
// Check if the tab is responding.
EsMessage m;
EsMemoryZero(&m, sizeof(EsMessage));
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.
EsMenuCloseAll();
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(id, true /* remove if found */);
if (!instance) return;
ContainerWindow *container = instance->tab->container;
if (instance->processID && !instance->notResponding) EsHandleClose(instance->embeddedWindowHandle);
EsHandleClose(instance->embeddedWindowHandle);
if (instance->processHandle) EsHandleClose(instance->processHandle);
if (instance->restoreEmbeddedWindowHandle) EsHandleClose(instance->restoreEmbeddedWindowHandle);
instance->embeddedWindowID = 0;
InstalledApplication *application = instance->application;
if (application && application->singleProcessHandle && instance->processID) {
if (application && application->singleProcessHandle) {
EsAssert(application->openInstanceCount);
application->openInstanceCount--;
@ -1854,22 +1870,26 @@ void EmbeddedWindowDestroyed(uint64_t id) {
}
}
if (container->tabBand->items.Length() == 1) {
EsElementDestroy(container->window);
EsElementDestroy(container->taskBarButton);
desktop.allContainerWindows.FindAndDeleteSwap(container, true);
} else {
if (container->active == instance->tab) {
container->active = nullptr;
if (instance->tab) {
ContainerWindow *container = instance->tab->container;
for (uintptr_t i = 0; i < container->tabBand->items.Length(); i++) {
if (container->tabBand->items[i] != instance->tab) continue;
WindowTabActivate((WindowTab *) container->tabBand->items[i ? (i - 1) : 1]);
break;
if (container->tabBand->items.Length() == 1) {
EsElementDestroy(container->window);
EsElementDestroy(container->taskBarButton);
desktop.allContainerWindows.FindAndDeleteSwap(container, true);
} else {
if (container->active == instance->tab) {
container->active = nullptr;
for (uintptr_t i = 0; i < container->tabBand->items.Length(); i++) {
if (container->tabBand->items[i] != instance->tab) continue;
WindowTabActivate((WindowTab *) container->tabBand->items[i ? (i - 1) : 1]);
break;
}
}
}
EsElementDestroy(instance->tab);
EsElementDestroy(instance->tab);
}
}
EsHeapFree(instance);

View File

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

View File

@ -1390,6 +1390,7 @@ struct EsApplicationStartupInformation {
STRING filePath;
EsWindow *targetWindow;
uint32_t flags;
int32_t data;
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(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(DesktopSettingsApplication, "Settings");
DEFINE_INTERFACE_STRING(DesktopSettingsTitle, "Settings");
// File operations.