summaryrefslogtreecommitdiff
path: root/mozilla-1423598-popup.patch
diff options
context:
space:
mode:
Diffstat (limited to 'mozilla-1423598-popup.patch')
-rw-r--r--mozilla-1423598-popup.patch204
1 files changed, 204 insertions, 0 deletions
diff --git a/mozilla-1423598-popup.patch b/mozilla-1423598-popup.patch
new file mode 100644
index 0000000..fc07bd8
--- /dev/null
+++ b/mozilla-1423598-popup.patch
@@ -0,0 +1,204 @@
+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 (!sGdkWindowMoveToRect) {
++ gtk_window_move(GTK_WINDOW(mShell), aPosition->x, aPosition->y);
++ if (aSize) {
++ gtk_window_resize(GTK_WINDOW(mShell), aSize->width, aSize->height);
++ }
++ 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;
++}
+
bgstack15