205 lines
7.2 KiB
Diff
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;
|
|
+}
|
|
|