Skip to content

Commit 90bdc45

Browse files
committed
fix(gui): resize mini chat only from corners
1 parent d1c3fd3 commit 90bdc45

2 files changed

Lines changed: 106 additions & 14 deletions

File tree

feeluown/gui/uimain/mini_mode.py

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,16 @@ def _show_context_menu(self, global_pos):
267267
menu.exec(global_pos)
268268

269269
def _handle_drag_event(self, obj, event):
270-
if self._is_interactive_drag_source(obj):
270+
drag_active = (
271+
self._drag_global_pos is not None or self._using_system_move
272+
)
273+
if self._is_interactive_drag_source(obj) and not (
274+
drag_active
275+
or (
276+
self.isVisible()
277+
and self._is_window_side(event.globalPosition().toPoint())
278+
)
279+
):
271280
self._drag_global_pos = None
272281
self._using_system_move = False
273282
return False
@@ -316,7 +325,7 @@ def _handle_resize_event(self, _obj, event):
316325
return True
317326
edges = self._resize_edges_at(global_pos)
318327
if edges is not None:
319-
self.setCursor(Qt.CursorShape.SizeHorCursor)
328+
self.setCursor(self._resize_cursor(edges))
320329
else:
321330
self.unsetCursor()
322331
return False
@@ -346,12 +355,37 @@ def _handle_resize_event(self, _obj, event):
346355

347356
def _resize_edges_at(self, global_pos):
348357
geometry = self.frameGeometry()
349-
if global_pos.x() <= geometry.left() + RESIZE_MARGIN:
350-
return Qt.Edge.LeftEdge
351-
if global_pos.x() >= geometry.right() - RESIZE_MARGIN:
352-
return Qt.Edge.RightEdge
358+
left = global_pos.x() <= geometry.left() + RESIZE_MARGIN
359+
right = global_pos.x() >= geometry.right() - RESIZE_MARGIN
360+
top = global_pos.y() <= geometry.top() + RESIZE_MARGIN
361+
bottom = global_pos.y() >= geometry.bottom() - RESIZE_MARGIN
362+
if left and top:
363+
return Qt.Edge.LeftEdge | Qt.Edge.TopEdge
364+
if right and top:
365+
return Qt.Edge.RightEdge | Qt.Edge.TopEdge
366+
if left and bottom:
367+
return Qt.Edge.LeftEdge | Qt.Edge.BottomEdge
368+
if right and bottom:
369+
return Qt.Edge.RightEdge | Qt.Edge.BottomEdge
353370
return None
354371

372+
def _resize_cursor(self, edges):
373+
if edges in (
374+
Qt.Edge.LeftEdge | Qt.Edge.TopEdge,
375+
Qt.Edge.RightEdge | Qt.Edge.BottomEdge,
376+
):
377+
return Qt.CursorShape.SizeFDiagCursor
378+
return Qt.CursorShape.SizeBDiagCursor
379+
380+
def _is_window_side(self, global_pos):
381+
geometry = self.frameGeometry()
382+
return (
383+
global_pos.x() <= geometry.left() + RESIZE_MARGIN
384+
or global_pos.x() >= geometry.right() - RESIZE_MARGIN
385+
or global_pos.y() <= geometry.top() + RESIZE_MARGIN
386+
or global_pos.y() >= geometry.bottom() - RESIZE_MARGIN
387+
)
388+
355389
def _resize_manually(self, global_pos):
356390
start_geometry = self._resize_start_geometry
357391
start_pos = self._resize_global_pos
@@ -360,19 +394,31 @@ def _resize_manually(self, global_pos):
360394

361395
delta_x = global_pos.x() - start_pos.x()
362396
width = start_geometry.width()
363-
if self._resize_edges == Qt.Edge.LeftEdge:
397+
height = start_geometry.height()
398+
if self._resize_edges & Qt.Edge.LeftEdge:
364399
width -= delta_x
365-
else:
400+
elif self._resize_edges & Qt.Edge.RightEdge:
366401
width += delta_x
402+
if self._resize_edges & Qt.Edge.TopEdge:
403+
height -= global_pos.y() - start_pos.y()
404+
elif self._resize_edges & Qt.Edge.BottomEdge:
405+
height += global_pos.y() - start_pos.y()
367406

