diff --git a/apps/file_manager/ui.cpp b/apps/file_manager/ui.cpp index dd7ee75..00be54f 100644 --- a/apps/file_manager/ui.cpp +++ b/apps/file_manager/ui.cpp @@ -1090,7 +1090,7 @@ void InstanceCreateUI(Instance *instance) { // Toolbar: EsElement *toolbar = EsWindowGetToolbar(instance->window); - EsPanel *buttonGroup = EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL); + EsPanel *buttonGroup = EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL | ES_ELEMENT_AUTO_GROUP); ADD_BUTTON_TO_TOOLBAR(commandGoBackwards, nullptr, ES_ICON_GO_PREVIOUS_SYMBOLIC, 'B', button); EsSpacerCreate(buttonGroup, ES_CELL_V_FILL, ES_STYLE_TOOLBAR_BUTTON_GROUP_SEPARATOR); ADD_BUTTON_TO_TOOLBAR(commandGoForwards, nullptr, ES_ICON_GO_NEXT_SYMBOLIC, 'F', button); @@ -1109,7 +1109,7 @@ void InstanceCreateUI(Instance *instance) { EsPanel *statusBar = EsPanelCreate(rootPanel, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_STATUS_BAR); instance->status = EsTextDisplayCreate(statusBar, ES_CELL_H_FILL); - buttonGroup = EsPanelCreate(statusBar, ES_PANEL_HORIZONTAL); + buttonGroup = EsPanelCreate(statusBar, ES_PANEL_HORIZONTAL | ES_ELEMENT_AUTO_GROUP); ADD_BUTTON_TO_STATUS_BAR(commandViewDetails, nullptr, ES_ICON_VIEW_LIST_SYMBOLIC, 0, button); EsSpacerCreate(buttonGroup, ES_CELL_V_FILL, ES_STYLE_TOOLBAR_BUTTON_GROUP_SEPARATOR); ADD_BUTTON_TO_STATUS_BAR(commandViewTiles, nullptr, ES_ICON_VIEW_LIST_COMPACT_SYMBOLIC, 0, button); diff --git a/apps/font_book.cpp b/apps/font_book.cpp index 1cfcc99..c0e011f 100644 --- a/apps/font_book.cpp +++ b/apps/font_book.cpp @@ -360,7 +360,7 @@ void _start() { EsSpacerCreate(toolbar, ES_CELL_H_FILL); - EsButton *button = EsButtonCreate(EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL), ES_BUTTON_DROPDOWN, {}, INTERFACE_STRING(FontBookVariants)); + EsButton *button = EsButtonCreate(toolbar, ES_BUTTON_DROPDOWN, {}, INTERFACE_STRING(FontBookVariants)); button->accessKey = 'V'; EsButtonOnCommand(button, VariantsPopupCreate); diff --git a/apps/image_editor.cpp b/apps/image_editor.cpp index 7db4b91..ac7c4f4 100644 --- a/apps/image_editor.cpp +++ b/apps/image_editor.cpp @@ -721,11 +721,11 @@ void InstanceCreate(EsMessage *message) { EsButton *button; EsFileMenuAddToToolbar(toolbar); - button = EsButtonCreate(EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL), ES_BUTTON_DROPDOWN, ES_STYLE_PUSH_BUTTON_TOOLBAR, INTERFACE_STRING(ImageEditorImage)); + button = EsButtonCreate(toolbar, ES_BUTTON_DROPDOWN, ES_STYLE_PUSH_BUTTON_TOOLBAR, INTERFACE_STRING(ImageEditorImage)); EsButtonSetIcon(button, ES_ICON_IMAGE_X_GENERIC); button->accessKey = 'I'; EsButtonOnCommand(button, MenuImage); - EsPanel *buttonGroup = EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL); + EsPanel *buttonGroup = EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL | ES_ELEMENT_AUTO_GROUP); button = EsButtonCreate(buttonGroup); EsCommandAddButton(EsCommandByID(instance, ES_COMMAND_UNDO), button); EsButtonSetIcon(button, ES_ICON_EDIT_UNDO_SYMBOLIC); @@ -738,13 +738,13 @@ void InstanceCreate(EsMessage *message) { EsSpacerCreate(toolbar, ES_CELL_FILL); - button = instance->toolDropdown = EsButtonCreate(EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL), ES_BUTTON_DROPDOWN, + button = instance->toolDropdown = EsButtonCreate(toolbar, ES_BUTTON_DROPDOWN, ES_STYLE_PUSH_BUTTON_TOOLBAR_BIG, INTERFACE_STRING(ImageEditorPickTool)); EsButtonSetIcon(button, ES_ICON_DRAW_FREEHAND); EsButtonOnCommand(button, MenuTools); button->accessKey = 'T'; - instance->toolPanel = EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL); + instance->toolPanel = EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL | ES_ELEMENT_AUTO_GROUP); button = EsButtonCreate(instance->toolPanel, ES_FLAGS_DEFAULT, ES_STYLE_PUSH_BUTTON_TOOLBAR_BIG, INTERFACE_STRING(ImageEditorToolBrush)); EsCommandAddButton(&instance->commandBrush, button); EsButtonSetIcon(button, ES_ICON_DRAW_FREEHAND); diff --git a/apps/system_monitor.cpp b/apps/system_monitor.cpp index 2698322..9322861 100644 --- a/apps/system_monitor.cpp +++ b/apps/system_monitor.cpp @@ -401,12 +401,15 @@ void ProcessApplicationMessage(EsMessage *message) { ES_CELL_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL | ES_PANEL_V_SCROLL_AUTO, &stylePanelMemoryStatistics); EsPanelSetBands(instance->panelMemoryStatistics, 2 /* columns */); - EsElement *buttonGroup = EsPanelCreate(EsWindowGetToolbar(window), ES_PANEL_HORIZONTAL); + EsElement *toolbar = EsWindowGetToolbar(window); + EsSpacerCreate(toolbar, ES_CELL_H_FILL); + EsElement *buttonGroup = EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL | ES_ELEMENT_AUTO_GROUP); AddTab(buttonGroup, DISPLAY_PROCESSES, "Processes", true); EsSpacerCreate(buttonGroup, ES_CELL_V_FILL, ES_STYLE_TOOLBAR_BUTTON_GROUP_SEPARATOR); AddTab(buttonGroup, DISPLAY_GENERAL_LOG, "System log"); EsSpacerCreate(buttonGroup, ES_CELL_V_FILL, ES_STYLE_TOOLBAR_BUTTON_GROUP_SEPARATOR); AddTab(buttonGroup, DISPLAY_MEMORY, "Memory"); + EsSpacerCreate(toolbar, ES_CELL_H_FILL); } else if (message->type == ES_MSG_INSTANCE_DESTROY) { processes.Free(); } diff --git a/apps/text_editor.cpp b/apps/text_editor.cpp index d04bb16..78f5273 100644 --- a/apps/text_editor.cpp +++ b/apps/text_editor.cpp @@ -287,7 +287,7 @@ void ProcessApplicationMessage(EsMessage *message) { EsFileMenuAddToToolbar(toolbarMain); - button = EsButtonCreate(EsPanelCreate(toolbarMain, ES_PANEL_HORIZONTAL), ES_FLAGS_DEFAULT, {}, INTERFACE_STRING(CommonSearchOpen)); + button = EsButtonCreate(toolbarMain, ES_FLAGS_DEFAULT, {}, INTERFACE_STRING(CommonSearchOpen)); button->accessKey = 'S'; EsButtonSetIcon(button, ES_ICON_EDIT_FIND_SYMBOLIC); @@ -296,7 +296,9 @@ void ProcessApplicationMessage(EsMessage *message) { EsElementFocus(instance->textboxSearch); }); - button = EsButtonCreate(EsPanelCreate(toolbarMain, ES_PANEL_HORIZONTAL), ES_BUTTON_DROPDOWN, {}, INTERFACE_STRING(CommonFormatPopup)); + EsSpacerCreate(toolbarMain, ES_CELL_H_FILL); + + button = EsButtonCreate(toolbarMain, ES_BUTTON_DROPDOWN, {}, INTERFACE_STRING(CommonFormatPopup)); button->accessKey = 'M'; EsButtonSetIcon(button, ES_ICON_FORMAT_TEXT_LARGER_SYMBOLIC); EsCommandAddButton(&instance->commandFormat, button); @@ -308,7 +310,7 @@ void ProcessApplicationMessage(EsMessage *message) { EsElement *toolbarSearch = instance->toolbarSearch = EsWindowGetToolbar(window, true); - button = EsButtonCreate(EsPanelCreate(toolbarSearch, ES_PANEL_HORIZONTAL), ES_FLAGS_DEFAULT, 0); + button = EsButtonCreate(toolbarSearch, ES_FLAGS_DEFAULT, 0); button->cName = "go back", button->accessKey = 'X'; EsButtonSetIcon(button, ES_ICON_GO_FIRST_SYMBOLIC); @@ -344,7 +346,7 @@ void ProcessApplicationMessage(EsMessage *message) { EsSpacerCreate(toolbarSearch, ES_FLAGS_DEFAULT, 0, 7, 0); instance->displaySearch = EsTextDisplayCreate(toolbarSearch, ES_CELL_H_FILL, {}, ""); - EsPanel *buttonGroup = EsPanelCreate(toolbarSearch, ES_PANEL_HORIZONTAL); + EsPanel *buttonGroup = EsPanelCreate(toolbarSearch, ES_PANEL_HORIZONTAL | ES_ELEMENT_AUTO_GROUP); button = EsButtonCreate(buttonGroup, ES_FLAGS_DEFAULT, {}, INTERFACE_STRING(CommonSearchNext)); button->accessKey = 'N'; EsCommandAddButton(&instance->commandFindNext, button); diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index 943592f..6d0e151 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -631,6 +631,11 @@ WindowTab *WindowTabMoveToNewContainer(WindowTab *tab, ContainerWindow *containe tab->applicationInstance = nullptr; tab->notRespondingInstance = nullptr; + // Copy across metadata. + EsMemoryCopy(newTab->title, tab->title, tab->titleBytes); + newTab->titleBytes = tab->titleBytes; + newTab->iconID = tab->iconID; + // Destroy the old tab, and activate the new one. WindowTabDestroy(tab); // Deplaces the embedded window from the old container. WindowTabActivate(newTab); @@ -1400,7 +1405,7 @@ void ShutdownModalCreate() { EsPanel *stack = EsPanelCreate(window, ES_CELL_FILL | ES_PANEL_Z_STACK); stack->cName = "window stack"; EsPanelCreate(stack, ES_CELL_FILL, ES_STYLE_PANEL_SHUTDOWN_OVERLAY)->cName = "modal overlay"; - EsPanel *dialog = EsPanelCreate(stack, ES_PANEL_VERTICAL | ES_CELL_CENTER, ES_STYLE_DIALOG_SHADOW); + EsPanel *dialog = EsPanelCreate(stack, ES_PANEL_VERTICAL | ES_CELL_CENTER | ES_ELEMENT_AUTO_GROUP, ES_STYLE_DIALOG_SHADOW); dialog->cName = "dialog"; EsPanel *heading = EsPanelCreate(dialog, ES_PANEL_HORIZONTAL | ES_CELL_H_FILL, ES_STYLE_DIALOG_HEADING); EsIconDisplayCreate(heading, ES_FLAGS_DEFAULT, {}, ES_ICON_SYSTEM_SHUTDOWN); diff --git a/desktop/gui.cpp b/desktop/gui.cpp index 310a1b8..3f84f24 100644 --- a/desktop/gui.cpp +++ b/desktop/gui.cpp @@ -1461,7 +1461,7 @@ void EsElement::InternalPaint(EsPainter *painter, int paintFlags) { int childType = 0; - if (parent && parent->GetChildCount()) { + if (parent && parent->GetChildCount() && (parent->flags & ES_ELEMENT_AUTO_GROUP)) { if (parent->GetChildCount() == 1 && parent->GetChild(0) == this) { childType = THEME_CHILD_TYPE_ONLY; } else if (parent->GetChild(0) == this) { @@ -3670,7 +3670,7 @@ EsDialog *EsDialogShow(EsWindow *window, const char *title, ptrdiff_t titleBytes EsElement *wrapper = EsPanelCreate(mainStack, ES_PANEL_VERTICAL | ES_CELL_FILL, ES_STYLE_DIALOG_WRAPPER); wrapper->cName = "dialog wrapper"; - dialog->mainPanel = EsPanelCreate(wrapper, ES_PANEL_VERTICAL | ES_CELL_SHRINK, ES_STYLE_DIALOG_SHADOW); + dialog->mainPanel = EsPanelCreate(wrapper, ES_PANEL_VERTICAL | ES_CELL_SHRINK | ES_ELEMENT_AUTO_GROUP, ES_STYLE_DIALOG_SHADOW); dialog->mainPanel->cName = "dialog"; EsElementStartTransition(dialog->mainPanel, ES_TRANSITION_ZOOM_OUT_LIGHT, ES_FLAGS_DEFAULT, 1.0f); window->dialogs.Add(dialog); @@ -4057,7 +4057,7 @@ EsButton *EsButtonCreate(EsElement *parent, uint64_t flags, const EsStyle *style if (style == ES_STYLE_PUSH_BUTTON_NORMAL || style == ES_STYLE_PUSH_BUTTON_DANGEROUS) { flags |= ES_BUTTON_PUSH; - } else if (style == ES_STYLE_PUSH_BUTTON_TOOLBAR || style == ES_STYLE_PUSH_BUTTON_TOOLBAR_MEDIUM + } else if (style == ES_STYLE_PUSH_BUTTON_TOOLBAR || style == ES_STYLE_PUSH_BUTTON_TOOLBAR_BIG || style == ES_STYLE_PUSH_BUTTON_STATUS_BAR) { flags |= ES_BUTTON_COMPACT | ES_BUTTON_NOT_FOCUSABLE; } else if (style == ES_STYLE_CHECKBOX_NORMAL || style == ES_STYLE_CHECKBOX_RADIOBOX) { @@ -5692,7 +5692,7 @@ void EsFileMenuCreate(EsInstance *_instance, EsElement *element, uint64_t menuFl instance->startupInformation->filePath, instance->startupInformation->filePathBytes); } - EsButton *renameButton = EsButtonCreate(EsPanelCreate(panel3, ES_PANEL_HORIZONTAL), ES_BUTTON_TOOLBAR); + EsButton *renameButton = EsButtonCreate(panel3, ES_BUTTON_TOOLBAR); if (!renameButton) goto show; EsButtonSetIcon(renameButton, ES_ICON_DOCUMENT_EDIT_SYMBOLIC); EsButtonOnCommand(renameButton, FileMenuRename); diff --git a/desktop/os.header b/desktop/os.header index aec967f..493e764 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -451,6 +451,7 @@ define ES_ELEMENT_LAYOUT_HINT_REVERSE ((_EsLongConstant) (1) << 44) // Hint for define ES_ELEMENT_STICKY_ACCESS_KEY ((_EsLongConstant) (1) << 45) // Don't exit access key mode after using the access key. define ES_ELEMENT_NON_CLIENT ((_EsLongConstant) (1) << 46) define ES_ELEMENT_FREE_USER_DATA ((_EsLongConstant) (1) << 47) // Call EsHeapFree on userData when destroying the element. +define ES_ELEMENT_AUTO_GROUP ((_EsLongConstant) (1) << 48) // Enables autoCorners and autoBorders. // For children of splitters: define ES_CELL_COLLAPSABLE ((_EsLongConstant) (1) << 51) @@ -857,6 +858,9 @@ private enum EsSyscallType { ES_SYSCALL_PIPE_CREATE ES_SYSCALL_PIPE_WRITE ES_SYSCALL_PIPE_READ + ES_SYSCALL_MAILSLOT_CREATE + ES_SYSCALL_MAILSLOT_SEND + ES_SYSCALL_MAILSLOT_RESPOND // Misc. diff --git a/desktop/settings.cpp b/desktop/settings.cpp index f85ebed..aa4328e 100644 --- a/desktop/settings.cpp +++ b/desktop/settings.cpp @@ -116,7 +116,7 @@ const EsStyle styleSettingsOverlayPanel = { }; const EsStyle styleSettingsButton = { - .inherit = ES_STYLE_PUSH_BUTTON_NORMAL, + .inherit = ES_STYLE_PUSH_BUTTON_TOOLBAR, .metrics = { .mask = ES_THEME_METRICS_PREFERRED_WIDTH | ES_THEME_METRICS_PREFERRED_HEIGHT | ES_THEME_METRICS_LAYOUT_VERTICAL @@ -870,8 +870,7 @@ void InstanceSettingsCreate(EsMessage *message) { { EsElement *toolbar = EsWindowGetToolbar(instance->window); - EsButton *backButton = EsButtonCreate(EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL), ES_BUTTON_TOOLBAR | ES_ELEMENT_STICKY_ACCESS_KEY, - 0, INTERFACE_STRING(DesktopSettingsBackButton)); + EsButton *backButton = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_STICKY_ACCESS_KEY, 0, INTERFACE_STRING(DesktopSettingsBackButton)); instance->backButton = backButton; backButton->accessKey = 'A'; EsButtonSetIcon(backButton, ES_ICON_GO_HOME_SYMBOLIC); @@ -880,8 +879,7 @@ void InstanceSettingsCreate(EsMessage *message) { EsSpacerCreate(toolbar, ES_CELL_FILL); - EsButton *undoButton = EsButtonCreate(EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL), ES_BUTTON_TOOLBAR | ES_ELEMENT_STICKY_ACCESS_KEY, - 0, INTERFACE_STRING(DesktopSettingsUndoButton)); + EsButton *undoButton = EsButtonCreate(toolbar, ES_BUTTON_TOOLBAR | ES_ELEMENT_STICKY_ACCESS_KEY, 0, INTERFACE_STRING(DesktopSettingsUndoButton)); instance->undoButton = undoButton; undoButton->accessKey = 'U'; EsButtonSetIcon(undoButton, ES_ICON_EDIT_UNDO_SYMBOLIC); diff --git a/desktop/styles.header b/desktop/styles.header index 1868b24..d5df4d6 100644 --- a/desktop/styles.header +++ b/desktop/styles.header @@ -111,7 +111,6 @@ define ES_STYLE_PUSH_BUTTON_STATUS_BAR (ES_STYLE_CAST(1495)) define ES_STYLE_PUSH_BUTTON_TOOLBAR (ES_STYLE_CAST(1359)) private define ES_STYLE_WINDOW_TAB_ACTIVE (ES_STYLE_CAST(1407)) define ES_STYLE_PUSH_BUTTON_TOOLBAR_BIG (ES_STYLE_CAST(1457)) -define ES_STYLE_PUSH_BUTTON_TOOLBAR_MEDIUM (ES_STYLE_CAST(1461)) private define ES_STYLE_SCROLLBAR_BAR_HORIZONTAL (ES_STYLE_CAST(1363)) private define ES_STYLE_WINDOW_TAB_INACTIVE (ES_STYLE_CAST(1409)) private define ES_STYLE_SCROLLBAR_BAR_VERTICAL (ES_STYLE_CAST(1365)) diff --git a/kernel/module.h b/kernel/module.h index 9a80cb5..f661565 100644 --- a/kernel/module.h +++ b/kernel/module.h @@ -189,6 +189,7 @@ enum KernelObjectType : uint32_t { KERNEL_OBJECT_NODE = 0x00000010, // A file system node (file or directory). KERNEL_OBJECT_EVENT = 0x00000020, // A synchronisation event. KERNEL_OBJECT_CONSTANT_BUFFER = 0x00000040, // A buffer of unmodifiable data stored in the kernel's address space. + KERNEL_OBJECT_MAILSLOT = 0x00000080, // A mailslot into a process's message queue. Can only send messages synchronously. #ifdef ENABLE_POSIX_SUBSYSTEM KERNEL_OBJECT_POSIX_FD = 0x00000100, // A POSIX file descriptor, used in the POSIX subsystem. #endif @@ -271,7 +272,7 @@ void KMutexAssertLocked(KMutex *mutex); struct KEvent { // Waiting and notifying. Can wait on multiple at once. Can be set and reset with interrupts disabled. volatile bool autoReset; // This should be first field in the structure, so that the type of KEvent can be easily declared with {autoReset}. - volatile uintptr_t state; + volatile uintptr_t state; // TODO Change this to a bool? K_PRIVATE LinkedList blockedThreads; volatile size_t handles; diff --git a/kernel/objects.cpp b/kernel/objects.cpp index 41fa53b..7479231 100644 --- a/kernel/objects.cpp +++ b/kernel/objects.cpp @@ -53,6 +53,15 @@ struct MessageQueue { KEvent notEmpty; }; +struct Mailslot { +#define MAILSLOT_RECEIVER (1 << 0) + struct Process *target; // Owns a handle. + KEvent responseReceivedEvent; + KEvent available; + volatile size_t handles; + volatile uintptr_t response; +}; + size_t totalHandleCount; struct HandleTableL2 { @@ -362,7 +371,7 @@ void CloseHandleToObject(void *object, KernelObjectType type, uint32_t flags) { uintptr_t HandleShare(Handle share, Process *process, uint32_t mode, EsHandle at = ES_INVALID_HANDLE) { #define HANDLE_SHARE_TYPE_MASK ((KernelObjectType) (KERNEL_OBJECT_SHMEM | KERNEL_OBJECT_CONSTANT_BUFFER | KERNEL_OBJECT_PROCESS \ - | KERNEL_OBJECT_DEVICE | KERNEL_OBJECT_NODE | KERNEL_OBJECT_EVENT | KERNEL_OBJECT_PIPE)) + | KERNEL_OBJECT_DEVICE | KERNEL_OBJECT_NODE | KERNEL_OBJECT_EVENT | KERNEL_OBJECT_PIPE | KERNEL_OBJECT_MAILSLOT)) if ((share.type & HANDLE_SHARE_TYPE_MASK) == 0) { KernelPanic("HandleShare - Invalid object type %x; allowed types are %x.\n", share.type, HANDLE_SHARE_TYPE_MASK); @@ -378,6 +387,8 @@ uintptr_t HandleShare(Handle share, Process *process, uint32_t mode, EsHandle at sharedFlags = (mode & 1) && (share.flags & (ES_FILE_WRITE_SHARED | ES_FILE_WRITE)) ? ES_FILE_READ_SHARED : share.flags; if (mode & 2) sharedFlags &= ~_ES_NODE_DIRECTORY_WRITE; } else if (share.type == KERNEL_OBJECT_PIPE) { + } else if (share.type == KERNEL_OBJECT_MAILSLOT) { + sharedFlags = (mode & 1) ? share.flags : 0; } if (!OpenHandleToObject(share.object, share.type, sharedFlags)) { diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 9d47d5f..3edb57c 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -1619,6 +1619,65 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_DEVICE_CONTROL) { SYSCALL_RETURN(ES_SUCCESS, false); } +SYSCALL_IMPLEMENT(ES_SYSCALL_MAILSLOT_CREATE) { + if (!OpenHandleToObject(currentProcess, KERNEL_OBJECT_PROCESS, ES_FLAGS_DEFAULT)) { + SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false); + } + + Mailslot *mailslot = (Mailslot *) EsHeapAllocate(sizeof(Mailslot), true, K_PAGED); + + if (mailslot) { + mailslot->target = currentProcess; + mailslot->responseReceivedEvent.autoReset = true; + mailslot->available.autoReset = true; + mailslot->handles = 1; + KEventSet(&mailslot->available); + + EsHandle handle = currentProcess->handleTable.OpenHandle(mailslot, MAILSLOT_RECEIVER, KERNEL_OBJECT_MAILSLOT); + SYSCALL_RETURN(handle, false); + } else { + SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false); + } +} + +SYSCALL_IMPLEMENT(ES_SYSCALL_MAILSLOT_RESPOND) { + SYSCALL_HANDLE_2(argument0, KERNEL_OBJECT_MAILSLOT, _mailslot); + if (~_mailslot.flags & MAILSLOT_RECEIVER) SYSCALL_RETURN(ES_FATAL_ERROR_INSUFFICIENT_PERMISSIONS, true); + Mailslot *mailslot = (Mailslot *) _mailslot.object; + mailslot->response = argument1; + __sync_synchronize(); + KEventSet(&mailslot->responseReceivedEvent, true /* maybe already set */); + SYSCALL_RETURN(ES_SUCCESS, false); +} + +SYSCALL_IMPLEMENT(ES_SYSCALL_MAILSLOT_SEND) { + SYSCALL_HANDLE(argument0, KERNEL_OBJECT_MAILSLOT, mailslot, Mailslot); + + _EsMessageWithObject message; + SYSCALL_READ(&message.message, argument2, sizeof(EsMessage)); + message.object = (void *) argument3; + + currentThread->terminatableState = THREAD_USER_BLOCK_REQUEST; + bool success = KEventWait(&mailslot->available); + currentThread->terminatableState = THREAD_IN_SYSCALL; + + if (success) { + mailslot->target->messageQueue.SendMessage(&message); + + currentThread->terminatableState = THREAD_USER_BLOCK_REQUEST; + success = KEventWait(&mailslot->responseReceivedEvent); + currentThread->terminatableState = THREAD_IN_SYSCALL; + + if (success) { + SYSCALL_WRITE(argument1, &mailslot->response, sizeof(mailslot->response)); + } + + KEventSet(&mailslot->available); + } + + SYSCALL_RETURN(success ? ES_SUCCESS : ES_ERROR_TIMEOUT_REACHED, false); +} + SYSCALL_IMPLEMENT(ES_SYSCALL_DEBUG_COMMAND) { SYSCALL_PERMISSION(ES_PERMISSION_TAKE_SYSTEM_SNAPSHOT); diff --git a/res/Theme Source.dat b/res/Theme Source.dat index e2e685a..2c75f1e 100644 Binary files a/res/Theme Source.dat and b/res/Theme Source.dat differ diff --git a/res/Theme.dat b/res/Theme.dat index 563c885..e969d98 100644 Binary files a/res/Theme.dat and b/res/Theme.dat differ diff --git a/util/designer2.cpp b/util/designer2.cpp index e0276d1..c82165a 100644 --- a/util/designer2.cpp +++ b/util/designer2.cpp @@ -20,7 +20,7 @@ // Prototyping display: previewing state transitions. // TODO Additional features: -// Inactive and disabled state. +// Inactive-and-disabled state. // Undoing a delete does not preserve an instance's layer. // Having to link to the end of a conditional object chain is a bit strange. // Automatically cleaning up unused objects. @@ -37,7 +37,7 @@ // Proper bezier path editor. // Path boolean operations. // Timeline editor for applying a given state change, with rows for possibly many different layers. -// Metrics: layoutVertical. +// Metrics: layoutVertical, textFigures. // TODO Reorganize old theming data! @@ -3057,6 +3057,32 @@ void CanvasZoom100(void *) { UIElementRefresh(canvas); } +void CanvasFindByID(void *) { + char *id = nullptr; + const char *dialog = "Enter the object ID:\n%t\n\n%l\n\n%f%b%b"; + const char *result = UIDialogShow(window, 0, dialog, &id, "OK", "Cancel"); + + if (0 == strcmp(result, "OK")) { + uint64_t _id = strtoul(id, 0, 10); + Object *object = nullptr; + + for (uintptr_t i = 0; i < objects.Length(); i++) { + if (objects[i].id == _id) { + object = &objects[i]; + break; + } + } + + if (!object) { + UIDialogShow(window, 0, "Error: The object was not found.\n%f%b", "OK"); + } else { + CanvasSelectObject(object); + } + } + + free(id); +} + ////////////////////////////////////////////////////////////// void ObjectChangeTypeInternal(void *cp) { @@ -3641,6 +3667,15 @@ void DocumentFileMenu(void *) { } #endif +void DocumentMenu(void *) { + UIMenu *menu = UIMenuCreate(window->pressed, UI_MENU_NO_SCROLL); + UIMenuAddItem(menu, 0, "Switch view", -1, CanvasSwitchView, 0); + UIMenuAddItem(menu, 0, "Switch selector index", -1, CanvasSwitchSelectorIndex, 0); + UIMenuAddItem(menu, 0, "Find by ID", -1, CanvasFindByID, 0); + UIMenuAddItem(menu, 0, "Zoom to 100%", -1, CanvasZoom100, 0); + UIMenuShow(menu); +} + int main(int argc, char **argv) { #ifndef OS_ESSENCE if (argc == 2) { @@ -3671,8 +3706,7 @@ int main(int argc, char **argv) { #else UIButtonCreate(0, 0, "Save", -1)->invoke = DocumentSave; #endif - UIButtonCreate(0, 0, "Switch view", -1)->invoke = CanvasSwitchView; - UIButtonCreate(0, 0, "Switch selector index", -1)->invoke = CanvasSwitchSelectorIndex; + UIButtonCreate(0, 0, "Menu", -1)->invoke = DocumentMenu; UIParentPop(); UISpacerCreate(0, UI_SPACER_LINE, 0, 1); inspector = &UIPanelCreate(0, UI_ELEMENT_V_FILL | UI_PANEL_GRAY | UI_PANEL_MEDIUM_SPACING | UI_PANEL_SCROLL | UI_PANEL_EXPAND)->e;