Bug 1195002 - draw to MozContainer window to allow GTK to draw decorations, r=karlt, a=lizzard
authorMartin Stransky <stransky@redhat.com>
Thu, 24 Sep 2015 04:50:00 +0200
changeset 298139 203e5d3c06ba63d4cea2b15107e508fde75b9c12
parent 298138 1d7fc1581e770af9865f789883aeca79d568f8c6
child 298140 08420d2c251ae6d791562cc3bf914bada728312a
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt, lizzard
bugs1195002
milestone43.0a2
Bug 1195002 - draw to MozContainer window to allow GTK to draw decorations, r=karlt, a=lizzard
widget/gtk/mozgtk/mozgtk.c
widget/gtk/nsWindow.cpp
--- a/widget/gtk/mozgtk/mozgtk.c
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -541,16 +541,17 @@ STUB(gtk_style_context_add_class)
 STUB(gtk_style_context_add_region)
 STUB(gtk_style_context_get)
 STUB(gtk_style_context_get_background_color)
 STUB(gtk_style_context_get_border)
 STUB(gtk_style_context_get_border_color)
 STUB(gtk_style_context_get_color)
 STUB(gtk_style_context_get_margin)
 STUB(gtk_style_context_get_padding)
+STUB(gtk_style_context_has_class)
 STUB(gtk_style_context_new)
 STUB(gtk_style_context_remove_region)
 STUB(gtk_style_context_restore)
 STUB(gtk_style_context_save)
 STUB(gtk_style_context_set_path)
 STUB(gtk_style_context_set_state)
 STUB(gtk_tree_view_column_get_button)
 STUB(gtk_widget_get_preferred_size)
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -396,23 +396,23 @@ UpdateLastInputEventTime(void *aGdkEvent
 
     sLastUserInputTime = timestamp;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
 
 nsWindow::nsWindow()
 {
-    mIsTopLevel       = false;
-    mIsDestroyed      = false;
-    mListenForResizes = false;
-    mIsShown          = false;
-    mNeedsShow        = false;
-    mEnabled          = true;
-    mCreated          = false;
+    mIsTopLevel          = false;
+    mIsDestroyed         = false;
+    mListenForResizes    = false;
+    mIsShown             = false;
+    mNeedsShow           = false;
+    mEnabled             = true;
+    mCreated             = false;
 
     mContainer           = nullptr;
     mGdkWindow           = nullptr;
     mShell               = nullptr;
     mPluginNativeWindow  = nullptr;
     mHasMappedToplevel   = false;
     mIsFullyObscured     = false;
     mRetryPointerGrab    = false;
@@ -1809,70 +1809,65 @@ nsWindow::EnableDragDrop(bool aEnable)
 NS_IMETHODIMP
 nsWindow::CaptureMouse(bool aCapture)
 {
     LOG(("CaptureMouse %p\n", (void *)this));
 
     if (!mGdkWindow)
         return NS_OK;
 
-    if (!mShell)
+    if (!mContainer)
         return NS_ERROR_FAILURE;
 
     if (aCapture) {
-        gtk_grab_add(mShell);
+        gtk_grab_add(GTK_WIDGET(mContainer));
         GrabPointer(GetLastUserInputTime());
     }
     else {
         ReleaseGrabs();
-        gtk_grab_remove(mShell);
+        gtk_grab_remove(GTK_WIDGET(mContainer));
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::CaptureRollupEvents(nsIRollupListener *aListener,
                               bool               aDoCapture)
 {
     if (!mGdkWindow)
         return NS_OK;
 
-    if (!mShell)
+    if (!mContainer)
         return NS_ERROR_FAILURE;
 
     LOG(("CaptureRollupEvents %p %i\n", this, int(aDoCapture)));
 
     if (aDoCapture) {
         gRollupListener = aListener;
         // real grab is only done when there is no dragging
         if (!nsWindow::DragInProgress()) {
             // Maybe the dnd flag is not yet set at this point, but dnd has already started
             // so let's be extra careful and skip this operation for dnd popup panels always
             // (panels with type="drag").
             GdkWindowTypeHint gdkTypeHint = gtk_window_get_type_hint(GTK_WINDOW(mShell));
             if (gdkTypeHint != GDK_WINDOW_TYPE_HINT_DND) {
-              // This widget grab ensures that a Gecko GtkWidget receives mouse
-              // events even when embedded in non-Gecko-owned GtkWidgets.
-              // The grab is placed on the toplevel GtkWindow instead of the
-              // MozContainer to avoid double dispatch of keyboard events
-              // (bug 707623).
-              gtk_grab_add(mShell);
+              gtk_grab_add(GTK_WIDGET(mContainer));
               GrabPointer(GetLastUserInputTime());
             }
         }
     }
     else {
         if (!nsWindow::DragInProgress()) {
             ReleaseGrabs();
         }
         // There may not have been a drag in process when aDoCapture was set,
         // so make sure to remove any added grab.  This is a no-op if the grab
         // was not added to this widget.
-        gtk_grab_remove(mShell);
+        gtk_grab_remove(GTK_WIDGET(mContainer));
         gRollupListener = nullptr;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::GetAttention(int32_t aCycleCount)
@@ -3086,45 +3081,35 @@ nsWindow::OnKeyPressEvent(GdkEventKey *a
             textString[2] = 0;
             compositionChangeEvent.mData = textString;
             compositionChangeEvent.time = event.time;
             compositionChangeEvent.timeStamp = GetEventTimeStamp(aEvent->time);
             DispatchEvent(&compositionChangeEvent, status);
         }
     }
 
-    // If the event was consumed, return.
-    if (status == nsEventStatus_eConsumeNoDefault) {
-        return TRUE;
-    }
-
-    return FALSE;
+    return TRUE;
 }
 
 gboolean
 nsWindow::OnKeyReleaseEvent(GdkEventKey *aEvent)
 {
     LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
 
     if (mIMContext && mIMContext->OnKeyEvent(this, aEvent)) {
         return TRUE;
     }
 
     // send the key event as a key up event
     WidgetKeyboardEvent event(true, eKeyUp, this);
     KeymapWrapper::InitKeyEvent(event, aEvent);
 
-    nsEventStatus status = DispatchInputEvent(&event);
-
-    // If the event was consumed, return.
-    if (status == nsEventStatus_eConsumeNoDefault) {
-        return TRUE;
-    }
-
-    return FALSE;
+    (void)DispatchInputEvent(&event);
+
+    return TRUE;
 }
 
 void
 nsWindow::OnScrollEvent(GdkEventScroll *aEvent)
 {
     // check to see if we should rollup
     if (CheckForRollup(aEvent->x_root, aEvent->y_root, true, false))
         return;
@@ -3597,35 +3582,51 @@ nsWindow::Create(nsIWidget        *aPare
                                    gdk_get_program_class());
 
             // 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);
         }
 
-        // Prevent GtkWindow from painting a background to flicker.
-        gtk_widget_set_app_paintable(mShell, TRUE);
-
         // Create a container to hold child windows and child GtkWidgets.
         GtkWidget *container = moz_container_new();
         mContainer = MOZ_CONTAINER(container);
-        // Use mShell's window for drawing and events.
-        gtk_widget_set_has_window(container, FALSE);
-        eventWidget = mShell;
+
+#if (MOZ_WIDGET_GTK == 2)
+        bool containerHasWindow = false;
+#else
+        // "csd" style is set when widget is realized so we need to call
+        // it explicitly now.
+        gtk_widget_realize(mShell);
+
+        // We can't draw directly to top-level window when client side
+        // decorations are enabled. We use container with GdkWindow instead.
+        GtkStyleContext* style = gtk_widget_get_style_context(mShell);
+        bool containerHasWindow = gtk_style_context_has_class(style, "csd");
+#endif
+        if (!containerHasWindow) {
+            // Use mShell's window for drawing and events.
+            gtk_widget_set_has_window(container, FALSE);
+            // Prevent GtkWindow from painting a background to flicker.
+            gtk_widget_set_app_paintable(mShell, TRUE);
+        }
+        // Set up event widget
+        eventWidget = containerHasWindow ? container : mShell;
         gtk_widget_add_events(eventWidget, kEvents);
+
         gtk_container_add(GTK_CONTAINER(mShell), container);
         gtk_widget_realize(container);
 
         // make sure this is the focus widget in the container
         gtk_widget_show(container);
         gtk_widget_grab_focus(container);
 
         // the drawing window
-        mGdkWindow = gtk_widget_get_window(mShell);
+        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.
 
             mCursor = eCursor_wait; // force SetCursor to actually set the
                                     // cursor, even though our internal state
                                     // indicates that we already have the