Bug 1456451 - [CSD] Update toplevel GdkWindow property when it's recreated at nsWindow::SetDrawsInTitlebar(), r?jhorak
Implement SetCompositorHint() which sets _NET_WM_BYPASS_COMPOSITOR GtkWindow property when it's recreated
at nsWindow::SetDrawsInTitlebar().
Window role/class is handled by nsWindow::RefreshWindowClass(), it uses stored window class
passed to nsWindow::SetWindowClass().
MozReview-Commit-ID: 1JJsK1ZQyvu
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -3885,27 +3885,17 @@ nsWindow::Create(nsIWidget* aParent,
}
#ifdef MOZ_X11
// Set window manager hint to keep fullscreen windows composited.
//
// If the window were to get unredirected, there could be visible
// tearing because Gecko does not align its framebuffer updates with
// vblank.
- if (mIsX11Display) {
- gulong value = 2; // Opt out of unredirection
- GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
- gdk_property_change(gtk_widget_get_window(mShell),
- gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE),
- cardinal_atom,
- 32, // format
- GDK_PROP_MODE_REPLACE,
- (guchar*)&value,
- 1);
- }
+ SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED);
#endif
}
break;
case eWindowType_plugin:
case eWindowType_plugin_ipc_chrome:
case eWindowType_plugin_ipc_content:
MOZ_ASSERT_UNREACHABLE("Unexpected eWindowType_plugin*");
@@ -4109,70 +4099,80 @@ nsWindow::Create(nsIWidget* aParent,
mSurfaceProvider.Initialize(this);
}
#endif
#endif
return NS_OK;
}
void
-nsWindow::SetWindowClass(const nsAString &xulWinType)
-{
- if (!mShell)
- return;
-
- const char *res_class = gdk_get_program_class();
- if (!res_class)
- return;
-
- char *res_name = ToNewCString(xulWinType);
- if (!res_name)
- return;
-
- const char *role = nullptr;
-
- // Parse res_name into a name and role. Characters other than
- // [A-Za-z0-9_-] are converted to '_'. Anything after the first
- // colon is assigned to role; if there's no colon, assign the
- // whole thing to both role and res_name.
- for (char *c = res_name; *c; c++) {
- if (':' == *c) {
- *c = 0;
- role = c + 1;
- }
- else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
- *c = '_';
- }
- res_name[0] = toupper(res_name[0]);
- if (!role) role = res_name;
-
- GdkWindow* gdkWindow = gtk_widget_get_window(mShell);
- gdk_window_set_role(gdkWindow, role);
+nsWindow::RefreshWindowClass(void)
+{
+ if (mGtkWindowTypeName.IsEmpty() || mGtkWindowRoleName.IsEmpty())
+ return;
+
+ GdkWindow* gdkWindow = gtk_widget_get_window(mShell);
+ gdk_window_set_role(gdkWindow, mGtkWindowRoleName.get());
#ifdef MOZ_X11
- if (mIsX11Display) {
- XClassHint *class_hint = XAllocClassHint();
- if (!class_hint) {
- free(res_name);
- return;
+ if (mIsX11Display) {
+ XClassHint *class_hint = XAllocClassHint();
+ if (!class_hint) {
+ return;
+ }
+ const char *res_class = gdk_get_program_class();
+ if (!res_class)
+ return;
+
+ class_hint->res_name = const_cast<char*>(mGtkWindowTypeName.get());
+ class_hint->res_class = const_cast<char*>(res_class);
+
+ // Can't use gtk_window_set_wmclass() for this; it prints
+ // a warning & refuses to make the change.
+ GdkDisplay *display = gdk_display_get_default();
+ XSetClassHint(GDK_DISPLAY_XDISPLAY(display),
+ gdk_x11_window_get_xid(gdkWindow),
+ class_hint);
+ XFree(class_hint);
+ }
+#endif /* MOZ_X11 */
+}
+
+void
+nsWindow::SetWindowClass(const nsAString &xulWinType)
+{
+ if (!mShell)
+ return;
+
+ char *res_name = ToNewCString(xulWinType);
+ if (!res_name)
+ return;
+
+ const char *role = nullptr;
+
+ // Parse res_name into a name and role. Characters other than
+ // [A-Za-z0-9_-] are converted to '_'. Anything after the first
+ // colon is assigned to role; if there's no colon, assign the
+ // whole thing to both role and res_name.
+ for (char *c = res_name; *c; c++) {
+ if (':' == *c) {
+ *c = 0;
+ role = c + 1;
}
- class_hint->res_name = res_name;
- class_hint->res_class = const_cast<char*>(res_class);
-
- // Can't use gtk_window_set_wmclass() for this; it prints
- // a warning & refuses to make the change.
- GdkDisplay *display = gdk_display_get_default();
- XSetClassHint(GDK_DISPLAY_XDISPLAY(display),
- gdk_x11_window_get_xid(gdkWindow),
- class_hint);
- XFree(class_hint);
- }
-#endif /* MOZ_X11 */
-
- free(res_name);
+ else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
+ *c = '_';
+ }
+ res_name[0] = toupper(res_name[0]);
+ if (!role) role = res_name;
+
+ mGtkWindowTypeName = res_name;
+ mGtkWindowRoleName = role;
+ free(res_name);
+
+ RefreshWindowClass();
}
void
nsWindow::NativeResize()
{
if (!AreBoundsSane()) {
// If someone has set this so that the needs show flag is false
// and it needs to be hidden, update the flag and hide the
@@ -6726,16 +6726,20 @@ nsWindow::SetDrawsInTitlebar(bool aState
gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell));
mNeedsShow = true;
NativeResize();
// Label mShell toplevel window so property_notify_event_cb callback
// can find its way home.
g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)),
"nsWindow", this);
+#ifdef MOZ_X11
+ SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED);
+#endif
+ RefreshWindowClass();
// When we use system titlebar setup managed by Gtk+ we also get
// _NET_FRAME_EXTENTS property for our toplevel window so we can't
// update the client offset it here.
if (aState) {
UpdateClientOffsetForCSDWindow();
}
@@ -7207,8 +7211,26 @@ nsWindow::SetProgress(unsigned long prog
progressPercent = MIN(progressPercent, 100);
set_window_hint_cardinal(GDK_WINDOW_XID(gtk_widget_get_window(mShell)),
PROGRESS_HINT,
progressPercent);
#endif // MOZ_X11
}
+
+#ifdef MOZ_X11
+void
+nsWindow::SetCompositorHint(WindowComposeRequest aState)
+{
+ if (mIsX11Display) {
+ gulong value = aState;
+ GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
+ gdk_property_change(gtk_widget_get_window(mShell),
+ gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE),
+ cardinal_atom,
+ 32, // format
+ GDK_PROP_MODE_REPLACE,
+ (guchar*)&value,
+ 1);
+ }
+}
+#endif
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -476,16 +476,28 @@ private:
GdkWindow** aWindow, gint* aButton,
gint* aRootX, gint* aRootY);
void ClearCachedResources();
nsIWidgetListener* GetListener();
bool IsComposited() const;
void UpdateClientOffsetForCSDWindow();
+#ifdef MOZ_X11
+ typedef enum { GTK_WIDGET_COMPOSIDED_DEFAULT = 0,
+ GTK_WIDGET_COMPOSIDED_DISABLED = 1,
+ GTK_WIDGET_COMPOSIDED_ENABLED = 2
+ } WindowComposeRequest;
+
+ void SetCompositorHint(WindowComposeRequest aState);
+#endif
+ nsCString mGtkWindowTypeName;
+ nsCString mGtkWindowRoleName;
+ void RefreshWindowClass();
+
GtkWidget *mShell;
MozContainer *mContainer;
GdkWindow *mGdkWindow;
PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
uint32_t mHasMappedToplevel : 1,
mIsFullyObscured : 1,