diff --git a/debian/libnotcurses1.symbols b/debian/libnotcurses1.symbols index 459c8d649..68cfe8ed3 100644 --- a/debian/libnotcurses1.symbols +++ b/debian/libnotcurses1.symbols @@ -51,7 +51,6 @@ libnotcurses.so.1 libnotcurses1 #MINVER# ncplane_gradient@Base 1.2.1 ncplane_greyscale@Base 1.2.1 ncplane_hline_interp@Base 1.2.1 - ncplane_mouseevent_p@Base 1.2.2 ncplane_move_above_unsafe@Base 1.2.1 ncplane_move_below_unsafe@Base 1.2.1 ncplane_move_bottom@Base 1.2.1 @@ -90,6 +89,7 @@ libnotcurses.so.1 libnotcurses1 #MINVER# ncplane_styles_on@Base 1.2.1 ncplane_styles_set@Base 1.2.1 ncplane_translate@Base 1.2.2 + ncplane_translate_abs@Base 1.2.3 ncplane_userptr@Base 1.2.1 ncplane_visual_open@Base 1.2.1 ncplane_vline_interp@Base 1.2.1 diff --git a/include/ncpp/Plane.hh b/include/ncpp/Plane.hh index 2afb918c4..ba06b733f 100644 --- a/include/ncpp/Plane.hh +++ b/include/ncpp/Plane.hh @@ -876,17 +876,17 @@ namespace ncpp ncplane_translate (src.plane, dst.plane, y, x); } + bool translate_abs (int *y = nullptr, int *x = nullptr) + { + return ncplane_translate_abs (*this, y, x); + } + // Upstream call doesn't take ncplane* but we put it here for parity with has_no_background below bool has_no_foreground (Cell &cell) const noexcept { return cell.has_no_foreground (); } - bool is_mouse_event (const ncinput *ni) const noexcept - { - return ncplane_mouseevent_p (plane, ni); - } - const char* get_extended_gcluster (Cell &cell) const noexcept { return cell_extended_gcluster (plane, cell); diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index 526cab341..93cdc2a88 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -328,11 +328,6 @@ API int notcurses_mouse_enable(struct notcurses* n); // Disable mouse events. Any events in the input queue can still be delivered. API int notcurses_mouse_disable(struct notcurses* n); -// Was the provided mouse event 'ni' within the bounds of the ncplane 'n'? Note -// that this doesn't necessarily mean the event affected 'n'; there could be a -// plane above it, this plane could be transparent, etc. -API bool ncplane_mouseevent_p(const struct ncplane* n, const struct ncinput *ni); - // Refresh our idea of the terminal's dimensions, reshaping the standard plane // if necessary, without a fresh render. References to ncplanes (and the // egcpools underlying cells) remain valid following a resize operation. @@ -414,6 +409,12 @@ API struct ncplane* ncplane_dup(struct ncplane* n, void* opaque); API void ncplane_translate(const struct ncplane* src, const struct ncplane* dst, int* RESTRICT y, int* RESTRICT x); +// Fed absolute 'y'/'x' coordinates, determine whether that coordinate is +// within the ncplane 'n'. If not, return false. If so, return true. Either +// way, translate the absolute coordinates relative to 'n'. If the point is not +// within 'n', these coordinates will not be within the dimensions of the plane. +API bool ncplane_translate_abs(const struct ncplane* n, int* RESTRICT y, int* RESTRICT x); + // Returns a 16-bit bitmask of supported curses-style attributes // (NCSTYLE_UNDERLINE, NCSTYLE_BOLD, etc.) The attribute is only // indicated as supported if the terminal can support it together with color. diff --git a/src/demo/hud.c b/src/demo/hud.c index d325f664a..af8337950 100644 --- a/src/demo/hud.c +++ b/src/demo/hud.c @@ -315,6 +315,11 @@ int hud_grab(int y, int x){ // new grab. stash point of original grab, and location of HUD at original // grab. any delta while grabbed (relative to the original grab point) // will see the HUD moved by delta (relative to the original HUD location). + int ty = y, tx = x; + // first, though, verify that we're clicking within the hud + if(!ncplane_translate_abs(hud, &ty, &tx)){ + return 0; + } hud_grab_x = x; hud_grab_y = y; ncplane_yx(hud, &hud_pos_y, &hud_pos_x); diff --git a/src/demo/input.c b/src/demo/input.c index 00440f1f3..4be8a6682 100644 --- a/src/demo/input.c +++ b/src/demo/input.c @@ -76,6 +76,7 @@ handle_mouse(const ncinput* ni){ if(ni->id != NCKEY_BUTTON1 && ni->id != NCKEY_RELEASE){ return 0; } + int y, x; int ret; if(ni->id == NCKEY_RELEASE){ ret = hud_release(); diff --git a/src/lib/input.c b/src/lib/input.c index fc7b8ccb4..35ed446d8 100644 --- a/src/lib/input.c +++ b/src/lib/input.c @@ -491,20 +491,3 @@ int prep_special_keys(notcurses* nc){ } return 0; } - -bool ncplane_mouseevent_p(const ncplane* n, const ncinput *ni){ - // incoming coordinates are absolute and 0-indexed - int y = ni->y; - int x = ni->x; - ncplane_translate(ncplane_stdplane_const(n), n, &y, &x); - if(y < 0 || x < 0){ - return false; - } - if(y >= n->leny){ - return false; - } - if(x >= n->lenx){ - return false; - } - return true; -} diff --git a/src/lib/menu.c b/src/lib/menu.c index b389e287b..b851f7eb2 100644 --- a/src/lib/menu.c +++ b/src/lib/menu.c @@ -508,12 +508,14 @@ const char* ncmenu_selected(const ncmenu* n, ncinput* ni){ } bool ncmenu_offer_input(ncmenu* n, const ncinput* nc){ - if(nc->id == NCKEY_RELEASE && ncplane_mouseevent_p(n->ncp, nc)){ + if(nc->id == NCKEY_RELEASE){ int y, x, dimy, dimx; y = nc->y; x = nc->x; ncplane_dim_yx(n->ncp, &dimy, &dimx); - ncplane_translate(ncplane_stdplane(n->ncp), n->ncp, &y, &x); + if(!ncplane_translate_abs(n->ncp, &y, &x)){ + return false; + } if(y != (n->bottom ? dimy - 1 : 0)){ return false; } diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 3469ae52c..5ed0d3fe3 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -1895,6 +1895,27 @@ void palette256_free(palette256* p){ free(p); } +bool ncplane_translate_abs(const ncplane* n, int* restrict y, int* restrict x){ + ncplane_translate(ncplane_stdplane_const(n), n, y, x); + if(y){ + if(*y < 0){ + return false; + } + if(*y >= n->leny){ + return false; + } + } + if(x){ + if(*x < 0){ + return false; + } + if(*x >= n->lenx){ + return false; + } + } + return true; +} + void ncplane_translate(const ncplane* src, const ncplane* dst, int* restrict y, int* restrict x){ if(y){ diff --git a/src/lib/selector.c b/src/lib/selector.c index 448723b7d..1edb7f61c 100644 --- a/src/lib/selector.c +++ b/src/lib/selector.c @@ -337,9 +337,11 @@ bool ncselector_offer_input(ncselector* n, const ncinput* nc){ }else if(nc->id == NCKEY_SCROLL_DOWN){ ncselector_nextitem(n); return true; - }else if(nc->id == NCKEY_RELEASE && ncplane_mouseevent_p(n->ncp, nc)){ + }else if(nc->id == NCKEY_RELEASE){ int y = nc->y, x = nc->x; - ncplane_translate(ncplane_stdplane(n->ncp), n->ncp, &y, &x); + if(!ncplane_translate_abs(n->ncp, &y, &x)){ + return false; + } if(y == n->uarrowy && x == n->arrowx){ ncselector_previtem(n); return true; diff --git a/tests/ncplane.cpp b/tests/ncplane.cpp index e66fb8d74..f6160a795 100644 --- a/tests/ncplane.cpp +++ b/tests/ncplane.cpp @@ -1005,7 +1005,8 @@ TEST_CASE("NCPlane") { int total = 0; for(ni.y = 0 ; ni.y < 5 ; ++ni.y){ for(ni.x = 0 ; ni.x < 5 ; ++ni.x){ - bool p = ncplane_mouseevent_p(n, &ni); + int y = ni.y, x = ni.x; + bool p = ncplane_translate_abs(n, &y, &x); if(ni.y >= 1 && ni.y <= 2 && ni.x >= 1 && ni.x <= 2){ CHECK(p); }else{