Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions guake/gsettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ def alignment_changed(self, settings, key, user_data):
"""If the gconf var window_halignment be changed, this method will
be called and will call the move function in guake.
"""
RectCalculator.set_final_window_rect(self.settings, self.guake.window)
rect = RectCalculator.set_final_window_rect(self.settings, self.guake.window)
self.guake._enforced_width = int(rect.width)
self.guake.set_tab_position()
self.guake.force_move_if_shown()

Expand All @@ -155,7 +156,8 @@ def size_changed(self, settings, key, user_data):
this method will be called and will call the resize function
in guake.
"""
RectCalculator.set_final_window_rect(self.settings, self.guake.window)
rect = RectCalculator.set_final_window_rect(self.settings, self.guake.window)
self.guake._enforced_width = int(rect.width)

def cursor_blink_mode_changed(self, settings, key, user_data):
"""Called when cursor blink mode settings has been changed"""
Expand Down
59 changes: 57 additions & 2 deletions guake/guake_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ def load_schema():

self.window.connect("focus-out-event", self.on_window_losefocus)
self.window.connect("focus-in-event", self.on_window_takefocus)
# Watchdog state: last width we enforced; see _on_window_configure.
self._enforced_width = None
self._size_restore_pending = False
self.window.connect("configure-event", self._on_window_configure)

# Handling the delete-event of the main window to avoid
# problems when closing it.
Expand Down Expand Up @@ -697,6 +701,10 @@ def show(self):
# setting window in all desktops

window_rect = RectCalculator.set_final_window_rect(self.settings, self.window)
self._enforced_width = int(window_rect.width)
# Used by the WM as the map-time size; without it KWin/XWayland maps
# at VTE natural width and we get a shrink-then-grow flicker.
self.window.set_default_size(window_rect.width, window_rect.height)
self.window.stick()

# add tab must be called before window.show to avoid a
Expand Down Expand Up @@ -739,13 +747,24 @@ def show(self):
# glib.timeout_add_seconds(1, lambda: self.timeout_restore(time))
#

# Flip type hint before mapping: doing it after show() makes KWin
# re-manage the window at VTE natural width (flicker).
self.window.set_type_hint(Gdk.WindowTypeHint.DOCK)
self.window.set_type_hint(Gdk.WindowTypeHint.NORMAL)
log.debug("order to present and deiconify")
self.window.present()
self.window.deiconify()
self.window.show()
# Re-assert size after mapping; the configure watchdog below
# catches any late snap-back by the compositor.
RectCalculator.set_final_window_rect(self.settings, self.window)
GLib.idle_add(
lambda: not getattr(self, "hidden", True)
and self.window.get_visible()
and RectCalculator.set_final_window_rect(self.settings, self.window)
and False
)
self.window.get_window().focus(time)
self.window.set_type_hint(Gdk.WindowTypeHint.DOCK)
self.window.set_type_hint(Gdk.WindowTypeHint.NORMAL)

# This is here because vte color configuration works only after the
# widget is shown.
Expand Down Expand Up @@ -787,6 +806,42 @@ def hide(self):
# Hide popover
self.notebook_manager.get_current_notebook().popover.hide()

def _on_window_configure(self, widget, event):
"""Watchdog: KWin/XWayland sometimes snaps the mapped window back
to VTE natural width. Re-assert the enforced size when a configure
shows a large unexpected shrink (debounced).
"""
try:
if getattr(self, "hidden", True):
return False
if self._enforced_width is None or self._size_restore_pending:
return False
if self.fullscreen_manager.is_fullscreen():
return False
if event.width < self._enforced_width - 64:
self._size_restore_pending = True
GLib.timeout_add(120, self._restore_enforced_size)
except Exception:
log.exception("configure watchdog failed")
return False

def _restore_enforced_size(self):
self._size_restore_pending = False
try:
if getattr(self, "hidden", True):
return False
if not self.window.get_visible():
return False
if self.fullscreen_manager.is_fullscreen():
return False
w, _h = self.window.get_size()
if self._enforced_width is not None and w < self._enforced_width - 64:
rect = RectCalculator.set_final_window_rect(self.settings, self.window)
self._enforced_width = int(rect.width)
except Exception:
log.exception("failed to restore enforced window size")
return False

def force_move_if_shown(self):
if not self.hidden:
# when displayed, GTK might refuse to move the window (X or Y position). Just hide and
Expand Down
27 changes: 27 additions & 0 deletions guake/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from guake.menus import mk_notebook_context_menu
from guake.prefs import PrefsDialog
from guake.utils import HidePrevention
from guake.utils import RectCalculator
from guake.utils import gdk_is_x11_display
from guake.utils import get_process_name
from guake.utils import save_tabs_when_changed
Expand All @@ -40,6 +41,7 @@

gi.require_version("Gtk", "3.0")
gi.require_version("Wnck", "3.0")
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import Gtk
Expand Down Expand Up @@ -359,6 +361,7 @@ def remove_page(self, page_num):

self.hide_tabbar_if_one_tab()
self.emit("page-deleted")
self.restore_window_size()

def delete_page_by_label(self, label, kill=True, prompt=0):
self.delete_page(self.find_tab_index_by_label(label), kill, prompt)
Expand Down Expand Up @@ -396,12 +399,36 @@ def new_page(self, directory=None, position=None, empty=False, open_tab_cwd=Fals
if not empty:
self.terminal_attached(terminal)
self.hide_tabbar_if_one_tab()
self.restore_window_size()

if self.guake:
# Attack background image draw callback to root terminal box
root_terminal_box.connect_after("draw", self.guake.background_image_manager.draw)
return root_terminal_box, page_num, terminal

def restore_window_size(self):
"""Re-assert the configured window size after a tab is added/removed.

GTK renegotiates the toplevel natural size on insert_page/show_all
and KWin (XWayland) shrinks Guake. show() already enforces the size
via RectCalculator, but new_page()/remove_page() did not.
"""
try:
guake = getattr(self, "guake", None)
if not guake or not getattr(guake, "window", None):
return
if getattr(guake, "hidden", True):
return
window = guake.window
if not window.get_visible():
return
GLib.idle_add(
lambda: RectCalculator.set_final_window_rect(guake.settings, window)
and False
)
except Exception: # never break tab creation on resize failure
log.exception("failed to restore window size after tab change")

def hide_tabbar_if_one_tab(self):
"""Hide the tab bar if hide-tabs-if-one-tab is true and there is only one
notebook page"""
Expand Down
4 changes: 4 additions & 0 deletions guake/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ def set_final_window_rect(cls, settings, window):

if width_percents == 100 and height_percents == 100:
log.debug("MAXIMIZING MAIN WINDOW")
window.set_size_request(-1, -1)
window.move(window_rect.x, window_rect.y)
window.maximize()
elif not FullscreenManager(settings, window).is_fullscreen():
Expand All @@ -319,6 +320,9 @@ def set_final_window_rect(cls, settings, window):
# Note: move_resize is only on GTK3
window.resize(window_rect.width, window_rect.height)
window.move(window_rect.x, window_rect.y)
# Floor the width: KWin/XWayland otherwise snaps a fresh map
# back to VTE natural width until something re-asserts it.
window.set_size_request(window_rect.width, -1)
log.debug("Updated window position: %r", window.get_position())

return window_rect
Expand Down