Skip to content
This repository was archived by the owner on Jun 30, 2023. It is now read-only.

Commit 716b74f

Browse files
committed
implement proper floating windows
1 parent b8b7243 commit 716b74f

File tree

1 file changed

+75
-15
lines changed

1 file changed

+75
-15
lines changed

Diff for: neovim_gui/gtk_ui.py

+75-15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55

66
from functools import partial
7+
from types import SimpleNamespace
78

89
import cairo
910

@@ -99,14 +100,29 @@ def __init__(self, font):
99100
self.grids = {}
100101
self.g = None
101102

102-
def create_drawing_area(self, handle):
103+
def get_grid(self, handle):
104+
if handle in self.grids:
105+
return self.grids[handle]
103106
g = Grid()
104107
g.handle = handle
105-
g._resize_timer_id = None
108+
g._pending = [0, 0, 0]
109+
g._screen = None
106110
drawing_area = Gtk.DrawingArea()
107111
drawing_area.connect('draw', partial(self._gtk_draw, g))
112+
g._pango_context = drawing_area.create_pango_context()
113+
g._drawing_area = drawing_area
114+
g._window = None
115+
g.options = None
116+
self.grids[handle] = g
117+
return g
118+
119+
def create_window(self, handle):
120+
g = self.get_grid(handle)
121+
g._resize_timer_id = None
108122
window = Gtk.Window()
109-
window.add(drawing_area)
123+
layout = Gtk.Fixed()
124+
window.add(layout)
125+
layout.put(g._drawing_area,0,0)
110126
window.set_events(window.get_events() |
111127
Gdk.EventMask.BUTTON_PRESS_MASK |
112128
Gdk.EventMask.BUTTON_RELEASE_MASK |
@@ -123,14 +139,9 @@ def create_drawing_area(self, handle):
123139
window.connect('focus-in-event', self._gtk_focus_in)
124140
window.connect('focus-out-event', self._gtk_focus_out)
125141
window.show_all()
126-
g._pango_context = drawing_area.create_pango_context()
127-
g._drawing_area = drawing_area
128142
g._window = window
129-
g._pending = [0, 0, 0]
130-
g._screen = None
143+
g._layout = layout
131144

132-
self.grids[handle] = g
133-
return g
134145

135146

136147
def start(self, bridge):
@@ -145,8 +156,10 @@ def start(self, bridge):
145156
im_context.set_use_preedit(False) # TODO: preedit at cursor position
146157
im_context.connect('commit', self._gtk_input)
147158
self._im_context = im_context
148-
self.g = self.create_drawing_area(1)
159+
self.create_window(1)
160+
self.g = self.get_grid(1)
149161
self._window = self.g._window
162+
self._layout = self.g._layout
150163
self._bridge = bridge
151164
Gtk.main()
152165

@@ -165,19 +178,60 @@ def wrapper():
165178
GObject.idle_add(wrapper)
166179

167180
def _nvim_grid_cursor_goto(self, grid, row, col):
168-
g = self.grids[grid]
181+
g = self.get_grid(grid)
169182
self.g = g
170183
if g._screen is not None:
171184
# TODO: this should really be asserted on the nvim side
172185
row, col = min(row, g._screen.rows-1), min(col, g._screen.columns-1)
173186
g._screen.cursor_goto(row,col)
174187
self._window= self.g._window
188+
self._screen = self.g._screen
189+
190+
def _nvim_float_info(self, win, handle, width, height, options):
191+
g = self.get_grid(handle)
192+
g.nvim_win = win
193+
g.options = SimpleNamespace(**options)
194+
self.configure_float(g)
195+
196+
def _nvim_float_close(self, win, handle):
197+
g = self.get_grid(handle)
198+
199+
if g._window is not None:
200+
g._layout.remove(g._drawing_area)
201+
g._window.destroy()
202+
elif g._drawing_area.get_parent() == self._layout:
203+
self._layout.remove(g._drawing_area)
204+
205+
def configure_float(self, g):
206+
if g.options.standalone:
207+
if not g._window:
208+
if g._drawing_area.get_parent() == self._layout:
209+
self._layout.remove(g._drawing_area)
210+
self.create_window(g.handle)
211+
else:
212+
if g._window is not None:
213+
g._layout.remove(g._drawing_area)
214+
g._window.destroy()
215+
# this is ugly, but I'm too lazy to refactor nvim_resize
216+
# to fit the flow of information
217+
if g._drawing_area.get_parent() != self._layout:
218+
self._layout.add(g._drawing_area)
219+
g._drawing_area.show()
220+
if g._screen is not None:
221+
x = g.options.x*self._cell_pixel_width
222+
y = g.options.y*self._cell_pixel_height
223+
w,h = g.pixel_size
224+
if len(g.options.anchor) >= 2:
225+
if g.options.anchor[0] == 'S':
226+
y -= h
227+
if g.options.anchor[1] == 'E':
228+
x -= w
229+
self._layout.move(g._drawing_area,x,y)
230+
175231

176232
def _nvim_grid_resize(self, grid, columns, rows):
177233
print("da")
178-
if grid not in self.grids:
179-
self.create_drawing_area(grid)
180-
g = self.grids[grid]
234+
g = self.get_grid(grid)
181235
da = g._drawing_area
182236
# create FontDescription object for the selected font/size
183237
font_str = '{0} {1}'.format(self._font_name, self._font_size)
@@ -202,7 +256,13 @@ def _nvim_grid_resize(self, grid, columns, rows):
202256
self._cell_pixel_width = cell_pixel_width
203257
self._cell_pixel_height = cell_pixel_height
204258
g._screen = Screen(columns, rows)
205-
g._window.resize(pixel_width, pixel_height)
259+
g._drawing_area.set_size_request(pixel_width, pixel_height)
260+
g.pixel_size = pixel_width, pixel_height
261+
if g.options is not None:
262+
self.configure_float(g)
263+
264+
if g._window is not None:
265+
g._window.resize(pixel_width, pixel_height)
206266

207267
def _nvim_grid_clear(self, grid):
208268
g = self.grids[grid]

0 commit comments

Comments
 (0)