show tasks button when user task started

This commit is contained in:
nakst 2021-09-03 10:24:28 +01:00
parent ce01df7c59
commit c80e762d86
6 changed files with 126 additions and 29 deletions

View File

@ -61,6 +61,7 @@ struct EnumString { const char *cName; int value; };
#define DESKTOP_MSG_SYSTEM_CONFIGURATION_GET (13) #define DESKTOP_MSG_SYSTEM_CONFIGURATION_GET (13)
#define DESKTOP_MSG_FILE_TYPES_GET (14) #define DESKTOP_MSG_FILE_TYPES_GET (14)
#define DESKTOP_MSG_UNHANDLED_KEY_EVENT (15) #define DESKTOP_MSG_UNHANDLED_KEY_EVENT (15)
#define DESKTOP_MSG_START_USER_TASK (16)
struct EsFileStore { struct EsFileStore {
#define FILE_STORE_HANDLE (1) #define FILE_STORE_HANDLE (1)
@ -1550,6 +1551,7 @@ const void *EsEmbeddedFileGet(const char *_name, ptrdiff_t nameBytes, size_t *by
struct UserTask { struct UserTask {
EsUserTaskCallbackFunction callback; EsUserTaskCallbackFunction callback;
EsGeneric data; EsGeneric data;
EsHandle taskHandle;
}; };
void UserTaskThread(EsGeneric _task) { void UserTaskThread(EsGeneric _task) {
@ -1558,23 +1560,48 @@ void UserTaskThread(EsGeneric _task) {
EsMessageMutexAcquire(); EsMessageMutexAcquire();
api.openInstanceCount--; api.openInstanceCount--;
// TODO Send ES_MSG_APPLICATION_EXIT if needed. // TODO Send ES_MSG_APPLICATION_EXIT if needed.
// TODO Tell Desktop the task is complete.
EsMessageMutexRelease(); EsMessageMutexRelease();
EsSyscall(ES_SYSCALL_WINDOW_CLOSE, task->taskHandle, 0, 0, 0);
EsHandleClose(task->taskHandle);
EsHeapFree(task); EsHeapFree(task);
} }
EsError EsUserTaskStart(EsUserTaskCallbackFunction callback, EsGeneric data) { EsError EsUserTaskStart(EsUserTaskCallbackFunction callback, EsGeneric data) {
EsMessageMutexCheck(); EsMessageMutexCheck();
UserTask *task = (UserTask *) EsHeapAllocate(sizeof(UserTask), true); UserTask *task = (UserTask *) EsHeapAllocate(sizeof(UserTask), true);
if (!task) return ES_ERROR_INSUFFICIENT_RESOURCES;
if (!task) {
return ES_ERROR_INSUFFICIENT_RESOURCES;
}
uint8_t m = DESKTOP_MSG_START_USER_TASK;
EsBuffer response = { .canGrow = true };
MessageDesktop(&m, 1, ES_INVALID_HANDLE, &response);
EsHandle handle;
EsBufferReadInto(&response, &handle, sizeof(handle));
EsHeapFree(response.out);
if (!handle) {
EsHeapFree(task);
return ES_ERROR_INSUFFICIENT_RESOURCES;
}
task->callback = callback; task->callback = callback;
task->data = data; task->data = data;
// TODO Tell Desktop about the task. (This'll also prevent it sending ES_MSG_APPLICATION_EXIT in single process mode.) task->taskHandle = handle;
api.openInstanceCount++;
EsThreadInformation information; EsThreadInformation information;
EsError error = EsThreadCreate(UserTaskThread, &information, task); EsError error = EsThreadCreate(UserTaskThread, &information, task);
if (error == ES_SUCCESS) EsHandleClose(information.handle);
else EsHeapFree(task); if (error == ES_SUCCESS) {
EsHandleClose(information.handle);
api.openInstanceCount++;
} else {
EsSyscall(ES_SYSCALL_WINDOW_CLOSE, task->taskHandle, 0, 0, 0);
EsHandleClose(task->taskHandle);
EsHeapFree(task);
}
return error; return error;
} }

View File

@ -137,7 +137,7 @@ struct BlankTabInstance : CommonDesktopInstance {
struct ApplicationInstance { struct ApplicationInstance {
// User interface. // User interface.
WindowTab *tab; // nullptr for notRespondingInstance. WindowTab *tab; // nullptr for notRespondingInstance and user tasks.
EsObjectID embeddedWindowID; EsObjectID embeddedWindowID;
EsHandle embeddedWindowHandle; EsHandle embeddedWindowHandle;
@ -145,8 +145,9 @@ struct ApplicationInstance {
InstalledApplication *application; InstalledApplication *application;
EsObjectID documentID, processID; EsObjectID documentID, processID;
EsHandle processHandle; EsHandle processHandle;
bool isUserTask;
// Tab information. // Metadata.
char title[128]; char title[128];
size_t titleBytes; size_t titleBytes;
uint32_t iconID; uint32_t iconID;
@ -182,6 +183,7 @@ struct {
TaskBar taskBar; TaskBar taskBar;
EsWindow *wallpaperWindow; EsWindow *wallpaperWindow;
EsButton *tasksButton;
bool shutdownWindowOpen; bool shutdownWindowOpen;
bool setupDesktopUIComplete; bool setupDesktopUIComplete;
@ -729,12 +731,12 @@ int TaskBarMessage(EsElement *element, EsMessage *message) {
return 0; return 0;
} }
int TaskBarTasksButtonMessage(EsElement *element, EsMessage *message) { int TaskBarTasksButtonMessage(EsElement *, EsMessage *message) {
if (message->type == ES_MSG_GET_WIDTH) { if (message->type == ES_MSG_GET_WIDTH) {
message->measure.width = GetConstantNumber("taskBarTasksButtonWidth"); message->measure.width = GetConstantNumber("taskBarTasksButtonWidth");
return ES_HANDLED; return ES_HANDLED;
} else if (message->type == ES_MSG_PAINT_ICON) { } else if (message->type == ES_MSG_PAINT_ICON) {
float progress = 0.33f; float progress = 0.0f; // TODO.
uint32_t color1 = GetConstantNumber("taskBarTasksButtonWheelColor1"); uint32_t color1 = GetConstantNumber("taskBarTasksButtonWheelColor1");
uint32_t color2 = GetConstantNumber("taskBarTasksButtonWheelColor2"); uint32_t color2 = GetConstantNumber("taskBarTasksButtonWheelColor2");
@ -1200,8 +1202,10 @@ void ApplicationInstanceCrashed(EsMessage *message) {
ApplicationInstance *instance = desktop.allApplicationInstances[i]; ApplicationInstance *instance = desktop.allApplicationInstances[i];
if (instance->processID == message->crash.pid) { if (instance->processID == message->crash.pid) {
ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, nullptr, instance); if (instance->tab) {
WindowTabActivate(instance->tab, true); ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, nullptr, instance);
WindowTabActivate(instance->tab, true);
}
} }
} }
@ -1884,8 +1888,8 @@ void DesktopSetup() {
desktop.taskBar.taskList.Initialise(panel, ES_CELL_FILL, ReorderListMessage, nullptr); desktop.taskBar.taskList.Initialise(panel, ES_CELL_FILL, ReorderListMessage, nullptr);
desktop.taskBar.taskList.cName = "task list"; desktop.taskBar.taskList.cName = "task list";
EsButton *tasksButton = EsButtonCreate(panel, ES_ELEMENT_HIDDEN, ES_STYLE_TASK_BAR_BUTTON, "Copying files" ELLIPSIS, -1); desktop.tasksButton = EsButtonCreate(panel, ES_ELEMENT_HIDDEN, ES_STYLE_TASK_BAR_BUTTON, "Copying files" ELLIPSIS, -1);
tasksButton->messageUser = TaskBarTasksButtonMessage; desktop.tasksButton->messageUser = TaskBarTasksButtonMessage;
EsButton *shutdownButton = EsButtonCreate(panel, ES_FLAGS_DEFAULT, ES_STYLE_TASK_BAR_EXTRA); EsButton *shutdownButton = EsButtonCreate(panel, ES_FLAGS_DEFAULT, ES_STYLE_TASK_BAR_EXTRA);
EsButtonSetIcon(shutdownButton, ES_ICON_SYSTEM_SHUTDOWN_SYMBOLIC); EsButtonSetIcon(shutdownButton, ES_ICON_SYSTEM_SHUTDOWN_SYMBOLIC);
@ -1953,7 +1957,7 @@ void DesktopSetup() {
desktop.setupDesktopUIComplete = true; desktop.setupDesktopUIComplete = true;
} }
void DesktopMessage2(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) { void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(message->desktop.windowID); ApplicationInstance *instance = ApplicationInstanceFindByWindowID(message->desktop.windowID);
if (buffer[0] == DESKTOP_MSG_START_APPLICATION) { if (buffer[0] == DESKTOP_MSG_START_APPLICATION) {
@ -2045,6 +2049,57 @@ void DesktopMessage2(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
if (application && (application->permissions & APPLICATION_PERMISSION_ALL_FILES)) { if (application && (application->permissions & APPLICATION_PERMISSION_ALL_FILES)) {
InstanceAnnouncePathMoved(application, buffer, message->desktop.bytes); InstanceAnnouncePathMoved(application, buffer, message->desktop.bytes);
} }
} else if (buffer[0] == DESKTOP_MSG_START_USER_TASK && pipe) {
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
if (!application) {
return;
}
// HACK User tasks use an embedded window object for IPC.
// This allows us to basically treat them like other instances.
EsHandle processHandle = EsProcessOpen(message->desktop.processID);
EsHandle windowHandle = EsSyscall(ES_SYSCALL_WINDOW_CREATE, ES_WINDOW_NORMAL, 0, 0, 0);
ApplicationInstance *instance = (ApplicationInstance *) EsHeapAllocate(sizeof(ApplicationInstance), true);
bool added = false;
if (processHandle && windowHandle && instance) {
added = desktop.allApplicationInstances.Add(instance);
}
if (!processHandle || !windowHandle || !instance || !added) {
if (processHandle) EsHandleClose(processHandle);
if (windowHandle) EsHandleClose(windowHandle);
if (instance) EsHeapFree(instance);
EsHandle invalid = ES_INVALID_HANDLE;
EsBufferWrite(pipe, &invalid, sizeof(invalid));
return;
}
instance->title[0] = ' ';
instance->titleBytes = 1;
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->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));
if (EsElementIsHidden(desktop.tasksButton)) {
EsPanelStartMovementAnimation((EsPanel *) EsElementGetLayoutParent(desktop.tasksButton), 1.5f /* duration scale */);
EsElementStartTransition(desktop.tasksButton, ES_TRANSITION_FADE_IN, ES_ELEMENT_TRANSITION_ENTRANCE, 1.5f);
EsElementSetHidden(desktop.tasksButton, false);
}
} else if (!instance) { } else if (!instance) {
// ------------------------------------------------- // -------------------------------------------------
// | Messages below here require a valid instance. | // | Messages below here require a valid instance. |
@ -2059,10 +2114,12 @@ void DesktopMessage2(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
} }
} }
instance->tab->Repaint(true); if (instance->tab) {
instance->tab->Repaint(true);
if (instance->tab == instance->tab->container->active) { if (instance->tab == instance->tab->container->active) {
instance->tab->container->taskBarButton->Repaint(true); instance->tab->container->taskBarButton->Repaint(true);
}
} }
} else if (buffer[0] == DESKTOP_MSG_REQUEST_SAVE) { } else if (buffer[0] == DESKTOP_MSG_REQUEST_SAVE) {
ApplicationInstanceRequestSave(instance, (const char *) buffer + 1, message->desktop.bytes - 1); ApplicationInstanceRequestSave(instance, (const char *) buffer + 1, message->desktop.bytes - 1);
@ -2201,7 +2258,7 @@ void DesktopMessage(EsMessage *message) {
if (buffer) { if (buffer) {
EsConstantBufferRead(message->desktop.buffer, buffer); EsConstantBufferRead(message->desktop.buffer, buffer);
EsBuffer pipe = { .canGrow = true }; EsBuffer pipe = { .canGrow = true };
DesktopMessage2(message, buffer, &pipe); DesktopSyscall(message, buffer, &pipe);
if (message->desktop.pipe) EsPipeWrite(message->desktop.pipe, pipe.out, pipe.position); if (message->desktop.pipe) EsPipeWrite(message->desktop.pipe, pipe.out, pipe.position);
EsHeapFree(pipe.out); EsHeapFree(pipe.out);
EsHeapFree(buffer); EsHeapFree(buffer);

View File

@ -321,6 +321,7 @@ struct ScrollPane {
struct PanelMovementItem { struct PanelMovementItem {
EsElement *element; EsElement *element;
EsRectangle oldBounds; EsRectangle oldBounds;
bool wasHidden;
}; };
struct EsPanel : EsElement { struct EsPanel : EsElement {
@ -1903,15 +1904,19 @@ void PanelMoveChild(EsElement *element, int width, int height, int offsetX, int
continue; continue;
} }
int oldWidth = Width(item->oldBounds); if (item->wasHidden) {
int oldHeight = Height(item->oldBounds); break;
int oldOffsetX = item->oldBounds.l; } else {
int oldOffsetY = item->oldBounds.t; int oldWidth = Width(item->oldBounds);
int oldHeight = Height(item->oldBounds);
int oldOffsetX = item->oldBounds.l;
int oldOffsetY = item->oldBounds.t;
element->InternalMove(LinearInterpolate(oldWidth, width, progress), element->InternalMove(LinearInterpolate(oldWidth, width, progress),
LinearInterpolate(oldHeight, height, progress), LinearInterpolate(oldHeight, height, progress),
LinearInterpolate(oldOffsetX, offsetX, progress), LinearInterpolate(oldOffsetX, offsetX, progress),
LinearInterpolate(oldOffsetY, offsetY, progress)); LinearInterpolate(oldOffsetY, offsetY, progress));
}
return; return;
} }
@ -3471,6 +3476,7 @@ void EsPanelStartMovementAnimation(EsPanel *panel, float timeMultiplier) {
item.element = element; item.element = element;
item.oldBounds = ES_RECT_4(element->offsetX, element->offsetX + element->width, item.oldBounds = ES_RECT_4(element->offsetX, element->offsetX + element->width,
element->offsetY, element->offsetY + element->height); element->offsetY, element->offsetY + element->height);
item.wasHidden = element->flags & ES_ELEMENT_HIDDEN;
panel->movementItems.Add(item); panel->movementItems.Add(item);
} }
@ -5643,6 +5649,11 @@ void EsElementSetHidden(EsElement *element, bool hidden) {
UIMaybeRemoveFocusedElement(element->window); UIMaybeRemoveFocusedElement(element->window);
} }
bool EsElementIsHidden(EsElement *element) {
EsMessageMutexCheck();
return element->flags & ES_ELEMENT_HIDDEN;
}
void EsElementSetDisabled(EsElement *element, bool disabled) { void EsElementSetDisabled(EsElement *element, bool disabled) {
EsMessageMutexCheck(); EsMessageMutexCheck();

View File

@ -2285,6 +2285,7 @@ function void EsElementFocus(EsElement *element, uint32_t flags = ES_FLAGS_DEFAU
function bool EsElementIsFocused(EsElement *element); function bool EsElementIsFocused(EsElement *element);
function void EsElementSetDisabled(EsElement *element, bool disabled = true); function void EsElementSetDisabled(EsElement *element, bool disabled = true);
function void EsElementSetHidden(EsElement *element, bool hidden = true); function void EsElementSetHidden(EsElement *element, bool hidden = true);
function bool EsElementIsHidden(EsElement *element);
function void EsElementSetCallback(EsElement *element, EsUICallbackFunction callback); function void EsElementSetCallback(EsElement *element, EsUICallbackFunction callback);
function void EsElementGetSize(EsElement *element, int *width, int *height); function void EsElementGetSize(EsElement *element, int *width, int *height);
function void EsElementRepaint(EsElement *element, const EsRectangle *region = ES_NULL); // Mark an element to be repainted. If region is null, then the whole element is repainted. function void EsElementRepaint(EsElement *element, const EsRectangle *region = ES_NULL); // Mark an element to be repainted. If region is null, then the whole element is repainted.

View File

@ -717,7 +717,7 @@ size_t EsGameControllerStatePoll(EsGameControllerState *buffer) {
return EsSyscall(ES_SYSCALL_GAME_CONTROLLER_STATE_POLL, (uintptr_t) buffer, 0, 0, 0); return EsSyscall(ES_SYSCALL_GAME_CONTROLLER_STATE_POLL, (uintptr_t) buffer, 0, 0, 0);
} }
void DesktopMessage2(EsMessage *message, uint8_t *buffer, EsBuffer *pipe); void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe);
void MessageDesktop(void *message, size_t messageBytes, EsHandle embeddedWindow = ES_INVALID_HANDLE, EsBuffer *responseBuffer = nullptr) { void MessageDesktop(void *message, size_t messageBytes, EsHandle embeddedWindow = ES_INVALID_HANDLE, EsBuffer *responseBuffer = nullptr) {
if (api.startupInformation->isDesktop) { if (api.startupInformation->isDesktop) {
@ -726,7 +726,7 @@ void MessageDesktop(void *message, size_t messageBytes, EsHandle embeddedWindow
m.desktop.windowID = embeddedWindow ? EsSyscall(ES_SYSCALL_WINDOW_GET_ID, embeddedWindow, 0, 0, 0) : 0; m.desktop.windowID = embeddedWindow ? EsSyscall(ES_SYSCALL_WINDOW_GET_ID, embeddedWindow, 0, 0, 0) : 0;
m.desktop.processID = EsProcessGetID(ES_CURRENT_PROCESS); m.desktop.processID = EsProcessGetID(ES_CURRENT_PROCESS);
m.desktop.bytes = messageBytes; m.desktop.bytes = messageBytes;
DesktopMessage2(&m, (uint8_t *) message, responseBuffer); DesktopSyscall(&m, (uint8_t *) message, responseBuffer);
} else { } else {
EsHandle pipeRead = ES_INVALID_HANDLE, pipeWrite = ES_INVALID_HANDLE; EsHandle pipeRead = ES_INVALID_HANDLE, pipeWrite = ES_INVALID_HANDLE;

View File

@ -433,3 +433,4 @@ EsFileCopy=431
EsListViewSelectNone=432 EsListViewSelectNone=432
EsElementIsFocused=433 EsElementIsFocused=433
EsUserTaskStart=434 EsUserTaskStart=434
EsElementIsHidden=435