comparison src/popupwin.c @ 17863:08f1dd29550e v8.1.1928

patch 8.1.1928: popup windows don't move with the text when making changes Commit: https://github.com/vim/vim/commit/12034e22dd80cf533ac1c681be521ab299383f63 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Aug 25 22:25:02 2019 +0200 patch 8.1.1928: popup windows don't move with the text when making changes Problem: Popup windows don't move with the text when making changes. Solution: Add the 'textprop" property to the popup window options, position the popup relative to a text property. (closes #4560) No tests yet.
author Bram Moolenaar <Bram@vim.org>
date Sun, 25 Aug 2019 22:30:03 +0200
parents bdddd215bf09
children f13a5c48320b
comparison
equal deleted inserted replaced
17862:debebb1dcef1 17863:08f1dd29550e
71 n = screen_screencol() + 1 + n; 71 n = screen_screencol() + 1 + n;
72 72
73 if (n < 1) 73 if (n < 1)
74 n = 1; 74 n = 1;
75 return n; 75 return n;
76 }
77
78 static void
79 get_pos_options(win_T *wp, dict_T *dict)
80 {
81 char_u *str;
82 int nr;
83 dictitem_T *di;
84
85 nr = popup_options_one(dict, (char_u *)"line");
86 if (nr > 0)
87 wp->w_wantline = nr;
88 nr = popup_options_one(dict, (char_u *)"col");
89 if (nr > 0)
90 wp->w_wantcol = nr;
91
92 di = dict_find(dict, (char_u *)"fixed", -1);
93 if (di != NULL)
94 wp->w_popup_fixed = dict_get_number(dict, (char_u *)"fixed") != 0;
95
96 str = dict_get_string(dict, (char_u *)"pos", FALSE);
97 if (str != NULL)
98 {
99 for (nr = 0;
100 nr < (int)(sizeof(poppos_entries) / sizeof(poppos_entry_T));
101 ++nr)
102 if (STRCMP(str, poppos_entries[nr].pp_name) == 0)
103 {
104 wp->w_popup_pos = poppos_entries[nr].pp_val;
105 nr = -1;
106 break;
107 }
108 if (nr != -1)
109 semsg(_(e_invarg2), str);
110 }
111 } 76 }
112 77
113 static void 78 static void
114 set_padding_border(dict_T *dict, int *array, char *name, int max_val) 79 set_padding_border(dict_T *dict, int *array, char *name, int max_val)
115 { 80 {
254 void 219 void
255 popup_start_drag(win_T *wp, int row, int col) 220 popup_start_drag(win_T *wp, int row, int col)
256 { 221 {
257 drag_start_row = mouse_row; 222 drag_start_row = mouse_row;
258 drag_start_col = mouse_col; 223 drag_start_col = mouse_col;
259 // TODO: handle using different corner
260 if (wp->w_wantline == 0) 224 if (wp->w_wantline == 0)
261 drag_start_wantline = wp->w_winrow + 1; 225 drag_start_wantline = wp->w_winrow + 1;
262 else 226 else
263 drag_start_wantline = wp->w_wantline; 227 drag_start_wantline = wp->w_wantline;
264 if (wp->w_wantcol == 0) 228 if (wp->w_wantcol == 0)
428 * Shared between popup_create() and f_popup_move(). 392 * Shared between popup_create() and f_popup_move().
429 */ 393 */
430 static void 394 static void
431 apply_move_options(win_T *wp, dict_T *d) 395 apply_move_options(win_T *wp, dict_T *d)
432 { 396 {
433 int nr; 397 int nr;
398 char_u *str;
399 dictitem_T *di;
434 400
435 if ((nr = dict_get_number(d, (char_u *)"minwidth")) > 0) 401 if ((nr = dict_get_number(d, (char_u *)"minwidth")) > 0)
436 wp->w_minwidth = nr; 402 wp->w_minwidth = nr;
437 if ((nr = dict_get_number(d, (char_u *)"minheight")) > 0) 403 if ((nr = dict_get_number(d, (char_u *)"minheight")) > 0)
438 wp->w_minheight = nr; 404 wp->w_minheight = nr;
439 if ((nr = dict_get_number(d, (char_u *)"maxwidth")) > 0) 405 if ((nr = dict_get_number(d, (char_u *)"maxwidth")) > 0)
440 wp->w_maxwidth = nr; 406 wp->w_maxwidth = nr;
441 if ((nr = dict_get_number(d, (char_u *)"maxheight")) > 0) 407 if ((nr = dict_get_number(d, (char_u *)"maxheight")) > 0)
442 wp->w_maxheight = nr; 408 wp->w_maxheight = nr;
443 get_pos_options(wp, d); 409
410 nr = popup_options_one(d, (char_u *)"line");
411 if (nr > 0)
412 wp->w_wantline = nr;
413 nr = popup_options_one(d, (char_u *)"col");
414 if (nr > 0)
415 wp->w_wantcol = nr;
416
417 di = dict_find(d, (char_u *)"fixed", -1);
418 if (di != NULL)
419 wp->w_popup_fixed = dict_get_number(d, (char_u *)"fixed") != 0;
420
421 str = dict_get_string(d, (char_u *)"pos", FALSE);
422 if (str != NULL)
423 {
424 for (nr = 0;
425 nr < (int)(sizeof(poppos_entries) / sizeof(poppos_entry_T));
426 ++nr)
427 if (STRCMP(str, poppos_entries[nr].pp_name) == 0)
428 {
429 wp->w_popup_pos = poppos_entries[nr].pp_val;
430 nr = -1;
431 break;
432 }
433 if (nr != -1)
434 semsg(_(e_invarg2), str);
435 }
436
437 str = dict_get_string(d, (char_u *)"textprop", FALSE);
438 if (str != NULL)
439 {
440 wp->w_popup_prop_type = 0;
441 if (*str != NUL)
442 {
443 nr = find_prop_type_id(str, wp->w_buffer);
444 if (nr <= 0)
445 nr = find_prop_type_id(str, NULL);
446 if (nr <= 0)
447 semsg(_(e_invarg2), str);
448 else
449 {
450 wp->w_popup_prop_type = nr;
451 wp->w_popup_prop_win = curwin;
452
453 di = dict_find(d, (char_u *)"textpropwin", -1);
454 if (di != NULL)
455 {
456 wp->w_popup_prop_win = find_win_by_nr_or_id(&di->di_tv);
457 if (win_valid(wp->w_popup_prop_win))
458 wp->w_popup_prop_win = curwin;
459 }
460 }
461 }
462 }
463
464 di = dict_find(d, (char_u *)"textpropid", -1);
465 if (di != NULL)
466 wp->w_popup_prop_id = dict_get_number(d, (char_u *)"textpropid");
444 } 467 }
445 468
446 static void 469 static void
447 handle_moved_argument(win_T *wp, dictitem_T *di, int mousemoved) 470 handle_moved_argument(win_T *wp, dictitem_T *di, int mousemoved)
448 { 471 {
1013 int org_width = wp->w_width; 1036 int org_width = wp->w_width;
1014 int org_height = wp->w_height; 1037 int org_height = wp->w_height;
1015 int org_leftcol = wp->w_leftcol; 1038 int org_leftcol = wp->w_leftcol;
1016 int org_leftoff = wp->w_popup_leftoff; 1039 int org_leftoff = wp->w_popup_leftoff;
1017 int minwidth; 1040 int minwidth;
1041 int wantline = wp->w_wantline; // adjusted for textprop
1042 int wantcol = wp->w_wantcol; // adjusted for textprop
1018 1043
1019 wp->w_winrow = 0; 1044 wp->w_winrow = 0;
1020 wp->w_wincol = 0; 1045 wp->w_wincol = 0;
1021 wp->w_leftcol = 0; 1046 wp->w_leftcol = 0;
1022 wp->w_popup_leftoff = 0; 1047 wp->w_popup_leftoff = 0;
1023 wp->w_popup_rightoff = 0; 1048 wp->w_popup_rightoff = 0;
1049
1050 // If no line was specified default to vertical centering.
1051 if (wantline == 0)
1052 center_vert = TRUE;
1053
1054 if (wp->w_popup_prop_type > 0 && win_valid(wp->w_popup_prop_win))
1055 {
1056 win_T *prop_win = wp->w_popup_prop_win;
1057 textprop_T prop;
1058 linenr_T prop_lnum;
1059 pos_T pos;
1060 int screen_row;
1061 int screen_scol;
1062 int screen_ccol;
1063 int screen_ecol;
1064
1065 // Popup window is positioned relative to a text property.
1066 if (find_visible_prop(prop_win,
1067 wp->w_popup_prop_type, wp->w_popup_prop_id,
1068 &prop, &prop_lnum) == FAIL)
1069 {
1070 // Text property is no longer visible, hide the popup.
1071 // Unhiding the popup is done in check_popup_unhidden().
1072 if ((wp->w_popup_flags & POPF_HIDDEN) == 0)
1073 {
1074 wp->w_popup_flags |= POPF_HIDDEN;
1075 --wp->w_buffer->b_nwindows;
1076 if (win_valid(wp->w_popup_prop_win))
1077 redraw_win_later(wp->w_popup_prop_win, SOME_VALID);
1078 }
1079 return;
1080 }
1081
1082 // Compute the desired position from the position of the text
1083 // property. Use "wantline" and "wantcol" as offsets.
1084 pos.lnum = prop_lnum;
1085 pos.col = prop.tp_col;
1086 if (wp->w_popup_pos == POPPOS_TOPLEFT
1087 || wp->w_popup_pos == POPPOS_BOTLEFT)
1088 pos.col += prop.tp_len - 1;
1089 textpos2screenpos(prop_win, &pos, &screen_row,
1090 &screen_scol, &screen_ccol, &screen_ecol);
1091
1092 if (wp->w_popup_pos == POPPOS_TOPLEFT
1093 || wp->w_popup_pos == POPPOS_TOPRIGHT)
1094 // below the text
1095 wantline = screen_row + wantline + 1;
1096 else
1097 // above the text
1098 wantline = screen_row + wantline - 1;
1099 center_vert = FALSE;
1100 if (wp->w_popup_pos == POPPOS_TOPLEFT
1101 || wp->w_popup_pos == POPPOS_BOTLEFT)
1102 // right of the text
1103 wantcol = screen_ecol + wantcol;
1104 else
1105 // left of the text
1106 wantcol = screen_scol + wantcol - 1;
1107 }
1108
1024 if (wp->w_popup_pos == POPPOS_CENTER) 1109 if (wp->w_popup_pos == POPPOS_CENTER)
1025 { 1110 {
1026 // center after computing the size 1111 // center after computing the size
1027 center_vert = TRUE; 1112 center_vert = TRUE;
1028 center_hor = TRUE; 1113 center_hor = TRUE;
1029 } 1114 }
1030 else 1115 else
1031 { 1116 {
1032 if (wp->w_wantline == 0) 1117 if (wantline != 0 && (wp->w_popup_pos == POPPOS_TOPLEFT
1033 center_vert = TRUE; 1118 || wp->w_popup_pos == POPPOS_TOPRIGHT))
1034 else if (wp->w_popup_pos == POPPOS_TOPLEFT 1119 {
1035 || wp->w_popup_pos == POPPOS_TOPRIGHT) 1120 wp->w_winrow = wantline - 1;
1036 {
1037 wp->w_winrow = wp->w_wantline - 1;
1038 if (wp->w_winrow >= Rows) 1121 if (wp->w_winrow >= Rows)
1039 wp->w_winrow = Rows - 1; 1122 wp->w_winrow = Rows - 1;
1040 } 1123 }
1041 1124
1042 if (wp->w_wantcol == 0) 1125 if (wantcol == 0)
1043 center_hor = TRUE; 1126 center_hor = TRUE;
1044 else if (wp->w_popup_pos == POPPOS_TOPLEFT 1127 else if (wp->w_popup_pos == POPPOS_TOPLEFT
1045 || wp->w_popup_pos == POPPOS_BOTLEFT) 1128 || wp->w_popup_pos == POPPOS_BOTLEFT)
1046 { 1129 {
1047 wp->w_wincol = wp->w_wantcol - 1; 1130 wp->w_wincol = wantcol - 1;
1048 if (wp->w_wincol >= Columns - 3) 1131 if (wp->w_wincol >= Columns - 3)
1049 wp->w_wincol = Columns - 3; 1132 wp->w_wincol = Columns - 3;
1050 } 1133 }
1051 } 1134 }
1052 1135
1159 wp->w_wincol = 0; 1242 wp->w_wincol = 0;
1160 } 1243 }
1161 else if (wp->w_popup_pos == POPPOS_BOTRIGHT 1244 else if (wp->w_popup_pos == POPPOS_BOTRIGHT
1162 || wp->w_popup_pos == POPPOS_TOPRIGHT) 1245 || wp->w_popup_pos == POPPOS_TOPRIGHT)
1163 { 1246 {
1164 int leftoff = wp->w_wantcol - (wp->w_width + extra_width); 1247 int leftoff = wantcol - (wp->w_width + extra_width);
1165 1248
1166 // Right aligned: move to the right if needed. 1249 // Right aligned: move to the right if needed.
1167 // No truncation, because that would change the height. 1250 // No truncation, because that would change the height.
1168 if (leftoff >= 0) 1251 if (leftoff >= 0)
1169 wp->w_wincol = leftoff; 1252 wp->w_wincol = leftoff;
1214 wp->w_winrow = 0; 1297 wp->w_winrow = 0;
1215 } 1298 }
1216 else if (wp->w_popup_pos == POPPOS_BOTRIGHT 1299 else if (wp->w_popup_pos == POPPOS_BOTRIGHT
1217 || wp->w_popup_pos == POPPOS_BOTLEFT) 1300 || wp->w_popup_pos == POPPOS_BOTLEFT)
1218 { 1301 {
1219 if ((wp->w_height + extra_height) <= wp->w_wantline) 1302 if ((wp->w_height + extra_height) <= wantline)
1220 // bottom aligned: may move down 1303 // bottom aligned: may move down
1221 wp->w_winrow = wp->w_wantline - (wp->w_height + extra_height); 1304 wp->w_winrow = wantline - (wp->w_height + extra_height);
1222 else 1305 else
1223 // not enough space, make top aligned 1306 // not enough space, make top aligned
1224 wp->w_winrow = wp->w_wantline + 1; 1307 wp->w_winrow = wantline + 1;
1225 } 1308 }
1309 if (wp->w_winrow >= Rows)
1310 wp->w_winrow = Rows - 1;
1311 else if (wp->w_winrow < 0)
1312 wp->w_winrow = 0;
1226 1313
1227 wp->w_popup_last_changedtick = CHANGEDTICK(wp->w_buffer); 1314 wp->w_popup_last_changedtick = CHANGEDTICK(wp->w_buffer);
1315 if (win_valid(wp->w_popup_prop_win))
1316 {
1317 wp->w_popup_prop_changedtick =
1318 CHANGEDTICK(wp->w_popup_prop_win->w_buffer);
1319 wp->w_popup_prop_topline = wp->w_popup_prop_win->w_topline;
1320 }
1228 1321
1229 // Need to update popup_mask if the position or size changed. 1322 // Need to update popup_mask if the position or size changed.
1230 // And redraw windows and statuslines that were behind the popup. 1323 // And redraw windows and statuslines that were behind the popup.
1231 if (org_winrow != wp->w_winrow 1324 if (org_winrow != wp->w_winrow
1232 || org_wincol != wp->w_wincol 1325 || org_wincol != wp->w_wincol
1835 invoke_popup_callback(wp, arg); 1928 invoke_popup_callback(wp, arg);
1836 1929
1837 popup_close(id); 1930 popup_close(id);
1838 } 1931 }
1839 1932
1933 static void
1934 popup_close_with_retval(win_T *wp, int retval)
1935 {
1936 typval_T res;
1937
1938 res.v_type = VAR_NUMBER;
1939 res.vval.v_number = retval;
1940 popup_close_and_callback(wp, &res);
1941 }
1942
1840 /* 1943 /*
1841 * Close popup "wp" because of a mouse click. 1944 * Close popup "wp" because of a mouse click.
1842 */ 1945 */
1843 void 1946 void
1844 popup_close_for_mouse_click(win_T *wp) 1947 popup_close_for_mouse_click(win_T *wp)
1845 { 1948 {
1846 typval_T res; 1949 popup_close_with_retval(wp, -2);
1847
1848 res.v_type = VAR_NUMBER;
1849 res.vval.v_number = -2;
1850 popup_close_and_callback(wp, &res);
1851 } 1950 }
1852 1951
1853 static void 1952 static void
1854 check_mouse_moved(win_T *wp, win_T *mouse_wp) 1953 check_mouse_moved(win_T *wp, win_T *mouse_wp)
1855 { 1954 {
1862 && wp->w_popup_mouse_row != 0 1961 && wp->w_popup_mouse_row != 0
1863 && (wp->w_popup_mouse_row != mouse_row 1962 && (wp->w_popup_mouse_row != mouse_row
1864 || mouse_col < wp->w_popup_mouse_mincol 1963 || mouse_col < wp->w_popup_mouse_mincol
1865 || mouse_col > wp->w_popup_mouse_maxcol)) 1964 || mouse_col > wp->w_popup_mouse_maxcol))
1866 { 1965 {
1867 typval_T res;
1868
1869 res.v_type = VAR_NUMBER;
1870 res.vval.v_number = -2;
1871 // Careful: this makes "wp" invalid. 1966 // Careful: this makes "wp" invalid.
1872 popup_close_and_callback(wp, &res); 1967 popup_close_with_retval(wp, -2);
1873 } 1968 }
1874 } 1969 }
1875 1970
1876 /* 1971 /*
1877 * Called when the mouse moved: may close a popup with "mousemoved". 1972 * Called when the mouse moved: may close a popup with "mousemoved".
2456 dict_add_number(dict, "maxwidth", wp->w_maxwidth); 2551 dict_add_number(dict, "maxwidth", wp->w_maxwidth);
2457 dict_add_number(dict, "firstline", wp->w_firstline); 2552 dict_add_number(dict, "firstline", wp->w_firstline);
2458 dict_add_number(dict, "scrollbar", wp->w_want_scrollbar); 2553 dict_add_number(dict, "scrollbar", wp->w_want_scrollbar);
2459 dict_add_number(dict, "zindex", wp->w_zindex); 2554 dict_add_number(dict, "zindex", wp->w_zindex);
2460 dict_add_number(dict, "fixed", wp->w_popup_fixed); 2555 dict_add_number(dict, "fixed", wp->w_popup_fixed);
2556 if (wp->w_popup_prop_type && win_valid(wp->w_popup_prop_win))
2557 {
2558 proptype_T *pt = text_prop_type_by_id(
2559 wp->w_popup_prop_win->w_buffer,
2560 wp->w_popup_prop_type);
2561
2562 if (pt != NULL)
2563 dict_add_string(dict, "textprop", pt->pt_name);
2564 dict_add_number(dict, "textpropwin", wp->w_popup_prop_win->w_id);
2565 dict_add_number(dict, "textpropid", wp->w_popup_prop_id);
2566 }
2461 dict_add_string(dict, "title", wp->w_popup_title); 2567 dict_add_string(dict, "title", wp->w_popup_title);
2462 dict_add_number(dict, "wrap", wp->w_p_wrap); 2568 dict_add_number(dict, "wrap", wp->w_p_wrap);
2463 dict_add_number(dict, "drag", (wp->w_popup_flags & POPF_DRAG) != 0); 2569 dict_add_number(dict, "drag", (wp->w_popup_flags & POPF_DRAG) != 0);
2464 dict_add_number(dict, "mapping", (wp->w_popup_flags & POPF_MAPPING) != 0); 2570 dict_add_number(dict, "mapping",
2571 (wp->w_popup_flags & POPF_MAPPING) != 0);
2465 dict_add_number(dict, "resize", (wp->w_popup_flags & POPF_RESIZE) != 0); 2572 dict_add_number(dict, "resize", (wp->w_popup_flags & POPF_RESIZE) != 0);
2466 dict_add_number(dict, "cursorline", 2573 dict_add_number(dict, "cursorline",
2467 (wp->w_popup_flags & POPF_CURSORLINE) != 0); 2574 (wp->w_popup_flags & POPF_CURSORLINE) != 0);
2468 dict_add_string(dict, "highlight", wp->w_p_wcr); 2575 dict_add_string(dict, "highlight", wp->w_p_wcr);
2469 if (wp->w_scrollbar_highlight != NULL) 2576 if (wp->w_scrollbar_highlight != NULL)
2601 linenr_T old_lnum = wp->w_cursor.lnum; 2708 linenr_T old_lnum = wp->w_cursor.lnum;
2602 2709
2603 // Emergency exit: CTRL-C closes the popup. 2710 // Emergency exit: CTRL-C closes the popup.
2604 if (c == Ctrl_C) 2711 if (c == Ctrl_C)
2605 { 2712 {
2606 rettv.v_type = VAR_NUMBER; 2713 popup_close_with_retval(wp, -1);
2607 rettv.vval.v_number = -1;
2608 popup_close_and_callback(wp, &rettv);
2609 return 1; 2714 return 1;
2610 } 2715 }
2611 2716
2612 argv[0].v_type = VAR_NUMBER; 2717 argv[0].v_type = VAR_NUMBER;
2613 argv[0].vval.v_number = (varnumber_T)wp->w_id; 2718 argv[0].vval.v_number = (varnumber_T)wp->w_id;
2685 */ 2790 */
2686 void 2791 void
2687 popup_check_cursor_pos() 2792 popup_check_cursor_pos()
2688 { 2793 {
2689 win_T *wp; 2794 win_T *wp;
2690 typval_T tv;
2691 2795
2692 popup_reset_handled(); 2796 popup_reset_handled();
2693 while ((wp = find_next_popup(TRUE)) != NULL) 2797 while ((wp = find_next_popup(TRUE)) != NULL)
2694 if (wp->w_popup_curwin != NULL 2798 if (wp->w_popup_curwin != NULL
2695 && (curwin != wp->w_popup_curwin 2799 && (curwin != wp->w_popup_curwin
2696 || curwin->w_cursor.lnum != wp->w_popup_lnum 2800 || curwin->w_cursor.lnum != wp->w_popup_lnum
2697 || curwin->w_cursor.col < wp->w_popup_mincol 2801 || curwin->w_cursor.col < wp->w_popup_mincol
2698 || curwin->w_cursor.col > wp->w_popup_maxcol)) 2802 || curwin->w_cursor.col > wp->w_popup_maxcol))
2699 { 2803 popup_close_with_retval(wp, -1);
2700 tv.v_type = VAR_NUMBER;
2701 tv.vval.v_number = -1;
2702 popup_close_and_callback(wp, &tv);
2703 }
2704 } 2804 }
2705 2805
2706 /* 2806 /*
2707 * Update "w_popup_mask_cells". 2807 * Update "w_popup_mask_cells".
2708 */ 2808 */
2820 } 2920 }
2821 } 2921 }
2822 } 2922 }
2823 2923
2824 /* 2924 /*
2925 * Only called when popup window "wp" is hidden: If the window is positioned
2926 * next to a text property, and it is now visible, then unhide the popup.
2927 * We don't check if visible popups become hidden, that is done in
2928 * popup_adjust_position().
2929 * Return TRUE if the popup became unhidden.
2930 */
2931 static int
2932 check_popup_unhidden(win_T *wp)
2933 {
2934 if (wp->w_popup_prop_type > 0 && win_valid(wp->w_popup_prop_win))
2935 {
2936 textprop_T prop;
2937 linenr_T lnum;
2938
2939 if (find_visible_prop(wp->w_popup_prop_win,
2940 wp->w_popup_prop_type, wp->w_popup_prop_id,
2941 &prop, &lnum) == OK)
2942 {
2943 wp->w_popup_flags &= ~POPF_HIDDEN;
2944 ++wp->w_buffer->b_nwindows;
2945 wp->w_popup_prop_topline = 0; // force repositioning
2946 return TRUE;
2947 }
2948 }
2949 return FALSE;
2950 }
2951
2952 /*
2953 * Return TRUE if popup_adjust_position() needs to be called for "wp".
2954 * That is when the buffer in the popup was changed, or the popup is following
2955 * a textprop and the referenced buffer was changed.
2956 */
2957 static int
2958 popup_need_position_adjust(win_T *wp)
2959 {
2960 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
2961 return TRUE;
2962 if (win_valid(wp->w_popup_prop_win))
2963 return wp->w_popup_prop_changedtick
2964 != CHANGEDTICK(wp->w_popup_prop_win->w_buffer)
2965 || wp->w_popup_prop_topline != wp->w_popup_prop_win->w_topline;
2966 return FALSE;
2967 }
2968
2969 /*
2825 * Update "popup_mask" if needed. 2970 * Update "popup_mask" if needed.
2826 * Also recomputes the popup size and positions. 2971 * Also recomputes the popup size and positions.
2827 * Also updates "popup_visible". 2972 * Also updates "popup_visible".
2828 * Also marks window lines for redrawing. 2973 * Also marks window lines for redrawing.
2829 */ 2974 */
2842 if (popup_mask_tab != curtab || type >= NOT_VALID) 2987 if (popup_mask_tab != curtab || type >= NOT_VALID)
2843 { 2988 {
2844 popup_mask_refresh = TRUE; 2989 popup_mask_refresh = TRUE;
2845 redraw_all_popups = TRUE; 2990 redraw_all_popups = TRUE;
2846 } 2991 }
2992
2993 // Check if any popup window buffer has changed and if any popup connected
2994 // to a text property has become visible.
2995 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
2996 if (wp->w_popup_flags & POPF_HIDDEN)
2997 popup_mask_refresh |= check_popup_unhidden(wp);
2998 else if (popup_need_position_adjust(wp))
2999 popup_mask_refresh = TRUE;
3000 for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
3001 if (wp->w_popup_flags & POPF_HIDDEN)
3002 popup_mask_refresh |= check_popup_unhidden(wp);
3003 else if (popup_need_position_adjust(wp))
3004 popup_mask_refresh = TRUE;
3005
2847 if (!popup_mask_refresh) 3006 if (!popup_mask_refresh)
2848 { 3007 return;
2849 // Check if any popup window buffer has changed.
2850 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
2851 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
2852 popup_mask_refresh = TRUE;
2853 for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
2854 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
2855 popup_mask_refresh = TRUE;
2856 if (!popup_mask_refresh)
2857 return;
2858 }
2859 3008
2860 // Need to update the mask, something has changed. 3009 // Need to update the mask, something has changed.
2861 popup_mask_refresh = FALSE; 3010 popup_mask_refresh = FALSE;
2862 popup_mask_tab = curtab; 3011 popup_mask_tab = curtab;
2863 popup_visible = FALSE; 3012 popup_visible = FALSE;
2884 int width; 3033 int width;
2885 int height; 3034 int height;
2886 3035
2887 popup_visible = TRUE; 3036 popup_visible = TRUE;
2888 3037
2889 // Recompute the position if the text changed. 3038 // Recompute the position if the text changed. It may make the popup
2890 if (redraw_all_popups 3039 // hidden if it's attach to a text property that is no longer visible.
2891 || wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer)) 3040 if (redraw_all_popups || popup_need_position_adjust(wp))
3041 {
2892 popup_adjust_position(wp); 3042 popup_adjust_position(wp);
3043 if (wp->w_popup_flags & POPF_HIDDEN)
3044 continue;
3045 }
2893 3046
2894 width = popup_width(wp); 3047 width = popup_width(wp);
2895 height = popup_height(wp); 3048 height = popup_height(wp);
2896 popup_update_mask(wp, width, height); 3049 popup_update_mask(wp, width, height);
2897 for (line = wp->w_winrow; 3050 for (line = wp->w_winrow;
3409 popup_close_preview(void) 3562 popup_close_preview(void)
3410 { 3563 {
3411 win_T *wp = popup_find_preview_window(); 3564 win_T *wp = popup_find_preview_window();
3412 3565
3413 if (wp != NULL) 3566 if (wp != NULL)
3414 { 3567 popup_close_with_retval(wp, -1);
3415 typval_T res;
3416
3417 res.v_type = VAR_NUMBER;
3418 res.vval.v_number = -1;
3419 popup_close_and_callback(wp, &res);
3420 }
3421 } 3568 }
3422 3569
3423 /* 3570 /*
3424 * Hide the info popup. 3571 * Hide the info popup.
3425 */ 3572 */
3430 3577
3431 if (wp != NULL) 3578 if (wp != NULL)
3432 popup_hide(wp); 3579 popup_hide(wp);
3433 } 3580 }
3434 #endif 3581 #endif
3582
3583 /*
3584 * Close any popup for a text property associated with "win".
3585 * Return TRUE if a popup was closed.
3586 */
3587 int
3588 popup_win_closed(win_T *win)
3589 {
3590 win_T *wp;
3591
3592 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
3593 if (wp->w_popup_prop_win == win)
3594 {
3595 popup_close_with_retval(wp, -1);
3596 return TRUE;
3597 }
3598 for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
3599 if (wp->w_popup_prop_win == win)
3600 {
3601 popup_close_with_retval(wp, -1);
3602 return TRUE;
3603 }
3604 return FALSE;
3605 }
3435 3606
3436 /* 3607 /*
3437 * Set the title of the popup window to the file name. 3608 * Set the title of the popup window to the file name.
3438 */ 3609 */
3439 void 3610 void