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

Commit d460e89

Browse files
committed
implement proper floating windows
1 parent 6726078 commit d460e89

File tree

1 file changed

+75
-15
lines changed

1 file changed

+75
-15
lines changed

neovim_gui/gtk_ui.py

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

77
from functools import partial
8+
from types import SimpleNamespace
89

910
import cairo
1011

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

103-
def create_drawing_area(self, handle):
104+
def get_grid(self, handle):
105+
if handle in self.grids:
106+
return self.grids[handle]
104107
g = Grid()
105108
g.handle = handle
106-
g._resize_timer_id = None
109+
g._pending = [0, 0, 0]
110+
g._screen = None
107111
drawing_area = Gtk.DrawingArea()
108112
drawing_area.connect('draw', partial(self._gtk_draw, g))
113+
g._pango_context = drawing_area.create_pango_context()
114+
g._drawing_area = drawing_area
115+
g._window = None
116+
g.options = None
117+
self.grids[handle] = g
118+
return g
119+
120+
def create_window(self, handle):
121+
g = self.get_grid(handle)
122+
g._resize_timer_id = None
109123
window = Gtk.Window()
110-
window.add(drawing_area)
124+
layout = Gtk.Fixed()
125+
window.add(layout)
126+
layout.put(g._drawing_area,0,0)
111127
window.set_events(window.get_events() |
112128
Gdk.EventMask.BUTTON_PRESS_MASK |
113129
Gdk.EventMask.BUTTON_RELEASE_MASK |
@@ -124,14 +140,9 @@ def create_drawing_area(self, handle):
124140
window.connect('focus-in-event', self._gtk_focus_in)
125141
window.connect('focus-out-event', self._gtk_focus_out)
126142
window.show_all()
127-
g._pango_context = drawing_area.create_pango_context()
128-
g._drawing_area = drawing_area
129143
g._window = window
130-
g._pending = [0, 0, 0]
131-
g._screen = None
144+
g._layout = layout
132145

133-
self.grids[handle] = g
134-
return g
135146

136147

137148
def start(self, bridge):
@@ -148,8 +159,10 @@ def start(self, bridge):
148159
im_context.set_use_preedit(False) # TODO: preedit at cursor position
149160
im_context.connect('commit', self._gtk_input)
150161
self._im_context = im_context
151-
self.g = self.create_drawing_area(1)
162+
self.create_window(1)
163+
self.g = self.get_grid(1)
152164
self._window = self.g._window
165+
self._layout = self.g._layout
153166
self._bridge = bridge
154167
Gtk.main()
155168

@@ -168,19 +181,60 @@ def wrapper():
168181
GObject.idle_add(wrapper)
169182

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

179235
def _nvim_grid_resize(self, grid, columns, rows):
180236
print("da")
181-
if grid not in self.grids:
182-
self.create_drawing_area(grid)
183-
g = self.grids[grid]
237+
g = self.get_grid(grid)
184238
da = g._drawing_area
185239
# create FontDescription object for the selected font/size
186240
font_str = '{0} {1}'.format(self._font_name, self._font_size)
@@ -205,7 +259,13 @@ def _nvim_grid_resize(self, grid, columns, rows):
205259
self._cell_pixel_width = cell_pixel_width
206260
self._cell_pixel_height = cell_pixel_height
207261
g._screen = Screen(columns, rows)
208-
g._window.resize(pixel_width, pixel_height)
262+
g._drawing_area.set_size_request(pixel_width, pixel_height)
263+
g.pixel_size = pixel_width, pixel_height
264+
if g.options is not None:
265+
self.configure_float(g)
266+
267+
if g._window is not None:
268+
g._window.resize(pixel_width, pixel_height)
209269

210270
def _nvim_grid_clear(self, grid):
211271
g = self.grids[grid]

0 commit comments

Comments
 (0)