firefox/mozilla-1423598-popup.patch
2019-03-21 12:19:07 +01:00

205 lines
7.2 KiB
Diff

diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -457,6 +457,10 @@
nsWindow* GetTransientForWindowIfPopup();
bool IsHandlingTouchSequence(GdkEventSequence* aSequence);
+ void NativeMoveResizeWaylandPopup(GdkPoint* aPosition, GdkRectangle* aSize);
+
+ GtkTextDirection GetTextDirection();
+
#ifdef MOZ_X11
typedef enum {GTK_WIDGET_COMPOSIDED_DEFAULT = 0,
GTK_WIDGET_COMPOSIDED_DISABLED = 1,
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -1109,13 +1109,89 @@
NotifyRollupGeometryChange();
}
+#ifdef DEBUG
+static void NativeMoveResizeWaylandPopupCallback(GdkWindow *window,
+ const GdkRectangle *flipped_rect, const GdkRectangle *final_rect,
+ gboolean flipped_x, gboolean flipped_y, void *unused)
+{
+ LOG(("NativeMoveResizeWaylandPopupCallback flipped %d %d\n",
+ flipped_rect->x, flipped_rect->y));
+ LOG(("NativeMoveResizeWaylandPopupCallback final %d %d\n",
+ final_rect->x, final_rect->y));
+}
+#endif
+
+void nsWindow::NativeMoveResizeWaylandPopup(GdkPoint* aPosition, GdkRectangle* aSize) {
+ // Available as of GTK 3.24+
+ static auto sGdkWindowMoveToRect =
+ (void (*)(GdkWindow *, const GdkRectangle *, GdkGravity, GdkGravity,
+ GdkAnchorHints, gint, gint))
+ dlsym(RTLD_DEFAULT, "gdk_window_move_to_rect");
+
+ if (aSize) {
+ gtk_window_resize(GTK_WINDOW(mShell), aSize->width, aSize->height);
+ }
+ if (!sGdkWindowMoveToRect) {
+ gtk_window_move(GTK_WINDOW(mShell), aPosition->x, aPosition->y);
+ return;
+ }
+
+ GdkWindow *gdkWindow = gtk_widget_get_window(GTK_WIDGET(mShell));
+ if (!gdkWindow) {
+ return;
+ }
+
+ GtkWidget* parentWidget =
+ GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
+
+ int x_parent, y_parent;
+ gdk_window_get_origin(gtk_widget_get_window(parentWidget), &x_parent, &y_parent);
+
+ GdkRectangle rect = { aPosition->x - x_parent,
+ aPosition->y - y_parent,
+ 1, 1};
+ if (aSize) {
+ rect.width = aSize->width;
+ rect.height = aSize->height;
+ }
+
+#ifdef DEBUG
+ LOG(("NativeMoveResizeWaylandPopup request position %d,%d\n",
+ aPosition->x, aPosition->y));
+ if (aSize) {
+ LOG(("NativeMoveResizeWaylandPopup request size %d,%d\n",
+ aSize->width, aSize->height));
+ }
+ LOG(("NativeMoveResizeWaylandPopup result %d %d\n", rect.x, rect.y));
+ g_signal_connect(gdkWindow, "moved-to-rect",
+ G_CALLBACK(NativeMoveResizeWaylandPopupCallback), this);
+#endif
+
+ GdkGravity rectAnchor = GDK_GRAVITY_NORTH_WEST;
+ GdkGravity menuAnchor = GDK_GRAVITY_NORTH_WEST;
+ if (GetTextDirection() == GTK_TEXT_DIR_RTL) {
+ rectAnchor = GDK_GRAVITY_NORTH_EAST;
+ menuAnchor = GDK_GRAVITY_NORTH_EAST;
+ }
+
+ GdkAnchorHints hints = GdkAnchorHints(GDK_ANCHOR_SLIDE | GDK_ANCHOR_FLIP);
+ if (aSize) {
+ hints = GdkAnchorHints(hints|GDK_ANCHOR_RESIZE);
+ }
+
+ sGdkWindowMoveToRect(gdkWindow, &rect, rectAnchor, menuAnchor, hints, 0, 0);
+}
+
void nsWindow::NativeMove() {
GdkPoint point = DevicePixelsToGdkPointRoundDown(mBounds.TopLeft());
-
- if (mIsTopLevel) {
- gtk_window_move(GTK_WINDOW(mShell), point.x, point.y);
- } else if (mGdkWindow) {
- gdk_window_move(mGdkWindow, point.x, point.y);
+ if (!mIsX11Display && mIsTopLevel && mWindowType == eWindowType_popup) {
+ NativeMoveResizeWaylandPopup(&point, nullptr);
+ } else {
+ if (mIsTopLevel) {
+ gtk_window_move(GTK_WINDOW(mShell), point.x, point.y);
+ } else if (mGdkWindow) {
+ gdk_window_move(mGdkWindow, point.x, point.y);
+ }
}
}
@@ -3397,11 +3473,6 @@
GDK_WINDOW_TYPE_HINT_DIALOG);
gtk_window_set_transient_for(GTK_WINDOW(mShell), topLevelParent);
} else if (mWindowType == eWindowType_popup) {
- // With popup windows, we want to control their position, so don't
- // wait for the window manager to place them (which wouldn't
- // happen with override-redirect windows anyway).
- NativeMove();
-
gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup",
gdk_get_program_class());
@@ -3456,6 +3527,14 @@
if (topLevelParent) {
gtk_window_set_transient_for(GTK_WINDOW(mShell), topLevelParent);
}
+
+ // We need realized mShell at NativeMove().
+ gtk_widget_realize(mShell);
+
+ // With popup windows, we want to control their position, so don't
+ // wait for the window manager to place them (which wouldn't
+ // happen with override-redirect windows anyway).
+ NativeMove();
} else { // must be eWindowType_toplevel
SetDefaultIcon();
gtk_window_set_wmclass(GTK_WINDOW(mShell), "Toplevel",
@@ -3895,23 +3974,27 @@
LOG(("nsWindow::NativeMoveResize [%p] %d %d %d %d\n", (void *)this, topLeft.x,
topLeft.y, size.width, size.height));
- if (mIsTopLevel) {
- // x and y give the position of the window manager frame top-left.
- gtk_window_move(GTK_WINDOW(mShell), topLeft.x, topLeft.y);
- // This sets the client window size.
- MOZ_ASSERT(size.width > 0 && size.height > 0,
- "Can't resize window smaller than 1x1.");
- gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
- } else if (mContainer) {
- GtkAllocation allocation;
- allocation.x = topLeft.x;
- allocation.y = topLeft.y;
- allocation.width = size.width;
- allocation.height = size.height;
- gtk_widget_size_allocate(GTK_WIDGET(mContainer), &allocation);
- } else if (mGdkWindow) {
- gdk_window_move_resize(mGdkWindow, topLeft.x, topLeft.y, size.width,
- size.height);
+ if (!mIsX11Display && mIsTopLevel && mWindowType == eWindowType_popup) {
+ NativeMoveResizeWaylandPopup(&topLeft, &size);
+ } else {
+ if (mIsTopLevel) {
+ // x and y give the position of the window manager frame top-left.
+ gtk_window_move(GTK_WINDOW(mShell), topLeft.x, topLeft.y);
+ // This sets the client window size.
+ MOZ_ASSERT(size.width > 0 && size.height > 0,
+ "Can't resize window smaller than 1x1.");
+ gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
+ } else if (mContainer) {
+ GtkAllocation allocation;
+ allocation.x = topLeft.x;
+ allocation.y = topLeft.y;
+ allocation.width = size.width;
+ allocation.height = size.height;
+ gtk_widget_size_allocate(GTK_WIDGET(mContainer), &allocation);
+ } else if (mGdkWindow) {
+ gdk_window_move_resize(mGdkWindow, topLeft.x, topLeft.y, size.width,
+ size.height);
+ }
}
#ifdef MOZ_X11
@@ -6791,3 +6874,18 @@
nsChangeHint_RepaintFrame);
}
}
+
+GtkTextDirection nsWindow::GetTextDirection() {
+ nsView *view = nsView::GetViewFor(this);
+ if (!view) {
+ return GTK_TEXT_DIR_LTR;
+ }
+ nsIFrame *frame = view->GetFrame();
+ if (!frame) {
+ return GTK_TEXT_DIR_LTR;
+ }
+
+ WritingMode wm = frame->GetWritingMode();
+ bool isFrameRTL = !(wm.IsVertical() ? wm.IsVerticalLR() : wm.IsBidiLTR());
+ return isFrameRTL ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
+}