Skip to content

Commit

Permalink
fix(menu): drop-down menu position
Browse files Browse the repository at this point in the history
1. This bug only occurs when 'mousemoveevent' is on
2. Steps to reproduce:
   - Use mouse to click on a symbol in winbar to open a menu
   - Close the menu
   - Move the mouse to an arbitrary position (inside nvim)
   - Use pick mode to select the same symbol
   - The menu is opened under the current mouse position instead of under
     the selected symbol
3. Cause: the menu is created with window configuration relative='mouse'
          the first time it is opened, so when we open it the second time
          the window is opened at the mouse position
4. Fix: pass window configurations to dropbar_menu_t:toggle() and
        dropbar_menu_t:open() to override original configurations
        if a menu is opened in pick mode
  • Loading branch information
bekaboo committed Jun 5, 2023
1 parent 35f6bb9 commit 1bee80f
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 34 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ Declared and defined in [`lua/dropbar/menu.lua`](https://github.com/Bekaboo/drop
| ------ | ------ |
| `dropbar_menu_t:new(opts: dropbar_menu_opts_t?): dropbar_menu_t` | constructor of `dropbar_menu_t` |
| `dropbar_menu_t:del()` | destructor of `dropbar_menu_t` |
| `dropbar_menu_t:eval_win_config()` | evaluate window configuration and store the result in `_win_configs` |
| `dropbar_menu_t:eval_win_configs(win_configs: table?)` | evaluate window configurations (`dropbar_menu_t.win_configs` merged with param `win_configs`) and store the result in `dropbar_menu_t._win_configs` |
| `dropbar_menu_t:get_component_at(pos: integer[]): dropbar_symbol_t?, { start: integer, end: integer }?` | get the component<sub>[`dropbar_symbol_t`](#dropbar_symbol_t)</sub> at position `pos` and its range it occupies in the entry it belongs to |
| `dropbar_menu_t:click_at(pos: integer[], min_width: integer?, n_clicks: integer?, button: string?, modifiers: string?)` | simulate a click at `pos` in the menu |
| `dropbar_menu_t:click_on(symbol: dropbar_symbol_t, min_width: integer?, n_clicks: integer?, button: string?, modifiers: string?)` | simulate a click at the component `symbol`<sub>[`dropbar_symbol_t`](#dropbar_symbol_t)</sub> of the menu |
Expand All @@ -1298,9 +1298,9 @@ Declared and defined in [`lua/dropbar/menu.lua`](https://github.com/Bekaboo/drop
| `dropbar_menu_t:hl_range_single(line: integer?, range: { start: integer, end: integer }?, hlgroup: string?)` | add highlight to a single range in a single line in the menu buffer; `hlgroups` defaults to `'DropBarMenuHoverSymbol'`<br> *all highlights with the same hlgroup added by this functions before will be cleared |
| `dropbar_menu_t:update_hover_hl(pos: integer[])` | update the hover highlights (`DropBarMenuHover*`) assuming the cursor/mouse is hovering at `pos` in the menu |
| `dropbar_menu_t:make_buf()` | create the menu buffer from the entries<sub>[`dropbar_menu_entry_t`](#dropbar_menu_entry_t) |
| `dropbar_menu_t:open()` | open the menu |
| `dropbar_menu_t:open(win_configs: table?)` | open the menu with window configurations `dropbar_menu_t.win_configs` merged with param `win_configs` |
| `dropbar_menu_t:close()` | close the menu |
| `dropbar_menu_t:toggle()` | toggle the menu |
| `dropbar_menu_t:toggle(win_configs; table)` | toggle the menu, passing `win_configs` to `dropbar_menu_t:open()` if decide to open the menu |
#### `dropbar_menu_entry_t`
Expand Down
23 changes: 18 additions & 5 deletions doc/dropbar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1359,9 +1359,14 @@ dropbar_menu_t:del() *dropbar_menu_t:del()*

Destructor of `dropbar_menu_t`

dropbar_menu_t:eval_win_config() *dropbar_menu_t:eval_win_config()*
*dropbar_menu_t:eval_win_configs()*
dropbar_menu_t:eval_win_configs([{win_configs}])

Evaluate window configuration and store the result in `_win_configs`
Evaluate window configurations |dropbar_menu_t.win_configs| and store
the result in |dropbar_menu_t._win_configs|

Parameters ~
• {win_configs} (table?): window configurations to override

dropbar_menu_t:get_component_at({pos}) *dropbar_menu_t:get_component_at()*

Expand Down Expand Up @@ -1454,18 +1459,26 @@ dropbar_menu_t:make_buf() *dropbar_menu_t:make_buf()*
Create the menu buffer from the entries
|dropbar-developers-classes-dropbar_menu_entry_t|

dropbar_menu_t:open() *dropbar_menu_t:open()*
dropbar_menu_t:open([{win_configs}]) *dropbar_menu_t:open()*

Open the menu with window configurations |dropbar_menu_t.win_configs|
merged with {win_configs}

Open the menu
Parameters ~
• {win_configs} (table?): window configurations to override

dropbar_menu_t:close() *dropbar_menu_t:close()*

Close the menu

dropbar_menu_t:toggle() *dropbar_menu_t:toggle()*
dropbar_menu_t:toggle([{win_configs}]) *dropbar_menu_t:toggle()*

Toggle the menu

Parameters ~
• {win_configs} (table?): window configurations passing to
|dropbar_menu_t:open()|

..............................................................................
DROPBAR_MENU_ENTRY_T *dropbar-developers-classes-dropbar_menu_entry_t*
*dropbar_menu_entry_t*
Expand Down
42 changes: 22 additions & 20 deletions lua/dropbar/bar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,38 @@ function dropbar_symbol_t:new(opts)
name = '',
icon = '',
on_click = opts
---@param this dropbar_symbol_t
and function(this, _, _, _, _)
if this.entry and this.entry.menu then
this.entry.menu:hl_line_single(this.entry.idx)
end

-- Called in pick mode, open the menu relative to the symbol
-- position in the winbar
local menu_win_configs = nil
if this.bar and this.bar.in_pick_mode then
local col = 0
for i, component in ipairs(this.bar.components) do
if i < this.bar_idx then
col = col
+ component:displaywidth()
+ this.bar.separator:displaywidth()
end
end
menu_win_configs = {
relative = 'win',
row = 0,
col = col,
}
end

-- Toggle menu on click, or create one if menu don't exist:
-- 1. If symbol inside a winbar, create a menu with entries
-- containing the symbol's siblings
-- 2. Else if symbol inside a menu, create menu with entries
-- containing the symbol's children
if this.menu then
this.menu:toggle()
this.menu:toggle(menu_win_configs)
return
end

Expand All @@ -99,25 +120,6 @@ function dropbar_symbol_t:new(opts)
return
end

-- Called in pick mode, open the menu relative to the symbol
-- position in the winbar
local menu_win_configs = nil
if this.bar and this.bar.in_pick_mode then
local col = 0
for i, component in ipairs(this.bar.components) do
if i < this.bar_idx then
col = col
+ component:displaywidth()
+ this.bar.separator:displaywidth()
end
end
menu_win_configs = {
relative = 'win',
row = 0,
col = col,
}
end

local menu = require('dropbar.menu')
this.menu = menu.dropbar_menu_t:new({
prev_win = menu_prev_win,
Expand Down
17 changes: 11 additions & 6 deletions lua/dropbar/menu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,15 @@ end

---Evaluate window configurations
---Side effects: update self._win_configs
---@param win_configs table? window configurations to override
---@return nil
---@see vim.api.nvim_open_win
function dropbar_menu_t:eval_win_config()
function dropbar_menu_t:eval_win_configs(win_configs)
-- Evaluate function-valued window configurations
self._win_configs = {}
for k, config in pairs(self.win_configs) do
for k, config in
pairs(vim.tbl_deep_extend('force', self.win_configs, win_configs or {}))
do
if type(config) == 'function' then
self._win_configs[k] = config(self)
else
Expand Down Expand Up @@ -506,8 +509,9 @@ end

---Open the menu
---Side effect: change self.win and self.buf
---@param win_configs table? window configurations to override
---@return nil
function dropbar_menu_t:open()
function dropbar_menu_t:open(win_configs)
if self.is_opened then
return
end
Expand All @@ -524,7 +528,7 @@ function dropbar_menu_t:open()
self.prev_win = parent_menu.win
end

self:eval_win_config()
self:eval_win_configs(win_configs)
self:make_buf()
self.win = vim.api.nvim_open_win(self.buf, true, self._win_configs)
self.is_opened = true
Expand Down Expand Up @@ -561,12 +565,13 @@ function dropbar_menu_t:close()
end

---Toggle the menu
---@param win_configs table? window configurations to override
---@return nil
function dropbar_menu_t:toggle()
function dropbar_menu_t:toggle(win_configs)
if self.is_opened then
self:close()
else
self:open()
self:open(win_configs)
end
end

Expand Down

0 comments on commit 1bee80f

Please sign in to comment.