start designer rewrite

This commit is contained in:
nakst 2021-09-28 20:53:11 +01:00
parent 78ab907d00
commit fe5b3adb7b
12 changed files with 1793 additions and 55 deletions

View File

@ -716,7 +716,7 @@ void InstanceCreate(EsMessage *message) {
EsButton *button;
EsToolbarAddFileMenu(toolbar);
EsFileMenuAddToToolbar(toolbar);
button = EsButtonCreate(toolbar, ES_BUTTON_DROPDOWN, ES_STYLE_PUSH_BUTTON_TOOLBAR_BIG, INTERFACE_STRING(ImageEditorImage));
EsButtonSetIcon(button, ES_ICON_IMAGE_X_GENERIC);
button->accessKey = 'I';

View File

@ -281,7 +281,7 @@ void ProcessApplicationMessage(EsMessage *message) {
EsElement *toolbarMain = instance->toolbarMain = EsWindowGetToolbar(window, true);
EsToolbarAddFileMenu(toolbarMain);
EsFileMenuAddToToolbar(toolbarMain);
button = EsButtonCreate(toolbarMain, ES_FLAGS_DEFAULT, {}, INTERFACE_STRING(CommonSearchOpen));
button->accessKey = 'S';

View File

@ -703,11 +703,14 @@ void InstanceClose(EsInstance *instance) {
EsDialogAddButton(dialog, ES_FLAGS_DEFAULT, ES_STYLE_PUSH_BUTTON_DANGEROUS, INTERFACE_STRING(FileCloseWithModificationsDelete),
[] (EsInstance *instance, EsElement *, EsCommand *) {
EsDialogClose(instance->window->dialogs.Last());
EsInstanceDestroy(instance);
});
EsButton *button = EsDialogAddButton(dialog, ES_BUTTON_DEFAULT, 0, INTERFACE_STRING(FileCloseWithModificationsSave),
[] (EsInstance *instance, EsElement *, EsCommand *) {
EsDialogClose(instance->window->dialogs.Last());
APIInstance *apiInstance = (APIInstance *) instance->_private;
if (apiInstance->startupInformation->filePathBytes) {
@ -1288,7 +1291,7 @@ EsMessage *EsMessageReceive() {
}
}
void InstanceSetModified(EsInstance *instance, bool modified) {
void EsInstanceSetModified(EsInstance *instance, bool modified) {
EsCommandSetEnabled(EsCommandByID(instance, ES_COMMAND_SAVE), modified);
uint8_t m[2];
@ -1330,7 +1333,7 @@ void EsInstanceOpenComplete(EsMessage *message, bool success, const char *errorT
EsUndoClear(instance->undoManager);
}
InstanceSetModified(instance, false);
EsInstanceSetModified(instance, false);
}
EsAssert(!message->instanceOpen.file->operationComplete);
@ -1359,7 +1362,7 @@ void EsInstanceSaveComplete(EsMessage *message, bool success) {
MessageDesktop(buffer, 1, instance->window->handle);
if (success) {
InstanceSetModified(instance, false);
EsInstanceSetModified(instance, false);
EsRectangle bounds = EsElementGetWindowBounds(instance->window->toolbarSwitcher);
size_t messageBytes;
char *message = EsStringAllocateAndFormat(&messageBytes, "Saved to %s", // TODO Localization.
@ -1763,7 +1766,7 @@ void EsUndoPush(EsUndoManager *manager, EsUndoCallback callback, const void *ite
}
if (manager->instance->undoManager == manager) {
InstanceSetModified(manager->instance, true);
EsInstanceSetModified(manager->instance, true);
}
}

View File

@ -1471,7 +1471,7 @@ bool ApplicationInstanceStart(int64_t applicationID, _EsApplicationStartupInform
if (desktop.inShutdown) {
return false;
}
InstalledApplication *application = nullptr;
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
@ -1499,6 +1499,10 @@ bool ApplicationInstanceStart(int64_t applicationID, _EsApplicationStartupInform
startupInformation = &_startupInformation;
}
if (instance->tab) {
EsButtonSetCheck(instance->tab->closeButton, ES_CHECK_UNCHECKED, false);
}
if (instance->tab && instance->tab->notRespondingInstance) {
ApplicationInstanceClose(instance->tab->notRespondingInstance);
instance->tab->notRespondingInstance = nullptr;

View File

@ -5526,7 +5526,7 @@ void FileMenuRename(EsInstance *_instance, EsElement *, EsCommand *) {
instance->fileMenuNameTextbox->messageUser = FileMenuNameTextboxMessage;
}
void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
void EsFileMenuCreate(EsInstance *_instance, EsElement *element, uint64_t menuFlags) {
// TODO Make this user-customizable?
// const EsFileMenuSettings *settings = (const EsFileMenuSettings *) element->userData.p;
@ -5535,7 +5535,7 @@ void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
EsInstanceClassEditorSettings *editorSettings = &instance->editorSettings;
bool newDocument = !instance->startupInformation || !instance->startupInformation->filePath;
EsMenu *menu = EsMenuCreate(element, ES_FLAGS_DEFAULT);
EsMenu *menu = EsMenuCreate(element, menuFlags);
if (!menu) return;
EsPanel *panel1 = EsPanelCreate(menu, ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel1);
if (!panel1) goto show;
@ -5611,7 +5611,11 @@ void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
show: EsMenuShow(menu);
}
void EsToolbarAddFileMenu(EsElement *element, const EsFileMenuSettings *settings) {
void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
EsFileMenuCreate(_instance, element);
}
void EsFileMenuAddToToolbar(EsElement *element, const EsFileMenuSettings *settings) {
EsButton *button = EsButtonCreate(element, ES_BUTTON_DROPDOWN, 0, INTERFACE_STRING(CommonFileMenu));
if (!button) return;
button->accessKey = 'F';

View File

@ -2313,6 +2313,7 @@ function void EsInstanceSetClassViewer(ES_INSTANCE_TYPE *instance, const EsInsta
function EsApplicationStartupRequest EsInstanceGetStartupRequest(ES_INSTANCE_TYPE *instance);
function void EsInstanceOpenComplete(EsMessage *message, bool success, STRING errorText = BLANK_STRING);
function void EsInstanceSaveComplete(EsMessage *message, bool success);
function void EsInstanceSetModified(ES_INSTANCE_TYPE *instance, bool modified);
function EsError EsUserTaskStart(EsUserTaskCallback callback, EsGeneric data, STRING title, uint32_t iconID);
function void EsUserTaskSetProgress(EsUserTask *task, double progress, EsFileOffsetDifference bytesPerSecond); // Set bytesPerSecond to -1 if not applicable.
@ -2389,7 +2390,8 @@ function EsDialog *EsDialogShow(EsWindow *window, STRING title, STRING content,
function EsButton *EsDialogAddButton(EsDialog *dialog, uint64_t flags = ES_FLAGS_DEFAULT, EsStyle *style = ES_NULL,
STRING label = BLANK_STRING, EsCommandCallback callback = ES_NULL);
function void EsToolbarAddFileMenu(EsElement *element, const EsFileMenuSettings *settings = ES_NULL);
function void EsFileMenuAddToToolbar(EsElement *toolbar, const EsFileMenuSettings *settings = ES_NULL);
function void EsFileMenuCreate(ES_INSTANCE_TYPE *instance, EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT);
private function EsHandle _EsWindowGetHandle(EsWindow *window);
private function void _EsUISetFont(EsFontFamily id);

View File

@ -1323,7 +1323,7 @@ void EsMemoryZero(void *destination, size_t bytes) {
}
void EsMemoryMove(void *_start, void *_end, intptr_t amount, bool zeroEmptySpace) {
// TODO Prevent this from being optimised out in the kernel./
// TODO Prevent this from being optimised out in the kernel.
uint8_t *start = (uint8_t *) _start;
uint8_t *end = (uint8_t *) _end;

View File

@ -363,7 +363,6 @@ EsWindowAddSizeAlternative=361
EsMenuAddCommandsFromToolbar=362
EsPanelStartMovementAnimation=363
EsElementStartTransition=364
EsToolbarAddFileMenu=365
EsFileWriteAllFromHandle=366
EsFileWriteAllGatherFromHandle=367
EsButtonSetIconFromBits=368
@ -462,3 +461,6 @@ EsInstanceGetStartupRequest=460
EsImageDisplayPaint=461
EsElementGetInsetBounds=462
EsDialogShow=463
EsInstanceSetModified=464
EsFileMenuAddToToolbar=465
EsFileMenuCreate=466

View File

@ -334,6 +334,7 @@ void BuildUtilities() {
#ifndef __APPLE__ // Luigi doesn't support macOS.
BUILD_UTILITY("config_editor", "-lX11 -Wno-unused-parameter", "");
#endif
#ifndef __APPLE__ // Luigi doesn't support macOS.
BUILD_UTILITY("reflect_gen", "", "designer/");
if (CheckDependencies("Utilities.DesignerHeader")) {
@ -345,8 +346,7 @@ void BuildUtilities() {
}
}
#ifndef __APPLE__ // Luigi doesn't support macOS.
if (CheckDependencies("Utilities.Designer1") || CheckDependencies("Utilities.Designer2")) {
if (CheckDependencies("Utilities.OldDesigner1") || CheckDependencies("Utilities.OldDesigner2")) {
if (!CallSystem("gcc -MMD -o bin/designer.o -c util/designer/designer.c -g -std=c2x -fsanitize=address " WARNING_FLAGS_C)
&& !CallSystem("gcc -MMD -o bin/designer_luigi.o -c util/designer/designer_luigi.c -g -std=c2x " WARNING_FLAGS_C)
&& !CallSystem("gcc -o bin/designer -g bin/designer.o bin/designer_luigi.o -lX11 -lm -fsanitize=address ")) {
@ -354,6 +354,12 @@ void BuildUtilities() {
ParseDependencies("bin/designer_luigi.d", "Utilities.Designer2", false);
}
}
if (CheckDependencies("Utilities.Designer")) {
if (!CallSystem("g++ -MMD -D UI_LINUX util/designer2.cpp -o bin/designer2 -g -lX11 -Wno-unused-parameter " WARNING_FLAGS)) {
ParseDependencies("bin/designer2.d", "Utilities.Designer", false);
}
}
#endif
}
@ -1174,6 +1180,9 @@ void DoCommand(const char *l) {
} else if (0 == strcmp(l, "designer")) {
BuildUtilities();
CallSystem("bin/designer \"res/Theme Source.dat\" \"res/Themes/Theme.dat\" \"res/Cursors.png\" \"desktop/styles.header\"");
} else if (0 == strcmp(l, "designer2")) {
BuildUtilities();
CallSystem("bin/designer2");
} else if (0 == strcmp(l, "replace-many")) {
forceRebuild = true;
printf("Enter the name of the replacement file: ");

1587
util/designer2.cpp Normal file

File diff suppressed because it is too large Load Diff

16
util/designer2.ini Normal file
View File

@ -0,0 +1,16 @@
[general]
name=Designer
icon=icon_applications_interfacedesign
[build]
source=util/designer2.cpp
compile_flags=-D UI_ESSENCE -Wno-unused-parameter
[@file_type]
extension=designer
name=Designer file
icon=icon_text_css
[@handler]
extension=designer
action=open

View File

@ -22,6 +22,8 @@
#define _UI_TO_STRING_2(x) _UI_TO_STRING_1(x)
#ifdef UI_WINDOWS
#undef _UNICODE
#undef UNICODE
#include <windows.h>
#define UI_ASSERT(x) do { if (!(x)) { ui.assertionFailure = true; \
@ -64,6 +66,9 @@
#define UI_CLOCK EsTimeStampMs
#define UI_CLOCKS_PER_SECOND 1000
#define UI_CLOCK_T uint64_t
// Callback to allow the application to process messages.
void _UIMessageProcess(EsMessage *message);
#endif
#ifdef UI_DEBUG
@ -97,7 +102,7 @@ typedef struct UITheme {
#define UI_SIZE_TEXTBOX_MARGIN (3)
#define UI_SIZE_TEXTBOX_WIDTH (200)
#define UI_SIZE_TEXTBOX_HEIGHT (25)
#define UI_SIZE_TEXTBOX_HEIGHT (27)
#define UI_SIZE_TAB_PANE_SPACE_TOP (2)
#define UI_SIZE_TAB_PANE_SPACE_LEFT (4)
@ -335,6 +340,7 @@ typedef struct UIWindow {
#define UI_WINDOW_MENU (1 << 0)
#define UI_WINDOW_INSPECTOR (1 << 1)
#define UI_WINDOW_CENTER_IN_OWNER (1 << 2)
#define UI_WINDOW_MAXIMIZE (1 << 3)
UIElement e;
@ -483,14 +489,20 @@ typedef struct UITextbox {
ptrdiff_t bytes;
int carets[2];
int scroll;
bool rejectNextKey;
} UITextbox;
typedef struct UIMenu {
#define UI_MENU_PLACE_ABOVE (1 << 0)
#define UI_MENU_NO_SCROLL (1 << 1)
#ifdef UI_ESSENCE
typedef EsMenu UIMenu;
#else
typedef struct UIMenu {
UIElement e;
int pointX, pointY;
UIScrollBar *vScroll;
} UIMenu;
#endif
typedef struct UISlider {
UIElement e;
@ -596,7 +608,7 @@ void UICodeInsertContent(UICode *code, const char *content, ptrdiff_t byteCount,
void UIDrawBlock(UIPainter *painter, UIRectangle rectangle, uint32_t color);
void UIDrawInvert(UIPainter *painter, UIRectangle rectangle);
void UIDrawLine(UIPainter *painter, int x0, int y0, int x1, int y1, uint32_t color);
bool UIDrawLine(UIPainter *painter, int x0, int y0, int x1, int y1, uint32_t color); // Returns false if the line was not visible.
void UIDrawGlyph(UIPainter *painter, int x, int y, int c, uint32_t color);
void UIDrawRectangle(UIPainter *painter, UIRectangle r, uint32_t mainColor, uint32_t borderColor, UIRectangle borderSize);
void UIDrawBorder(UIPainter *painter, UIRectangle r, uint32_t borderColor, UIRectangle borderSize);
@ -685,6 +697,9 @@ struct {
#ifdef UI_ESSENCE
EsInstance *instance;
void *menuData[256]; // HACK This limits the number of menu items to 128.
uintptr_t menuIndex;
#endif
#ifdef UI_FREETYPE
@ -1072,10 +1087,22 @@ void UIDrawBlock(UIPainter *painter, UIRectangle rectangle, uint32_t color) {
return;
}
#ifdef UI_SSE2
__m128i color4 = _mm_set_epi32(color, color, color, color);
#endif
for (int line = rectangle.t; line < rectangle.b; line++) {
uint32_t *bits = painter->bits + line * painter->width + rectangle.l;
int count = UI_RECT_WIDTH(rectangle);
#ifdef UI_SSE2
while (count >= 4) {
_mm_storeu_si128((__m128i *) bits, color4);
bits += 4;
count -= 4;
}
#endif
while (count--) {
*bits++ = color;
}
@ -1086,26 +1113,38 @@ void UIDrawBlock(UIPainter *painter, UIRectangle rectangle, uint32_t color) {
#endif
}
void UIDrawLine(UIPainter *painter, int x0, int y0, int x1, int y1, uint32_t color) {
// Clip the line to the painter's clip rectangle.
bool UIDrawLine(UIPainter *painter, int x0, int y0, int x1, int y1, uint32_t color) {
// Apply the clip.
if (x0 > x1) { int t = x0; x0 = x1; x1 = t; }
if (y0 > y1) { int t = y0; y0 = y1; y1 = t; }
UIRectangle bounds = UIRectangleIntersection(painter->clip, UI_RECT_4(x0, x1, y0, y1));
UIRectangle c = painter->clip;
int dx = x1 - x0, dy = y1 - y0;
int points[8], count = 0;
int iLY = dx ? (y0 + (bounds.l - x0) * dy / dx) : 0x7FFFFFFF;
int iRY = dx ? (y0 + (bounds.r - x0) * dy / dx) : 0x7FFFFFFF;
int iTX = dy ? (x0 + (bounds.t - y0) * dx / dy) : 0x7FFFFFFF;
int iBX = dy ? (x0 + (bounds.b - y0) * dx / dy) : 0x7FFFFFFF;
if (iLY >= bounds.t && iLY <= bounds.b) points[count + 0] = bounds.l, points[count + 1] = iLY, count += 2;
if (iRY >= bounds.t && iRY <= bounds.b) points[count + 0] = bounds.r, points[count + 1] = iRY, count += 2;
if (iTX >= bounds.l && iTX <= bounds.r) points[count + 1] = bounds.t, points[count + 0] = iTX, count += 2;
if (iBX >= bounds.l && iBX <= bounds.r) points[count + 1] = bounds.b, points[count + 0] = iBX, count += 2;
if (count < 4) return;
x0 = points[0], y0 = points[1], x1 = points[2], y1 = points[3];
if (x0 == x1 && y0 == y1 && count > 4) x1 = points[4], y1 = points[5];
const int p[4] = { -dx, dx, -dy, dy };
const int q[4] = { x0 - c.l, c.r - x0, y0 - c.t, c.b - y0 };
float t0 = 0.0f, t1 = 1.0f; // How far along the line the points end up.
for (int i = 0; i < 4; i++) {
if (!p[i] && q[i] < 0) return false;
float r = (float) q[i] / p[i];
if (p[i] < 0 && r > t1) return false;
if (p[i] > 0 && r < t0) return false;
if (p[i] < 0 && r > t0) t0 = r;
if (p[i] > 0 && r < t1) t1 = r;
}
x1 = x0 + t1 * dx, y1 = y0 + t1 * dy;
x0 += t0 * dx, y0 += t0 * dy;
// Calculate the delta X and delta Y.
if (y1 < y0) {
int t;
t = x0, x0 = x1, x1 = t;
t = y0, y0 = y1, y1 = t;
}
dx = x1 - x0, dy = y1 - y0;
int dxs = dx < 0 ? -1 : 1;
if (dx < 0) dx = -dx;
// Draw the line using Bresenham's line algorithm.
@ -1114,7 +1153,7 @@ void UIDrawLine(UIPainter *painter, int x0, int y0, int x1, int y1, uint32_t col
if (dy * dy < dx * dx) {
int m = 2 * dy - dx;
for (int i = 0; i < dx; i++, bits++) {
for (int i = 0; i < dx; i++, bits += dxs) {
*bits = color;
if (m > 0) bits += painter->width, m -= 2 * dx;
m += 2 * dy;
@ -1124,10 +1163,12 @@ void UIDrawLine(UIPainter *painter, int x0, int y0, int x1, int y1, uint32_t col
for (int i = 0; i < dy; i++, bits += painter->width) {
*bits = color;
if (m > 0) bits++, m -= 2 * dy;
if (m > 0) bits += dxs, m -= 2 * dy;
m += 2 * dx;
}
}
return true;
}
void UIDrawInvert(UIPainter *painter, UIRectangle rectangle) {
@ -1645,6 +1686,20 @@ UIPanel *UIPanelCreate(UIElement *parent, uint32_t flags) {
return panel;
}
void _UIButtonCalculateColors(UIElement *element, uint32_t *color, uint32_t *textColor) {
bool disabled = element->flags & UI_ELEMENT_DISABLED;
bool focused = element == element->window->focused;
bool pressed = element == element->window->pressed;
bool hovered = element == element->window->hovered;
*color = disabled ? ui.theme.buttonDisabled
: (pressed && hovered) ? ui.theme.buttonPressed
: (pressed || hovered) ? ui.theme.buttonHovered
: focused ? ui.theme.selected : ui.theme.buttonNormal;
*textColor = disabled ? ui.theme.textDisabled
: *color == ui.theme.selected ? ui.theme.textSelected : ui.theme.text;
}
int _UIButtonMessage(UIElement *element, UIMessage message, int di, void *dp) {
UIButton *button = (UIButton *) element;
bool isMenuItem = element->flags & UI_BUTTON_MENU_ITEM;
@ -1668,16 +1723,8 @@ int _UIButtonMessage(UIElement *element, UIMessage message, int di, void *dp) {
} else if (message == UI_MSG_PAINT) {
UIPainter *painter = (UIPainter *) dp;
bool disabled = element->flags & UI_ELEMENT_DISABLED;
bool focused = element == element->window->focused;
bool pressed = element == element->window->pressed;
bool hovered = element == element->window->hovered;
uint32_t color = disabled ? ui.theme.buttonDisabled
: (pressed && hovered) ? ui.theme.buttonPressed
: (pressed || hovered) ? ui.theme.buttonHovered
: focused ? ui.theme.selected : ui.theme.buttonNormal;
uint32_t textColor = disabled ? ui.theme.textDisabled
: color == ui.theme.selected ? ui.theme.textSelected : ui.theme.text;
uint32_t color, textColor;
_UIButtonCalculateColors(element, &color, &textColor);
UIDrawRectangle(painter, element->bounds, color, ui.theme.border, UI_RECT_1(isMenuItem ? 0 : 1));
@ -1931,6 +1978,19 @@ int _UITabPaneMessage(UIElement *element, UIMessage message, int di, void *dp) {
child->flags |= UI_ELEMENT_HIDE;
}
child = child->next;
index++;
}
} else if (message == UI_MSG_GET_HEIGHT) {
UIElement *child = element->children;
int index = 0;
int baseHeight = UI_SIZE_BUTTON_HEIGHT * element->window->scale;
while (child) {
if (tabPane->active == index) {
return baseHeight + UIElementMessage(child, UI_MSG_GET_HEIGHT, di, dp);
}
child = child->next;
index++;
}
@ -2785,7 +2845,10 @@ int _UITextboxMessage(UIElement *element, UIMessage message, int di, void *dp) {
UIKeyTyped *m = (UIKeyTyped *) dp;
bool handled = true;
if (m->code == UI_KEYCODE_BACKSPACE || m->code == UI_KEYCODE_DELETE) {
if (textbox->rejectNextKey) {
textbox->rejectNextKey = false;
handled = false;
} else if (m->code == UI_KEYCODE_BACKSPACE || m->code == UI_KEYCODE_DELETE) {
if (textbox->carets[0] == textbox->carets[1]) {
UITextboxMoveCaret(textbox, m->code == UI_KEYCODE_BACKSPACE, element->window->ctrl);
}
@ -3512,6 +3575,7 @@ bool _UIMenusClose() {
return anyClosed;
}
#ifndef UI_ESSENCE
int _UIMenuItemMessage(UIElement *element, UIMessage message, int di, void *dp) {
if (message == UI_MSG_CLICKED) {
_UIMenusClose();
@ -3556,11 +3620,12 @@ int _UIMenuMessage(UIElement *element, UIMessage message, int di, void *dp) {
UIElement *child = element->children;
int position = element->bounds.t + 2 - menu->vScroll->position;
int totalHeight = 0;
int scrollBarSize = (menu->e.flags & UI_MENU_NO_SCROLL) ? 0 : UI_SIZE_SCROLL_BAR;
while (child) {
if (~child->flags & UI_ELEMENT_NON_CLIENT) {
int height = UIElementMessage(child, UI_MSG_GET_HEIGHT, 0, 0);
UIElementMove(child, UI_RECT_4(element->bounds.l + 2, element->bounds.r - UI_SIZE_SCROLL_BAR - 2,
UIElementMove(child, UI_RECT_4(element->bounds.l + 2, element->bounds.r - scrollBarSize - 2,
position, position + height), false);
position += height;
totalHeight += height;
@ -3570,7 +3635,7 @@ int _UIMenuMessage(UIElement *element, UIMessage message, int di, void *dp) {
}
UIRectangle scrollBarBounds = element->bounds;
scrollBarBounds.l = scrollBarBounds.r - UI_SIZE_SCROLL_BAR * element->window->scale;
scrollBarBounds.l = scrollBarBounds.r - scrollBarSize * element->window->scale;
menu->vScroll->maximum = totalHeight;
menu->vScroll->page = UI_RECT_HEIGHT(element->bounds);
UIElementMove(&menu->vScroll->e, scrollBarBounds, true);
@ -3625,6 +3690,7 @@ UIMenu *UIMenuCreate(UIElement *parent, uint32_t flags) {
return menu;
}
#endif
UIRectangle UIElementScreenBounds(UIElement *element) {
int x = 0, y = 0;
@ -3865,7 +3931,9 @@ UIElement *_UIElementPreviousSibling(UIElement *element) {
return sibling;
}
void _UIWindowInputEvent(UIWindow *window, UIMessage message, int di, void *dp) {
bool _UIWindowInputEvent(UIWindow *window, UIMessage message, int di, void *dp) {
bool handled = true;
if (window->pressed) {
if (message == UI_MSG_MOUSE_MOVE) {
UIElementMessage(window->pressed, UI_MSG_MOUSE_DRAG, di, dp);
@ -3943,7 +4011,7 @@ void _UIWindowInputEvent(UIWindow *window, UIMessage message, int di, void *dp)
element = element->parent;
}
} else if (message == UI_MSG_KEY_TYPED) {
bool handled = false;
handled = false;
if (window->focused) {
UIElement *element = window->focused;
@ -3993,6 +4061,8 @@ void _UIWindowInputEvent(UIWindow *window, UIMessage message, int di, void *dp)
if (~element->flags & UI_ELEMENT_WINDOW) {
UIElementFocus(element);
}
handled = true;
} else if (!window->dialog) {
for (intptr_t i = window->shortcutCount - 1; i >= 0; i--) {
UIShortcut *shortcut = window->shortcuts + i;
@ -4000,6 +4070,7 @@ void _UIWindowInputEvent(UIWindow *window, UIMessage message, int di, void *dp)
if (shortcut->code == m->code && shortcut->ctrl == window->ctrl
&& shortcut->shift == window->shift && shortcut->alt == window->alt) {
shortcut->invoke(shortcut->cp);
handled = true;
break;
}
}
@ -4018,6 +4089,7 @@ void _UIWindowInputEvent(UIWindow *window, UIMessage message, int di, void *dp)
}
end: _UIUpdate();
return handled;
}
void _UIInitialiseCommon() {
@ -4259,6 +4331,11 @@ UIWindow *UIWindowCreate(UIWindow *owner, uint32_t flags, const char *cTitle, in
| ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask
| EnterWindowMask | LeaveWindowMask | ButtonMotionMask | KeymapStateMask | FocusChangeMask);
if (flags & UI_WINDOW_MAXIMIZE) {
Atom atoms[2] = { XInternAtom(ui.display, "_NET_WM_STATE_MAXIMIZED_HORZ", 0), XInternAtom(ui.display, "_NET_WM_STATE_MAXIMIZED_VERT", 0) };
XChangeProperty(ui.display, window->window, XInternAtom(ui.display, "_NET_WM_STATE", 0), XA_ATOM, 32, PropModeReplace, (unsigned char *) atoms, 2);
}
if (~flags & UI_WINDOW_MENU) {
XMapRaised(ui.display, window->window);
}
@ -4517,6 +4594,22 @@ bool _UIProcessEvent(XEvent *event) {
window->alt = true;
window->altCode = event->xkey.keycode;
_UIWindowInputEvent(window, UI_MSG_MOUSE_MOVE, 0, 0);
} else if (symbol == XK_KP_Left) {
m.code = UI_KEYCODE_LEFT;
} else if (symbol == XK_KP_Right) {
m.code = UI_KEYCODE_RIGHT;
} else if (symbol == XK_KP_Up) {
m.code = UI_KEYCODE_UP;
} else if (symbol == XK_KP_Down) {
m.code = UI_KEYCODE_DOWN;
} else if (symbol == XK_KP_Home) {
m.code = UI_KEYCODE_HOME;
} else if (symbol == XK_KP_End) {
m.code = UI_KEYCODE_END;
} else if (symbol == XK_KP_Enter) {
m.code = UI_KEYCODE_ENTER;
} else if (symbol == XK_KP_Delete) {
m.code = UI_KEYCODE_DELETE;
}
_UIWindowInputEvent(window, UI_MSG_KEY_TYPED, 0, &m);
@ -5083,14 +5176,32 @@ bool _UIMessageLoopSingle(int *result) {
if (ui.animating) {
// TODO.
} else {
EsMessageReceive();
_UIMessageProcess(EsMessageReceive());
}
return true;
}
UIMenu *UIMenuCreate(UIElement *parent, uint32_t flags) {
ui.menuIndex = 0;
return EsMenuCreate(parent->window->window, ES_MENU_AT_CURSOR);
}
void _UIMenuItemCallback(EsMenu *menu, EsGeneric context) {
((void (*)(void *)) ui.menuData[context.u * 2 + 0])(ui.menuData[context.u * 2 + 1]);
}
void UIMenuAddItem(UIMenu *menu, uint32_t flags, const char *label, ptrdiff_t labelBytes, void (*invoke)(void *cp), void *cp) {
EsAssert(ui.menuIndex < 128);
ui.menuData[ui.menuIndex * 2 + 0] = (void *) invoke;
ui.menuData[ui.menuIndex * 2 + 1] = cp;
EsMenuAddItem(menu, (flags & UI_BUTTON_CHECKED) ? ES_MENU_ITEM_CHECKED : ES_FLAGS_DEFAULT,
label, labelBytes, _UIMenuItemCallback, ui.menuIndex);
ui.menuIndex++;
}
void UIMenuShow(UIMenu *menu) {
// TODO.
EsMenuShow(menu);
}
int _UIWindowCanvasMessage(EsElement *element, EsMessage *message) {
@ -5122,7 +5233,7 @@ int _UIWindowCanvasMessage(EsElement *element, EsMessage *message) {
m.text = c;
m.textBytes = EsMessageGetInputText(message, c);
m.code = message->keyboard.scancode;
_UIWindowInputEvent(window, UI_MSG_KEY_TYPED, 0, &m);
return _UIWindowInputEvent(window, UI_MSG_KEY_TYPED, 0, &m) ? ES_HANDLED : 0;
} else if (message->type == ES_MSG_MOUSE_LEFT_CLICK) {
_UIInspectorSetFocusedWindow(window);
} else if (message->type == ES_MSG_USER_START) {