diff --git a/source/changelog.lisp b/source/changelog.lisp index dcda371278a..97c45c827a1 100644 --- a/source/changelog.lisp +++ b/source/changelog.lisp @@ -27,6 +27,7 @@ (define-version "4.0.0" (:ul + (:li "Fix fullscreen and maximized window logic.") (:li "Refactor input to be handled on the buffer level rather than the window level.") (:li "Deprecate " (:code "input-skip-dispatcher") ".") diff --git a/source/foreign-interface.lisp b/source/foreign-interface.lisp index 7ee020b7a6f..79eef818e7a 100644 --- a/source/foreign-interface.lisp +++ b/source/foreign-interface.lisp @@ -26,15 +26,32 @@ If the `:setter-p' option is non-nil, then a dummy setf method is defined." (define-ffi-generic ffi-window-delete (window) (:documentation "Delete WINDOW.")) -(define-ffi-generic ffi-window-fullscreen (window) - (:documentation "Set fullscreen WINDOW state on.")) -(define-ffi-generic ffi-window-unfullscreen (window) - (:documentation "Set fullscreen WINDOW state off.")) - -(define-ffi-generic ffi-window-maximize (window) - (:documentation "Set WINDOW to a maximized state.")) -(define-ffi-generic ffi-window-unmaximize (window) - (:documentation "Set WINDOW to an unmaximized state.")) +(define-ffi-generic ffi-window-fullscreen (window &key &allow-other-keys) + (:method :around ((window window) &key (user-event-p t) &allow-other-keys) + (setf (slot-value window 'fullscreen-p) t) + (when user-event-p (call-next-method))) + (:documentation "Set fullscreen WINDOW state on. +USER-EVENT-P helps to distinguish events requested by the user or +renderer (e.g. fullscreen a video stream).")) +(define-ffi-generic ffi-window-unfullscreen (window &key &allow-other-keys) + (:method :around ((window window) &key (user-event-p t) &allow-other-keys) + (setf (slot-value window 'fullscreen-p) nil) + (when user-event-p (call-next-method))) + (:documentation "Set fullscreen WINDOW state off. +See `ffi-window-fullscreen'.")) + +(define-ffi-generic ffi-window-maximize (window &key &allow-other-keys) + (:method :around ((window window) &key (user-event-p t) &allow-other-keys) + (setf (slot-value window 'maximized-p) t) + (when user-event-p (call-next-method))) + (:documentation "Set WINDOW to a maximized state. +USER-EVENT-P helps to distinguish events requested by the user or renderer.")) +(define-ffi-generic ffi-window-unmaximize (window &key &allow-other-keys) + (:method :around ((window window) &key (user-event-p t) &allow-other-keys) + (setf (slot-value window 'maximized-p) nil) + (when user-event-p (call-next-method))) + (:documentation "Set WINDOW to an unmaximized state. +See `ffi-window-maximize'.")) (define-ffi-generic ffi-buffer-url (buffer) (:documentation "Return the URL associated with BUFFER as a `quri:uri'. diff --git a/source/renderer/electron.lisp b/source/renderer/electron.lisp index 35cac853227..69424a3a2ad 100644 --- a/source/renderer/electron.lisp +++ b/source/renderer/electron.lisp @@ -403,16 +403,16 @@ (defmethod ffi-width ((window electron-window)) (electron:get-bounds window 'width)) -(defmethod ffi-window-fullscreen ((window electron-window)) +(defmethod ffi-window-fullscreen ((window electron-window) &key &allow-other-keys) (electron:fullscreen window)) -(defmethod ffi-window-unfullscreen ((window electron-window)) +(defmethod ffi-window-unfullscreen ((window electron-window) &key &allow-other-keys) (electron:unfullscreen window)) -(defmethod ffi-window-maximize ((window electron-window)) +(defmethod ffi-window-maximize ((window electron-window) &key &allow-other-keys) (electron:maximize window)) -(defmethod ffi-window-unmaximize ((window electron-window)) +(defmethod ffi-window-unmaximize ((window electron-window) &key &allow-other-keys) (electron:unmaximize window)) ;; Input handling diff --git a/source/renderer/gtk.lisp b/source/renderer/gtk.lisp index 379fd29f390..3b1e5c2b20c 100644 --- a/source/renderer/gtk.lisp +++ b/source/renderer/gtk.lisp @@ -500,12 +500,18 @@ response. The BODY is wrapped with `with-protect'." (on-signal-destroy window)) (connect-signal window "window-state-event" nil (widget event) (declare (ignore widget)) - (setf (nyxt::fullscreen-p window) - (find :fullscreen - (gdk:gdk-event-window-state-new-window-state event))) - (setf (nyxt::maximized-p window) - (find :maximized - (gdk:gdk-event-window-state-new-window-state event))) + (let ((fullscreen-p) + (maximized-p)) + (dolist (state (gdk:gdk-event-window-state-new-window-state event)) + (case state + (:fullscreen + (setq fullscreen-p t) + (ffi-window-fullscreen window :user-event-p nil)) + (:maximized + (setq maximized-p t) + (ffi-window-maximize window :user-event-p nil)))) + (unless fullscreen-p (ffi-window-unfullscreen window :user-event-p nil)) + (unless maximized-p (ffi-window-unmaximize window :user-event-p nil))) nil)) (unless nyxt::*headless-p* @@ -523,16 +529,16 @@ response. The BODY is wrapped with `with-protect'." (define-ffi-method ffi-window-delete ((window gtk-window)) (gtk:gtk-widget-destroy (gtk-object window))) -(define-ffi-method ffi-window-fullscreen ((window gtk-window)) +(define-ffi-method ffi-window-fullscreen ((window gtk-window) &key &allow-other-keys) (gtk:gtk-window-fullscreen (gtk-object window))) -(define-ffi-method ffi-window-unfullscreen ((window gtk-window)) +(define-ffi-method ffi-window-unfullscreen ((window gtk-window) &key &allow-other-keys) (gtk:gtk-window-unfullscreen (gtk-object window))) -(define-ffi-method ffi-window-maximize ((window gtk-window)) +(define-ffi-method ffi-window-maximize ((window gtk-window) &key &allow-other-keys) (gtk:gtk-window-maximize (gtk-object window))) -(define-ffi-method ffi-window-unmaximize ((window gtk-window)) +(define-ffi-method ffi-window-unmaximize ((window gtk-window) &key &allow-other-keys) (gtk:gtk-window-unmaximize (gtk-object window))) (defun derive-key-string (keyval character) @@ -1610,13 +1616,17 @@ the `active-buffer'." nil) (connect-signal buffer "enter-fullscreen" nil (web-view) (declare (ignore web-view)) - (setf (nyxt::fullscreen-p (current-window)) t) - (toggle-fullscreen :skip-renderer-resize t) + (ffi-window-fullscreen (current-window) :user-event-p nil) + ;; As to account for JS's Fullscreen API. + (disable-message-buffer (current-window)) + (disable-status-buffer (current-window)) nil) (connect-signal buffer "leave-fullscreen" nil (web-view) (declare (ignore web-view)) - (setf (nyxt::fullscreen-p (current-window)) nil) - (toggle-fullscreen :skip-renderer-resize t) + (ffi-window-unfullscreen (current-window) :user-event-p nil) + ;; Ideally, the UI state prior to fullscreen must be recovered. + (enable-message-buffer (current-window)) + (enable-status-buffer (current-window)) nil) buffer) diff --git a/source/window.lisp b/source/window.lisp index 82c47e2ce78..b089ca5e5a3 100644 --- a/source/window.lisp +++ b/source/window.lisp @@ -178,66 +178,47 @@ not try to quit the browser." (window-set-buffer window buffer) (values window buffer))) -(define-command toggle-fullscreen (&key (window (current-window)) - skip-renderer-resize) - "Fullscreen WINDOW, or the current window, when omitted. -When `skip-renderer-resize' is non-nil, don't ask the renderer to fullscreen the window." - (let ((fullscreen (fullscreen-p window))) - (unless skip-renderer-resize - (if fullscreen - (ffi-window-unfullscreen window) - (ffi-window-fullscreen window))) - (toggle-status-buffer :show-p (not fullscreen)) - (toggle-message-buffer :show-p (not fullscreen)))) - -(define-command toggle-maximize (&key (window (current-window))) - "Maximize WINDOW, or the current window, when omitted." - (let ((maximized (maximized-p window))) - (if maximized - (ffi-window-unmaximize window) - (ffi-window-maximize window)))) - +(define-command toggle-fullscreen (&optional (window (current-window))) + "Toggle fullscreen state of window." + (if (fullscreen-p window) + (ffi-window-unfullscreen window) + (ffi-window-fullscreen window))) + +(define-command toggle-maximize (&optional (window (current-window))) + "Toggle maximized state of window." + (if (maximized-p window) + (ffi-window-unmaximize window) + (ffi-window-maximize window))) + +(export-always 'enable-status-buffer) (defun enable-status-buffer (&optional (window (current-window))) (setf (ffi-height (status-buffer window)) (height (status-buffer window)))) +(export-always 'disable-status-buffer) (defun disable-status-buffer (&optional (window (current-window))) (setf (ffi-height (status-buffer window)) 0)) +(export-always 'enable-message-buffer) (defun enable-message-buffer (&optional (window (current-window))) (setf (ffi-height (message-buffer window)) (height (message-buffer window)))) +(export-always 'disable-message-buffer) (defun disable-message-buffer (&optional (window (current-window))) (setf (ffi-height (message-buffer window)) 0)) (define-command toggle-toolbars (&optional (window (current-window))) "Toggle the visibility of the message and status buffers." - (toggle-status-buffer :window window) - (toggle-message-buffer :window window)) - -(define-command toggle-status-buffer (&key (window (current-window)) - (show-p nil show-provided-p)) - "Toggle the visibility of the status buffer. - -If SHOW-P is provided: -- If SHOW-P is T, then `status-buffer' is always enabled; -- Otherwise, it is always disabled." - (cond ((and show-provided-p show-p) - (enable-status-buffer window)) - ((and (not show-provided-p) - (zerop (ffi-height (status-buffer window)))) - (enable-status-buffer window)) - (t (disable-status-buffer window)))) - -(define-command toggle-message-buffer (&key (window (current-window)) - (show-p nil show-provided-p)) - "Toggle the visibility of the message buffer. - -If SHOW-P is provided: -- If SHOW-P is T, then `message-buffer' is always enabled; -- Otherwise, it is always disabled." - (cond ((and show-provided-p show-p) - (enable-message-buffer window)) - ((and (not show-provided-p) - (zerop (height (message-buffer window)))) - (enable-message-buffer window)) - (t (disable-message-buffer window)))) + (toggle-status-buffer window) + (toggle-message-buffer window)) + +(define-command toggle-status-buffer (&optional (window (current-window))) + "Toggle the visibility of the status buffer." + (if (zerop (ffi-height (status-buffer window))) + (enable-status-buffer window) + (disable-status-buffer window))) + +(define-command toggle-message-buffer (&optional (window (current-window))) + "Toggle the visibility of the message buffer." + (if (zerop (ffi-height (message-buffer window))) + (enable-message-buffer window) + (disable-message-buffer window)))