From 44214359c0f95dcce3a1390506e9fd74202d5ae7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= jaakko.keranen@iki.fi
Date: Sat, 19 Feb 2022 15:16:51 +0200
Subject: [PATCH 1/1] Fixed several event handling issues
Events are expected to have a valid windowID now, and the current window also has to be correct when dispatching or processing any events.
src/app.c | 38 ++++++++++++++++++++++--------
src/app.h | 2 ++
src/macos.m | 51 ++++++++++++++---------------------------
src/periodic.c | 19 ++++++++-------
src/ui/documentwidget.c | 2 +-
src/ui/touch.c | 3 ++-
src/ui/widget.c | 3 ++-
src/ui/window.c | 10 ++++----
src/ui/window.h | 2 +-
9 files changed, 69 insertions(+), 61 deletions(-)
diff --git a/src/app.c b/src/app.c
index ec8b59b3..010c6d74 100644
--- a/src/app.c
+++ b/src/app.c
@@ -559,6 +559,7 @@ static iBool loadState_App_(iApp *d) {
const int winState = read32_File(f);
const int keyRoot = (winState & 1);
const iBool isCurrent = (winState & current_WindowStateFlag) != 0;
+// printf("[State] '%.4s' split:%d state:%x\n", magic, splitMode, winState);
if (numWins == 1) {
win = d->window;
}
@@ -575,7 +576,7 @@ static iBool loadState_App_(iApp *d) {
setCurrent_Root(NULL);
win->pendingSplitMode = splitMode;
setSplitMode_MainWindow(win, splitMode | noEvents_WindowSplit);
win->base.keyRoot = d->window->base.roots[keyRoot];
win->base.keyRoot = win->base.roots[keyRoot];
}
else if (!memcmp(magic, magicSidebar_App_, 4)) {
if (!win) {
@@ -1061,8 +1062,8 @@ static void init_App_(iApp *d, int argc, char **argv) {
}
postCommand_App("~navbar.actions.changed");
postCommand_App("~toolbar.actions.changed");
d->autoReloadTimer = SDL_AddTimer(60 * 1000, postAutoReloadCommand_App_, NULL);
postCommand_Root(NULL, "document.autoreload");
#if defined (LAGRANGE_ENABLE_IDLE_SLEEP)
@@ -1390,6 +1391,12 @@ static iPtrArray *listWindows_App_(const iApp *d, iPtrArray *windows) {
return windows;
}
+iPtrArray *listWindows_App(void) {
+}
void processEvents_App(enum iAppEventMode eventMode) {
iApp *d = &app_;
iRoot *oldCurrentRoot = current_Root(); /* restored afterwards */
@@ -1672,6 +1679,9 @@ static void runTickers_App_(iApp *d) {
iConstForEach(Array, i, &pending->values) {
const iTicker *ticker = i.value;
if (ticker->callback) {
if (ticker->root) {
setCurrent_Window(ticker->root->window);
}
setCurrent_Root(ticker->root); /* root might be NULL */
ticker->callback(ticker->context);
}
@@ -1864,9 +1874,9 @@ void postCommand_Root(iRoot *d, const char *command) {
}
SDL_Event ev = { .type = SDL_USEREVENT };
ev.user.code = command_UserEventCode;
-// ev.user.windowID = id_Window(get_Window());
ev.user.data1 = strdup(command);
ev.user.data2 = d; /* all events are root-specific */
SDL_PushEvent(&ev);
iWindow *win = get_Window();
#if defined (iPlatformAndroid)
@@ -1969,6 +1979,10 @@ size_t windowIndex_App(const iMainWindow *win) {
return indexOf_PtrArray(&app_.mainWindows, win);
}
+const iPtrArray *mainWindows_App(void) {
+}
void setActiveWindow_App(iMainWindow *win) {
iApp *d = &app_;
d->window = win;
@@ -2527,12 +2541,16 @@ iBool handleCommand_App(const char *cmd) {
return iTrue;
}
else if (equal_Command(cmd, "window.maximize")) {
if (!argLabel_Command(cmd, "toggle")) {
setSnap_MainWindow(d->window, maximized_WindowSnap);
}
else {
setSnap_MainWindow(d->window, snap_MainWindow(d->window) == maximized_WindowSnap ? 0 :
maximized_WindowSnap);
const size_t winIndex = argU32Label_Command(cmd, "index");
if (winIndex < size_PtrArray(&d->mainWindows)) {
iMainWindow *win = at_PtrArray(&d->mainWindows, winIndex);
if (!argLabel_Command(cmd, "toggle")) {
setSnap_MainWindow(win, maximized_WindowSnap);
}
else {
setSnap_MainWindow(
win, snap_MainWindow(win) == maximized_WindowSnap ? 0 : maximized_WindowSnap);
}
}
return iTrue;
}
diff --git a/src/app.h b/src/app.h
index dd24ec8e..63a477a5 100644
--- a/src/app.h
+++ b/src/app.h
@@ -98,6 +98,7 @@ iPeriodic * periodic_App (void);
iDocumentWidget * document_App (void);
iObjectList * listDocuments_App (const iRoot rootOrNull); / NULL for all roots */
iStringSet * listOpenURLs_App (void); /* all tabs */
+iPtrArray * listWindows_App (void);
iDocumentWidget * newTab_App (const iDocumentWidget *duplicateOf, iBool switchToNew);
void trimCache_App (void);
void trimMemory_App (void);
@@ -128,6 +129,7 @@ void setActiveWindow_App (iMainWindow *win);
void closeWindow_App (iMainWindow *win);
size_t numWindows_App (void);
size_t windowIndex_App (const iMainWindow *win);
+const iPtrArray *mainWindows_App(void);
void addPopup_App (iWindow *popup);
void removePopup_App (iWindow *popup);
void postRefresh_App (void);
diff --git a/src/macos.m b/src/macos.m
index 7b248c3b..5f376874 100644
--- a/src/macos.m
+++ b/src/macos.m
@@ -83,7 +83,9 @@ static void ignoreImmediateKeyDownEvents_(void) {
However, we shouldn't double-activate menu items when a shortcut key is used in our
widgets. Quite a kludge: take advantage of Window's focus-acquisition threshold to
ignore the immediately following key down events. */
as_Window(w.ptr)->focusGainedAt = SDL_GetTicks();
}
/----------------------------------------------------------------------------------------------/
@@ -435,9 +437,17 @@ static iBool processScrollWheelEvent_(NSEvent *event) {
const iBool isPerPixel = (event.hasPreciseScrollingDeltas != 0);
const iBool isInertia = (event.momentumPhase & (NSEventPhaseBegan | NSEventPhaseChanged)) != 0;
const iBool isEnded = event.scrollingDeltaX == 0.0f && event.scrollingDeltaY == 0.0f && !isInertia;
/* Not the main window. */
If it's for an auxiliary window, let the system handle it. */
if (event.window == nsWindow_(as_Window(i.ptr)->win)) {
win = i.ptr;
break;
}
/* Not a main window. */
return iFalse;
}
if (isPerPixel) {
@@ -478,16 +488,18 @@ static iBool processScrollWheelEvent_(NSEvent *event) {
else {
SDL_MouseWheelEvent e = { .type = SDL_MOUSEWHEEL };
e.timestamp = SDL_GetTicks();
e.windowID = id_Window(win);
e.which = 1; /* Distinction between trackpad and regular mouse. */
/* Disregard any wheel acceleration. */
e.x = event.scrollingDeltaX > 0 ? 1 : event.scrollingDeltaX < 0 ? -1 : 0;
e.y = event.scrollingDeltaY > 0 ? 1 : event.scrollingDeltaY < 0 ? -1 : 0;
e.y = event.scrollingDeltaY > 0 ? 1 : event.scrollingDeltaY < 0 ? -1 : 0;
SDL_PushEvent((SDL_Event *) &e);
return iTrue;
}
/* Post corresponding MOUSEWHEEL events. */
SDL_MouseWheelEvent e = { .type = SDL_MOUSEWHEEL };
e.timestamp = SDL_GetTicks();
e.which = isPerPixel ? 0 : 1; /* Distinction between trackpad and regular mouse. */
setPerPixel_MouseWheelEvent(&e, isPerPixel);
if (isPerPixel) {
@@ -517,28 +529,6 @@ static iBool processScrollWheelEvent_(NSEvent *event) {
// printf("#### [%d] dx:%d dy:%d phase:%ld inertia:%d end:%d\n", preventTapGlitch_, e.x, e.y, (long) event.momentumPhase,
// isInertia, isEnded); fflush(stdout);
SDL_PushEvent((SDL_Event *) &e);
-#if 0
/* On macOS, we handle both trackpad and mouse events. We expect SDL to identify
which device is sending the event. */
if (ev.wheel.which == 0) {
/* Trackpad with precise scrolling w/inertia (points). */
setPerPixel_MouseWheelEvent(&ev.wheel, iTrue);
ev.wheel.x *= -d->window->base.pixelRatio;
ev.wheel.y *= d->window->base.pixelRatio;
/* Only scroll on one axis at a time. */
if (iAbs(ev.wheel.x) > iAbs(ev.wheel.y)) {
ev.wheel.y = 0;
}
else {
ev.wheel.x = 0;
}
}
else {
/* Disregard wheel acceleration applied by the OS. */
ev.wheel.x = -ev.wheel.x;
ev.wheel.y = iSign(ev.wheel.y);
}
-#endif
return iTrue;
}
@@ -565,13 +555,6 @@ void setupApplication_MacOS(void) {
windowCloseItem.action = @selector(closeTab);
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel
handler:^NSEvent*(NSEvent *event){
-// printf("event type: %lu\n", (unsigned long) event.type);
-// fflush(stdout);
-// if (event.type == NSEventTypeGesture) {
-// trackSwipe_(event);
-// printf("GESTURE phase:%lu\n", (unsigned long) event.phase);
-//fflush(stdout);
-// }
if (event.type == NSEventTypeScrollWheel &&
processScrollWheelEvent_(event)) {
return nil; /* was eaten */
diff --git a/src/periodic.c b/src/periodic.c
index b4f51ed3..0558ed50 100644
--- a/src/periodic.c
+++ b/src/periodic.c
@@ -107,14 +107,17 @@ iBool dispatchCommands_Periodic(iPeriodic *d) {
iConstForEach(Array, i, &d->commands.values) {
const iPeriodicCommand *pc = i.value;
iAssert(isInstance_Object(pc->context, &Class_Widget));
const SDL_UserEvent ev = {
.type = SDL_USEREVENT,
.code = command_UserEventCode,
.data1 = (void *) cstr_String(&pc->command),
.data2 = findRoot_Window(get_Window(), pc->context)
};
if (ev.data2) {
setCurrent_Root(ev.data2);
iRoot *root = constAs_Widget(pc->context)->root;
if (root) {
const SDL_UserEvent ev = {
.type = SDL_USEREVENT,
.code = command_UserEventCode,
.data1 = (void *) cstr_String(&pc->command),
.data2 = root,
.windowID = id_Window(root->window),
};
setCurrent_Window(root->window);
setCurrent_Root(root);
dispatchEvent_Widget(pc->context, (const SDL_Event *) &ev);
wasPosted = iTrue;
}
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index f8cc10b9..76c26e27 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -5582,7 +5582,7 @@ static void prerender_DocumentWidget_(iAny *context) {
.vis = visibleRange_DocumentView_(&d->view),
.showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0
};
if (d->view.visBuf->buffers[0].texture) {
makePaletteGlobal_GmDocument(d->view.doc);
if (render_DocumentView_(&d->view, &ctx, iTrue /* just fill up progressively */)) {
diff --git a/src/ui/touch.c b/src/ui/touch.c
index a178a913..21a92b80 100644
--- a/src/ui/touch.c
+++ b/src/ui/touch.c
@@ -244,7 +244,8 @@ static void dispatchNotification_Touch_(const iTouch *d, int code) {
.timestamp = SDL_GetTicks(),
.code = code,
.data1 = d->affinity,
.data2 = d->affinity->root
.data2 = d->affinity->root,
.windowID = id_Window(window_Widget(d->affinity)),
});
setCurrent_Root(oldRoot);
}
diff --git a/src/ui/widget.c b/src/ui/widget.c
index fc754b7a..2e878878 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -168,7 +168,8 @@ void deinit_Widget(iWidget *d) {
if (d->flags & visualOffset_WidgetFlag) {
removeTicker_App(visualOffsetAnimation_Widget_, d);
}
if (win->lastHover == d) {
win->lastHover = NULL;
}
diff --git a/src/ui/window.c b/src/ui/window.c
index 0a97b97c..6f680cd4 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -682,6 +682,7 @@ iBool isFullscreen_MainWindow(const iMainWindow *d) {
}
iRoot *findRoot_Window(const iWindow *d, const iWidget *widget) {
while (widget->parent) {
widget = widget->parent;
}
@@ -1023,7 +1024,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
}
}
case SDL_RENDER_TARGETS_RESET:
case SDL_RENDER_DEVICE_RESET: {
case SDL_RENDER_DEVICE_RESET: {
if (mw) {
invalidate_MainWindow_(mw, iTrue /* force full reset */);
}
@@ -1109,7 +1110,7 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) {
if (mouseGrab_Widget()) {
iWidget *grabbed = mouseGrab_Widget();
setCurrent_Root(findRoot_Window(d, grabbed));
setCurrent_Root(grabbed->root /* findRoot_Window(d, grabbed)*/);
wasUsed = dispatchEvent_Widget(grabbed, &event);
}
}
@@ -1200,13 +1201,11 @@ static uint32_t windowId_SDLEvent_(const SDL_Event *ev) {
}
iBool dispatchEvent_Window(iWindow *d, const SDL_Event *ev) {
-#if 0
/* For the right window? */
const uint32_t evWin = windowId_SDLEvent_(ev);
if (evWin && evWin != id_Window(d)) {
return iFalse; /* Meant for a different window. */
}
-#endif
if (ev->type == SDL_MOUSEMOTION) {
/* Hover widget may change. */
setHover_Widget(NULL);
@@ -1591,6 +1590,7 @@ void setSplitMode_MainWindow(iMainWindow *d, int splitFlags) {
}
iWindow *w = as_Window(d);
iAssert(current_Root() == NULL);
if (d->splitMode != splitMode) {
int oldCount = numRoots_Window(w);
setFreezeDraw_MainWindow(d, iTrue);
@@ -1619,8 +1619,8 @@ void setSplitMode_MainWindow(iMainWindow *d, int splitFlags) {
/* The last child is the [+] button for adding a tab. */
moveTabButtonToEnd_Widget(findChild_Widget(docTabs, "newtab"));
setFlags_Widget(findWidget_Root("navbar.unsplit"), hidden_WidgetFlag, iTrue);
iRelease(tabs);
postCommandf_App("tabs.switch id:%s", cstr_String(id_Widget(constAs_Widget(curPage))));
iRelease(tabs);
}
else if (oldCount == 1 && splitMode) {
/* Add a second root. */
diff --git a/src/ui/window.h b/src/ui/window.h
index 5abf23eb..c7d59380 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -139,7 +139,7 @@ iAnyObject * hitChild_Window (const iWindow *, iInt2 coord);
uint32_t frameTime_Window (const iWindow *);
SDL_Renderer * renderer_Window (const iWindow *);
int numRoots_Window (const iWindow *);
-iRoot * findRoot_Window (const iWindow *, const iWidget *widget);
+//iRoot * findRoot_Window (const iWindow *, const iWidget *widget);
iRoot * otherRoot_Window (const iWindow *, iRoot *root);
iBool processEvent_Window (iWindow *, const SDL_Event *);
--
2.25.1
text/plain
This content has been proxied by September (3851b).