Bug 1641546 - Make sure alwaysontop windows don't pull focus when first opening on Linux GTK. r=stransky
authorMike Conley <mconley@mozilla.com>
Fri, 05 Jun 2020 09:16:30 +0000
changeset 534155 a2b64d290c0b11b0dd8fb98a44b0a5a7f5ca844a
parent 534154 2dc2a430c2e7d950f13753450c4f086ab04d0879
child 534156 4746c37be3e6ff7c566f44070eddd66908acfd20
push id37483
push userapavel@mozilla.com
push dateFri, 05 Jun 2020 21:40:11 +0000
treeherdermozilla-central@dadc7312128e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstransky
bugs1641546
milestone79.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1641546 - Make sure alwaysontop windows don't pull focus when first opening on Linux GTK. r=stransky Differential Revision: https://phabricator.services.mozilla.com/D77695
widget/gtk/mozgtk/mozgtk.c
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
--- a/widget/gtk/mozgtk/mozgtk.c
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -519,16 +519,17 @@ STUB(gtk_window_maximize)
 STUB(gtk_window_move)
 STUB(gtk_window_new)
 STUB(gtk_window_present_with_time)
 STUB(gtk_window_resize)
 STUB(gtk_window_set_accept_focus)
 STUB(gtk_window_set_decorated)
 STUB(gtk_window_set_deletable)
 STUB(gtk_window_set_destroy_with_parent)
+STUB(gtk_window_set_focus_on_map)
 STUB(gtk_window_set_geometry_hints)
 STUB(gtk_window_set_icon_name)
 STUB(gtk_window_set_modal)
 STUB(gtk_window_set_skip_taskbar_hint)
 STUB(gtk_window_set_startup_id)
 STUB(gtk_window_set_title)
 STUB(gtk_window_set_transient_for)
 STUB(gtk_window_set_type_hint)
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -474,16 +474,17 @@ nsWindow::nsWindow() {
   mPendingConfigures = 0;
   mCSDSupportLevel = CSD_SUPPORT_NONE;
   mDrawToContainer = false;
   mDrawInTitlebar = false;
   mTitlebarBackdropState = false;
 
   mHasAlphaVisual = false;
   mIsPIPWindow = false;
+  mAlwaysOnTop = false;
 
   mWindowScaleFactorChanged = true;
   mWindowScaleFactor = 1;
 
   mIsAccelerated = false;
 }
 
 nsWindow::~nsWindow() {
@@ -4172,16 +4173,17 @@ nsresult nsWindow::Create(nsIWidget* aPa
       mWindowType = eWindowType_toplevel;
     } else if (mWindowType == eWindowType_popup && !aNativeParent && !aParent) {
       // Workaround for Wayland where the popup windows always need to have
       // parent window. For example webrtc ui is a popup window without parent.
       mWindowType = eWindowType_toplevel;
     }
   }
 
+  mAlwaysOnTop = aInitData && aInitData->mAlwaysOnTop;
   mIsPIPWindow = aInitData && aInitData->mPIPWindow;
 
   // ok, create our windows
   switch (mWindowType) {
     case eWindowType_dialog:
     case eWindowType_popup:
     case eWindowType_toplevel:
     case eWindowType_invisible: {
@@ -4389,17 +4391,17 @@ nsresult nsWindow::Create(nsIWidget* aPa
         }
 
         // each toplevel window gets its own window group
         GtkWindowGroup* group = gtk_window_group_new();
         gtk_window_group_add_window(group, GTK_WINDOW(mShell));
         g_object_unref(group);
       }
 
-      if (aInitData->mAlwaysOnTop) {
+      if (mAlwaysOnTop) {
         gtk_window_set_keep_above(GTK_WINDOW(mShell), TRUE);
       }
 
       // Create a container to hold child windows and child GtkWidgets.
       GtkWidget* container = moz_container_new();
       mContainer = MOZ_CONTAINER(container);
 #ifdef MOZ_WAYLAND
       if (!mIsX11Display && mIsAccelerated) {
@@ -4446,21 +4448,31 @@ nsresult nsWindow::Create(nsIWidget* aPa
         moz_container_force_default_visual(mContainer);
       }
 
       // If we draw to mContainer window then configure it now because
       // gtk_container_add() realizes the child widget.
       gtk_widget_set_has_window(container, mDrawToContainer);
 
       gtk_container_add(GTK_CONTAINER(mShell), container);
+
+      // alwaysontop windows are generally used for peripheral indicators,
+      // so we don't focus them by default.
+      if (mAlwaysOnTop) {
+        gtk_window_set_focus_on_map(GTK_WINDOW(mShell), FALSE);
+      }
+
       gtk_widget_realize(container);
 
       // make sure this is the focus widget in the container
       gtk_widget_show(container);
-      gtk_widget_grab_focus(container);
+
+      if (!mAlwaysOnTop) {
+        gtk_widget_grab_focus(container);
+      }
 
       // the drawing window
       mGdkWindow = gtk_widget_get_window(eventWidget);
 
       if (mWindowType == eWindowType_popup) {
         // gdk does not automatically set the cursor for "temporary"
         // windows, which are what gtk uses for popups.
 
@@ -4973,16 +4985,17 @@ void nsWindow::NativeShow(bool aAction) 
       }
       // Update popup window hierarchy run-time on Wayland.
       if (IsWaylandPopup()) {
         if (!ConfigureWaylandPopupWindows()) {
           mNeedsShow = true;
           return;
         }
       }
+
       gtk_widget_show(mShell);
       if (!mIsX11Display) {
         WaylandStartVsync();
       }
     } else if (mContainer) {
       gtk_widget_show(GTK_WIDGET(mContainer));
     } else if (mGdkWindow) {
       gdk_window_show_unraised(mGdkWindow);
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -576,16 +576,17 @@ class nsWindow final : public nsBaseWidg
   // If true, draw our own window titlebar.
   bool mDrawInTitlebar;
   // Draw titlebar with :backdrop css state (inactive/unfocused).
   bool mTitlebarBackdropState;
   // Draggable titlebar region maintained by UpdateWindowDraggingRegion
   LayoutDeviceIntRegion mDraggableRegion;
   // It's PictureInPicture window.
   bool mIsPIPWindow;
+  bool mAlwaysOnTop;
 
 #ifdef ACCESSIBILITY
   RefPtr<mozilla::a11y::Accessible> mRootAccessible;
 
   /**
    * Request to create the accessible for this window if it is top level.
    */
   void CreateRootAccessible();