mirror of https://gitlab.com/nakst/essence
open document reference counting
This commit is contained in:
parent
56bd531f66
commit
b8731dc27e
|
@ -987,8 +987,7 @@ void EsInstanceSaveComplete(EsMessage *message, bool success) {
|
|||
}
|
||||
|
||||
if (success) {
|
||||
message->instanceSave.file->error = EsFileControl(message->instanceSave.file->handle,
|
||||
ES_FILE_CONTROL_NOTIFY_MONITORS | ES_FILE_CONTROL_FLUSH);
|
||||
message->instanceSave.file->error = EsFileControl(message->instanceSave.file->handle, ES_FILE_CONTROL_FLUSH);
|
||||
|
||||
if (message->instanceSave.file->error != ES_SUCCESS) {
|
||||
success = false;
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
// - New tab page - search; recent files.
|
||||
// - Right click menu.
|
||||
// - Duplicate tabs.
|
||||
// - If a process exits, its tabs won't close because Desktop has a handle.
|
||||
// - Also clear any OpenDocument currentWriter fields it owns.
|
||||
|
||||
// TODO Graphical issues:
|
||||
// - New tab button isn't flush with right border when tab band full.
|
||||
|
@ -31,6 +29,7 @@
|
|||
// TODO Only let File Manager read the file_type sections of the system configuration.
|
||||
// TODO Restarting Desktop if it crashes.
|
||||
// TODO Make sure applications can't delete |Fonts: and |Themes:.
|
||||
// TODO Handle open document deletion.
|
||||
|
||||
#define MSG_SETUP_DESKTOP_UI ((EsMessageType) (ES_MSG_USER_START + 1))
|
||||
|
||||
|
@ -105,6 +104,7 @@ struct OpenDocument {
|
|||
EsHandle readHandle;
|
||||
EsObjectID id;
|
||||
EsObjectID currentWriter;
|
||||
uintptr_t referenceCount;
|
||||
};
|
||||
|
||||
struct InstalledApplication {
|
||||
|
@ -122,10 +122,14 @@ struct InstalledApplication {
|
|||
bool notified; // Temporary flag.
|
||||
};
|
||||
|
||||
struct CrashedTabInstance : EsInstance {
|
||||
struct CommonDesktopInstance : EsInstance {
|
||||
void (*destroy)(EsInstance *);
|
||||
};
|
||||
|
||||
struct BlankTabInstance : EsInstance {
|
||||
struct CrashedTabInstance : CommonDesktopInstance {
|
||||
};
|
||||
|
||||
struct BlankTabInstance : CommonDesktopInstance {
|
||||
};
|
||||
|
||||
struct ApplicationInstance {
|
||||
|
@ -184,6 +188,8 @@ struct {
|
|||
EsObjectID nextClipboardProcessID;
|
||||
EsHandle clipboardFile;
|
||||
ClipboardInformation clipboardInformation;
|
||||
|
||||
bool configurationModified;
|
||||
} desktop;
|
||||
|
||||
int TaskBarButtonMessage(EsElement *element, EsMessage *message);
|
||||
|
@ -192,6 +198,9 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
|
|||
void ApplicationInstanceClose(ApplicationInstance *instance);
|
||||
ApplicationInstance *ApplicationInstanceFindByWindowID(EsObjectID windowID, bool remove = false);
|
||||
void EmbeddedWindowDestroyed(EsObjectID id);
|
||||
void ConfigurationWriteToFile();
|
||||
void OpenDocumentOpenReference(EsObjectID id);
|
||||
void OpenDocumentCloseReference(EsObjectID id);
|
||||
|
||||
#include "settings.cpp"
|
||||
|
||||
|
@ -908,6 +917,11 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
|
|||
instance->processHandle = ES_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (instance->documentID) {
|
||||
OpenDocumentCloseReference(instance->documentID);
|
||||
instance->documentID = 0;
|
||||
}
|
||||
|
||||
instance->application = application;
|
||||
|
||||
if (application->useSingleProcess && application->singleProcessHandle) {
|
||||
|
@ -1017,6 +1031,11 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
|
|||
instance->processID = EsProcessGetID(process);
|
||||
instance->processHandle = EsSyscall(ES_SYSCALL_PROCESS_SHARE, process, ES_CURRENT_PROCESS, 0, 0);
|
||||
|
||||
if (startupInformation->documentID) {
|
||||
instance->documentID = startupInformation->documentID;
|
||||
OpenDocumentOpenReference(instance->documentID);
|
||||
}
|
||||
|
||||
EsMessage m = { ES_MSG_INSTANCE_CREATE };
|
||||
|
||||
if (~startupInformation->flags & ES_APPLICATION_STARTUP_MANUAL_PATH) {
|
||||
|
@ -1077,9 +1096,16 @@ ApplicationInstance *ApplicationInstanceCreate(int64_t id, EsApplicationStartupI
|
|||
instance->titleBytes = 1;
|
||||
instance->tab = tab;
|
||||
desktop.allApplicationInstances.Add(instance);
|
||||
ApplicationInstanceStart(id, startupInformation, instance);
|
||||
if (!hidden) WindowTabActivate(tab);
|
||||
return instance;
|
||||
|
||||
if (ApplicationInstanceStart(id, startupInformation, instance)) {
|
||||
if (!hidden) WindowTabActivate(tab);
|
||||
return instance;
|
||||
} else {
|
||||
// TODO Destroy the tab/container window.
|
||||
// Or, we probably didn't want to create them in the first place.
|
||||
EsHeapFree(instance);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationTemporaryDestroy(InstalledApplication *application) {
|
||||
|
@ -1171,15 +1197,39 @@ void ApplicationProcessTerminated(EsObjectID pid) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
|
||||
OpenDocument *document = &desktop.openDocuments[i];
|
||||
|
||||
if (document->currentWriter == pid) {
|
||||
document->currentWriter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Document management:
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void OpenDocumentCloseReference(EsObjectID id) {
|
||||
OpenDocument *document = desktop.openDocuments.Get(&id);
|
||||
EsAssert(document->referenceCount && document->referenceCount < 0x10000000 /* sanity check */);
|
||||
document->referenceCount--;
|
||||
if (document->referenceCount) return;
|
||||
EsHeapFree(document->path);
|
||||
EsHeapFree(document->temporarySavePath);
|
||||
EsHandleClose(document->readHandle);
|
||||
desktop.openDocuments.Delete(&id);
|
||||
}
|
||||
|
||||
void OpenDocumentOpenReference(EsObjectID id) {
|
||||
OpenDocument *document = desktop.openDocuments.Get(&id);
|
||||
EsAssert(document->referenceCount && document->referenceCount < 0x10000000 /* sanity check */);
|
||||
document->referenceCount++;
|
||||
}
|
||||
|
||||
void OpenDocumentWithApplication(EsApplicationStartupInformation *startupInformation) {
|
||||
bool foundDocument = false;
|
||||
EsObjectID documentID;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
|
||||
OpenDocument *document = &desktop.openDocuments[i];
|
||||
|
@ -1188,7 +1238,8 @@ void OpenDocumentWithApplication(EsApplicationStartupInformation *startupInforma
|
|||
&& 0 == EsMemoryCompare(document->path, startupInformation->filePath, document->pathBytes)) {
|
||||
foundDocument = true;
|
||||
startupInformation->readHandle = document->readHandle;
|
||||
documentID = document->id;
|
||||
startupInformation->documentID = document->id;
|
||||
document->referenceCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1207,18 +1258,16 @@ void OpenDocumentWithApplication(EsApplicationStartupInformation *startupInforma
|
|||
document.pathBytes = startupInformation->filePathBytes;
|
||||
document.readHandle = file.handle;
|
||||
document.id = ++desktop.currentDocumentID;
|
||||
documentID = document.id;
|
||||
document.referenceCount = 1;
|
||||
EsMemoryCopy(document.path, startupInformation->filePath, startupInformation->filePathBytes);
|
||||
*desktop.openDocuments.Put(&document.id) = document;
|
||||
|
||||
startupInformation->readHandle = document.readHandle;
|
||||
startupInformation->documentID = document.id;
|
||||
}
|
||||
|
||||
ApplicationInstance *instance = ApplicationInstanceCreate(startupInformation->id, startupInformation, nullptr);
|
||||
|
||||
if (instance) {
|
||||
instance->documentID = documentID;
|
||||
}
|
||||
ApplicationInstanceCreate(startupInformation->id, startupInformation, nullptr);
|
||||
OpenDocumentCloseReference(startupInformation->documentID);
|
||||
}
|
||||
|
||||
EsError TemporaryFileCreate(EsHandle *handle, char **path, size_t *pathBytes) {
|
||||
|
@ -1319,6 +1368,9 @@ void ApplicationInstanceRequestSave(ApplicationInstance *instance, const char *n
|
|||
if (document->currentWriter) {
|
||||
m.tabOperation.error = ES_ERROR_FILE_CANNOT_GET_EXCLUSIVE_USE;
|
||||
} else {
|
||||
EsHeapFree(document->temporarySavePath);
|
||||
document->temporarySavePath = nullptr;
|
||||
|
||||
EsHandle fileHandle;
|
||||
m.tabOperation.error = TemporaryFileCreate(&fileHandle, &document->temporarySavePath, &document->temporarySavePathBytes);
|
||||
|
||||
|
@ -1526,7 +1578,7 @@ void ConfigurationLoadApplications() {
|
|||
}, 0);
|
||||
}
|
||||
|
||||
void ConfigurationWriteSectionsToBuffer(const char *sectionClass, const char *section, EsBuffer *pipe) {
|
||||
void ConfigurationWriteSectionsToBuffer(const char *sectionClass, const char *section, bool includeComments, EsBuffer *pipe) {
|
||||
char buffer[4096];
|
||||
EsMutexAcquire(&api.systemConfigurationMutex);
|
||||
|
||||
|
@ -1547,7 +1599,7 @@ void ConfigurationWriteSectionsToBuffer(const char *sectionClass, const char *se
|
|||
for (uintptr_t i = 0; i < group->itemCount; i++) {
|
||||
EsSystemConfigurationItem *item = group->items + i;
|
||||
|
||||
if (!item->keyBytes || item->key[0] == ';') {
|
||||
if ((!item->keyBytes || item->key[0] == ';') && !includeComments) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1561,6 +1613,37 @@ void ConfigurationWriteSectionsToBuffer(const char *sectionClass, const char *se
|
|||
EsMutexRelease(&api.systemConfigurationMutex);
|
||||
}
|
||||
|
||||
void ConfigurationWriteToFile() {
|
||||
if (!desktop.configurationModified) {
|
||||
return;
|
||||
}
|
||||
|
||||
EsBuffer buffer = { .canGrow = true };
|
||||
ConfigurationWriteSectionsToBuffer(nullptr, nullptr, true /* include comments */, &buffer);
|
||||
|
||||
if (!buffer.error) {
|
||||
if (ES_SUCCESS == EsFileWriteAll(EsLiteral(K_SYSTEM_CONFIGURATION "_"), buffer.out, buffer.position)) {
|
||||
// TODO Atomic delete and move.
|
||||
if (ES_SUCCESS == EsPathDelete(EsLiteral(K_SYSTEM_CONFIGURATION))) {
|
||||
if (ES_SUCCESS == EsPathMove(EsLiteral(K_SYSTEM_CONFIGURATION "_"), EsLiteral(K_SYSTEM_CONFIGURATION))) {
|
||||
EsPrint("ConfigurationWriteToFile - New configuration successfully written.\n");
|
||||
desktop.configurationModified = true;
|
||||
} else {
|
||||
EsPrint("ConfigurationWriteToFile - Error while moving to final path.\n");
|
||||
}
|
||||
} else {
|
||||
EsPrint("ConfigurationWriteToFile - Error while deleting old file.\n");
|
||||
}
|
||||
} else {
|
||||
EsPrint("ConfigurationWriteToFile - Error while writing to file.\n");
|
||||
}
|
||||
} else {
|
||||
EsPrint("ConfigurationWriteToFile - Error while writing to buffer.\n");
|
||||
}
|
||||
|
||||
EsHeapFree(buffer.out);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Image utilities:
|
||||
//////////////////////////////////////////////////////
|
||||
|
@ -1885,8 +1968,8 @@ void DesktopMessage2(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
EsHandleClose(processHandle);
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_SYSTEM_CONFIGURATION_GET && pipe) {
|
||||
ConfigurationWriteSectionsToBuffer("font", nullptr, pipe);
|
||||
ConfigurationWriteSectionsToBuffer(nullptr, "ui", pipe);
|
||||
ConfigurationWriteSectionsToBuffer("font", nullptr, false, pipe);
|
||||
ConfigurationWriteSectionsToBuffer(nullptr, "ui", false, pipe);
|
||||
} else if (buffer[0] == DESKTOP_MSG_REQUEST_SHUTDOWN) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
|
||||
|
@ -1897,7 +1980,7 @@ void DesktopMessage2(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
|
||||
if (application && (application->permissions & APPLICATION_PERMISSION_VIEW_FILE_TYPES)) {
|
||||
ConfigurationWriteSectionsToBuffer("file_type", nullptr, pipe);
|
||||
ConfigurationWriteSectionsToBuffer("file_type", nullptr, false, pipe);
|
||||
}
|
||||
} else if (!instance) {
|
||||
// -------------------------------------------------
|
||||
|
@ -1965,8 +2048,6 @@ void DesktopMessage2(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
}
|
||||
|
||||
void EmbeddedWindowDestroyed(EsObjectID id) {
|
||||
// TODO Close open documents.
|
||||
|
||||
EsMenuCloseAll();
|
||||
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(id, true /* remove if found */);
|
||||
if (!instance) return;
|
||||
|
@ -1974,6 +2055,10 @@ void EmbeddedWindowDestroyed(EsObjectID id) {
|
|||
EsHandleClose(instance->embeddedWindowHandle);
|
||||
if (instance->processHandle) EsHandleClose(instance->processHandle);
|
||||
|
||||
if (instance->documentID) {
|
||||
OpenDocumentCloseReference(instance->documentID);
|
||||
}
|
||||
|
||||
InstalledApplication *application = instance->application;
|
||||
|
||||
if (application && application->singleInstance) {
|
||||
|
@ -2126,6 +2211,12 @@ void DesktopMessage(EsMessage *message) {
|
|||
EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &bounds, 0, ES_WINDOW_MOVE_ALWAYS_ON_TOP);
|
||||
wrapper->StartAnimating();
|
||||
}
|
||||
} else if (message->type == ES_MSG_INSTANCE_DESTROY) {
|
||||
CommonDesktopInstance *instance = (CommonDesktopInstance *) message->instanceDestroy.instance;
|
||||
|
||||
if (instance->destroy) {
|
||||
instance->destroy(instance);
|
||||
}
|
||||
} else if (message->type == MSG_SETUP_DESKTOP_UI) {
|
||||
DesktopSetup();
|
||||
}
|
||||
|
|
|
@ -654,8 +654,7 @@ define ES_ECHO_REQUEST_MAX_LENGTH (48)
|
|||
|
||||
define ES_CONNECTION_OPEN_WAIT (1 << 0)
|
||||
|
||||
define ES_FILE_CONTROL_NOTIFY_MONITORS (1 << 0)
|
||||
define ES_FILE_CONTROL_FLUSH (1 << 1)
|
||||
define ES_FILE_CONTROL_FLUSH (1 << 0)
|
||||
|
||||
define ES_ELEMENT_UPDATE_CONTENT_WIDTH (1 << 0)
|
||||
define ES_ELEMENT_UPDATE_CONTENT_HEIGHT (1 << 1)
|
||||
|
@ -1392,7 +1391,10 @@ struct EsApplicationStartupInformation {
|
|||
EsWindow *targetWindow;
|
||||
uint32_t flags;
|
||||
int32_t data;
|
||||
EsHandle readHandle; // Internal use.
|
||||
|
||||
// Internal use only.
|
||||
EsHandle readHandle;
|
||||
EsObjectID documentID;
|
||||
};
|
||||
|
||||
struct EsINIState {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// TODO Save system configuration file on closing the instance or going back to all settings.
|
||||
// TODO Undo button overlapped slightly when scrollbar shown.
|
||||
|
||||
struct SettingsInstance : EsInstance {
|
||||
struct SettingsInstance : CommonDesktopInstance {
|
||||
EsPanel *switcher;
|
||||
EsPanel *mainPage;
|
||||
EsButton *undoButton;
|
||||
|
@ -131,6 +130,7 @@ void SettingsBackButton(EsInstance *_instance, EsElement *, EsCommand *) {
|
|||
instance->undoButton = nullptr;
|
||||
instance->controls.Free();
|
||||
EsPanelSwitchTo(instance->switcher, instance->mainPage, ES_TRANSITION_ZOOM_OUT, ES_PANEL_SWITCHER_DESTROY_PREVIOUS_AFTER_TRANSITION, 1.0f);
|
||||
ConfigurationWriteToFile();
|
||||
}
|
||||
|
||||
void SettingsNumberBoxSetValue(EsElement *element, int32_t newValue) {
|
||||
|
@ -156,6 +156,7 @@ void SettingsNumberBoxSetValue(EsElement *element, int32_t newValue) {
|
|||
if (oldValue != newValue) {
|
||||
SettingsUpdateGlobalAndWindowManager();
|
||||
EsElementSetDisabled(instance->undoButton, false);
|
||||
desktop.configurationModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,6 +222,7 @@ void SettingsCheckboxCommand(EsInstance *_instance, EsElement *element, EsComman
|
|||
if (oldValue == newValue) return;
|
||||
SettingsUpdateGlobalAndWindowManager();
|
||||
EsElementSetDisabled(instance->undoButton, false);
|
||||
desktop.configurationModified = true;
|
||||
}
|
||||
|
||||
void SettingsAddCheckbox(EsElement *table, const char *string, ptrdiff_t stringBytes, char accessKey,
|
||||
|
@ -328,6 +330,7 @@ int SettingsSliderMessage(EsElement *element, EsMessage *message) {
|
|||
if (oldValue != newValue) {
|
||||
SettingsUpdateGlobalAndWindowManager();
|
||||
EsElementSetDisabled(instance->undoButton, false);
|
||||
desktop.configurationModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -536,4 +539,8 @@ void InstanceSettingsCreate(EsMessage *message) {
|
|||
EsButtonOnCommand(button, SettingsButtonPressed);
|
||||
}
|
||||
}
|
||||
|
||||
instance->destroy = [] (EsInstance *) {
|
||||
ConfigurationWriteToFile();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ EsError EsFileWriteAllGatherFromHandle(EsHandle handle, const void **data, size_
|
|||
offset += sizes[i];
|
||||
}
|
||||
|
||||
error = EsFileControl(handle, ES_FILE_CONTROL_NOTIFY_MONITORS | ES_FILE_CONTROL_FLUSH);
|
||||
error = EsFileControl(handle, ES_FILE_CONTROL_FLUSH);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue