summaryrefslogtreecommitdiff
path: root/src/ui/widget.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-09-20 11:37:23 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-09-20 11:37:23 +0300
commit2d81addf78d6a8b0fb2f2959b04a385c4adffdf2 (patch)
tree5e0f45b9c945499bc6a6669563de13c5203981a6 /src/ui/widget.c
parent201021092d204680b353c82ce9e9beb76f3044e8 (diff)
Experimenting with independent popup windows
Toe dipping into multiple window support by allowing popup menu widgets to be displayed in independent windows. This is not a 100% replacement for native menus, but it gets pretty close.
Diffstat (limited to 'src/ui/widget.c')
-rw-r--r--src/ui/widget.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 23c19315..7b33a752 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -271,6 +271,10 @@ iWidget *root_Widget(const iWidget *d) {
271 return d ? d->root->widget : NULL; 271 return d ? d->root->widget : NULL;
272} 272}
273 273
274iWindow *window_Widget(const iAnyObject *d) {
275 return constAs_Widget(d)->root->window;
276}
277
274void showCollapsed_Widget(iWidget *d, iBool show) { 278void showCollapsed_Widget(iWidget *d, iBool show) {
275 const iBool isVisible = !(d->flags & hidden_WidgetFlag); 279 const iBool isVisible = !(d->flags & hidden_WidgetFlag);
276 if ((isVisible && !show) || (!isVisible && show)) { 280 if ((isVisible && !show) || (!isVisible && show)) {
@@ -979,11 +983,10 @@ void unhover_Widget(void) {
979} 983}
980 984
981iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { 985iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
982 //iAssert(d->root == get_Root());
983 if (!d->parent) { 986 if (!d->parent) {
984 if (get_Window()->focus && get_Window()->focus->root == d->root && isKeyboardEvent_(ev)) { 987 if (window_Widget(d)->focus && window_Widget(d)->focus->root == d->root && isKeyboardEvent_(ev)) {
985 /* Root dispatches keyboard events directly to the focused widget. */ 988 /* Root dispatches keyboard events directly to the focused widget. */
986 if (dispatchEvent_Widget(get_Window()->focus, ev)) { 989 if (dispatchEvent_Widget(window_Widget(d)->focus, ev)) {
987 return iTrue; 990 return iTrue;
988 } 991 }
989 } 992 }
@@ -1012,7 +1015,8 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
1012 } 1015 }
1013 } 1016 }
1014 else if (ev->type == SDL_MOUSEMOTION && 1017 else if (ev->type == SDL_MOUSEMOTION &&
1015 (!get_Window()->hover || hasParent_Widget(d, get_Window()->hover)) && 1018 ev->motion.windowID == SDL_GetWindowID(window_Widget(d)->win) &&
1019 (!window_Widget(d)->hover || hasParent_Widget(d, window_Widget(d)->hover)) &&
1016 flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag && 1020 flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag &&
1017 ~flags_Widget(d) & disabled_WidgetFlag) { 1021 ~flags_Widget(d) & disabled_WidgetFlag) {
1018 if (contains_Widget(d, init_I2(ev->motion.x, ev->motion.y))) { 1022 if (contains_Widget(d, init_I2(ev->motion.x, ev->motion.y))) {
@@ -1031,11 +1035,11 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
1031 iReverseForEach(ObjectList, i, d->children) { 1035 iReverseForEach(ObjectList, i, d->children) {
1032 iWidget *child = as_Widget(i.object); 1036 iWidget *child = as_Widget(i.object);
1033 //iAssert(child->root == d->root); 1037 //iAssert(child->root == d->root);
1034 if (child == get_Window()->focus && isKeyboardEvent_(ev)) { 1038 if (child == window_Widget(d)->focus && isKeyboardEvent_(ev)) {
1035 continue; /* Already dispatched. */ 1039 continue; /* Already dispatched. */
1036 } 1040 }
1037 if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) { 1041 if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) {
1038 /* Already dispatched. */ 1042 /* Already dispatched. */
1039 continue; 1043 continue;
1040 } 1044 }
1041 if (dispatchEvent_Widget(child, ev)) { 1045 if (dispatchEvent_Widget(child, ev)) {
@@ -1050,7 +1054,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
1050#endif 1054#endif
1051#if 0 1055#if 0
1052 if (ev->type == SDL_MOUSEMOTION) { 1056 if (ev->type == SDL_MOUSEMOTION) {
1053 printf("[%p] %s:'%s' (on top) ate the motion\n", 1057 printf("[%p] %s:'%s' ate the motion\n",
1054 child, class_Widget(child)->name, 1058 child, class_Widget(child)->name,
1055 cstr_String(id_Widget(child))); 1059 cstr_String(id_Widget(child)));
1056 fflush(stdout); 1060 fflush(stdout);
@@ -1246,7 +1250,7 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) {
1246 ev->button.x, 1250 ev->button.x,
1247 ev->button.y); 1251 ev->button.y);
1248 } 1252 }
1249 setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); 1253 setCursor_Window(window_Widget(d), SDL_SYSTEM_CURSOR_ARROW);
1250 return iTrue; 1254 return iTrue;
1251 } 1255 }
1252 return iFalse; 1256 return iFalse;
@@ -1270,6 +1274,7 @@ iLocalDef iBool isDrawn_Widget_(const iWidget *d) {
1270void drawLayerEffects_Widget(const iWidget *d) { 1274void drawLayerEffects_Widget(const iWidget *d) {
1271 /* Layered effects are not buffered, so they are drawn here separately. */ 1275 /* Layered effects are not buffered, so they are drawn here separately. */
1272 iAssert(isDrawn_Widget_(d)); 1276 iAssert(isDrawn_Widget_(d));
1277 iAssert(window_Widget(d) == get_Window());
1273 iBool shadowBorder = (d->flags & keepOnTop_WidgetFlag && ~d->flags & mouseModal_WidgetFlag) != 0; 1278 iBool shadowBorder = (d->flags & keepOnTop_WidgetFlag && ~d->flags & mouseModal_WidgetFlag) != 0;
1274 iBool fadeBackground = (d->bgColor >= 0 || d->frameColor >= 0) && d->flags & mouseModal_WidgetFlag; 1279 iBool fadeBackground = (d->bgColor >= 0 || d->frameColor >= 0) && d->flags & mouseModal_WidgetFlag;
1275 if (deviceType_App() == phone_AppDeviceType) { 1280 if (deviceType_App() == phone_AppDeviceType) {
@@ -1539,6 +1544,7 @@ static void endBufferDraw_Widget_(const iWidget *d) {
1539} 1544}
1540 1545
1541void draw_Widget(const iWidget *d) { 1546void draw_Widget(const iWidget *d) {
1547 iAssert(window_Widget(d) == get_Window());
1542 if (!isDrawn_Widget_(d)) { 1548 if (!isDrawn_Widget_(d)) {
1543 if (d->drawBuf) { 1549 if (d->drawBuf) {
1544// printf("[%p] drawBuffer released\n", d); 1550// printf("[%p] drawBuffer released\n", d);
@@ -1820,7 +1826,17 @@ iBool equalWidget_Command(const char *cmd, const iWidget *widget, const char *ch
1820 if (equal_Command(cmd, checkCommand)) { 1826 if (equal_Command(cmd, checkCommand)) {
1821 const iWidget *src = pointer_Command(cmd); 1827 const iWidget *src = pointer_Command(cmd);
1822 iAssert(!src || strstr(cmd, " ptr:")); 1828 iAssert(!src || strstr(cmd, " ptr:"));
1823 return src == widget || hasParent_Widget(src, widget); 1829 if (src == widget || hasParent_Widget(src, widget)) {
1830 return iTrue;
1831 }
1832// if (src && type_Window(window_Widget(src)) == popup_WindowType) {
1833// /* Special case: command was emitted from a popup widget. The popup root widget actually
1834// belongs to someone else. */
1835// iWidget *realParent = userData_Object(src->root->widget);
1836// iAssert(realParent);
1837// iAssert(isInstance_Object(realParent, &Class_Widget));
1838// return realParent == widget || hasParent_Widget(realParent, widget);
1839// }
1824 } 1840 }
1825 return iFalse; 1841 return iFalse;
1826} 1842}
@@ -1962,6 +1978,10 @@ void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) {
1962 } 1978 }
1963 if (!isGlobal) { 1979 if (!isGlobal) {
1964 iAssert(isInstance_Object(d, &Class_Widget)); 1980 iAssert(isInstance_Object(d, &Class_Widget));
1981 if (type_Window(window_Widget(d)) == popup_WindowType) {
1982 postCommandf_Root(((const iWidget *) d)->root, "cancel popup:1 ptr:%p", d);
1983 d = userData_Object(root_Widget(d));
1984 }
1965 appendFormat_String(&str, " ptr:%p", d); 1985 appendFormat_String(&str, " ptr:%p", d);
1966 } 1986 }
1967 postCommandString_Root(((const iWidget *) d)->root, &str); 1987 postCommandString_Root(((const iWidget *) d)->root, &str);