diff options
Diffstat (limited to 'mozilla-1423598-popup.patch')
-rw-r--r-- | mozilla-1423598-popup.patch | 204 |
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; ++} + |