mirror of https://gitlab.com/nakst/essence
close applications before shutdown; introduce ApplicationProcess
This commit is contained in:
parent
c166eee594
commit
4206aae3f6
|
@ -3,6 +3,7 @@ name=System Monitor
|
|||
icon=icon_utilities_system_monitor
|
||||
permission_manage_processes=1
|
||||
permission_shutdown=1
|
||||
use_single_instance=1
|
||||
|
||||
[build]
|
||||
source=apps/system_monitor.cpp
|
||||
|
|
|
@ -139,8 +139,6 @@ struct {
|
|||
uintptr_t performanceTimerStackCount;
|
||||
|
||||
ThreadLocalStorage firstThreadLocalStorage;
|
||||
|
||||
size_t openInstanceCount; // Also counts user tasks.
|
||||
} api;
|
||||
|
||||
ptrdiff_t tlsStorageOffset;
|
||||
|
@ -159,6 +157,7 @@ EsFileStore *FileStoreCreateFromPath(const char *path, size_t pathBytes);
|
|||
EsFileStore *FileStoreCreateFromHandle(EsHandle handle);
|
||||
void FileStoreCloseHandle(EsFileStore *fileStore);
|
||||
EsError NodeOpen(const char *path, size_t pathBytes, uint32_t flags, _EsNodeInformation *node);
|
||||
void ApplicationProcessTerminated(EsObjectID pid);
|
||||
|
||||
#include "syscall.cpp"
|
||||
|
||||
|
@ -742,7 +741,6 @@ EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, const char *appl
|
|||
APIInstance *apiInstance = InstanceSetup(instance);
|
||||
apiInstance->applicationName = applicationName;
|
||||
apiInstance->applicationNameBytes = applicationNameBytes;
|
||||
api.openInstanceCount++;
|
||||
|
||||
if (message && message->createInstance.data != ES_INVALID_HANDLE && message->createInstance.dataBytes > 1) {
|
||||
apiInstance->startupInformation = (EsApplicationStartupInformation *) EsHeapAllocate(message->createInstance.dataBytes, false);
|
||||
|
@ -854,33 +852,30 @@ EsMessage *EsMessageReceive() {
|
|||
EsAssert(message.message.instanceSave.file->operationComplete);
|
||||
FileStoreCloseHandle(message.message.instanceSave.file);
|
||||
} else if (message.message.type == ES_MSG_APPLICATION_EXIT) {
|
||||
if (api.startupInformation->isDesktop) {
|
||||
// Desktop tracks the number of instances it owns, so it needs to know when it exits.
|
||||
ApplicationProcessTerminated(EsProcessGetID(ES_CURRENT_PROCESS));
|
||||
} else {
|
||||
#ifdef DEBUG_BUILD
|
||||
FontDatabaseFree();
|
||||
FreeUnusedStyles(true /* include permanent styles */);
|
||||
theming.loadedStyles.Free();
|
||||
SystemConfigurationUnload();
|
||||
api.mountPoints.Free();
|
||||
api.postBox.Free();
|
||||
api.timers.Free();
|
||||
gui.animatingElements.Free();
|
||||
gui.accessKeys.entries.Free();
|
||||
gui.allWindows.Free();
|
||||
calculator.Free();
|
||||
HashTableFree(&gui.keyboardShortcutNames, false);
|
||||
MemoryLeakDetectorCheckpoint(&heap);
|
||||
EsPrint("ES_MSG_APPLICATION_EXIT - Heap allocation count: %d (%d from malloc).\n", heap.allocationsCount, mallocCount);
|
||||
FontDatabaseFree();
|
||||
FreeUnusedStyles(true /* include permanent styles */);
|
||||
theming.loadedStyles.Free();
|
||||
SystemConfigurationUnload();
|
||||
api.mountPoints.Free();
|
||||
api.postBox.Free();
|
||||
api.timers.Free();
|
||||
gui.animatingElements.Free();
|
||||
gui.accessKeys.entries.Free();
|
||||
gui.allWindows.Free();
|
||||
calculator.Free();
|
||||
HashTableFree(&gui.keyboardShortcutNames, false);
|
||||
MemoryLeakDetectorCheckpoint(&heap);
|
||||
EsPrint("ES_MSG_APPLICATION_EXIT - Heap allocation count: %d (%d from malloc).\n", heap.allocationsCount, mallocCount);
|
||||
#endif
|
||||
EsProcessTerminateCurrent();
|
||||
} else if (message.message.type == ES_MSG_INSTANCE_DESTROY) {
|
||||
api.openInstanceCount--;
|
||||
|
||||
APIInstance *instance = (APIInstance *) message.message.instanceDestroy.instance->_private;
|
||||
|
||||
if (instance->startupInformation && (instance->startupInformation->flags & ES_APPLICATION_STARTUP_SINGLE_INSTANCE_IN_PROCESS)
|
||||
&& !api.openInstanceCount) {
|
||||
EsMessage m = { ES_MSG_APPLICATION_EXIT };
|
||||
EsMessagePost(nullptr, &m);
|
||||
EsProcessTerminateCurrent();
|
||||
}
|
||||
} else if (message.message.type == ES_MSG_INSTANCE_DESTROY) {
|
||||
APIInstance *instance = (APIInstance *) message.message.instanceDestroy.instance->_private;
|
||||
|
||||
if (instance->startupInformation) {
|
||||
EsHeapFree((void *) instance->startupInformation->filePath);
|
||||
|
@ -1723,8 +1718,6 @@ void UserTaskThread(EsGeneric _task) {
|
|||
EsUserTask *task = (EsUserTask *) _task.p;
|
||||
task->callback(task, task->data);
|
||||
EsMessageMutexAcquire();
|
||||
api.openInstanceCount--;
|
||||
// TODO Send ES_MSG_APPLICATION_EXIT if needed.
|
||||
EsMessageMutexRelease();
|
||||
EsSyscall(ES_SYSCALL_WINDOW_CLOSE, task->taskHandle, 0, 0, 0);
|
||||
EsHandleClose(task->taskHandle);
|
||||
|
@ -1791,7 +1784,6 @@ EsError EsUserTaskStart(EsUserTaskCallback callback, EsGeneric data, const char
|
|||
|
||||
if (error == ES_SUCCESS) {
|
||||
EsHandleClose(information.handle);
|
||||
api.openInstanceCount++;
|
||||
} else {
|
||||
EsSyscall(ES_SYSCALL_WINDOW_CLOSE, task->taskHandle, 0, 0, 0);
|
||||
EsHandleClose(task->taskHandle);
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
// TODO Tabs:
|
||||
// - Dragging out of the window.
|
||||
// - Dragging onto other windows.
|
||||
// - Keyboard shortcuts.
|
||||
// - New tab page - search; recent files.
|
||||
// - Right click menu.
|
||||
// - Duplicate tabs.
|
||||
|
@ -119,9 +116,7 @@ struct InstalledApplication {
|
|||
bool useSingleInstance;
|
||||
struct ApplicationInstance *singleInstance;
|
||||
uint64_t permissions;
|
||||
size_t openInstanceCount; // Only used if useSingleProcess is true.
|
||||
EsHandle singleProcessHandle;
|
||||
bool notified; // Temporary flag.
|
||||
struct ApplicationProcess *singleProcess;
|
||||
EsFileOffset totalSize; // 0 if uncalculated.
|
||||
};
|
||||
|
||||
|
@ -135,6 +130,13 @@ struct CrashedTabInstance : CommonDesktopInstance {
|
|||
struct BlankTabInstance : CommonDesktopInstance {
|
||||
};
|
||||
|
||||
struct ApplicationProcess {
|
||||
EsObjectID id;
|
||||
EsHandle handle;
|
||||
InstalledApplication *application;
|
||||
size_t instanceCount;
|
||||
};
|
||||
|
||||
struct ApplicationInstance {
|
||||
// User interface.
|
||||
WindowTab *tab; // nullptr for notRespondingInstance and user tasks.
|
||||
|
@ -143,8 +145,8 @@ struct ApplicationInstance {
|
|||
|
||||
// Currently loaded application.
|
||||
InstalledApplication *application;
|
||||
EsObjectID documentID, processID;
|
||||
EsHandle processHandle;
|
||||
EsObjectID documentID;
|
||||
ApplicationProcess *process;
|
||||
bool isUserTask;
|
||||
|
||||
// Metadata.
|
||||
|
@ -154,6 +156,15 @@ struct ApplicationInstance {
|
|||
double progress;
|
||||
};
|
||||
|
||||
const EsStyle styleSmallParagraph = {
|
||||
.inherit = ES_STYLE_TEXT_PARAGRAPH,
|
||||
|
||||
.metrics = {
|
||||
.mask = ES_THEME_METRICS_TEXT_SIZE,
|
||||
.textSize = 8,
|
||||
},
|
||||
};
|
||||
|
||||
const EsStyle styleNewTabContent = {
|
||||
.metrics = {
|
||||
.mask = ES_THEME_METRICS_INSETS | ES_THEME_METRICS_GAP_MAJOR,
|
||||
|
@ -174,6 +185,7 @@ const EsStyle styleButtonGroupContainer = {
|
|||
struct {
|
||||
Array<InstalledApplication *> installedApplications;
|
||||
Array<ApplicationInstance *> allApplicationInstances;
|
||||
Array<ApplicationProcess *> allApplicationProcesses;
|
||||
Array<ContainerWindow *> allContainerWindows;
|
||||
|
||||
InstalledApplication *fileManager;
|
||||
|
@ -199,6 +211,12 @@ struct {
|
|||
|
||||
Array<ApplicationInstance *> allOngoingUserTasks;
|
||||
double totalUserTaskProgress;
|
||||
|
||||
#define SHUTDOWN_TIMEOUT (3000) // Maximum time to wait for applications to exit.
|
||||
EsHandle shutdownReady; // Set when all applications have exited.
|
||||
bool inShutdown;
|
||||
|
||||
bool inspectorOpen;
|
||||
} desktop;
|
||||
|
||||
int TaskBarButtonMessage(EsElement *element, EsMessage *message);
|
||||
|
@ -420,6 +438,61 @@ int ReorderListMessage(EsElement *_list, EsMessage *message) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Desktop Inspector:
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void DesktopInspectorThread(EsGeneric) {
|
||||
EsMessageMutexAcquire();
|
||||
EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_PLAIN);
|
||||
EsRectangle screen;
|
||||
EsSyscall(ES_SYSCALL_SCREEN_WORK_AREA_GET, 0, (uintptr_t) &screen, 0, 0);
|
||||
screen.l = screen.r - 400;
|
||||
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_FLAGS_DEFAULT, 0, ES_WINDOW_PROPERTY_SOLID);
|
||||
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, 180, 0, ES_WINDOW_PROPERTY_ALPHA);
|
||||
EsPanel *panel = EsPanelCreate(window, ES_CELL_FILL, ES_STYLE_PANEL_FILLED);
|
||||
EsMessageMutexRelease();
|
||||
|
||||
while (true) {
|
||||
EsMessageMutexAcquire();
|
||||
EsElementDestroyContents(panel);
|
||||
char buffer[256];
|
||||
size_t bytes;
|
||||
|
||||
EsTextDisplayCreate(panel, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING1, "Desktop Inspector");
|
||||
EsSpacerCreate(panel, ES_CELL_H_FILL, 0, 0, 5);
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
bytes = EsStringFormat(buffer, sizeof(buffer), "inst: eid %d, title '%s', pid %d, docid %d, app '%z'%z",
|
||||
instance->embeddedWindowID, instance->titleBytes, instance->title, instance->process->id,
|
||||
instance->documentID, instance->application->cName, instance->isUserTask ? ", utask" : "");
|
||||
EsTextDisplayCreate(panel, ES_CELL_H_FILL, &styleSmallParagraph, buffer, bytes);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
ApplicationProcess *process = desktop.allApplicationProcesses[i];
|
||||
bytes = EsStringFormat(buffer, sizeof(buffer), "proc: pid %d, app '%z', instances %d",
|
||||
process->id, process->application ? process->application->cName : "??", process->instanceCount);
|
||||
EsTextDisplayCreate(panel, ES_CELL_H_FILL, &styleSmallParagraph, buffer, bytes);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
InstalledApplication *application = desktop.installedApplications[i];
|
||||
bytes = EsStringFormat(buffer, sizeof(buffer), "app: '%z'%z%z%z, spid %d, seid %d",
|
||||
application->cName, application->temporary ? ", temp" : "", application->useSingleProcess ? ", 1proc" : "",
|
||||
application->useSingleInstance ? ", 1inst" : "",
|
||||
application->singleProcess ? application->singleProcess->id : 0,
|
||||
application->singleInstance ? application->singleInstance->embeddedWindowID : 0);
|
||||
EsTextDisplayCreate(panel, ES_CELL_H_FILL, &styleSmallParagraph, buffer, bytes);
|
||||
}
|
||||
|
||||
EsMessageMutexRelease();
|
||||
EsSleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Container windows:
|
||||
//////////////////////////////////////////////////////
|
||||
|
@ -427,7 +500,7 @@ int ReorderListMessage(EsElement *_list, EsMessage *message) {
|
|||
void WindowTabClose(WindowTab *tab) {
|
||||
if (tab->notRespondingInstance) {
|
||||
// The application is not responding, so force quit the process.
|
||||
EsProcessTerminate(tab->applicationInstance->processHandle, 1);
|
||||
EsProcessTerminate(tab->applicationInstance->process->handle, 1);
|
||||
} else {
|
||||
ApplicationInstanceClose(tab->applicationInstance);
|
||||
}
|
||||
|
@ -497,6 +570,11 @@ int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) {
|
|||
|
||||
if (ctrlOnly && scancode == ES_SCANCODE_N) {
|
||||
ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_BLANK_TAB, nullptr, nullptr);
|
||||
} else if (message->keyboard.modifiers == (ES_MODIFIER_CTRL | ES_MODIFIER_FLAG) && scancode == ES_SCANCODE_D) {
|
||||
if (!desktop.inspectorOpen) {
|
||||
desktop.inspectorOpen = true;
|
||||
EsThreadCreate(DesktopInspectorThread, nullptr, 0);
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -713,7 +791,7 @@ int WindowTabMessage(EsElement *element, EsMessage *message) {
|
|||
ApplicationInstance *instance = tab->applicationInstance;
|
||||
EsMessage m = { ES_MSG_TAB_INSPECT_UI };
|
||||
m.tabOperation.id = instance->embeddedWindowID;
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
}, tab);
|
||||
}
|
||||
|
||||
|
@ -1008,6 +1086,33 @@ int TaskBarTasksButtonMessage(EsElement *element, EsMessage *message) {
|
|||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
void Shutdown(uintptr_t action) {
|
||||
// TODO This doesn't wait for Desktop instances.
|
||||
|
||||
if (desktop.inShutdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!desktop.allApplicationProcesses.Length()) {
|
||||
// No applications are open, so we can shut down immediately.
|
||||
EsSyscall(ES_SYSCALL_SHUTDOWN, action, 0, 0, 0);
|
||||
}
|
||||
|
||||
desktop.inShutdown = true;
|
||||
desktop.shutdownReady = EsEventCreate(true);
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
// Tell all applications to close.
|
||||
ApplicationInstanceClose(desktop.allApplicationInstances[i]);
|
||||
}
|
||||
|
||||
EsThreadCreate([] (EsGeneric action) {
|
||||
// Shut down either when all applications exit, or after the timeout.
|
||||
EsWait(&desktop.shutdownReady, 1, SHUTDOWN_TIMEOUT);
|
||||
EsSyscall(ES_SYSCALL_SHUTDOWN, action.u, 0, 0, 0);
|
||||
}, nullptr, action);
|
||||
}
|
||||
|
||||
void ShutdownModalCreate() {
|
||||
if (desktop.shutdownWindowOpen) {
|
||||
return;
|
||||
|
@ -1048,11 +1153,11 @@ void ShutdownModalCreate() {
|
|||
// Setup command callbacks when the buttons are pressed.
|
||||
|
||||
EsButtonOnCommand(shutdownButton, [] (EsInstance *, EsElement *, EsCommand *) {
|
||||
EsSyscall(ES_SYSCALL_SHUTDOWN, SHUTDOWN_ACTION_POWER_OFF, 0, 0, 0);
|
||||
Shutdown(SHUTDOWN_ACTION_POWER_OFF);
|
||||
});
|
||||
|
||||
EsButtonOnCommand(restartButton, [] (EsInstance *, EsElement *, EsCommand *) {
|
||||
EsSyscall(ES_SYSCALL_SHUTDOWN, SHUTDOWN_ACTION_RESTART, 0, 0, 0);
|
||||
Shutdown(SHUTDOWN_ACTION_RESTART);
|
||||
});
|
||||
|
||||
EsButtonOnCommand(cancelButton, [] (EsInstance *, EsElement *element, EsCommand *) {
|
||||
|
@ -1070,7 +1175,7 @@ void InstanceForceQuit(EsInstance *, EsElement *element, EsCommand *) {
|
|||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->tab && instance->tab->notRespondingInstance && instance->tab->notRespondingInstance->embeddedWindowID == element->window->id) {
|
||||
EsProcessTerminate(instance->processHandle, 1);
|
||||
EsProcessTerminate(instance->process->handle, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1155,15 +1260,46 @@ void ApplicationInstanceClose(ApplicationInstance *instance) {
|
|||
// TODO Force closing not responding instances.
|
||||
EsMessage m = { ES_MSG_TAB_CLOSE_REQUEST };
|
||||
m.tabOperation.id = instance->embeddedWindowID;
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
}
|
||||
|
||||
void ApplicationInstanceCleanup(ApplicationInstance *instance) {
|
||||
if (instance->documentID) {
|
||||
OpenDocumentCloseReference(instance->documentID);
|
||||
instance->documentID = 0;
|
||||
}
|
||||
|
||||
InstalledApplication *application = instance->application;
|
||||
|
||||
if (application && application->singleInstance == instance) {
|
||||
application->singleInstance = nullptr;
|
||||
}
|
||||
|
||||
if (instance->process) {
|
||||
EsAssert(instance->process->instanceCount);
|
||||
instance->process->instanceCount--;
|
||||
|
||||
if (!instance->process->instanceCount) {
|
||||
EsMessage m = { ES_MSG_APPLICATION_EXIT };
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
}
|
||||
}
|
||||
|
||||
instance->process = nullptr;
|
||||
instance->application = nullptr;
|
||||
}
|
||||
|
||||
bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInformation *startupInformation, ApplicationInstance *instance) {
|
||||
if (desktop.inShutdown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InstalledApplication *application = nullptr;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
if (desktop.installedApplications[i]->id == applicationID) {
|
||||
application = desktop.installedApplications[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1190,34 +1326,29 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
|
|||
instance->tab->notRespondingInstance = nullptr;
|
||||
}
|
||||
|
||||
if (instance->processHandle) {
|
||||
EsHandleClose(instance->processHandle);
|
||||
instance->processID = 0;
|
||||
instance->processHandle = ES_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (instance->documentID) {
|
||||
OpenDocumentCloseReference(instance->documentID);
|
||||
instance->documentID = 0;
|
||||
}
|
||||
ApplicationInstanceCleanup(instance);
|
||||
|
||||
instance->application = application;
|
||||
|
||||
if (application->useSingleProcess && application->singleProcessHandle) {
|
||||
EsProcessState state;
|
||||
EsProcessGetState(application->singleProcessHandle, &state);
|
||||
|
||||
if (state.flags & (ES_PROCESS_STATE_ALL_THREADS_TERMINATED | ES_PROCESS_STATE_TERMINATING | ES_PROCESS_STATE_CRASHED)) {
|
||||
EsHandleClose(application->singleProcessHandle);
|
||||
application->singleProcessHandle = ES_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
EsHandle process = application->singleProcessHandle;
|
||||
ApplicationProcess *process = application->singleProcess;
|
||||
|
||||
if (application->createInstance) {
|
||||
process = ES_CURRENT_PROCESS;
|
||||
} else if (!application->useSingleProcess || process == ES_INVALID_HANDLE) {
|
||||
EsObjectID desktopProcessID = EsProcessGetID(ES_CURRENT_PROCESS);
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
if (desktop.allApplicationProcesses[i]->id == desktopProcessID) {
|
||||
process = desktop.allApplicationProcesses[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!process) {
|
||||
process = (ApplicationProcess *) EsHeapAllocate(sizeof(ApplicationProcess), true);
|
||||
process->handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, ES_CURRENT_PROCESS, ES_CURRENT_PROCESS, 0, 0);
|
||||
process->id = desktopProcessID;
|
||||
desktop.allApplicationProcesses.Add(process);
|
||||
}
|
||||
} else if (!process) {
|
||||
EsProcessInformation information;
|
||||
EsProcessCreationArguments arguments = {};
|
||||
|
||||
|
@ -1336,8 +1467,13 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
|
|||
}
|
||||
|
||||
if (!ES_CHECK_ERROR(error)) {
|
||||
process = information.handle;
|
||||
EsHandleClose(information.mainThread.handle);
|
||||
|
||||
process = (ApplicationProcess *) EsHeapAllocate(sizeof(ApplicationProcess), true);
|
||||
process->handle = information.handle;
|
||||
process->id = information.pid;
|
||||
process->application = application;
|
||||
desktop.allApplicationProcesses.Add(process);
|
||||
} else {
|
||||
EsApplicationStartupInformation s = {};
|
||||
s.data = CRASHED_TAB_INVALID_EXECUTABLE;
|
||||
|
@ -1346,11 +1482,11 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
|
|||
}
|
||||
|
||||
if (application->useSingleProcess) {
|
||||
application->singleProcessHandle = process;
|
||||
application->singleProcess = process;
|
||||
}
|
||||
|
||||
instance->processID = EsProcessGetID(process);
|
||||
instance->processHandle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, process, ES_CURRENT_PROCESS, 0, 0);
|
||||
instance->process = process;
|
||||
process->instanceCount++;
|
||||
|
||||
if (startupInformation->documentID) {
|
||||
instance->documentID = startupInformation->documentID;
|
||||
|
@ -1374,33 +1510,23 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
|
|||
// Share handles to the file and the startup information buffer.
|
||||
|
||||
if (startupInformation->readHandle) {
|
||||
startupInformation->readHandle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, startupInformation->readHandle, process, 0, 0);
|
||||
}
|
||||
|
||||
if (!application->useSingleProcess && !application->createInstance) {
|
||||
startupInformation->flags |= ES_APPLICATION_STARTUP_SINGLE_INSTANCE_IN_PROCESS;
|
||||
startupInformation->readHandle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, startupInformation->readHandle, process->handle, 0, 0);
|
||||
}
|
||||
|
||||
uint8_t *createInstanceDataBuffer = ApplicationStartupInformationToBuffer(startupInformation, &m.createInstance.dataBytes);
|
||||
m.createInstance.data = EsConstantBufferCreate(createInstanceDataBuffer, m.createInstance.dataBytes, process);
|
||||
m.createInstance.data = EsConstantBufferCreate(createInstanceDataBuffer, m.createInstance.dataBytes, process->handle);
|
||||
EsHeapFree(createInstanceDataBuffer);
|
||||
|
||||
EsHandle handle = EsSyscall(ES_SYSCALL_WINDOW_CREATE, ES_WINDOW_NORMAL, 0, 0, 0);
|
||||
instance->embeddedWindowHandle = handle;
|
||||
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);
|
||||
m.createInstance.window = EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, process->handle, 0, ES_WINDOW_PROPERTY_EMBED_OWNER);
|
||||
|
||||
if (application->createInstance) {
|
||||
application->createInstance(&m);
|
||||
} else {
|
||||
EsMessagePostRemote(process, &m);
|
||||
|
||||
if (!application->useSingleProcess) {
|
||||
EsHandleClose(process);
|
||||
} else {
|
||||
application->openInstanceCount++;
|
||||
}
|
||||
EsMessagePostRemote(process->handle, &m);
|
||||
}
|
||||
|
||||
if (application->useSingleInstance) {
|
||||
|
@ -1432,7 +1558,6 @@ ApplicationInstance *ApplicationInstanceCreate(int64_t id, EsApplicationStartupI
|
|||
|
||||
void ApplicationTemporaryDestroy(InstalledApplication *application) {
|
||||
if (!application->temporary) return;
|
||||
EsAssert(!application->singleProcessHandle);
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
if (desktop.installedApplications[i] == application) {
|
||||
|
@ -1449,6 +1574,27 @@ void ApplicationTemporaryDestroy(InstalledApplication *application) {
|
|||
EsAssert(false);
|
||||
}
|
||||
|
||||
ApplicationProcess *ApplicationProcessFindByPID(EsObjectID pid, bool removeIfFound = false) {
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
ApplicationProcess *process = desktop.allApplicationProcesses[i];
|
||||
|
||||
if (process->id == pid) {
|
||||
if (removeIfFound) {
|
||||
desktop.allApplicationProcesses.DeleteSwap(i);
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InstalledApplication *ApplicationFindByPID(EsObjectID pid) {
|
||||
ApplicationProcess *process = ApplicationProcessFindByPID(pid);
|
||||
return process ? process->application : nullptr;
|
||||
}
|
||||
|
||||
void ApplicationInstanceCrashed(EsMessage *message) {
|
||||
EsHandle processHandle = EsProcessOpen(message->crash.pid);
|
||||
EsAssert(processHandle); // Since the process is paused, it cannot be removed.
|
||||
|
@ -1461,10 +1607,21 @@ void ApplicationInstanceCrashed(EsMessage *message) {
|
|||
: EnumLookupNameFromValue(enumStrings_EsSyscallType, state.crashReason.duringSystemCall);
|
||||
EsPrint("Process %d has crashed with error %z, during system call %z.\n", state.id, fatalErrorString, systemCallString);
|
||||
|
||||
InstalledApplication *application = ApplicationFindByPID(message->crash.pid);
|
||||
|
||||
if (application) {
|
||||
if (application->singleProcess && application->singleProcess->id == message->crash.pid) {
|
||||
application->singleProcess = nullptr;
|
||||
}
|
||||
|
||||
application->singleInstance = nullptr;
|
||||
ApplicationTemporaryDestroy(application);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->processID == message->crash.pid) {
|
||||
if (instance->process->id == message->crash.pid) {
|
||||
if (instance->tab) {
|
||||
ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, nullptr, instance);
|
||||
WindowTabActivate(instance->tab, true);
|
||||
|
@ -1472,55 +1629,37 @@ void ApplicationInstanceCrashed(EsMessage *message) {
|
|||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
if (desktop.installedApplications[i]->useSingleProcess && desktop.installedApplications[i]->singleProcessHandle
|
||||
&& EsProcessGetID(desktop.installedApplications[i]->singleProcessHandle) == message->crash.pid) {
|
||||
EsHandleClose(desktop.installedApplications[i]->singleProcessHandle);
|
||||
desktop.installedApplications[i]->singleProcessHandle = ES_INVALID_HANDLE;
|
||||
desktop.installedApplications[i]->singleInstance = nullptr;
|
||||
desktop.installedApplications[i]->openInstanceCount = 0;
|
||||
ApplicationTemporaryDestroy(desktop.installedApplications[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EsProcessTerminate(processHandle, 1);
|
||||
EsHandleClose(processHandle);
|
||||
}
|
||||
|
||||
InstalledApplication *ApplicationFindByPID(EsObjectID pid) {
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->processID == pid) {
|
||||
return instance->application;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ApplicationProcessTerminated(EsObjectID pid) {
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->processID != pid) {
|
||||
continue;
|
||||
if (instance->process->id == pid) {
|
||||
EmbeddedWindowDestroyed(instance->embeddedWindowID);
|
||||
i--; // EmbeddedWindowDestroyed removes it from the array.
|
||||
}
|
||||
|
||||
EmbeddedWindowDestroyed(instance->embeddedWindowID);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
if (desktop.installedApplications[i]->useSingleProcess && desktop.installedApplications[i]->singleProcessHandle
|
||||
&& EsProcessGetID(desktop.installedApplications[i]->singleProcessHandle) == pid) {
|
||||
EsHandleClose(desktop.installedApplications[i]->singleProcessHandle);
|
||||
desktop.installedApplications[i]->singleProcessHandle = ES_INVALID_HANDLE;
|
||||
desktop.installedApplications[i]->singleInstance = nullptr;
|
||||
desktop.installedApplications[i]->openInstanceCount = 0;
|
||||
ApplicationTemporaryDestroy(desktop.installedApplications[i]);
|
||||
break;
|
||||
ApplicationProcess *process = ApplicationProcessFindByPID(pid, true /* remove from array */);
|
||||
|
||||
if (process) {
|
||||
InstalledApplication *application = process->application;
|
||||
|
||||
if (application) {
|
||||
if (application->singleProcess && application->singleProcess->id == pid) {
|
||||
application->singleProcess = nullptr;
|
||||
}
|
||||
|
||||
application->singleInstance = nullptr;
|
||||
ApplicationTemporaryDestroy(application);
|
||||
}
|
||||
|
||||
EsAssert(!process->instanceCount);
|
||||
EsHandleClose(process->handle);
|
||||
EsHeapFree(process);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
|
||||
|
@ -1530,6 +1669,10 @@ void ApplicationProcessTerminated(EsObjectID pid) {
|
|||
document->currentWriter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!desktop.allApplicationProcesses.Length() && desktop.inShutdown) {
|
||||
EsEventSet(desktop.shutdownReady);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
@ -1625,7 +1768,7 @@ EsError TemporaryFileCreate(EsHandle *handle, char **path, size_t *pathBytes, ui
|
|||
}
|
||||
|
||||
void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *newName, size_t newNameBytes, bool failIfAlreadyExists) {
|
||||
if (!instance->processHandle) return;
|
||||
if (!instance->process) return;
|
||||
|
||||
EsMessage m = {};
|
||||
m.type = ES_MSG_INSTANCE_SAVE_RESPONSE;
|
||||
|
@ -1643,7 +1786,7 @@ void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *n
|
|||
if (!nameBytes || (failIfAlreadyExists && nameBytes != folderBytes + newNameBytes)) {
|
||||
EsHeapFree(name);
|
||||
m.tabOperation.error = nameBytes ? ES_ERROR_FILE_ALREADY_EXISTS : ES_ERROR_TOO_MANY_FILES_WITH_NAME;
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1652,7 +1795,7 @@ void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *n
|
|||
if (file.error != ES_SUCCESS) {
|
||||
EsHeapFree(name);
|
||||
m.tabOperation.error = file.error;
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1679,9 +1822,9 @@ void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *n
|
|||
|
||||
EsMessage m = { ES_MSG_INSTANCE_DOCUMENT_RENAMED };
|
||||
m.tabOperation.id = instance->embeddedWindowID;
|
||||
m.tabOperation.handle = EsConstantBufferCreate(name + nameOffset, nameBytes - nameOffset, instance->processHandle);
|
||||
m.tabOperation.handle = EsConstantBufferCreate(name + nameOffset, nameBytes - nameOffset, instance->process->handle);
|
||||
m.tabOperation.bytes = nameBytes - nameOffset;
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1702,12 +1845,12 @@ void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *n
|
|||
|
||||
if (m.tabOperation.error == ES_SUCCESS) {
|
||||
document->currentWriter = instance->embeddedWindowID;
|
||||
m.tabOperation.handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, fileHandle, instance->processHandle, 0, 0);
|
||||
m.tabOperation.handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, fileHandle, instance->process->handle, 0, 0);
|
||||
EsHandleClose(fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
}
|
||||
|
||||
void InstanceAnnouncePathMoved(InstalledApplication *fromApplication, const char *oldPath, size_t oldPathBytes, const char *newPath, size_t newPathBytes) {
|
||||
|
@ -1749,16 +1892,16 @@ void InstanceAnnouncePathMoved(InstalledApplication *fromApplication, const char
|
|||
|
||||
if (instance->documentID != documentID) continue;
|
||||
if (instance->application == fromApplication) continue;
|
||||
if (!instance->processHandle) continue;
|
||||
if (!instance->process) continue;
|
||||
|
||||
EsMessage m = { ES_MSG_INSTANCE_DOCUMENT_RENAMED };
|
||||
m.tabOperation.id = instance->embeddedWindowID;
|
||||
m.tabOperation.handle = EsConstantBufferCreate(newPath + newNameOffset, newPathBytes - newNameOffset, instance->processHandle);
|
||||
m.tabOperation.handle = EsConstantBufferCreate(newPath + newNameOffset, newPathBytes - newNameOffset, instance->process->handle);
|
||||
m.tabOperation.bytes = newPathBytes - newNameOffset;
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
}
|
||||
|
||||
if (fromApplication != desktop.fileManager && desktop.fileManager && desktop.fileManager->singleProcessHandle) {
|
||||
if (fromApplication != desktop.fileManager && desktop.fileManager && desktop.fileManager->singleProcess) {
|
||||
char *data = (char *) EsHeapAllocate(sizeof(size_t) * 2 + oldPathBytes + newPathBytes, false);
|
||||
EsMemoryCopy(data + 0, &oldPathBytes, sizeof(size_t));
|
||||
EsMemoryCopy(data + sizeof(size_t), &newPathBytes, sizeof(size_t));
|
||||
|
@ -1767,8 +1910,8 @@ void InstanceAnnouncePathMoved(InstalledApplication *fromApplication, const char
|
|||
EsMessage m = {};
|
||||
m.type = ES_MSG_FILE_MANAGER_PATH_MOVED;
|
||||
m.user.context2 = sizeof(size_t) * 2 + oldPathBytes + newPathBytes;
|
||||
m.user.context1 = EsConstantBufferCreate(data, m.user.context2.u, desktop.fileManager->singleProcessHandle);
|
||||
EsMessagePostRemote(desktop.fileManager->singleProcessHandle, &m);
|
||||
m.user.context1 = EsConstantBufferCreate(data, m.user.context2.u, desktop.fileManager->singleProcess->handle);
|
||||
EsMessagePostRemote(desktop.fileManager->singleProcess->handle, &m);
|
||||
EsHeapFree(data);
|
||||
}
|
||||
}
|
||||
|
@ -1800,25 +1943,25 @@ void ApplicationInstanceCompleteSave(ApplicationInstance *fromInstance) {
|
|||
|
||||
document->currentWriter = 0;
|
||||
|
||||
if (desktop.fileManager->singleProcessHandle) {
|
||||
if (desktop.fileManager->singleProcess) {
|
||||
EsMessage m = {};
|
||||
m.type = ES_MSG_FILE_MANAGER_FILE_MODIFIED;
|
||||
m.user.context1 = EsConstantBufferCreate(document->path, document->pathBytes, desktop.fileManager->singleProcessHandle);
|
||||
m.user.context1 = EsConstantBufferCreate(document->path, document->pathBytes, desktop.fileManager->singleProcess->handle);
|
||||
m.user.context2 = document->pathBytes;
|
||||
EsMessagePostRemote(desktop.fileManager->singleProcessHandle, &m);
|
||||
EsMessagePostRemote(desktop.fileManager->singleProcess->handle, &m);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->documentID != document->id) continue;
|
||||
if (!instance->processHandle) continue;
|
||||
if (!instance->process) continue;
|
||||
|
||||
EsMessage m = { ES_MSG_INSTANCE_DOCUMENT_UPDATED };
|
||||
m.tabOperation.isSource = instance == fromInstance;
|
||||
m.tabOperation.id = instance->embeddedWindowID;
|
||||
m.tabOperation.handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, document->readHandle, instance->processHandle, 0, 0);
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
m.tabOperation.handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, document->readHandle, instance->process->handle, 0, 0);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1831,6 +1974,7 @@ void ConfigurationLoadApplications() {
|
|||
|
||||
{
|
||||
InstalledApplication *application = (InstalledApplication *) EsHeapAllocate(sizeof(InstalledApplication), true);
|
||||
application->cName = (char *) "(blank tab)";
|
||||
application->id = APPLICATION_ID_DESKTOP_BLANK_TAB;
|
||||
application->hidden = true;
|
||||
application->createInstance = InstanceBlankTabCreate;
|
||||
|
@ -1849,6 +1993,7 @@ void ConfigurationLoadApplications() {
|
|||
|
||||
{
|
||||
InstalledApplication *application = (InstalledApplication *) EsHeapAllocate(sizeof(InstalledApplication), true);
|
||||
application->cName = (char *) "(crashed tab)";
|
||||
application->id = APPLICATION_ID_DESKTOP_CRASHED;
|
||||
application->hidden = true;
|
||||
application->createInstance = InstanceCrashedTabCreate;
|
||||
|
@ -2014,12 +2159,12 @@ ApplicationInstance *ApplicationInstanceFindForeground() {
|
|||
void CheckForegroundWindowResponding(EsGeneric) {
|
||||
ApplicationInstance *instance = ApplicationInstanceFindForeground();
|
||||
EsTimerSet(2500, CheckForegroundWindowResponding, 0);
|
||||
if (!instance) return;
|
||||
if (!instance || !instance->process) return;
|
||||
|
||||
WindowTab *tab = instance->tab;
|
||||
|
||||
EsProcessState state;
|
||||
EsProcessGetState(instance->processHandle, &state);
|
||||
EsProcessGetState(instance->process->handle, &state);
|
||||
|
||||
if (state.flags & ES_PROCESS_STATE_PINGED) {
|
||||
if (tab->notRespondingInstance) {
|
||||
|
@ -2042,7 +2187,7 @@ void CheckForegroundWindowResponding(EsGeneric) {
|
|||
EsMessage m;
|
||||
EsMemoryZero(&m, sizeof(EsMessage));
|
||||
m.type = ES_MSG_PING;
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2215,10 +2360,10 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
|
||||
ApplicationInstance *foreground = ApplicationInstanceFindForeground();
|
||||
|
||||
if (foreground && foreground->processHandle) {
|
||||
if (foreground && foreground->process) {
|
||||
EsMessage m = { ES_MSG_PRIMARY_CLIPBOARD_UPDATED };
|
||||
m.tabOperation.id = foreground->embeddedWindowID;
|
||||
EsMessagePostRemote(foreground->processHandle, &m);
|
||||
EsMessagePostRemote(foreground->process->handle, &m);
|
||||
}
|
||||
} else {
|
||||
EsHandleClose(desktop.nextClipboardFile);
|
||||
|
@ -2270,12 +2415,14 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
InstanceAnnouncePathMoved(application, oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_START_USER_TASK && pipe) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
ApplicationProcess *process = ApplicationProcessFindByPID(message->desktop.processID);
|
||||
|
||||
if (!application) {
|
||||
if (!process || !process->instanceCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
InstalledApplication *application = process->application;
|
||||
|
||||
// HACK User tasks use an embedded window object for IPC.
|
||||
// This allows us to basically treat them like other instances.
|
||||
|
||||
|
@ -2303,15 +2450,10 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
instance->isUserTask = true;
|
||||
instance->embeddedWindowHandle = windowHandle;
|
||||
instance->embeddedWindowID = EsSyscall(ES_SYSCALL_WINDOW_GET_ID, windowHandle, 0, 0, 0);
|
||||
instance->processHandle = processHandle;
|
||||
instance->processID = message->desktop.processID;
|
||||
instance->process = process;
|
||||
instance->process->instanceCount++;
|
||||
instance->application = application;
|
||||
|
||||
if (application->singleProcessHandle) {
|
||||
EsAssert(application->openInstanceCount);
|
||||
application->openInstanceCount++;
|
||||
}
|
||||
|
||||
EsHandle targetWindowHandle = EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, windowHandle, processHandle, 0, ES_WINDOW_PROPERTY_EMBED_OWNER);
|
||||
EsBufferWrite(pipe, &targetWindowHandle, sizeof(targetWindowHandle));
|
||||
|
||||
|
@ -2373,7 +2515,7 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
m.type = ES_MSG_INSTANCE_RENAME_RESPONSE;
|
||||
m.tabOperation.id = instance->embeddedWindowID;
|
||||
m.tabOperation.error = EsPathMove(oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
|
||||
if (m.tabOperation.error == ES_SUCCESS) {
|
||||
InstanceAnnouncePathMoved(nullptr, oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
|
@ -2433,31 +2575,8 @@ void EmbeddedWindowDestroyed(EsObjectID id) {
|
|||
if (!instance) return;
|
||||
|
||||
EsHandleClose(instance->embeddedWindowHandle);
|
||||
if (instance->processHandle) EsHandleClose(instance->processHandle);
|
||||
|
||||
if (instance->documentID) {
|
||||
OpenDocumentCloseReference(instance->documentID);
|
||||
}
|
||||
|
||||
InstalledApplication *application = instance->application;
|
||||
|
||||
if (application && application->singleInstance) {
|
||||
application->singleInstance = nullptr;
|
||||
}
|
||||
|
||||
if (application && application->singleProcessHandle) {
|
||||
EsAssert(application->openInstanceCount);
|
||||
application->openInstanceCount--;
|
||||
|
||||
if (!application->openInstanceCount && application->useSingleProcess) {
|
||||
EsMessage m = { ES_MSG_APPLICATION_EXIT };
|
||||
EsMessagePostRemote(application->singleProcessHandle, &m);
|
||||
EsHandleClose(application->singleProcessHandle);
|
||||
application->singleProcessHandle = ES_INVALID_HANDLE;
|
||||
ApplicationTemporaryDestroy(application);
|
||||
application = nullptr;
|
||||
}
|
||||
}
|
||||
ApplicationInstanceCleanup(instance);
|
||||
|
||||
if (instance->tab) {
|
||||
WindowTabDestroy(instance->tab);
|
||||
|
@ -2521,63 +2640,44 @@ void DesktopMessage(EsMessage *message) {
|
|||
} else if (message->type == ES_MSG_REGISTER_FILE_SYSTEM) {
|
||||
EsHandle rootDirectory = message->registerFileSystem.rootDirectory;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
ApplicationProcess *process = desktop.allApplicationProcesses[i];
|
||||
|
||||
if (instance->application && (instance->application->permissions & APPLICATION_PERMISSION_ALL_FILES)
|
||||
&& instance->processHandle && !instance->application->notified) {
|
||||
message->registerFileSystem.rootDirectory = EsSyscall(ES_SYSCALL_HANDLE_SHARE, rootDirectory, instance->processHandle, 0, 0);
|
||||
EsMessagePostRemote(instance->processHandle, message);
|
||||
if (instance->application->useSingleProcess) instance->application->notified = true;
|
||||
if (process->application && (process->application->permissions & APPLICATION_PERMISSION_ALL_FILES)) {
|
||||
message->registerFileSystem.rootDirectory = EsSyscall(ES_SYSCALL_HANDLE_SHARE, rootDirectory, process->handle, 0, 0);
|
||||
EsMessagePostRemote(process->handle, message);
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
desktop.installedApplications[i]->notified = false;
|
||||
}
|
||||
} else if (message->type == ES_MSG_DEVICE_CONNECTED) {
|
||||
EsHandle handle = message->device.handle;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
ApplicationProcess *process = desktop.allApplicationProcesses[i];
|
||||
|
||||
if (instance->application && (instance->application->permissions & APPLICATION_PERMISSION_ALL_DEVICES)
|
||||
&& instance->processHandle && !instance->application->notified) {
|
||||
message->device.handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, handle, instance->processHandle, 0, 0);
|
||||
EsMessagePostRemote(instance->processHandle, message);
|
||||
if (instance->application->useSingleProcess) instance->application->notified = true;
|
||||
if (process->application && (process->application->permissions & APPLICATION_PERMISSION_ALL_DEVICES)) {
|
||||
message->device.handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, handle, process->handle, 0, 0);
|
||||
EsMessagePostRemote(process->handle, message);
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
desktop.installedApplications[i]->notified = false;
|
||||
}
|
||||
} else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM || message->type == ES_MSG_DEVICE_DISCONNECTED) {
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
ApplicationProcess *process = desktop.allApplicationProcesses[i];
|
||||
|
||||
if (!instance->application) {
|
||||
if (!process->application) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
|
||||
if (~instance->application->permissions & APPLICATION_PERMISSION_ALL_FILES) {
|
||||
if (~process->application->permissions & APPLICATION_PERMISSION_ALL_FILES) {
|
||||
continue;
|
||||
}
|
||||
} else if (message->type == ES_MSG_DEVICE_DISCONNECTED) {
|
||||
if (~instance->application->permissions & APPLICATION_PERMISSION_ALL_DEVICES) {
|
||||
if (~process->application->permissions & APPLICATION_PERMISSION_ALL_DEVICES) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (instance->processHandle && !instance->application->notified) {
|
||||
EsMessagePostRemote(instance->processHandle, message);
|
||||
if (instance->application->useSingleProcess) instance->application->notified = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
desktop.installedApplications[i]->notified = false;
|
||||
EsMessagePostRemote(process->handle, message);
|
||||
}
|
||||
} else if (message->type == ES_MSG_SET_SCREEN_RESOLUTION) {
|
||||
if (desktop.setupDesktopUIComplete) {
|
||||
|
|
|
@ -695,7 +695,6 @@ define ES_ELEMENT_FOCUS_ENSURE_VISIBLE (1 << 0)
|
|||
define ES_ELEMENT_FOCUS_FROM_KEYBOARD (1 << 1)
|
||||
|
||||
define ES_APPLICATION_STARTUP_MANUAL_PATH (1 << 0)
|
||||
define ES_APPLICATION_STARTUP_SINGLE_INSTANCE_IN_PROCESS (1 << 1)
|
||||
|
||||
define ES_LIST_VIEW_INLINE_TEXTBOX_COPY_EXISTING_TEXT (1 << 0)
|
||||
define ES_LIST_VIEW_INLINE_TEXTBOX_REJECT_EDIT_IF_FOCUS_LOST (1 << 1)
|
||||
|
|
|
@ -146,17 +146,8 @@ void SettingsUpdateGlobalAndWindowManager() {
|
|||
EsMemoryZero(&m, sizeof(EsMessage));
|
||||
m.type = ES_MSG_UI_SCALE_CHANGED;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->processHandle && !instance->application->notified) {
|
||||
EsMessagePostRemote(instance->processHandle, &m);
|
||||
if (instance->application->useSingleProcess) instance->application->notified = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
desktop.installedApplications[i]->notified = false;
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
EsMessagePostRemote(desktop.allApplicationProcesses[i]->handle, &m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue