cursor locator

This commit is contained in:
nakst 2021-08-23 19:07:44 +01:00
parent d74af82763
commit fc013e8485
10 changed files with 105 additions and 26 deletions

View File

@ -260,7 +260,7 @@ EsError NodeOpen(const char *path, size_t pathBytes, uint32_t flags, _EsNodeInfo
return EsSyscall(ES_SYSCALL_NODE_OPEN, (uintptr_t) path, pathBytes, flags, (uintptr_t) node);
}
EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes) {
EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, bool createIfNeeded = false) {
if (keyBytes == -1) keyBytes = EsCStringLength(key);
for (uintptr_t i = 0; i < group->itemCount; i++) {
@ -269,10 +269,23 @@ EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup
}
}
if (createIfNeeded) {
EsSystemConfigurationItem item = {};
item.key = (char *) EsHeapAllocate(keyBytes, false);
item.keyBytes = keyBytes;
EsMemoryCopy(item.key, key, keyBytes);
Array<EsSystemConfigurationItem> items = { group->items };
EsSystemConfigurationItem *_item = items.Add(item);
group->items = items.array;
group->itemCount++;
return _item;
}
return nullptr;
}
EsSystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptrdiff_t sectionBytes) {
EsSystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptrdiff_t sectionBytes, bool createIfNeeded = false) {
if (sectionBytes == -1) sectionBytes = EsCStringLength(section);
for (uintptr_t i = 0; i < api.systemConfigurationGroups.Length(); i++) {
@ -281,6 +294,14 @@ EsSystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptr
}
}
if (createIfNeeded) {
EsSystemConfigurationGroup group = {};
group.section = (char *) EsHeapAllocate(sectionBytes, false);
group.sectionBytes = sectionBytes;
EsMemoryCopy(group.section, section, sectionBytes);
return api.systemConfigurationGroups.Add(group);
}
return nullptr;
}
@ -791,7 +812,7 @@ EsMessage *EsMessageReceive() {
EsMessageSend((EsElement *) message.object, &message.message);
} else if (type == ES_MSG_TIMER) {
((EsTimerCallbackFunction) message.message.user.context1.p)(message.message.user.context2);
} else if (type >= ES_MSG_WM_START && type <= ES_MSG_WM_END) {
} else if (type >= ES_MSG_WM_START && type <= ES_MSG_WM_END && message.object) {
#if 0
ProcessMessageTiming timing = {};
double start = EsTimeStampMs();
@ -802,11 +823,9 @@ EsMessage *EsMessageReceive() {
timing.endLayout - timing.startLayout,
timing.endPaint - timing.startPaint,
timing.endUpdate - timing.startUpdate);
#else
UIProcessWindowManagerMessage((EsWindow *) message.object, &message.message, nullptr);
#endif
if (message.object) {
UIProcessWindowManagerMessage((EsWindow *) message.object, &message.message, nullptr);
}
} else if (type == ES_MSG_TAB_INSPECT_UI) {
EsInstance *_instance = InstanceFromWindowID(message.message.tabOperation.id);

View File

@ -2019,6 +2019,30 @@ void EmbeddedWindowDestroyed(EsObjectID id) {
EsHeapFree(instance);
}
int CursorLocatorMessage(EsElement *element, EsMessage *message) {
EsWindow *window = element->window;
if (message->type == ES_MSG_ANIMATE) {
window->announcementTimeMs += message->animate.deltaMs;
double progress = window->announcementTimeMs / GetConstantNumber("cursorLocatorDuration");
if (progress > 1) {
EsElementDestroy(window);
} else {
EsElementRelayout(element);
message->animate.complete = false;
return ES_HANDLED;
}
} else if (message->type == ES_MSG_LAYOUT) {
EsElement *child = element->GetChild(0);
double progress = 1.0 - window->announcementTimeMs / GetConstantNumber("cursorLocatorDuration");
int width = progress * child->GetWidth(0), height = progress * child->GetHeight(0);
child->InternalMove(width, height, (element->width - width) / 2, (element->height - height) / 2);
}
return 0;
}
void DesktopMessage(EsMessage *message) {
if (message->type == ES_MSG_POWER_BUTTON_PRESSED) {
ShutdownModalCreate();
@ -2089,6 +2113,19 @@ void DesktopMessage(EsMessage *message) {
} else {
// The screen resolution will be correctly queried in DesktopSetup.
}
} else if (message->type == ES_MSG_SINGLE_CTRL_PRESS) {
if (EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("locate_cursor_on_ctrl"))) {
EsPoint position = EsMouseGetPosition();
EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_TIP);
EsElement *wrapper = EsCustomElementCreate(window, ES_CELL_FILL, ES_STYLE_CLEAR_BACKGROUND);
wrapper->messageUser = CursorLocatorMessage;
window->announcementBase = position;
EsElement *element = EsCustomElementCreate(wrapper, ES_CELL_FILL, ES_STYLE_CURSOR_LOCATOR);
int width = element->GetWidth(0), height = element->GetHeight(0);
EsRectangle bounds = ES_RECT_4PD(position.x - width / 2, position.y - height / 2, width, height);
EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &bounds, 0, ES_WINDOW_MOVE_ALWAYS_ON_TOP);
wrapper->StartAnimating();
}
} else if (message->type == MSG_SETUP_DESKTOP_UI) {
DesktopSetup();
}

View File

@ -449,7 +449,7 @@ struct EsWindow : EsElement {
EsElement *source; // Menu source.
EsWindow *targetMenu; // The menu that keyboard events should be sent to.
int32_t announcementBaseY;
EsPoint announcementBase;
double announcementTimeMs;
};
@ -3582,7 +3582,6 @@ int AnnouncementMessage(EsElement *element, EsMessage *message) {
double progress = window->announcementTimeMs / GetConstantNumber("announcementDuration");
if (progress > 1) {
progress = 1;
EsElementDestroy(window);
return 0;
}
@ -3595,7 +3594,7 @@ int AnnouncementMessage(EsElement *element, EsMessage *message) {
EsRectangle bounds = EsWindowGetBounds(window);
int32_t height = Height(bounds);
bounds.t = window->announcementBaseY - inOnly * GetConstantNumber("announcementMovement");
bounds.t = window->announcementBase.y - inOnly * GetConstantNumber("announcementMovement");
bounds.b = bounds.t + height;
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, 0xFF * inOut, 0, ES_WINDOW_PROPERTY_ALPHA);
@ -3619,11 +3618,12 @@ void EsAnnouncementShow(EsWindow *parent, uint64_t flags, int32_t x, int32_t y,
int32_t width = display->GetWidth(0);
int32_t height = display->GetHeight(width);
EsRectangle parentBounds = EsWindowGetBounds(parent);
EsRectangle parentBounds = {};
if (parent) parentBounds = EsWindowGetBounds(parent);
EsRectangle bounds = ES_RECT_4PD(x - width / 2 + parentBounds.l, y - height + parentBounds.t, width, height);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, 0x00, 0, ES_WINDOW_PROPERTY_ALPHA);
EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &bounds, 0, ES_WINDOW_MOVE_ADJUST_TO_FIT_SCREEN | ES_WINDOW_MOVE_ALWAYS_ON_TOP);
window->announcementBaseY = EsWindowGetBounds(window).t;
window->announcementBase.y = EsWindowGetBounds(window).t;
window->StartAnimating();
}
@ -6003,11 +6003,14 @@ void AccessKeyModeHandleKeyPress(EsMessage *message) {
return;
}
EsWindow *window = gui.accessKeys.window;
int ic, isc;
ConvertScancodeToCharacter(message->keyboard.scancode, &ic, &isc, false, false);
ic = EsCRTtoupper(ic);
bool keepAccessKeyModeActive = false;
bool regatherKeys = false;
if (ic >= 'A' && ic <= 'Z' && !gui.accessKeys.typedCharacter) {
if (gui.accessKeys.numbers[ic - 'A'] > 1) {
@ -6023,6 +6026,7 @@ void AccessKeyModeHandleKeyPress(EsMessage *message) {
EsElementFocus(entry->element, ES_ELEMENT_FOCUS_ENSURE_VISIBLE | ES_ELEMENT_FOCUS_FROM_KEYBOARD);
keepAccessKeyModeActive = entry->element->flags & ES_ELEMENT_STICKY_ACCESS_KEY;
regatherKeys = true;
}
}
}
@ -6036,14 +6040,19 @@ void AccessKeyModeHandleKeyPress(EsMessage *message) {
EsElementFocus(entry->element, ES_ELEMENT_FOCUS_ENSURE_VISIBLE | ES_ELEMENT_FOCUS_FROM_KEYBOARD);
keepAccessKeyModeActive = entry->element->flags & ES_ELEMENT_STICKY_ACCESS_KEY;
regatherKeys = true;
}
}
}
if (!keepAccessKeyModeActive) {
AccessKeyModeExit();
} else if (regatherKeys) {
AccessKeyModeExit();
window->InternalMove(window->width, window->height, 0, 0);
AccessKeyModeEnter(window);
} else {
gui.accessKeys.window->Repaint(true);
window->Repaint(true);
}
}

