From 6bb77d889e3e2205db65a723e44d6070b1730f47 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Thu, 26 Aug 2021 16:15:52 +0100 Subject: [PATCH] settings applications list --- apps/font_book.cpp | 40 ++--- apps/text_editor.cpp | 16 +- desktop/api.cpp | 5 +- desktop/desktop.cpp | 1 + desktop/gui.cpp | 104 +++++++----- desktop/list_view.cpp | 71 ++++++-- desktop/os.header | 8 +- desktop/prefix.h | 1 + desktop/settings.cpp | 233 ++++++++++++++++++++------ kernel/module.h | 3 - kernel/syscall.cpp | 20 --- kernel/windows.cpp | 3 +- res/System Configuration Template.ini | 1 + res/Theme Source.dat | Bin 50824 -> 50824 bytes res/Themes/Theme.dat | Bin 52516 -> 52516 bytes shared/strings.cpp | 4 + util/api_table.ini | 8 +- util/build_core.c | 2 +- util/header_generator.c | 33 +++- 19 files changed, 371 insertions(+), 182 deletions(-) diff --git a/apps/font_book.cpp b/apps/font_book.cpp index 2c03fbc..091cdef 100644 --- a/apps/font_book.cpp +++ b/apps/font_book.cpp @@ -235,32 +235,32 @@ void VariantsPopupCreate(Instance *instance, EsElement *element, EsCommand *) { EsPanel *panel = EsPanelCreate(menu, ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_POPUP); EsListView *list = EsListViewCreate(panel, ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal100), 1); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal200), 2); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal300), 3); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal400), 4); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal500), 5); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal600), 6); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal700), 7); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal800), 8); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantNormal900), 9); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic100), 11); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic200), 12); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic300), 13); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic400), 14); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic500), 15); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic600), 16); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic700), 17); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic800), 18); - EsListViewInsertFixedItem(list, INTERFACE_STRING(FontBookVariantItalic900), 19); - EsListViewSelectFixedItem(list, instance->fontVariant); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal100), 1); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal200), 2); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal300), 3); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal400), 4); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal500), 5); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal600), 6); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal700), 7); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal800), 8); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantNormal900), 9); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic100), 11); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic200), 12); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic300), 13); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic400), 14); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic500), 15); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic600), 16); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic700), 17); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic800), 18); + EsListViewFixedItemInsert(list, INTERFACE_STRING(FontBookVariantItalic900), 19); + EsListViewFixedItemSelect(list, instance->fontVariant); list->messageUser = [] (EsElement *element, EsMessage *message) { if (message->type == ES_MSG_LIST_VIEW_SELECT) { Instance *instance = element->instance; EsGeneric selected; - if (EsListViewGetSelectedFixedItem(((EsListView *) element), &selected)) { + if (EsListViewFixedItemGetSelected(((EsListView *) element), &selected)) { instance->fontVariant = selected.i; EsListViewInvalidateAll(element->instance->fontList); } diff --git a/apps/text_editor.cpp b/apps/text_editor.cpp index fa6dc69..81247f7 100644 --- a/apps/text_editor.cpp +++ b/apps/text_editor.cpp @@ -124,19 +124,19 @@ void FormatPopupCreate(Instance *instance) { for (uintptr_t i = 0; i < sizeof(presetSizes) / sizeof(presetSizes[0]); i++) { char buffer[64]; - EsListViewInsertFixedItem(list, buffer, EsStringFormat(buffer, sizeof(buffer), "%d pt", presetSizes[i]), presetSizes[i]); + EsListViewFixedItemInsert(list, buffer, EsStringFormat(buffer, sizeof(buffer), "%d pt", presetSizes[i]), presetSizes[i]); } EsTextStyle textStyle = {}; EsTextboxGetTextStyle(instance->textboxDocument, &textStyle); - EsListViewSelectFixedItem(list, textStyle.size); + EsListViewFixedItemSelect(list, textStyle.size); list->messageUser = [] (EsElement *element, EsMessage *message) { if (message->type == ES_MSG_LIST_VIEW_SELECT) { Instance *instance = element->instance; EsGeneric newSize; - if (EsListViewGetSelectedFixedItem(((EsListView *) element), &newSize)) { + if (EsListViewFixedItemGetSelected(((EsListView *) element), &newSize)) { EsTextStyle textStyle = {}; EsTextboxGetTextStyle(instance->textboxDocument, &textStyle); textStyle.size = newSize.u; @@ -152,17 +152,17 @@ void FormatPopupCreate(Instance *instance) { EsPanel *column = EsPanelCreate(panel, ES_FLAGS_DEFAULT, &styleFormatPopupColumn); EsTextDisplayCreate(column, ES_CELL_H_EXPAND, ES_STYLE_TEXT_LABEL, INTERFACE_STRING(CommonFormatLanguage)); EsListView *list = EsListViewCreate(column, ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED); - EsListViewInsertFixedItem(list, INTERFACE_STRING(CommonFormatPlainText), 0); - EsListViewInsertFixedItem(list, "C/C++", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C); - EsListViewInsertFixedItem(list, "Ini file", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI); - EsListViewSelectFixedItem(list, instance->syntaxHighlightingLanguage); + EsListViewFixedItemInsert(list, INTERFACE_STRING(CommonFormatPlainText), 0); + EsListViewFixedItemInsert(list, "C/C++", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C); + EsListViewFixedItemInsert(list, "Ini file", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI); + EsListViewFixedItemSelect(list, instance->syntaxHighlightingLanguage); list->messageUser = [] (EsElement *element, EsMessage *message) { if (message->type == ES_MSG_LIST_VIEW_SELECT) { Instance *instance = element->instance; EsGeneric newLanguage; - if (EsListViewGetSelectedFixedItem(((EsListView *) element), &newLanguage)) { + if (EsListViewFixedItemGetSelected(((EsListView *) element), &newLanguage)) { SetLanguage(instance, newLanguage.u); } } diff --git a/desktop/api.cpp b/desktop/api.cpp index 554f97f..430885a 100644 --- a/desktop/api.cpp +++ b/desktop/api.cpp @@ -692,8 +692,9 @@ const EsApplicationStartupInformation *EsInstanceGetStartupInformation(EsInstanc } void EsInstanceDestroy(EsInstance *instance) { - EsInstance *inspector = ((APIInstance *) instance->_private)->attachedInspector; - if (inspector) EsInstanceDestroy(inspector); + InspectorWindow **inspector = &((APIInstance *) instance->_private)->attachedInspector; + if (*inspector) EsInstanceDestroy(*inspector); + *inspector = nullptr; UndoManagerDestroy(instance->undoManager); EsAssert(instance->window->instance == instance); instance->window->destroyInstanceAfterClose = true; diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index 3a870b5..f0f62bc 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -120,6 +120,7 @@ struct InstalledApplication { size_t openInstanceCount; // Only used if useSingleProcess is true. EsHandle singleProcessHandle; bool notified; // Temporary flag. + EsFileOffset totalSize; // 0 if uncalculated. }; struct CommonDesktopInstance : EsInstance { diff --git a/desktop/gui.cpp b/desktop/gui.cpp index 168ba1b..800a2c9 100644 --- a/desktop/gui.cpp +++ b/desktop/gui.cpp @@ -74,6 +74,7 @@ struct TableCell { // Miscellanous forward declarations. void UIWindowPaintNow(EsWindow *window, ProcessMessageTiming *timing, bool afterResize); +void UIWindowLayoutNow(EsWindow *window, ProcessMessageTiming *timing); EsElement *WindowGetMainPanel(EsWindow *window); int AccessKeyLayerMessage(EsElement *element, EsMessage *message); void AccessKeyModeExit(); @@ -99,7 +100,7 @@ void InspectorNotifyElementContentChanged(EsElement *element); #define UI_STATE_DESTROYING_CHILD (1 << 5) #define UI_STATE_HOVERED (1 << 6) -#define UI_STATE_PRESSED (1 << 7) +#define UI_STATE_LEFT_PRESSED (1 << 7) #define UI_STATE_STRONG_PRESSED (1 << 8) #define UI_STATE_FOCUS_WITHIN (1 << 9) #define UI_STATE_FOCUSED (1 << 10) @@ -293,6 +294,7 @@ struct ScrollPane { double position[2]; int64_t limit[2]; int32_t fixedViewport[2]; + bool autoScrollbars[2]; bool dragScrolling; #define SCROLL_MODE_NONE (0) // No scrolling takes place on this axis. @@ -1716,9 +1718,10 @@ bool EsElement::RefreshStyleState() { if (flags & ES_ELEMENT_DISABLED) { styleStateFlags |= THEME_PRIMARY_STATE_DISABLED; } else { - if (((state & UI_STATE_PRESSED) && ((state & UI_STATE_HOVERED) || gui.draggingStarted || (state & UI_STATE_STRONG_PRESSED))) || (state & UI_STATE_MENU_SOURCE)) { + if (((state & UI_STATE_LEFT_PRESSED) && ((state & UI_STATE_HOVERED) || gui.draggingStarted || (state & UI_STATE_STRONG_PRESSED))) + || (state & UI_STATE_MENU_SOURCE)) { styleStateFlags |= THEME_PRIMARY_STATE_PRESSED; - } else if (((state & UI_STATE_HOVERED) && !window->pressed) || (state & UI_STATE_PRESSED)) { + } else if (((state & UI_STATE_HOVERED) && !window->pressed) || (window && window->pressed == this)) { styleStateFlags |= THEME_PRIMARY_STATE_HOVERED; } else { styleStateFlags |= THEME_PRIMARY_STATE_IDLE; @@ -2860,7 +2863,7 @@ bool ScrollPane::RefreshLimit(int axis, int64_t *contentSize) { EsMessageSend(parent, &m); *contentSize = axis ? m.measure.height : m.measure.width; - limit[axis] = *contentSize - (axis ? bounds.b : bounds.r) + fixedViewport[axis]; + limit[axis] = *contentSize - (axis ? bounds.b : bounds.r); if (limit[axis] < 0) limit[axis] = 0; if (parent->state & UI_STATE_INSPECTING) { @@ -2906,11 +2909,13 @@ void ScrollPane::Refresh() { if (bar[0]) { bar[0]->InternalMove(parent->width - parent->internalOffsetRight, bar[0]->currentStyle->preferredHeight, 0, parent->height - parent->internalOffsetBottom); + autoScrollbars[0] = ~bar[0]->flags & ES_ELEMENT_DISABLED; } if (bar[1]) { bar[1]->InternalMove(bar[1]->currentStyle->preferredWidth, parent->height - parent->internalOffsetBottom, parent->width - parent->internalOffsetRight, 0); + autoScrollbars[1] = ~bar[1]->flags & ES_ELEMENT_DISABLED; } if (pad) { @@ -5854,7 +5859,7 @@ void UIMousePressReleased(EsWindow *window, EsMessage *message, bool sendClick) UIMessageSendPropagateToAncestors(pressed, &m); } - pressed->state &= ~UI_STATE_PRESSED; + pressed->state &= ~UI_STATE_LEFT_PRESSED; EsMessage m = { ES_MSG_PRESSED_END }; EsMessageSend(pressed, &m); @@ -6144,7 +6149,7 @@ void AccessKeyModeHandleKeyPress(EsMessage *message) { AccessKeyModeExit(); } else if (regatherKeys) { AccessKeyModeExit(); - window->InternalMove(window->width, window->height, 0, 0); + UIWindowLayoutNow(window, nullptr); AccessKeyModeEnter(window); } else { window->Repaint(true); @@ -6372,6 +6377,47 @@ void UIWindowPaintNow(EsWindow *window, ProcessMessageTiming *timing, bool after window->updateRegion = ES_RECT_4(window->windowWidth, 0, window->windowHeight, 0); } +void UIWindowLayoutNow(EsWindow *window, ProcessMessageTiming *timing) { + if (timing) timing->startLayout = EsTimeStampMs(); + + window->InternalMove(window->width, window->height, 0, 0); + + if (window->ensureVisible) { + EsElement *child = window->ensureVisible, *e = window->ensureVisible; + + while (e->parent) { + EsMessage m = { ES_MSG_ENSURE_VISIBLE }; + m.child = child; + e = e->parent; + + if (ES_HANDLED == EsMessageSend(e, &m)) { + child = e; + } + } + + window->ensureVisible = nullptr; + } + + if (window->processCheckVisible) { + for (uintptr_t i = 0; i < window->checkVisible.Length(); i++) { + EsElement *element = window->checkVisible[i]; + EsAssert(element->state & UI_STATE_CHECK_VISIBLE); + EsRectangle bounds = element->GetWindowBounds(); + bool offScreen = bounds.r < 0 || bounds.b < 0 || bounds.l >= element->window->width || bounds.t >= element->window->height; + if (!offScreen) continue; + element->state &= ~UI_STATE_CHECK_VISIBLE; + window->checkVisible.Delete(i); + i--; + EsMessage m = { ES_MSG_NOT_VISIBLE }; + EsMessageSend(element, &m); + } + + window->processCheckVisible = false; + } + + if (timing) timing->endLayout = EsTimeStampMs(); +} + bool UISetCursor(EsWindow *window) { EsCursorStyle cursorStyle = ES_CURSOR_NORMAL; EsElement *element = window->pressed ?: window->hovered; @@ -6551,7 +6597,10 @@ void UIProcessWindowManagerMessage(EsWindow *window, EsMessage *message, Process // window->hovered will be set to nullptr, so save the element here. EsElement *element = window->hovered; - element->state |= UI_STATE_PRESSED; + if (message->type == ES_MSG_MOUSE_LEFT_DOWN) { + element->state |= UI_STATE_LEFT_PRESSED; + } + window->pressed = element; EsMessage m = { ES_MSG_PRESSED_START }; EsMessageSend(element, &m); @@ -6729,44 +6778,7 @@ void UIProcessWindowManagerMessage(EsWindow *window, EsMessage *message, Process bool changedCursor = UISetCursor(window); if (window->receivedFirstResize || window->windowStyle != ES_WINDOW_NORMAL) { - if (timing) timing->startLayout = EsTimeStampMs(); - - window->InternalMove(window->width, window->height, 0, 0); - - if (window->ensureVisible) { - EsElement *child = window->ensureVisible, *e = window->ensureVisible; - - while (e->parent) { - EsMessage m = { ES_MSG_ENSURE_VISIBLE }; - m.child = child; - e = e->parent; - - if (ES_HANDLED == EsMessageSend(e, &m)) { - child = e; - } - } - - window->ensureVisible = nullptr; - } - - if (window->processCheckVisible) { - for (uintptr_t i = 0; i < window->checkVisible.Length(); i++) { - EsElement *element = window->checkVisible[i]; - EsAssert(element->state & UI_STATE_CHECK_VISIBLE); - EsRectangle bounds = element->GetWindowBounds(); - bool offScreen = bounds.r < 0 || bounds.b < 0 || bounds.l >= element->window->width || bounds.t >= element->window->height; - if (!offScreen) continue; - element->state &= ~UI_STATE_CHECK_VISIBLE; - window->checkVisible.Delete(i); - i--; - EsMessage m = { ES_MSG_NOT_VISIBLE }; - EsMessageSend(element, &m); - } - - window->processCheckVisible = false; - } - - if (timing) timing->endLayout = EsTimeStampMs(); + UIWindowLayoutNow(window, timing); } if (THEME_RECT_VALID(window->updateRegion) && window->width == (int) window->windowWidth && window->height == (int) window->windowHeight) { @@ -7036,7 +7048,7 @@ void InspectorNotifyElementEvent(EsElement *element, const char *cCategory, cons if (cCategory) EsBufferFormat(&buffer, "%z: ", cCategory); EsBufferFormatV(&buffer, cFormat, arguments); va_end(arguments); - EsListViewInsertFixedItem(inspector->listEvents, _buffer, buffer.position); + EsListViewFixedItemInsert(inspector->listEvents, _buffer, buffer.position); EsListViewScrollToEnd(inspector->listEvents); } diff --git a/desktop/list_view.cpp b/desktop/list_view.cpp index 3ef96c1..6edaa23 100644 --- a/desktop/list_view.cpp +++ b/desktop/list_view.cpp @@ -26,10 +26,16 @@ struct ListViewGroup { bool initialised; }; -struct ListViewFixedItem { +struct ListViewFixedString { char *string; - size_t stringBytes; + size_t bytes; +}; + +struct ListViewFixedItem { + ListViewFixedString firstColumn; + Array otherColumns; EsGeneric data; + uint32_t iconID; }; int ListViewProcessItemMessage(EsElement *element, EsMessage *message); @@ -635,16 +641,13 @@ struct EsListView : EsElement { position + contentBounds.l, currentStyle->insets.t - this->scroll.position[1] + visibleItem->indent * currentStyle->gapWrap + contentBounds.t); position += visibleItem->element->width; - } else if (flags & ES_LIST_VIEW_COLUMNS) { + } else if ((flags & ES_LIST_VIEW_COLUMNS) && ((~flags & ES_LIST_VIEW_CHOICE_SELECT) || (this->scroll.autoScrollbars[0]))) { int indent = visibleItem->indent * currentStyle->gapWrap; int firstColumn = columns[0].width + secondaryCellStyle->gapMajor; visibleItem->startAtSecondColumn = indent > firstColumn; if (indent > firstColumn) indent = firstColumn; - visibleItem->element->InternalMove( - totalColumnWidth - indent, - visibleItem->size, - indent - this->scroll.position[0] + contentBounds.l + currentStyle->insets.l, - position + contentBounds.t); + visibleItem->element->InternalMove(totalColumnWidth - indent, visibleItem->size, + indent - this->scroll.position[0] + contentBounds.l + currentStyle->insets.l, position + contentBounds.t); position += visibleItem->element->height; } else { int indent = visibleItem->indent * currentStyle->gapWrap + currentStyle->insets.l; @@ -1142,7 +1145,8 @@ struct EsListView : EsElement { if (EsRectangleClip(drawBounds, message->painter->clip, nullptr) && ES_HANDLED == EsMessageSend(this, &m)) { - UIStyle *style = i ? secondaryCellStyle : primaryCellStyle; + UIStyle *style = (flags & ES_LIST_VIEW_CHOICE_SELECT) ? ((UIStyle *) message->painter->style) + : i ? secondaryCellStyle : primaryCellStyle; uint8_t previousTextAlign = style->textAlign; @@ -1576,6 +1580,7 @@ struct EsListView : EsElement { if (flags & ES_LIST_VIEW_COLUMNS) { message->measure.width = totalColumnWidth + currentStyle->insets.l + currentStyle->insets.r; + message->measure.height += columnHeader->currentStyle->preferredHeight; } } } else if (message->type == ES_MSG_LAYOUT) { @@ -1621,7 +1626,12 @@ struct EsListView : EsElement { } for (uintptr_t i = 0; i < fixedItems.Length(); i++) { - EsHeapFree(fixedItems[i].string); + for (uintptr_t j = 0; j < fixedItems[i].otherColumns.Length(); j++) { + EsHeapFree(fixedItems[i].otherColumns[j].string); + } + + EsHeapFree(fixedItems[i].firstColumn.string); + fixedItems[i].otherColumns.Free(); } primaryCellStyle->CloseReference(); @@ -1806,7 +1816,12 @@ struct EsListView : EsElement { } else if (message->type == ES_MSG_LIST_VIEW_GET_CONTENT && (flags & ES_LIST_VIEW_FIXED_ITEMS)) { uintptr_t index = message->getContent.index; EsAssert(index < fixedItems.Length()); - EsBufferFormat(message->getContent.buffer, "%s", fixedItems[index].stringBytes, fixedItems[index].string); + ListViewFixedString emptyString = {}; + ListViewFixedItem *item = &fixedItems[index]; + ListViewFixedString *string = message->getContent.column == 0 ? &item->firstColumn + : message->getContent.column <= item->otherColumns.Length() ? &item->otherColumns[message->getContent.column - 1] : &emptyString; + EsBufferFormat(message->getContent.buffer, "%s", string->bytes, string->string); + if (message->getContent.column == 0) message->getContent.icon = item->iconID; } else if (message->type == ES_MSG_LIST_VIEW_IS_SELECTED && (flags & ES_LIST_VIEW_FIXED_ITEMS)) { message->selectItem.isSelected = message->selectItem.index == fixedItemSelection; } else { @@ -2321,7 +2336,7 @@ void EsListViewInvalidateContent(EsListView *view, EsListViewIndex group, EsList } } -void EsListViewInsertFixedItem(EsListView *view, const char *string, ptrdiff_t stringBytes, EsGeneric data, EsListViewIndex index) { +EsListViewIndex EsListViewFixedItemInsert(EsListView *view, const char *string, ptrdiff_t stringBytes, EsGeneric data, EsListViewIndex index, uint32_t iconID) { EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS); if (stringBytes == -1) { @@ -2339,20 +2354,33 @@ void EsListViewInsertFixedItem(EsListView *view, const char *string, ptrdiff_t s EsAssert(index >= 0 && index <= (intptr_t) view->fixedItems.Length()); ListViewFixedItem item = {}; item.data = data; - HeapDuplicate((void **) &item.string, string, stringBytes); - item.stringBytes = stringBytes; + item.iconID = iconID; + HeapDuplicate((void **) &item.firstColumn.string, string, stringBytes); + item.firstColumn.bytes = stringBytes; view->fixedItems.Insert(item, index); EsListViewInsert(view, 0, index, 1); + return index; } -bool EsListViewSelectFixedItem(EsListView *view, EsGeneric data) { +void EsListViewFixedItemAddString(EsListView *view, EsListViewIndex index, const char *string, ptrdiff_t stringBytes) { + EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS); + EsMessageMutexCheck(); + EsAssert(index >= 0 && index < (intptr_t) view->fixedItems.Length()); + ListViewFixedString fixedString = {}; + fixedString.bytes = stringBytes == -1 ? EsCStringLength(string) : stringBytes; + HeapDuplicate((void **) &fixedString, string, fixedString.bytes); + view->fixedItems[index].otherColumns.Add(fixedString); + EsListViewInvalidateContent(view, 0, index); +} + +bool EsListViewFixedItemFindIndex(EsListView *view, EsGeneric data, EsListViewIndex *index) { EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS); EsMessageMutexCheck(); for (uintptr_t i = 0; i < view->fixedItems.Length(); i++) { if (view->fixedItems[i].data == data) { - EsListViewSelect(view, 0, i); + *index = i; return true; } } @@ -2360,7 +2388,16 @@ bool EsListViewSelectFixedItem(EsListView *view, EsGeneric data) { return false; } -bool EsListViewGetSelectedFixedItem(EsListView *view, EsGeneric *data) { +bool EsListViewFixedItemSelect(EsListView *view, EsGeneric data) { + EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS); + EsMessageMutexCheck(); + EsListViewIndex index; + bool found = EsListViewFixedItemFindIndex(view, data, &index); + if (found) EsListViewSelect(view, 0, index); + return found; +} + +bool EsListViewFixedItemGetSelected(EsListView *view, EsGeneric *data) { EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS); EsMessageMutexCheck(); diff --git a/desktop/os.header b/desktop/os.header index 56ac323..6c47169 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -2422,6 +2422,8 @@ function void EsListViewInsert(EsListView *view, EsListViewIndex group, EsListVi function void EsListViewRemove(EsListView *view, EsListViewIndex group, EsListViewIndex firstIndex, EsListViewIndex count); function void EsListViewRemoveAll(EsListView *view, EsListViewIndex group); // (Fixed items.) -function void EsListViewInsertFixedItem(EsListView *view, STRING string = BLANK_STRING, EsGeneric data = ES_NULL, EsListViewIndex index = -1); -function bool EsListViewSelectFixedItem(EsListView *view, EsGeneric data); // Returns false if the item was not found. -function bool EsListViewGetSelectedFixedItem(EsListView *view, EsGeneric *data); // Returns false if no item was selected. +function EsListViewIndex EsListViewFixedItemInsert(EsListView *view, STRING string = BLANK_STRING, EsGeneric data = ES_NULL, EsListViewIndex index = -1, uint32_t iconID = 0); +function void EsListViewFixedItemAddString(EsListView *view, EsListViewIndex index, STRING string = BLANK_STRING); // For additional columns. +function bool EsListViewFixedItemFindIndex(EsListView *view, EsGeneric data, EsListViewIndex *index); // Returns false if the item was not found. +function bool EsListViewFixedItemSelect(EsListView *view, EsGeneric data); // Returns false if the item was not found. +function bool EsListViewFixedItemGetSelected(EsListView *view, EsGeneric *data); // Returns false if no item was selected. diff --git a/desktop/prefix.h b/desktop/prefix.h index 6483280..259fd40 100644 --- a/desktop/prefix.h +++ b/desktop/prefix.h @@ -294,6 +294,7 @@ struct BundleFile { #define CURSOR_USE_ACCELERATION (1 << 0) #define CURSOR_USE_ALT_SLOW (1 << 1) #define CURSOR_SPEED(x) ((x) >> 16) +#define CURSOR_TRAILS(x) (((x) >> 13) & 7) #define SHUTDOWN_ACTION_POWER_OFF (1) #define SHUTDOWN_ACTION_RESTART (2) diff --git a/desktop/settings.cpp b/desktop/settings.cpp index c373a20..16f7a81 100644 --- a/desktop/settings.cpp +++ b/desktop/settings.cpp @@ -1,10 +1,17 @@ // TODO Undo button overlapped slightly when scrollbar shown. +// Maybe we should use a toolbar for these buttons? +// Need to make an animation for showing/hiding the toolbar. struct SettingsInstance : CommonDesktopInstance { EsPanel *switcher; EsPanel *mainPage; - EsButton *undoButton; + EsButton *undoButton, *backButton; Array controls; + + // Applications page: + EsHandle workerThread; + EsListView *applicationsList; + volatile bool workerStop; }; struct SettingsPage { @@ -53,6 +60,17 @@ const EsStyle styleSettingsGroupContainer2 = { }, }; +const EsStyle styleSettingsGroupContainer3 = { + .inherit = ES_STYLE_BUTTON_GROUP_CONTAINER, + + .metrics = { + .mask = ES_THEME_METRICS_PREFERRED_WIDTH | ES_THEME_METRICS_INSETS | ES_THEME_METRICS_GAP_MAJOR, + .insets = ES_RECT_1(15), + .preferredWidth = 600, + .gapMajor = 15, + }, +}; + const EsStyle styleSettingsNumberTextbox = { .inherit = ES_STYLE_TEXTBOX_BORDERED_SINGLE, @@ -111,6 +129,20 @@ const EsStyle styleSliderRow = { }, }; +const EsStyle styleApplicationsList = { + .inherit = ES_STYLE_LIST_CHOICE_BORDERED, + + .metrics = { + .mask = ES_THEME_METRICS_PREFERRED_HEIGHT, + .preferredHeight = 0, + }, +}; + +EsListViewColumn settingsApplicationListColumns[] = { + { INTERFACE_STRING(FileManagerColumnName), ES_FLAGS_DEFAULT, 150 }, + { INTERFACE_STRING(FileManagerColumnSize), ES_LIST_VIEW_COLUMN_RIGHT_ALIGNED, 100 }, +}; + void SettingsUpdateGlobalAndWindowManager() { api.global->clickChainTimeoutMs = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("click_chain_timeout_ms")); api.global->swapLeftAndRightButtons = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("swap_left_and_right_buttons")); @@ -122,13 +154,27 @@ void SettingsUpdateGlobalAndWindowManager() { int32_t cursorSpeed = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("cursor_speed")); double cursorSpeedFactor = EsCRTexp2(0.25 * cursorSpeed /* -20 to 20, 0 is default */) /* 1/32 to 32, 1 is default */; cursorProperties |= (uint32_t) (cursorSpeedFactor * 0x100) << 16; // Speed. + cursorProperties |= (uint32_t) EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("cursor_trails")) << 13; // Trail count. EsSyscall(ES_SYSCALL_CURSOR_PROPERTIES_SET, cursorProperties, 0, 0, 0); } void SettingsBackButton(EsInstance *_instance, EsElement *, EsCommand *) { SettingsInstance *instance = (SettingsInstance *) _instance; - instance->undoButton = nullptr; + + EsElementSetDisabled(instance->undoButton, true); + EsElementSetHidden(instance->undoButton, true); + EsElementSetDisabled(instance->backButton, true); + instance->controls.Free(); + + if (instance->workerThread) { + instance->workerStop = true; + EsWaitSingle(instance->workerThread); + EsHandleClose(instance->workerThread); + instance->workerThread = ES_INVALID_HANDLE; + instance->workerStop = false; + } + EsPanelSwitchTo(instance->switcher, instance->mainPage, ES_TRANSITION_ZOOM_OUT, ES_PANEL_SWITCHER_DESTROY_PREVIOUS_AFTER_TRANSITION, 1.0f); ConfigurationWriteToFile(); } @@ -186,16 +232,6 @@ void SettingsAddTitle(EsElement *container, SettingsPage *page) { EsSpacerCreate(container, ES_CELL_H_FILL, ES_STYLE_BUTTON_GROUP_SEPARATOR); } -void SettingsAddUndoButton(EsElement *stack) { - EsPanel *overlay = EsPanelCreate(stack, ES_CELL_H_RIGHT | ES_CELL_V_TOP, &styleSettingsOverlayPanel); - EsButton *undoButton = EsButtonCreate(overlay, ES_BUTTON_TOOLBAR | ES_ELEMENT_STICKY_ACCESS_KEY, 0, INTERFACE_STRING(DesktopSettingsUndoButton)); - undoButton->accessKey = 'U'; - ((SettingsInstance *) stack->instance)->undoButton = undoButton; - EsButtonSetIcon(undoButton, ES_ICON_EDIT_UNDO_SYMBOLIC); - EsButtonOnCommand(undoButton, SettingsUndoButton); - EsElementSetDisabled(undoButton, true); -} - void SettingsPageUnimplemented(EsElement *element, SettingsPage *page) { EsPanel *content = EsPanelCreate(element, ES_CELL_FILL | ES_PANEL_V_SCROLL_AUTO, &styleNewTabContent); EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2); @@ -354,11 +390,11 @@ void SettingsAddSlider(EsElement *table, const char *string, ptrdiff_t stringByt EsPanel *stack = EsPanelCreate(table, ES_CELL_H_FILL); EsTextDisplayCreate(stack, ES_CELL_H_LEFT, 0, string, stringBytes); - EsPanel *row = EsPanelCreate(stack, ES_PANEL_HORIZONTAL | ES_CELL_H_CENTER, &styleSliderRow); - EsTextDisplayCreate(row, ES_FLAGS_DEFAULT, 0, lowString, lowStringBytes); + EsPanel *row = EsPanelCreate(stack, ES_PANEL_HORIZONTAL | ES_CELL_H_FILL, &styleSliderRow); + EsTextDisplayCreate(row, ES_CELL_H_PUSH | ES_CELL_H_RIGHT, 0, lowString, lowStringBytes); EsSlider *slider = EsSliderCreate(row, ES_ELEMENT_FREE_USER_DATA, 0, LinearMap(control->minimumValue, control->maximumValue, 0, 1, control->originalValueInt), steps); - EsTextDisplayCreate(row, ES_FLAGS_DEFAULT, 0, highString, highStringBytes); + EsTextDisplayCreate(row, ES_CELL_H_PUSH | ES_CELL_H_LEFT, 0, highString, highStringBytes); slider->userData = control; slider->accessKey = accessKey; slider->messageUser = SettingsSliderMessage; @@ -381,12 +417,13 @@ int SettingsDoubleClickTestMessage(EsElement *element, EsMessage *message) { } void SettingsPageMouse(EsElement *element, SettingsPage *page) { + EsElementSetHidden(((SettingsInstance *) element->instance)->undoButton, false); + EsPanel *content = EsPanelCreate(element, ES_CELL_FILL | ES_PANEL_V_SCROLL_AUTO, &styleNewTabContent); EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2); SettingsAddTitle(container, page); EsPanel *table; - EsTextbox *textbox; SettingsAddSlider(container, INTERFACE_STRING(DesktopSettingsMouseSpeed), 'M', "general", "cursor_speed", -20, 20, 41, INTERFACE_STRING(DesktopSettingsMouseSpeedSlow), INTERFACE_STRING(DesktopSettingsMouseSpeedFast)); @@ -397,22 +434,14 @@ void SettingsPageMouse(EsElement *element, SettingsPage *page) { EsSpacerCreate(container, ES_CELL_H_FILL, ES_STYLE_BUTTON_GROUP_SEPARATOR); + SettingsAddSlider(container, INTERFACE_STRING(DesktopSettingsMouseCursorTrails), 'T', "general", "cursor_trails", 0, 7, 8, + INTERFACE_STRING(DesktopSettingsMouseCursorTrailsNone), INTERFACE_STRING(DesktopSettingsMouseCursorTrailsMany)); + table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, &styleSettingsTable); EsPanelSetBands(table, 2); - // TODO Mouse trails. - EsTextDisplayCreate(table, ES_CELL_H_RIGHT | ES_CELL_H_PUSH, 0, INTERFACE_STRING(DesktopSettingsMouseCursorTrails)); - textbox = EsTextboxCreate(table, ES_CELL_H_LEFT | ES_CELL_H_PUSH | ES_TEXTBOX_EDIT_BASED, &styleSettingsNumberTextbox); - textbox->accessKey = 'T'; - EsTextboxUseNumberOverlay(textbox, false); - EsTextboxInsert(textbox, "0"); - - // TODO Scroll wheel. - EsTextDisplayCreate(table, ES_CELL_H_RIGHT | ES_CELL_H_PUSH, 0, INTERFACE_STRING(DesktopSettingsMouseLinesPerScrollNotch)); - textbox = EsTextboxCreate(table, ES_CELL_H_LEFT | ES_CELL_H_PUSH | ES_TEXTBOX_EDIT_BASED, &styleSettingsNumberTextbox); - textbox->accessKey = 'S'; - EsTextboxUseNumberOverlay(textbox, false); - EsTextboxInsert(textbox, "3"); + SettingsAddNumberBox(table, INTERFACE_STRING(DesktopSettingsMouseLinesPerScrollNotch), 'S', "general", "scroll_lines_per_notch", + 1, 100, nullptr, 0, 0.04); table = EsPanelCreate(container, ES_CELL_H_FILL, &styleSettingsCheckboxGroup); SettingsAddCheckbox(table, INTERFACE_STRING(DesktopSettingsMouseSwapLeftAndRightButtons), 'B', "general", "swap_left_and_right_buttons"); @@ -431,11 +460,11 @@ void SettingsPageMouse(EsElement *element, SettingsPage *page) { EsTextDisplayCreate(testBox, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(DesktopSettingsMouseTestDoubleClickIntroduction)); EsSpacerCreate(testBox, ES_FLAGS_DEFAULT, 0, 0, 5); EsCustomElementCreate(testBox, ES_FLAGS_DEFAULT, ES_STYLE_DOUBLE_CLICK_TEST)->messageUser = SettingsDoubleClickTestMessage; - - SettingsAddUndoButton(element); } void SettingsPageKeyboard(EsElement *element, SettingsPage *page) { + EsElementSetHidden(((SettingsInstance *) element->instance)->undoButton, false); + EsPanel *content = EsPanelCreate(element, ES_CELL_FILL | ES_PANEL_V_SCROLL_AUTO, &styleNewTabContent); EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2); SettingsAddTitle(container, page); @@ -467,23 +496,104 @@ void SettingsPageKeyboard(EsElement *element, SettingsPage *page) { EsTextDisplayCreate(testBox, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(DesktopSettingsKeyboardTestTextboxIntroduction)); EsSpacerCreate(testBox, ES_FLAGS_DEFAULT, 0, 0, 5); EsTextboxCreate(testBox, ES_CELL_H_LEFT)->accessKey = 'T'; +} - SettingsAddUndoButton(element); +void SettingsPageApplicationsWorkerThread(EsGeneric context) { + SettingsInstance *instance = (SettingsInstance *) context.p; + EsListViewIndex index; + char buffer[64]; + EsDirectoryChild information; + + while (!instance->workerStop) { + // Find an application that we need to calculate the size of. + + EsMessageMutexAcquire(); + + InstalledApplication *application = nullptr; + + for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) { + application = desktop.installedApplications[i]; + + if (!application->totalSize && EsListViewFixedItemFindIndex(instance->applicationsList, application, &index)) { + break; + } else { + application = nullptr; + } + } + + EsMessageMutexRelease(); + + if (!application) { + break; // All applications have had their sizes calculated. + } + + // TODO What happens if the application is uninstalled here? + // TODO Include settings and cached data. + + if (!EsPathQueryInformation(application->cExecutable, -1, &information)) { + continue; + } + + EsMessageMutexAcquire(); + + application->totalSize = information.fileSize; + + if (EsListViewFixedItemFindIndex(instance->applicationsList, application, &index)) { + EsListViewFixedItemAddString(instance->applicationsList, index, buffer, EsStringFormat(buffer, sizeof(buffer), "%D", application->totalSize)); + } + + EsMessageMutexRelease(); + } +} + +void SettingsPageApplications(EsElement *element, SettingsPage *page) { + SettingsInstance *instance = (SettingsInstance *) element->instance; + EsPanel *content = EsPanelCreate(element, ES_CELL_FILL | ES_PANEL_V_SCROLL_AUTO, &styleNewTabContent); + EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer3); + SettingsAddTitle(container, page); + + EsTextDisplayCreate(container, ES_CELL_H_FILL, 0, INTERFACE_STRING(DesktopSettingsApplicationSelectItem)); + uint64_t listFlags = ES_CELL_H_FILL | ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS | ES_LIST_VIEW_COLUMNS; + EsListView *list = EsListViewCreate(container, listFlags, &styleApplicationsList); + instance->applicationsList = list; + EsListViewSetColumns(list, settingsApplicationListColumns, sizeof(settingsApplicationListColumns) / sizeof(settingsApplicationListColumns[0])); + list->accessKey = 'L'; + + // TODO Insets/gaps on the choice style items is incorrect. + // TODO Sorting. + // TODO Operations on the application. + + for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) { + InstalledApplication *application = desktop.installedApplications[i]; + + if (!application->temporary && !application->createInstance && application->cExecutable) { + EsListViewIndex index = EsListViewFixedItemInsert(list, application->cName, -1, application, -1, + (EsStandardIcon) application->iconID ?: ES_ICON_APPLICATION_DEFAULT_ICON); + + if (application->totalSize) { + char buffer[64]; + EsListViewFixedItemAddString(list, index, buffer, EsStringFormat(buffer, sizeof(buffer), "%D", application->totalSize)); + } + } + } + + EsThreadInformation thread; + EsThreadCreate(SettingsPageApplicationsWorkerThread, &thread, instance); + instance->workerThread = thread.handle; } SettingsPage settingsPages[] = { { INTERFACE_STRING(DesktopSettingsAccessibility), ES_ICON_PREFERENCES_DESKTOP_ACCESSIBILITY, SettingsPageUnimplemented, 'A' }, // TODO. - { INTERFACE_STRING(DesktopSettingsApplications), ES_ICON_APPLICATIONS_OTHER, SettingsPageUnimplemented, 'A' }, // TODO. - { INTERFACE_STRING(DesktopSettingsDateAndTime), ES_ICON_PREFERENCES_SYSTEM_TIME, SettingsPageUnimplemented, 'D' }, // TODO. - { INTERFACE_STRING(DesktopSettingsDevices), ES_ICON_COMPUTER_LAPTOP, SettingsPageUnimplemented, 'D' }, // TODO. + { INTERFACE_STRING(DesktopSettingsApplications), ES_ICON_APPLICATIONS_OTHER, SettingsPageApplications, 'B' }, // TODO. + { INTERFACE_STRING(DesktopSettingsDateAndTime), ES_ICON_PREFERENCES_SYSTEM_TIME, SettingsPageUnimplemented, 'C' }, // TODO. { INTERFACE_STRING(DesktopSettingsDisplay), ES_ICON_PREFERENCES_DESKTOP_DISPLAY, SettingsPageUnimplemented, 'D' }, // TODO. - { INTERFACE_STRING(DesktopSettingsKeyboard), ES_ICON_INPUT_KEYBOARD, SettingsPageKeyboard, 'K' }, - { INTERFACE_STRING(DesktopSettingsLocalisation), ES_ICON_PREFERENCES_DESKTOP_LOCALE, SettingsPageUnimplemented, 'L' }, // TODO. - { INTERFACE_STRING(DesktopSettingsMouse), ES_ICON_INPUT_MOUSE, SettingsPageMouse, 'M' }, - { INTERFACE_STRING(DesktopSettingsNetwork), ES_ICON_PREFERENCES_SYSTEM_NETWORK, SettingsPageUnimplemented, 'N' }, // TODO. - { INTERFACE_STRING(DesktopSettingsPower), ES_ICON_PREFERENCES_SYSTEM_POWER, SettingsPageUnimplemented, 'P' }, // TODO. - { INTERFACE_STRING(DesktopSettingsSound), ES_ICON_PREFERENCES_DESKTOP_SOUND, SettingsPageUnimplemented, 'S' }, // TODO. - { INTERFACE_STRING(DesktopSettingsTheme), ES_ICON_APPLICATIONS_INTERFACEDESIGN, SettingsPageUnimplemented, 'T' }, // TODO. + { INTERFACE_STRING(DesktopSettingsKeyboard), ES_ICON_INPUT_KEYBOARD, SettingsPageKeyboard, 'E' }, + { INTERFACE_STRING(DesktopSettingsLocalisation), ES_ICON_PREFERENCES_DESKTOP_LOCALE, SettingsPageUnimplemented, 'F' }, // TODO. + { INTERFACE_STRING(DesktopSettingsMouse), ES_ICON_INPUT_MOUSE, SettingsPageMouse, 'G' }, + { INTERFACE_STRING(DesktopSettingsNetwork), ES_ICON_PREFERENCES_SYSTEM_NETWORK, SettingsPageUnimplemented, 'H' }, // TODO. + { INTERFACE_STRING(DesktopSettingsPower), ES_ICON_PREFERENCES_SYSTEM_POWER, SettingsPageUnimplemented, 'J' }, // TODO. + { INTERFACE_STRING(DesktopSettingsSound), ES_ICON_PREFERENCES_DESKTOP_SOUND, SettingsPageUnimplemented, 'K' }, // TODO. + { INTERFACE_STRING(DesktopSettingsTheme), ES_ICON_APPLICATIONS_INTERFACEDESIGN, SettingsPageUnimplemented, 'M' }, // TODO. }; void SettingsButtonPressed(EsInstance *_instance, EsElement *element, EsCommand *) { @@ -493,15 +603,8 @@ void SettingsButtonPressed(EsInstance *_instance, EsElement *element, EsCommand EsPanel *stack = EsPanelCreate(instance->switcher, ES_CELL_FILL | ES_PANEL_Z_STACK); page->create(stack, page); - { - EsPanel *overlay = EsPanelCreate(stack, ES_CELL_H_LEFT | ES_CELL_V_TOP, &styleSettingsOverlayPanel); - EsButton *backButton = EsButtonCreate(overlay, ES_CELL_H_LEFT | ES_BUTTON_TOOLBAR | ES_ELEMENT_STICKY_ACCESS_KEY, 0, INTERFACE_STRING(DesktopSettingsBackButton)); - backButton->accessKey = 'A'; - EsButtonSetIcon(backButton, ES_ICON_GO_HOME_SYMBOLIC); - EsButtonOnCommand(backButton, SettingsBackButton); - } - EsPanelSwitchTo(instance->switcher, stack, ES_TRANSITION_ZOOM_IN, ES_FLAGS_DEFAULT, 1.0f); + EsElementSetDisabled(instance->backButton, false); } void InstanceSettingsCreate(EsMessage *message) { @@ -514,6 +617,27 @@ void InstanceSettingsCreate(EsMessage *message) { instance->mainPage = content; EsPanelSwitchTo(instance->switcher, content, ES_TRANSITION_NONE); + { + EsElement *toolbar = EsWindowGetToolbar(instance->window); + + 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); + EsButtonOnCommand(backButton, SettingsBackButton); + EsElementSetDisabled(backButton, true); + + EsSpacerCreate(toolbar, ES_CELL_FILL); + + 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); + EsButtonOnCommand(undoButton, SettingsUndoButton); + EsElementSetDisabled(undoButton, true); + EsElementSetHidden(undoButton, true); + } + { EsPanel *row = EsPanelCreate(content, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL); EsIconDisplayCreate(row, ES_FLAGS_DEFAULT, ES_STYLE_ICON_DISPLAY, ES_ICON_PREFERENCES_DESKTOP); @@ -531,11 +655,12 @@ void InstanceSettingsCreate(EsMessage *message) { }, nullptr); for (uintptr_t i = 0; i < sizeof(settingsPages) / sizeof(settingsPages[0]); i++) { + SettingsPage *page = &settingsPages[i]; EsButton *button = EsButtonCreate(container, ES_ELEMENT_NO_FOCUS_ON_CLICK | ES_CELL_H_FILL | ES_ELEMENT_STICKY_ACCESS_KEY, - &styleSettingsButton, settingsPages[i].string, settingsPages[i].stringBytes); - button->userData = &settingsPages[i]; - button->accessKey = settingsPages[i].accessKey; - EsButtonSetIcon(button, settingsPages[i].iconID); + &styleSettingsButton, page->string, page->stringBytes); + button->userData = page; + button->accessKey = EsCRTisalpha(page->string[0]) ? page->string[0] : page->accessKey; + EsButtonSetIcon(button, page->iconID); EsButtonOnCommand(button, SettingsButtonPressed); } } diff --git a/kernel/module.h b/kernel/module.h index 1005d40..3e75b30 100644 --- a/kernel/module.h +++ b/kernel/module.h @@ -178,9 +178,6 @@ extern "C" uint64_t ProcessorReadMXCSR(); extern "C" uint64_t KGetTimeInMs(); // Scheduler time. -bool KCopyToUser(K_USER_BUFFER void *destination, const void *source, size_t bytes); -bool KCopyFromUser(void *destination, K_USER_BUFFER const void *source, size_t bytes); - void *KGetRSDP(); size_t KGetCPUCount(); CPULocalStorage *KGetCPULocal(uintptr_t index); diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 1d76b6f..5a6f761 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -2006,24 +2006,4 @@ uintptr_t DoSyscall(EsSyscallType index, return returnValue; } -bool KCopyToUser(K_USER_BUFFER void *destination, const void *source, size_t length) { - __sync_synchronize(); - Thread *currentThread = GetCurrentThread(); - MMRegion *region = MMFindAndPinRegion(currentThread->process->vmm, (uintptr_t) destination, length); - if (!region) return false; - EsMemoryCopy(destination, source, length); - MMUnpinRegion(currentThread->process->vmm, region); - return true; -} - -bool KCopyFromUser(void *destination, K_USER_BUFFER const void *source, size_t length) { - __sync_synchronize(); - Thread *currentThread = GetCurrentThread(); - MMRegion *region = MMFindAndPinRegion(currentThread->process->vmm, (uintptr_t) source, length); - if (!region) return false; - EsMemoryCopy(destination, source, length); - MMUnpinRegion(currentThread->process->vmm, region); - return true; -} - #endif diff --git a/kernel/windows.cpp b/kernel/windows.cpp index 9800a39..9a0609e 100644 --- a/kernel/windows.cpp +++ b/kernel/windows.cpp @@ -2,11 +2,12 @@ // TODO Don't send key released messages if the focused window has changed. // TODO Blur clamping is incorrect with minimal repainting! +// TODO Cursor trails. // Terminology: // Dynamic resize - flicker-free resizing in container windows with an embedded window owned by a separate process. // Direct update - paint first onto the video card's framebuffer, then onto the window manager's; used to reduce latency. -// Fast scroll - scrolling by shifting the bits in the window's surface, rather than repainting the entire area. +// Fast scroll - scrolling by shifting the bits in the window's surface, rather than repainting the entire area. TODO This is currently a bit broken. struct EmbeddedWindow { void Destroy(); diff --git a/res/System Configuration Template.ini b/res/System Configuration Template.ini index 187f5aa..180dc18 100644 --- a/res/System Configuration Template.ini +++ b/res/System Configuration Template.ini @@ -10,6 +10,7 @@ installation_state=0 click_chain_timeout_ms=500 show_cursor_shadow=1 use_cursor_alt_slow=1 +scroll_lines_per_notch=3 [ui] ; User interface settings that are accessible by all applications. diff --git a/res/Theme Source.dat b/res/Theme Source.dat index 2bf4adf9199a24638b53aca9a8bb62e50cc9de30..719c1e7331f7a11758254e504997c8f3fe128a2b 100644 GIT binary patch delta 24 gcmeC^W$x%@-oV?)B*3(pzj3`2W8~)jhfgvA0BKGM5dZ)H delta 24 gcmeC^W$x%@-oV?)#K5?jzj3`2WAx_zhfgvA0BCIq0ssI2 diff --git a/res/Themes/Theme.dat b/res/Themes/Theme.dat index acb9d5b01680a259b393c01b104a9c62e097755b..8b0318cc2fc532857cdca7e4d3a535c9aa4ddd9b 100644 GIT binary patch delta 64 zcmV-G0KfmFnggVo1F#Vf2kh=kY)Kjqt0qnDeT%K^~G)x-?nAj|H&Wt6gFG%&tzl<3QV5BBQkjcFU#gP0uP)x7=R#< UlYwFLmEesWjBhu$#mp-J0JT9IK>z>% diff --git a/shared/strings.cpp b/shared/strings.cpp index 4981adc..0ec8115 100644 --- a/shared/strings.cpp +++ b/shared/strings.cpp @@ -121,6 +121,10 @@ DEFINE_INTERFACE_STRING(DesktopSettingsMouseUseAcceleration, "Move cursor faster DEFINE_INTERFACE_STRING(DesktopSettingsMouseSlowOnAlt, "Move cursor slower when Alt is held"); DEFINE_INTERFACE_STRING(DesktopSettingsMouseSpeedSlow, "Slow"); DEFINE_INTERFACE_STRING(DesktopSettingsMouseSpeedFast, "Fast"); +DEFINE_INTERFACE_STRING(DesktopSettingsMouseCursorTrailsNone, "None"); +DEFINE_INTERFACE_STRING(DesktopSettingsMouseCursorTrailsMany, "Many"); + +DEFINE_INTERFACE_STRING(DesktopSettingsApplicationSelectItem, "Select an application:"); // File operations. diff --git a/util/api_table.ini b/util/api_table.ini index 44645a6..97a5550 100644 --- a/util/api_table.ini +++ b/util/api_table.ini @@ -35,8 +35,6 @@ EsMouseSetPosition=33 EsPaintTargetClear=34 EsCommandSetCheck=35 EsTextboxGetContentsAsDouble=36 -EsListViewGetSelectedFixedItem=37 -EsListViewInsertFixedItem=38 EsDirectoryEnumerateChildren=39 EsPathExists=40 EsInstanceSetClassViewer=41 @@ -337,7 +335,6 @@ EsMenuCreate=335 EsTextPlanReplaceStyleRenderProperties=336 EsInstanceSetActiveUndoManager=337 EsClipboardReadText=338 -EsListViewSelectFixedItem=339 EsSpacerCreate=340 EsTextPlanCreate=341 EsStringEndsWith=342 @@ -421,3 +418,8 @@ EsFileStoreGetSize=419 EsFileStoreMap=420 EsTimerCancel=421 EsSliderSetValue=422 +EsListViewFixedItemInsert=424 +EsListViewFixedItemAddString=425 +EsListViewFixedItemFindIndex=426 +EsListViewFixedItemSelect=427 +EsListViewFixedItemGetSelected=428 diff --git a/util/build_core.c b/util/build_core.c index e76fc2a..d694d9d 100644 --- a/util/build_core.c +++ b/util/build_core.c @@ -559,7 +559,7 @@ void BuildApplication(Application *application) { #ifdef OS_ESSENCE // TODO. #else - system(application->customCompileCommand); + application->error = system(application->customCompileCommand); #endif } else { char symbolFile[256]; diff --git a/util/header_generator.c b/util/header_generator.c index 996d901..1013d0b 100644 --- a/util/header_generator.c +++ b/util/header_generator.c @@ -759,7 +759,7 @@ void OutputOdinRecord(Entry *record, int indent) { } } -void OutputOdinFunction(Entry *entry) { +void OutputOdinFunction(Entry *entry, Entry *root) { bool hasReturnValue = strcmp(entry->children[0].variable.type, "void") || entry->children[0].variable.pointer; for (int i = 0; i < arrlen(entry->children); i++) { @@ -809,7 +809,18 @@ void OutputOdinFunction(Entry *entry) { initialValue = "\"\""; } - FilePrintFormat(output, " = %s", initialValue); + bool needLeadingDot = false; + + for (int i = 0; i < arrlen(root->children); i++) { + Entry *entry = root->children + i; + + if (entry->type == ENTRY_ENUM && 0 == strcmp(variable->variable.type, entry->name)) { + needLeadingDot = true; + break; + } + } + + FilePrintFormat(output, " = %c%s", needLeadingDot ? '.' : ' ', initialValue); } } @@ -871,6 +882,20 @@ void OutputOdinFunction(Entry *entry) { void OutputOdin(Entry *root) { FilePrintFormat(output, "package es\n"); + // HACK Workaround for Odin issue #854. + + for (int i = 0; i < arrlen(root->children); i++) { + Entry *entry = root->children + i; + + if (entry->type == ENTRY_STRUCT && 0 == strcmp(entry->name, "EsElementPublic")) { + FilePrintFormat(output, "%s :: struct {\n", TrimPrefix(entry->name)); + OutputOdinRecord(entry, 0); + FilePrintFormat(output, "}\n"); + arrdel(root->children, i); + break; + } + } + FilePrintFormat(output, "Generic :: rawptr;\n"); FilePrintFormat(output, "INSTANCE_TYPE :: Instance;\n"); @@ -890,7 +915,7 @@ void OutputOdin(Entry *root) { OutputOdinRecord(entry, 0); FilePrintFormat(output, "}\n"); } else if (entry->type == ENTRY_ENUM) { - FilePrintFormat(output, "using %s :: enum i32 {\n", TrimPrefix(entry->name)); + FilePrintFormat(output, "%s :: enum i32 {\n", TrimPrefix(entry->name)); for (int i = 0; i < arrlen(entry->children); i++) { if (entry->children[i].define.value) { @@ -905,7 +930,7 @@ void OutputOdin(Entry *root) { bool hasParent = 0 != strcmp(entry->apiType.parent, "none"); FilePrintFormat(output, "%s :: %s;\n", TrimPrefix(entry->name), hasParent ? TrimPrefix(entry->apiType.parent) : "rawptr"); } else if (entry->type == ENTRY_FUNCTION) { - OutputOdinFunction(entry); + OutputOdinFunction(entry, root); } else if (entry->type == ENTRY_TYPE_NAME) { FilePrintFormat(output, "%s :: %s;\n", TrimPrefix(entry->name), TrimPrefix(OdinReplaceTypes(entry->oldTypeName, true))); }