368407
width = max(self.minimumWidth(), width)
369408
if self.maximumWidth() < 16777215:
370409
width = min(self.maximumWidth(), width)
371-
if self._resize_edges == Qt.Edge.LeftEdge:
410+
height = max(self.minimumHeight(), height)
411+
if self.maximumHeight() < 16777215:
412+
height = min(self.maximumHeight(), height)
413+
if self._resize_edges & Qt.Edge.LeftEdge:
372414
x = start_geometry.right() - width + 1
373415
else:
374416
x = start_geometry.x()
375-
self.setGeometry(x, start_geometry.y(), width, self.height())
417+
if self._resize_edges & Qt.Edge.TopEdge:
418+
y = start_geometry.bottom() - height + 1
419+
else:
420+
y = start_geometry.y()
421+
self.setGeometry(x, y, width, height)
376422

377423
def _start_system_move(self):
378424
handle = self.windowHandle()
@@ -443,7 +489,11 @@ def _is_chat_panel_child(self, obj):
443489
return False
444490

445491
def _resize_to_content(self):
446-
if self._resizing_to_content:
492+
if (
493+
self._resizing_to_content
494+
or self._using_system_resize
495+
or self._resize_start_geometry is not None
496+
):
447497
return
448498
self._resizing_to_content = True
449499
try:

tests/gui/uimain/test_uimain.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,9 @@ def test_mini_mode_window_prefers_system_move(qtbot, app_mock, monkeypatch):
11901190
assert not window._using_system_move
11911191

11921192

1193-
def test_mini_mode_window_resizes_from_right_edge(qtbot, app_mock, monkeypatch):
1193+
def test_mini_mode_window_resizes_from_bottom_right_corner(
1194+
qtbot, app_mock, monkeypatch
1195+
):
11941196
_prepare_dynamic_island_app(app_mock)
11951197
app_mock.ai = FakeAI()
11961198
window = MiniModeWindow(app_mock)
@@ -1200,8 +1202,11 @@ def test_mini_mode_window_resizes_from_right_edge(qtbot, app_mock, monkeypatch):
12001202
monkeypatch.setattr(window, "_start_system_resize", lambda _edges: False)
12011203

12021204
start_geometry = window.frameGeometry()
1203-
start_pos = QPointF(start_geometry.right(), start_geometry.center().y())
1204-
moved_pos = QPointF(start_geometry.right() + 40, start_geometry.center().y())
1205+
start_pos = QPointF(start_geometry.right(), start_geometry.bottom())
1206+
moved_pos = QPointF(
1207+
start_geometry.right() + 40,
1208+
start_geometry.bottom() + 20,
1209+
)
12051210

12061211
assert window._handle_resize_event(
12071212
window,
@@ -1217,6 +1222,43 @@ def test_mini_mode_window_resizes_from_right_edge(qtbot, app_mock, monkeypatch):
12171222
)
12181223

12191224
assert window.width() == start_geometry.width() + 40
1225+
assert window.height() == start_geometry.height() + 20
1226+
1227+
1228+
def test_mini_mode_window_moves_from_edge_middle(qtbot, app_mock, monkeypatch):
1229+
_prepare_dynamic_island_app(app_mock)
1230+
app_mock.ai = FakeAI()
1231+
window = MiniModeWindow(app_mock)
1232+
qtbot.addWidget(window)
1233+
window.show()
1234+
window._toggle_ai_chat_panel()
1235+
monkeypatch.setattr(window, "_start_system_move", lambda: False)
1236+
1237+
start_geometry = window.frameGeometry()
1238+
edge_pos = QPointF(start_geometry.right(), start_geometry.center().y())
1239+
moved_pos = QPointF(edge_pos.x() + 40, edge_pos.y() + 20)
1240+
1241+
assert not window._handle_resize_event(
1242+
window,
1243+
_FakeMouseEvent(QEvent.Type.MouseButtonPress, edge_pos),
1244+
)
1245+
assert window._handle_drag_event(
1246+
window,
1247+
_FakeMouseEvent(QEvent.Type.MouseButtonPress, edge_pos),
1248+
)
1249+
assert window._handle_drag_event(
1250+
window,
1251+
_FakeMouseEvent(QEvent.Type.MouseMove, moved_pos),
1252+
)
1253+
assert window._handle_drag_event(
1254+
window,
1255+
_FakeMouseEvent(QEvent.Type.MouseButtonRelease, moved_pos),
1256+
)
1257+
1258+
assert window.pos() == QPoint(
1259+
start_geometry.x() + 40,
1260+
start_geometry.y() + 20,
1261+
)
12201262

12211263

12221264
def test_mini_mode_window_does_not_drag_from_controls(qtbot, app_mock):

0 commit comments

Comments
 (0)