View File

@ -954,6 +954,7 @@ enum EsMessageType {
ES_MSG_DESKTOP = 0x4806
ES_MSG_DEVICE_CONNECTED = 0x4807
ES_MSG_DEVICE_DISCONNECTED = 0x4808
ES_MSG_SINGLE_CTRL_PRESS = 0x4809
// Messages sent from Desktop to application instances:
ES_MSG_TAB_INSPECT_UI = 0x4A01

View File

@ -121,8 +121,8 @@ void SettingsNumberBoxSetValue(EsElement *element, int32_t newValue) {
EsTextboxInsert(textbox, buffer, bytes);
EsMutexAcquire(&api.systemConfigurationMutex);
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1); // TODO Create if needed.
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1); // TODO Create if needed.
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true);
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
int32_t oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value);
item->value = (char *) EsHeapAllocate(65, true);
@ -162,7 +162,7 @@ void SettingsAddTitle(EsElement *container, SettingsPage *page) {
void SettingsAddUndoButton(EsElement *stack) {
EsPanel *overlay = EsPanelCreate(stack, ES_CELL_H_RIGHT | ES_CELL_V_TOP, &styleSettingsOverlayPanel);
EsButton *undoButton = EsButtonCreate(overlay, ES_BUTTON_TOOLBAR, 0, INTERFACE_STRING(DesktopSettingsUndoButton));
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);
@ -184,8 +184,8 @@ void SettingsCheckboxCommand(EsInstance *_instance, EsElement *element, EsComman
bool newValue = EsButtonGetCheck(button) == ES_CHECK_CHECKED;
EsMutexAcquire(&api.systemConfigurationMutex);
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1); // TODO Create if needed.
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1); // TODO Create if needed.
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true);
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
bool oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value);
item->value = (char *) EsHeapAllocate(2, true);
@ -209,7 +209,7 @@ void SettingsAddCheckbox(EsElement *table, const char *string, ptrdiff_t stringB
control->globalPointerBool = globalPointerBool;
control->originalValueBool = EsSystemConfigurationReadInteger(control->cConfigurationSection, -1, control->cConfigurationKey, -1);
EsButton *button = EsButtonCreate(table, ES_CELL_H_FILL | ES_BUTTON_CHECKBOX | ES_ELEMENT_FREE_USER_DATA, 0, string, stringBytes);
EsButton *button = EsButtonCreate(table, ES_CELL_H_FILL | ES_BUTTON_CHECKBOX | ES_ELEMENT_FREE_USER_DATA | ES_ELEMENT_STICKY_ACCESS_KEY, 0, string, stringBytes);
button->userData = control;
button->accessKey = accessKey;
if (control->originalValueBool) EsButtonSetCheck(button, ES_CHECK_CHECKED, false);
@ -327,8 +327,10 @@ void SettingsPageMouse(EsElement *element, SettingsPage *page) {
table = EsPanelCreate(container, ES_CELL_H_FILL, &styleSettingsCheckboxGroup);
SettingsAddCheckbox(table, INTERFACE_STRING(DesktopSettingsMouseSwapLeftAndRightButtons), 'B',
"general", "swap_left_and_right_buttons", &api.global->swapLeftAndRightButtons);
EsButtonCreate(table, ES_CELL_H_FILL | ES_BUTTON_CHECKBOX, 0, INTERFACE_STRING(DesktopSettingsMouseShowShadow))->accessKey = 'W'; // TODO.
EsButtonCreate(table, ES_CELL_H_FILL | ES_BUTTON_CHECKBOX, 0, INTERFACE_STRING(DesktopSettingsMouseLocateCursorOnCtrl))->accessKey = 'L'; // TODO.
SettingsAddCheckbox(table, INTERFACE_STRING(DesktopSettingsMouseShowShadow), 'W',
"general", "show_cursor_shadow", nullptr); // TODO.
SettingsAddCheckbox(table, INTERFACE_STRING(DesktopSettingsMouseLocateCursorOnCtrl), 'L',
"general", "locate_cursor_on_ctrl", nullptr);
EsSpacerCreate(container, ES_CELL_H_FILL, ES_STYLE_BUTTON_GROUP_SEPARATOR);
@ -407,7 +409,7 @@ void SettingsButtonPressed(EsInstance *_instance, EsElement *element, EsCommand
{
EsPanel *overlay = EsPanelCreate(stack, ES_CELL_H_LEFT | ES_CELL_V_TOP, &styleSettingsOverlayPanel);
EsButton *backButton = EsButtonCreate(overlay, ES_CELL_H_LEFT | ES_BUTTON_TOOLBAR, 0, INTERFACE_STRING(DesktopSettingsBackButton));
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);
@ -443,7 +445,7 @@ void InstanceSettingsCreate(EsMessage *message) {
}, nullptr);
for (uintptr_t i = 0; i < sizeof(settingsPages) / sizeof(settingsPages[0]); i++) {
EsButton *button = EsButtonCreate(container, ES_ELEMENT_NO_FOCUS_ON_CLICK | ES_CELL_H_FILL,
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;

View File

@ -10,6 +10,7 @@ define ES_STYLE_BUTTON_GROUP_SEPARATOR (ES_STYLE_CAST(1233))
define_private ES_STYLE_CANVAS_SHADOW (ES_STYLE_CAST(1451))
define_private ES_STYLE_CHECKBOX_NORMAL (ES_STYLE_CAST(1559))
define_private ES_STYLE_CHECKBOX_RADIOBOX (ES_STYLE_CAST(1567))
define ES_STYLE_CLEAR_BACKGROUND (ES_STYLE_CAST(1597))
define_private ES_STYLE_COLOR_CHOSEN_POINT (ES_STYLE_CAST(1241))
define_private ES_STYLE_COLOR_CIRCLE (ES_STYLE_CAST(1243))
define_private ES_STYLE_COLOR_HEX_TEXTBOX (ES_STYLE_CAST(1245))
@ -17,6 +18,7 @@ define_private ES_STYLE_COLOR_PICKER_MAIN_PANEL (ES_STYLE_CAST(1247))
define_private ES_STYLE_COLOR_SLIDER (ES_STYLE_CAST(1249))
define_private ES_STYLE_CONTAINER_WINDOW_ACTIVE (ES_STYLE_CAST(1251))
define_private ES_STYLE_CONTAINER_WINDOW_INACTIVE (ES_STYLE_CAST(1255))
define_private ES_STYLE_CURSOR_LOCATOR (ES_STYLE_CAST(1591))
define ES_STYLE_DIALOG_BUTTON_AREA (ES_STYLE_CAST(1259))
define ES_STYLE_DIALOG_CONTENT (ES_STYLE_CAST(1261))
define ES_STYLE_DIALOG_HEADING (ES_STYLE_CAST(1263))

View File

@ -123,6 +123,7 @@ struct WindowManager {
// Miscellaneous:
EsRectangle workArea;
bool inSingleCtrlPress;
// Game controllers:
@ -181,8 +182,6 @@ void SendMessageToWindow(Window *window, EsMessage *message) {
return;
}
window->lastEmbedKeyboardMessage.type = ES_MSG_INVALID;
if (message->type == ES_MSG_WINDOW_RESIZED) {
message->windowResized.content = ES_RECT_4(0, window->width, 0, window->height);
window->owner->messageQueue.SendMessage(window->apiWindow, message);
@ -309,6 +308,17 @@ void WindowManager::PressKey(unsigned scancode) {
KernelPanic("WindowManager::PressKey - Panic key pressed.\n");
}
if (scancode == ES_SCANCODE_LEFT_CTRL) {
inSingleCtrlPress = true;
} else if (scancode == (ES_SCANCODE_LEFT_CTRL | K_SCANCODE_KEY_RELEASED) && inSingleCtrlPress) {
EsMessage m;
EsMemoryZero(&m, sizeof(EsMessage));
m.type = ES_MSG_SINGLE_CTRL_PRESS;
desktopProcess->messageQueue.SendMessage(nullptr, &m);
} else {
inSingleCtrlPress = false;
}
if (eyedropping) {
if (scancode == (ES_SCANCODE_ESCAPE | K_SCANCODE_KEY_RELEASED)) {
EndEyedrop(true);

View File

@ -8,7 +8,6 @@ settings_path=0:/Settings
default_user_documents_path=0:/
installation_state=0
click_chain_timeout_ms=500
swap_left_and_right_buttons=0
[ui]
; User interface settings that are accessible by all applications.

Binary file not shown.

Binary file not shown.