mirror of https://gitlab.com/nakst/essence
show tasks button when user task started
This commit is contained in:
parent
ce01df7c59
commit
c80e762d86
|
@ -61,6 +61,7 @@ struct EnumString { const char *cName; int value; };
|
|||
#define DESKTOP_MSG_SYSTEM_CONFIGURATION_GET (13)
|
||||
#define DESKTOP_MSG_FILE_TYPES_GET (14)
|
||||
#define DESKTOP_MSG_UNHANDLED_KEY_EVENT (15)
|
||||
#define DESKTOP_MSG_START_USER_TASK (16)
|
||||
|
||||
struct EsFileStore {
|
||||
#define FILE_STORE_HANDLE (1)
|
||||
|
@ -1550,6 +1551,7 @@ const void *EsEmbeddedFileGet(const char *_name, ptrdiff_t nameBytes, size_t *by
|
|||
struct UserTask {
|
||||
EsUserTaskCallbackFunction callback;
|
||||
EsGeneric data;
|
||||
EsHandle taskHandle;
|
||||
};
|
||||
|
||||
void UserTaskThread(EsGeneric _task) {
|
||||
|
@ -1558,23 +1560,48 @@ void UserTaskThread(EsGeneric _task) {
|
|||
EsMessageMutexAcquire();
|
||||
api.openInstanceCount--;
|
||||
// TODO Send ES_MSG_APPLICATION_EXIT if needed.
|
||||
// TODO Tell Desktop the task is complete.
|
||||
EsMessageMutexRelease();
|
||||
EsSyscall(ES_SYSCALL_WINDOW_CLOSE, task->taskHandle, 0, 0, 0);
|
||||
EsHandleClose(task->taskHandle);
|
||||
EsHeapFree(task);
|
||||
}
|
||||
|
||||
EsError EsUserTaskStart(EsUserTaskCallbackFunction callback, EsGeneric data) {
|
||||
EsMessageMutexCheck();
|
||||
|
||||
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->data = data;
|
||||
// TODO Tell Desktop about the task. (This'll also prevent it sending ES_MSG_APPLICATION_EXIT in single process mode.)
|
||||
api.openInstanceCount++;
|
||||
task->taskHandle = handle;
|
||||
EsThreadInformation information;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ struct BlankTabInstance : CommonDesktopInstance {
|
|||
|
||||
struct ApplicationInstance {
|
||||
// User interface.
|
||||
WindowTab *tab; // nullptr for notRespondingInstance.
|
||||
WindowTab *tab; // nullptr for notRespondingInstance and user tasks.
|
||||
EsObjectID embeddedWindowID;
|
||||
EsHandle embeddedWindowHandle;
|
||||
|
||||
|
@ -145,8 +145,9 @@ struct ApplicationInstance {
|
|||
InstalledApplication *application;
|
||||
EsObjectID documentID, processID;
|
||||
EsHandle processHandle;
|
||||
bool isUserTask;
|
||||
|
||||
// Tab information.
|
||||
// Metadata.
|
||||
char title[128];
|
||||
size_t titleBytes;
|
||||
uint32_t iconID;
|
||||
|
@ -182,6 +183,7 @@ struct {
|
|||
|
||||
TaskBar taskBar;
|
||||
EsWindow *wallpaperWindow;
|
||||
EsButton *tasksButton;
|
||||
|
||||
bool shutdownWindowOpen;
|
||||
bool setupDesktopUIComplete;
|
||||
|
@ -729,12 +731,12 @@ int TaskBarMessage(EsElement *element, EsMessage *message) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int TaskBarTasksButtonMessage(EsElement *element, EsMessage *message) {
|
||||
int TaskBarTasksButtonMessage(EsElement *, EsMessage *message) {
|
||||
if (message->type == ES_MSG_GET_WIDTH) {
|
||||
message->measure.width = GetConstantNumber("taskBarTasksButtonWidth");
|
||||
return ES_HANDLED;
|
||||
} else if (message->type == ES_MSG_PAINT_ICON) {
|
||||
float progress = 0.33f;
|
||||
float progress = 0.0f; // TODO.
|
||||
|
||||
uint32_t color1 = GetConstantNumber("taskBarTasksButtonWheelColor1");
|
||||
uint32_t color2 = GetConstantNumber("taskBarTasksButtonWheelColor2");
|
||||
|
@ -1200,8 +1202,10 @@ void ApplicationInstanceCrashed(EsMessage *message) {
|
|||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->processID == message->crash.pid) {
|
||||
ApplicationInstanceStart(APPLICATION_ID_DESKTOP_CRASHED, nullptr, instance);
|
||||
WindowTabActivate(instance->tab, true);
|
||||
if (instance->tab) {
|
||||
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.cName = "task list";
|
||||
|
||||
EsButton *tasksButton = EsButtonCreate(panel, ES_ELEMENT_HIDDEN, ES_STYLE_TASK_BAR_BUTTON, "Copying files" ELLIPSIS, -1);
|
||||
tasksButton->messageUser = TaskBarTasksButtonMessage;
|
||||
desktop.tasksButton = EsButtonCreate(panel, ES_ELEMENT_HIDDEN, ES_STYLE_TASK_BAR_BUTTON, "Copying files" ELLIPSIS, -1);
|
||||
desktop.tasksButton->messageUser = TaskBarTasksButtonMessage;
|
||||
|
||||
EsButton *shutdownButton = EsButtonCreate(panel, ES_FLAGS_DEFAULT, ES_STYLE_TASK_BAR_EXTRA);
|
||||
EsButtonSetIcon(shutdownButton, ES_ICON_SYSTEM_SHUTDOWN_SYMBOLIC);
|
||||
|
@ -1953,7 +1957,7 @@ void DesktopSetup() {
|
|||
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);
|
||||
|
||||
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)) {
|
||||
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) {
|
||||
// -------------------------------------------------
|
||||
// | 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) {
|
||||
instance->tab->container->taskBarButton->Repaint(true);
|
||||
if (instance->tab == instance->tab->container->active) {
|
||||
instance->tab->container->taskBarButton->Repaint(true);
|
||||
}
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_REQUEST_SAVE) {
|
||||
ApplicationInstanceRequestSave(instance, (const char *) buffer + 1, message->desktop.bytes - 1);
|
||||
|
@ -2201,7 +2258,7 @@ void DesktopMessage(EsMessage *message) {
|
|||
if (buffer) {
|
||||
EsConstantBufferRead(message->desktop.buffer, buffer);
|
||||
EsBuffer pipe = { .canGrow = true };
|
||||
DesktopMessage2(message, buffer, &pipe);
|
||||
DesktopSyscall(message, buffer, &pipe);
|
||||
if (message->desktop.pipe) EsPipeWrite(message->desktop.pipe, pipe.out, pipe.position);
|
||||
EsHeapFree(pipe.out);
|
||||
EsHeapFree(buffer);
|
||||
|
|
|
@ -321,6 +321,7 @@ struct ScrollPane {
|
|||
struct PanelMovementItem {
|
||||
EsElement *element;
|
||||
EsRectangle oldBounds;
|
||||
bool wasHidden;
|
||||
};
|
||||
|
||||
struct EsPanel : EsElement {
|
||||
|
@ -1903,15 +1904,19 @@ void PanelMoveChild(EsElement *element, int width, int height, int offsetX, int
|
|||
continue;
|
||||
}
|
||||
|
||||
int oldWidth = Width(item->oldBounds);
|
||||
int oldHeight = Height(item->oldBounds);
|
||||
int oldOffsetX = item->oldBounds.l;
|
||||
int oldOffsetY = item->oldBounds.t;
|
||||
if (item->wasHidden) {
|
||||
break;
|
||||
} else {
|
||||
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),
|
||||
LinearInterpolate(oldHeight, height, progress),
|
||||
LinearInterpolate(oldOffsetX, offsetX, progress),
|
||||
LinearInterpolate(oldOffsetY, offsetY, progress));
|
||||
element->InternalMove(LinearInterpolate(oldWidth, width, progress),
|
||||
LinearInterpolate(oldHeight, height, progress),
|
||||
LinearInterpolate(oldOffsetX, offsetX, progress),
|
||||
LinearInterpolate(oldOffsetY, offsetY, progress));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -3471,6 +3476,7 @@ void EsPanelStartMovementAnimation(EsPanel *panel, float timeMultiplier) {
|
|||
item.element = element;
|
||||
item.oldBounds = ES_RECT_4(element->offsetX, element->offsetX + element->width,
|
||||
element->offsetY, element->offsetY + element->height);
|
||||
item.wasHidden = element->flags & ES_ELEMENT_HIDDEN;
|
||||
panel->movementItems.Add(item);
|
||||
}
|
||||
|
||||
|
@ -5643,6 +5649,11 @@ void EsElementSetHidden(EsElement *element, bool hidden) {
|
|||
UIMaybeRemoveFocusedElement(element->window);
|
||||
}
|
||||
|
||||
bool EsElementIsHidden(EsElement *element) {
|
||||
EsMessageMutexCheck();
|
||||
return element->flags & ES_ELEMENT_HIDDEN;
|
||||
}
|
||||
|
||||
void EsElementSetDisabled(EsElement *element, bool disabled) {
|
||||
EsMessageMutexCheck();
|
||||
|
||||
|
|
|
@ -2285,6 +2285,7 @@ function void EsElementFocus(EsElement *element, uint32_t flags = ES_FLAGS_DEFAU
|
|||
function bool EsElementIsFocused(EsElement *element);
|
||||
function void EsElementSetDisabled(EsElement *element, bool disabled = true);
|
||||
function void EsElementSetHidden(EsElement *element, bool hidden = true);
|
||||
function bool EsElementIsHidden(EsElement *element);
|
||||
function void EsElementSetCallback(EsElement *element, EsUICallbackFunction callback);
|
||||
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.
|
||||
|
|
|
@ -717,7 +717,7 @@ size_t EsGameControllerStatePoll(EsGameControllerState *buffer) {
|
|||
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) {
|
||||
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.processID = EsProcessGetID(ES_CURRENT_PROCESS);
|
||||
m.desktop.bytes = messageBytes;
|
||||
DesktopMessage2(&m, (uint8_t *) message, responseBuffer);
|
||||
DesktopSyscall(&m, (uint8_t *) message, responseBuffer);
|
||||
} else {
|
||||
EsHandle pipeRead = ES_INVALID_HANDLE, pipeWrite = ES_INVALID_HANDLE;
|
||||
|
||||
|
|
|
@ -433,3 +433,4 @@ EsFileCopy=431
|
|||
EsListViewSelectNone=432
|
||||
EsElementIsFocused=433
|
||||
EsUserTaskStart=434
|
||||
EsElementIsHidden=435
|
||||
|
|
Loading…
Reference in New Issue