зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 86630db403c1 (bug 1623974) for causing failures in browser_toolbox_zoom_popup.js and in wpt.
CLOSED TREE
This commit is contained in:
Родитель
9d87851a27
Коммит
25a1d0163b
|
@ -536,20 +536,11 @@ void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
|
||||||
}
|
}
|
||||||
prefSize = BoundsCheck(minSize, prefSize, maxSize);
|
prefSize = BoundsCheck(minSize, prefSize, maxSize);
|
||||||
|
|
||||||
|
|
||||||
bool sizeChanged = (mPrefSize != prefSize);
|
|
||||||
// if the size changed then set the bounds to be the preferred size
|
// if the size changed then set the bounds to be the preferred size
|
||||||
|
bool sizeChanged = (mPrefSize != prefSize);
|
||||||
if (sizeChanged) {
|
if (sizeChanged) {
|
||||||
SetXULBounds(aState, nsRect(0, 0, prefSize.width, prefSize.height), false);
|
SetXULBounds(aState, nsRect(0, 0, prefSize.width, prefSize.height), false);
|
||||||
mPrefSize = prefSize;
|
mPrefSize = prefSize;
|
||||||
#if MOZ_WAYLAND
|
|
||||||
nsIWidget* widget = GetWidget();
|
|
||||||
if (widget) {
|
|
||||||
// When the popup size changed in the DOM, we need to flush widget
|
|
||||||
// preferred popup rect to avoid showing it in wrong size.
|
|
||||||
widget->FlushPreferredPopupRect();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needCallback = false;
|
bool needCallback = false;
|
||||||
|
@ -1416,17 +1407,7 @@ nsresult nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame,
|
||||||
// tell us which axis the popup is flush against in case we have to move
|
// tell us which axis the popup is flush against in case we have to move
|
||||||
// it around later. The AdjustPositionForAnchorAlign method accounts for
|
// it around later. The AdjustPositionForAnchorAlign method accounts for
|
||||||
// the popup's margin.
|
// the popup's margin.
|
||||||
|
screenPoint = AdjustPositionForAnchorAlign(anchorRect, hFlip, vFlip);
|
||||||
#ifdef MOZ_WAYLAND
|
|
||||||
if (gdk_display_get_default() &&
|
|
||||||
!GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
|
|
||||||
screenPoint = nsPoint(anchorRect.x, anchorRect.y);
|
|
||||||
mAnchorRect = anchorRect;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
screenPoint = AdjustPositionForAnchorAlign(anchorRect, hFlip, vFlip);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// with no anchor, the popup is positioned relative to the root frame
|
// with no anchor, the popup is positioned relative to the root frame
|
||||||
anchorRect = rootScreenRect;
|
anchorRect = rootScreenRect;
|
||||||
|
@ -1538,17 +1519,6 @@ nsresult nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame,
|
||||||
// Ensure that anchorRect is on screen.
|
// Ensure that anchorRect is on screen.
|
||||||
anchorRect = anchorRect.Intersect(screenRect);
|
anchorRect = anchorRect.Intersect(screenRect);
|
||||||
|
|
||||||
#ifdef MOZ_WAYLAND
|
|
||||||
nsIWidget* widget = GetWidget();
|
|
||||||
if (widget) {
|
|
||||||
nsRect prefRect = widget->GetPreferredPopupRect();
|
|
||||||
if (prefRect.width > 0 && prefRect.height > 0) {
|
|
||||||
screenRect = prefRect;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NS_WARNING("No widget associated with popup frame.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// shrink the the popup down if it is larger than the screen size
|
// shrink the the popup down if it is larger than the screen size
|
||||||
if (mRect.width > screenRect.width) mRect.width = screenRect.width;
|
if (mRect.width > screenRect.width) mRect.width = screenRect.width;
|
||||||
if (mRect.height > screenRect.height) mRect.height = screenRect.height;
|
if (mRect.height > screenRect.height) mRect.height = screenRect.height;
|
||||||
|
|
|
@ -547,14 +547,6 @@ class nsMenuPopupFrame final : public nsBoxFrame,
|
||||||
// frame hierarchy, it's needed for Linux/Wayland which demands
|
// frame hierarchy, it's needed for Linux/Wayland which demands
|
||||||
// strict popup windows hierarchy.
|
// strict popup windows hierarchy.
|
||||||
nsIWidget* GetParentMenuWidget();
|
nsIWidget* GetParentMenuWidget();
|
||||||
#ifdef MOZ_WAYLAND
|
|
||||||
// We need following getters for Wayland for calling gdk_window_move_to_rect
|
|
||||||
nsRect GetAnchorRect() { return mAnchorRect; }
|
|
||||||
int GetPopupAlignment() { return mPopupAlignment; }
|
|
||||||
int GetPopupAnchor() { return mPopupAnchor; }
|
|
||||||
int GetPopupPosition() { return mPosition; }
|
|
||||||
FlipType GetFlipType() { return mFlip; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsString mIncrementalString; // for incremental typing navigation
|
nsString mIncrementalString; // for incremental typing navigation
|
||||||
|
@ -587,11 +579,7 @@ class nsMenuPopupFrame final : public nsBoxFrame,
|
||||||
int32_t mXPos;
|
int32_t mXPos;
|
||||||
int32_t mYPos;
|
int32_t mYPos;
|
||||||
nsIntRect mScreenRect;
|
nsIntRect mScreenRect;
|
||||||
// Used for store rectangle which the popup is going to be anchored to,
|
|
||||||
// we need that for Wayland
|
|
||||||
#ifdef MOZ_WAYLAND
|
|
||||||
nsRect mAnchorRect;
|
|
||||||
#endif
|
|
||||||
// If the panel prefers to "slide" rather than resize, then the arrow gets
|
// If the panel prefers to "slide" rather than resize, then the arrow gets
|
||||||
// positioned at this offset (along either the x or y axis, depending on
|
// positioned at this offset (along either the x or y axis, depending on
|
||||||
// mPosition)
|
// mPosition)
|
||||||
|
|
|
@ -137,7 +137,6 @@ using namespace mozilla::widget;
|
||||||
#include "NativeKeyBindings.h"
|
#include "NativeKeyBindings.h"
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include "nsPresContext.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
|
@ -432,8 +431,6 @@ nsWindow::nsWindow() {
|
||||||
mNeedsCompositorResume = false;
|
mNeedsCompositorResume = false;
|
||||||
mCompositorInitiallyPaused = false;
|
mCompositorInitiallyPaused = false;
|
||||||
#endif
|
#endif
|
||||||
mWaitingForMoveToRectCB = false;
|
|
||||||
mPendingSizeRect = LayoutDeviceIntRect(0, 0, 0, 0);
|
|
||||||
|
|
||||||
if (!gGlobalsInitialized) {
|
if (!gGlobalsInitialized) {
|
||||||
gGlobalsInitialized = true;
|
gGlobalsInitialized = true;
|
||||||
|
@ -1161,14 +1158,9 @@ void nsWindow::Move(double aX, double aY) {
|
||||||
|
|
||||||
if (!mCreated) return;
|
if (!mCreated) return;
|
||||||
|
|
||||||
int32_t p2a = AppUnitsPerCSSPixel();
|
NativeMove();
|
||||||
if (mPreferredPopupRect.x != mBounds.x * p2a &&
|
|
||||||
mPreferredPopupRect.y != mBounds.y * p2a) {
|
NotifyRollupGeometryChange();
|
||||||
NativeMove();
|
|
||||||
NotifyRollupGeometryChange();
|
|
||||||
} else {
|
|
||||||
LOG((" mBounds same as mPreferredPopupRect, no need to move"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsWindow::IsWaylandPopup() {
|
bool nsWindow::IsWaylandPopup() {
|
||||||
|
@ -1230,23 +1222,19 @@ void nsWindow::CleanupWaylandPopups() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsMenuPopupFrame* GetMenuPopupFrame(nsIFrame* aFrame) {
|
|
||||||
if (aFrame) {
|
|
||||||
nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(aFrame);
|
|
||||||
return menuPopupFrame;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The MenuList popups are used as dropdown menus for example in WebRTC
|
// The MenuList popups are used as dropdown menus for example in WebRTC
|
||||||
// microphone/camera chooser or autocomplete widgets.
|
// microphone/camera chooser or autocomplete widgets.
|
||||||
bool nsWindow::IsMainMenuWindow() {
|
bool nsWindow::IsMainMenuWindow() {
|
||||||
nsMenuPopupFrame* menuPopupFrame = GetMenuPopupFrame(GetFrame());
|
nsIFrame* frame = GetFrame();
|
||||||
if (menuPopupFrame) {
|
if (frame) {
|
||||||
LOG((" nsMenuPopupFrame [%p] type: %d IsMenu: %d, IsMenuList: %d\n",
|
nsMenuPopupFrame* menuPopupFrame = nullptr;
|
||||||
menuPopupFrame, menuPopupFrame->PopupType(), menuPopupFrame->IsMenu(),
|
menuPopupFrame = do_QueryFrame(frame);
|
||||||
menuPopupFrame->IsMenuList()));
|
if (menuPopupFrame) {
|
||||||
return mPopupType == ePopupTypeMenu && !menuPopupFrame->IsMenuList();
|
LOG((" nsMenuPopupFrame [%p] type: %d IsMenu: %d, IsMenuList: %d\n",
|
||||||
|
menuPopupFrame, menuPopupFrame->PopupType(),
|
||||||
|
menuPopupFrame->IsMenu(), menuPopupFrame->IsMenuList()));
|
||||||
|
return mPopupType == ePopupTypeMenu && !menuPopupFrame->IsMenuList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1323,9 +1311,13 @@ GtkWidget* nsWindow::ConfigureWaylandPopupWindows() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we're already configured.
|
// Check if we're already configured. Popup can be reattached to various
|
||||||
|
// windows, so don't consider them configured. Also the widget-overflow needs
|
||||||
|
// special care because the opened (remote) popups has to be closed before is
|
||||||
|
// it shown again.
|
||||||
if (gVisibleWaylandPopupWindows &&
|
if (gVisibleWaylandPopupWindows &&
|
||||||
g_list_find(gVisibleWaylandPopupWindows, this)) {
|
g_list_find(gVisibleWaylandPopupWindows, this) &&
|
||||||
|
mPopupType != ePopupTypeTooltip && !IsWidgetOverflowWindow()) {
|
||||||
LOG((" [%p] is already configured.\n", (void*)this));
|
LOG((" [%p] is already configured.\n", (void*)this));
|
||||||
return GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
|
return GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
|
||||||
}
|
}
|
||||||
|
@ -1333,24 +1325,18 @@ GtkWidget* nsWindow::ConfigureWaylandPopupWindows() {
|
||||||
// If we're opening a new window we don't want to attach it to a tooltip
|
// If we're opening a new window we don't want to attach it to a tooltip
|
||||||
// as it's short lived temporary window.
|
// as it's short lived temporary window.
|
||||||
HideWaylandTooltips();
|
HideWaylandTooltips();
|
||||||
|
|
||||||
// Cleanup already closed menus
|
// Cleanup already closed menus
|
||||||
CleanupWaylandPopups();
|
CleanupWaylandPopups();
|
||||||
|
|
||||||
if (gVisibleWaylandPopupWindows &&
|
GtkWindow* parentGtkWindow = nullptr;
|
||||||
(HasRemoteContent() || IsWidgetOverflowWindow())) {
|
if (HasRemoteContent() || IsWidgetOverflowWindow()) {
|
||||||
nsWindow* openedWindow =
|
LOG(
|
||||||
static_cast<nsWindow*>(gVisibleWaylandPopupWindows->data);
|
(" Hiding all opened popups because the window is remote content or "
|
||||||
LOG((" this [%p], lastOpenedWindow [%p]", this, openedWindow));
|
"overflow-widget"));
|
||||||
if (openedWindow != this) {
|
HideWaylandOpenedPopups();
|
||||||
LOG(
|
|
||||||
(" Hiding all opened popups because the window is remote content or "
|
|
||||||
"overflow-widget"));
|
|
||||||
HideWaylandOpenedPopups();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWindow* parentGtkWindow = GetCurrentWindow();
|
parentGtkWindow = GetCurrentWindow();
|
||||||
if (parentGtkWindow) {
|
if (parentGtkWindow) {
|
||||||
MOZ_ASSERT(parentGtkWindow != GTK_WINDOW(this->GetGtkWidget()),
|
MOZ_ASSERT(parentGtkWindow != GTK_WINDOW(this->GetGtkWidget()),
|
||||||
"Cannot set self as parent");
|
"Cannot set self as parent");
|
||||||
|
@ -1387,37 +1373,6 @@ void nsWindow::NativeMoveResizeWaylandPopupCB(const GdkRectangle* aFinalSize,
|
||||||
LOG((" orig mBounds x=%d y=%d width=%d height=%d\n", mBounds.x, mBounds.y,
|
LOG((" orig mBounds x=%d y=%d width=%d height=%d\n", mBounds.x, mBounds.y,
|
||||||
mBounds.width, mBounds.height));
|
mBounds.width, mBounds.height));
|
||||||
|
|
||||||
// Remove signal handler because it can also be called from
|
|
||||||
// xdg_popup_configure
|
|
||||||
GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(mShell));
|
|
||||||
if (g_signal_handler_find(
|
|
||||||
gdkWindow, G_SIGNAL_MATCH_FUNC, 0, 0, nullptr,
|
|
||||||
FuncToGpointer(NativeMoveResizeWaylandPopupCallback), this)) {
|
|
||||||
LOG((" Disconnecting NativeMoveResizeWaylandPopupCallback"));
|
|
||||||
g_signal_handlers_disconnect_by_func(
|
|
||||||
gdkWindow, FuncToGpointer(NativeMoveResizeWaylandPopupCallback), this);
|
|
||||||
}
|
|
||||||
mWaitingForMoveToRectCB = false;
|
|
||||||
|
|
||||||
// We ignore the callback position data because the another resize has been
|
|
||||||
// called before the callback have been triggered.
|
|
||||||
if (mPendingSizeRect.height > 0 || mPendingSizeRect.width > 0) {
|
|
||||||
LOG(
|
|
||||||
(" Another resize called during waiting for callback, calling "
|
|
||||||
"Resize(%d, %d)\n",
|
|
||||||
mPendingSizeRect.width, mPendingSizeRect.height));
|
|
||||||
// Set the preferred size to zero to avoid wrong size of popup because the
|
|
||||||
// mPreferredPopupRect is used in nsMenuPopupFrame to set dimensions
|
|
||||||
mPreferredPopupRect = nsRect(0, 0, 0, 0);
|
|
||||||
|
|
||||||
// We need to schedule another resize because the window has been resized
|
|
||||||
// again before callback was called.
|
|
||||||
Resize(mPendingSizeRect.width, mPendingSizeRect.height, true);
|
|
||||||
DispatchResized();
|
|
||||||
mPendingSizeRect.width = mPendingSizeRect.height = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWindow* parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell));
|
GtkWindow* parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell));
|
||||||
if (!parentGtkWindow || !GTK_IS_WIDGET(parentGtkWindow)) {
|
if (!parentGtkWindow || !GTK_IS_WIDGET(parentGtkWindow)) {
|
||||||
NS_WARNING("Popup has no parent!");
|
NS_WARNING("Popup has no parent!");
|
||||||
|
@ -1431,11 +1386,11 @@ void nsWindow::NativeMoveResizeWaylandPopupCB(const GdkRectangle* aFinalSize,
|
||||||
gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(parentGtkWindow)),
|
gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(parentGtkWindow)),
|
||||||
&x_parent, &y_parent);
|
&x_parent, &y_parent);
|
||||||
|
|
||||||
LayoutDeviceIntRect newBounds(aFinalSize->x, aFinalSize->y, aFinalSize->width,
|
LayoutDeviceIntRect newBounds(aFinalSize->x + x_parent,
|
||||||
|
aFinalSize->y + y_parent, aFinalSize->width,
|
||||||
aFinalSize->height);
|
aFinalSize->height);
|
||||||
|
|
||||||
newBounds.x = GdkCoordToDevicePixels(newBounds.x);
|
newBounds.Scale(nsWindow::GdkScaleFactor());
|
||||||
newBounds.y = GdkCoordToDevicePixels(newBounds.y);
|
|
||||||
LOG((" new mBounds x=%d y=%d width=%d height=%d\n", newBounds.x,
|
LOG((" new mBounds x=%d y=%d width=%d height=%d\n", newBounds.x,
|
||||||
newBounds.y, newBounds.width, newBounds.height));
|
newBounds.y, newBounds.width, newBounds.height));
|
||||||
|
|
||||||
|
@ -1443,70 +1398,22 @@ void nsWindow::NativeMoveResizeWaylandPopupCB(const GdkRectangle* aFinalSize,
|
||||||
(newBounds.x != mBounds.x || newBounds.y != mBounds.y);
|
(newBounds.x != mBounds.x || newBounds.y != mBounds.y);
|
||||||
bool needsSizeUpdate =
|
bool needsSizeUpdate =
|
||||||
(newBounds.width != mBounds.width || newBounds.height != mBounds.height);
|
(newBounds.width != mBounds.width || newBounds.height != mBounds.height);
|
||||||
// Update view
|
|
||||||
|
|
||||||
if (needsSizeUpdate) {
|
if (!needsPositionUpdate && !needsSizeUpdate) {
|
||||||
int32_t p2a = AppUnitsPerCSSPixel();
|
return;
|
||||||
mPreferredPopupRect = nsRect(NSIntPixelsToAppUnits(newBounds.x, p2a),
|
}
|
||||||
NSIntPixelsToAppUnits(newBounds.y, p2a),
|
|
||||||
NSIntPixelsToAppUnits(newBounds.width, p2a),
|
if (needsPositionUpdate && needsSizeUpdate) {
|
||||||
NSIntPixelsToAppUnits(newBounds.height, p2a));
|
mBounds = newBounds;
|
||||||
|
NotifyWindowMoved(newBounds.x, newBounds.y);
|
||||||
|
} else if (needsPositionUpdate) {
|
||||||
|
mBounds = newBounds;
|
||||||
|
NotifyWindowMoved(newBounds.x, newBounds.y);
|
||||||
|
} else {
|
||||||
Resize(newBounds.width, newBounds.height, true);
|
Resize(newBounds.width, newBounds.height, true);
|
||||||
DispatchResized();
|
|
||||||
|
|
||||||
nsMenuPopupFrame* popupFrame = GetMenuPopupFrame(GetFrame());
|
|
||||||
if (popupFrame) {
|
|
||||||
RefPtr<PresShell> presShell = popupFrame->PresShell();
|
|
||||||
presShell->FrameNeedsReflow(popupFrame, IntrinsicDirty::Resize,
|
|
||||||
NS_FRAME_IS_DIRTY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsPositionUpdate) {
|
|
||||||
// The newBounds are in coordinates relative to the parent window/popup.
|
|
||||||
// The NotifyWindowMoved requires the coordinates relative to the toplevel.
|
|
||||||
// We use the gdk_window_get_origin to get correct coordinates.
|
|
||||||
gint x = 0, y = 0;
|
|
||||||
gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(mShell)), &x, &y);
|
|
||||||
NotifyWindowMoved(GdkCoordToDevicePixels(x), GdkCoordToDevicePixels(y));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_WAYLAND
|
|
||||||
static GdkGravity PopupAlignmentToGdkGravity(int8_t aAlignment) {
|
|
||||||
switch (aAlignment) {
|
|
||||||
case POPUPALIGNMENT_NONE:
|
|
||||||
return GDK_GRAVITY_NORTH_WEST;
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_TOPLEFT:
|
|
||||||
return GDK_GRAVITY_NORTH_WEST;
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_TOPRIGHT:
|
|
||||||
return GDK_GRAVITY_NORTH_EAST;
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_BOTTOMLEFT:
|
|
||||||
return GDK_GRAVITY_SOUTH_WEST;
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_BOTTOMRIGHT:
|
|
||||||
return GDK_GRAVITY_SOUTH_EAST;
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_LEFTCENTER:
|
|
||||||
return GDK_GRAVITY_WEST;
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_RIGHTCENTER:
|
|
||||||
return GDK_GRAVITY_EAST;
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_TOPCENTER:
|
|
||||||
return GDK_GRAVITY_NORTH;
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_BOTTOMCENTER:
|
|
||||||
return GDK_GRAVITY_SOUTH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return GDK_GRAVITY_STATIC;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void nsWindow::NativeMoveResizeWaylandPopup(GdkPoint* aPosition,
|
void nsWindow::NativeMoveResizeWaylandPopup(GdkPoint* aPosition,
|
||||||
GdkRectangle* aSize) {
|
GdkRectangle* aSize) {
|
||||||
// Available as of GTK 3.24+
|
// Available as of GTK 3.24+
|
||||||
|
@ -1542,93 +1449,41 @@ void nsWindow::NativeMoveResizeWaylandPopup(GdkPoint* aPosition,
|
||||||
LOG(("nsWindow::NativeMoveResizeWaylandPopup: Set popup parent %p\n",
|
LOG(("nsWindow::NativeMoveResizeWaylandPopup: Set popup parent %p\n",
|
||||||
parentWindow));
|
parentWindow));
|
||||||
|
|
||||||
// Get anchor rectangle
|
int x_parent, y_parent;
|
||||||
LayoutDeviceIntRect anchorRect(0, 0, 0, 0);
|
if (parentWindow) {
|
||||||
nsMenuPopupFrame* popupFrame = GetMenuPopupFrame(GetFrame());
|
gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(parentWindow)),
|
||||||
if (popupFrame) {
|
|
||||||
#ifdef MOZ_WAYLAND
|
|
||||||
anchorRect = LayoutDeviceIntRect::FromAppUnitsToNearest(
|
|
||||||
popupFrame->GetAnchorRect(), AppUnitsPerCSSPixel());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (anchorRect.width == 0) {
|
|
||||||
LOG((" No anchor rect given, use aPosition for anchor"));
|
|
||||||
anchorRect.SetRect(aPosition->x, aPosition->y, 1, 1);
|
|
||||||
}
|
|
||||||
LOG((" anchor x %d y %d width %d height %d (absolute coords)\n",
|
|
||||||
anchorRect.x, anchorRect.y, anchorRect.width, anchorRect.height));
|
|
||||||
|
|
||||||
// Anchor rect is in the toplevel coordinates but we need to transfer it to
|
|
||||||
// the coordinates relative to the popup parent for the
|
|
||||||
// gdk_window_move_to_rect
|
|
||||||
int x_parent = 0, y_parent = 0;
|
|
||||||
GtkWindow* parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell));
|
|
||||||
if (parentGtkWindow) {
|
|
||||||
gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(parentGtkWindow)),
|
|
||||||
&x_parent, &y_parent);
|
&x_parent, &y_parent);
|
||||||
|
} else {
|
||||||
|
NS_WARNING(("no parent window, this should not happen for popup!"));
|
||||||
|
x_parent = y_parent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkRectangle rect = {aPosition->x - x_parent, aPosition->y - y_parent, 1, 1};
|
||||||
|
if (aSize) {
|
||||||
|
rect.width = aSize->width;
|
||||||
|
rect.height = aSize->height;
|
||||||
}
|
}
|
||||||
LOG((" x_parent %d y_parent %d\n", x_parent, y_parent));
|
LOG((" x_parent %d y_parent %d\n", x_parent, y_parent));
|
||||||
anchorRect.MoveBy(-x_parent, -y_parent);
|
LOG((" aPosition x %d aPosition y %d\n", aPosition->x, aPosition->y));
|
||||||
GdkRectangle rect = {anchorRect.x, anchorRect.y, anchorRect.width,
|
LOG((" rect.x %d rect.y %d\n", rect.x, rect.y));
|
||||||
anchorRect.height};
|
|
||||||
|
if (!g_signal_handler_find(
|
||||||
|
gdkWindow, G_SIGNAL_MATCH_FUNC, 0, 0, nullptr,
|
||||||
|
FuncToGpointer(NativeMoveResizeWaylandPopupCallback), this)) {
|
||||||
|
g_signal_connect(gdkWindow, "moved-to-rect",
|
||||||
|
G_CALLBACK(NativeMoveResizeWaylandPopupCallback), this);
|
||||||
|
}
|
||||||
|
|
||||||
// Get gravity and flip type
|
|
||||||
GdkGravity rectAnchor = GDK_GRAVITY_NORTH_WEST;
|
GdkGravity rectAnchor = GDK_GRAVITY_NORTH_WEST;
|
||||||
GdkGravity menuAnchor = GDK_GRAVITY_NORTH_WEST;
|
GdkGravity menuAnchor = GDK_GRAVITY_NORTH_WEST;
|
||||||
FlipType flipType = FlipType_Default;
|
if (GetTextDirection() == GTK_TEXT_DIR_RTL) {
|
||||||
int8_t position = -1;
|
rectAnchor = GDK_GRAVITY_NORTH_EAST;
|
||||||
if (popupFrame) {
|
menuAnchor = GDK_GRAVITY_NORTH_EAST;
|
||||||
#ifdef MOZ_WAYLAND
|
|
||||||
rectAnchor = PopupAlignmentToGdkGravity(popupFrame->GetPopupAnchor());
|
|
||||||
menuAnchor = PopupAlignmentToGdkGravity(popupFrame->GetPopupAlignment());
|
|
||||||
flipType = popupFrame->GetFlipType();
|
|
||||||
position = popupFrame->GetAlignmentPosition();
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
LOG((" NO ANCHOR INFO"));
|
|
||||||
if (GetTextDirection() == GTK_TEXT_DIR_RTL) {
|
|
||||||
rectAnchor = GDK_GRAVITY_NORTH_EAST;
|
|
||||||
menuAnchor = GDK_GRAVITY_NORTH_EAST;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG((" parentRect gravity: %d anchor gravity: %d\n", rectAnchor, menuAnchor));
|
|
||||||
|
|
||||||
GdkAnchorHints hints = GdkAnchorHints(GDK_ANCHOR_RESIZE);
|
|
||||||
|
|
||||||
// slideHorizontal from nsMenuPopupFrame::SetPopupPosition
|
|
||||||
if (position >= POPUPPOSITION_BEFORESTART &&
|
|
||||||
position <= POPUPPOSITION_AFTEREND) {
|
|
||||||
hints = GdkAnchorHints(hints | GDK_ANCHOR_SLIDE_X);
|
|
||||||
}
|
|
||||||
// slideVertical from nsMenuPopupFrame::SetPopupPosition
|
|
||||||
if (position >= POPUPPOSITION_STARTBEFORE &&
|
|
||||||
position <= POPUPPOSITION_ENDAFTER) {
|
|
||||||
hints = GdkAnchorHints(hints | GDK_ANCHOR_SLIDE_Y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popupFrame && rectAnchor == GDK_GRAVITY_CENTER &&
|
GdkAnchorHints hints = GdkAnchorHints(GDK_ANCHOR_SLIDE | GDK_ANCHOR_FLIP);
|
||||||
menuAnchor == GDK_GRAVITY_CENTER) {
|
if (aSize) {
|
||||||
// only slide
|
hints = GdkAnchorHints(hints | GDK_ANCHOR_RESIZE);
|
||||||
hints = GdkAnchorHints(hints | GDK_ANCHOR_SLIDE);
|
|
||||||
} else {
|
|
||||||
switch (flipType) {
|
|
||||||
case FlipType_Both:
|
|
||||||
hints = GdkAnchorHints(hints | GDK_ANCHOR_FLIP);
|
|
||||||
break;
|
|
||||||
case FlipType_Slide:
|
|
||||||
hints = GdkAnchorHints(hints | GDK_ANCHOR_SLIDE);
|
|
||||||
break;
|
|
||||||
case FlipType_Default:
|
|
||||||
hints = GdkAnchorHints(hints | GDK_ANCHOR_FLIP);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!IsMainMenuWindow()) {
|
|
||||||
// we don't want to slide menus to fit the screen rather resize them
|
|
||||||
hints = GdkAnchorHints(hints | GDK_ANCHOR_SLIDE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A workaround for https://gitlab.gnome.org/GNOME/gtk/issues/1986
|
// A workaround for https://gitlab.gnome.org/GNOME/gtk/issues/1986
|
||||||
|
@ -1651,45 +1506,7 @@ void nsWindow::NativeMoveResizeWaylandPopup(GdkPoint* aPosition,
|
||||||
} else {
|
} else {
|
||||||
LOG((" No aSize given"));
|
LOG((" No aSize given"));
|
||||||
}
|
}
|
||||||
|
sGdkWindowMoveToRect(gdkWindow, &rect, rectAnchor, menuAnchor, hints, 0, 0);
|
||||||
// Inspired by nsMenuPopupFrame::AdjustPositionForAnchorAlign
|
|
||||||
nsPoint cursorOffset(0, 0);
|
|
||||||
#ifdef MOZ_WAYLAND
|
|
||||||
// Offset is already computed to the tooltips
|
|
||||||
if (popupFrame && mPopupType != ePopupTypeTooltip) {
|
|
||||||
nsMargin margin(0, 0, 0, 0);
|
|
||||||
popupFrame->StyleMargin()->GetMargin(margin);
|
|
||||||
switch (popupFrame->GetPopupAlignment()) {
|
|
||||||
case POPUPALIGNMENT_TOPRIGHT:
|
|
||||||
cursorOffset.MoveBy(-margin.right, margin.top);
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_BOTTOMLEFT:
|
|
||||||
cursorOffset.MoveBy(margin.left, -margin.bottom);
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_BOTTOMRIGHT:
|
|
||||||
cursorOffset.MoveBy(-margin.right, -margin.bottom);
|
|
||||||
break;
|
|
||||||
case POPUPALIGNMENT_TOPLEFT:
|
|
||||||
default:
|
|
||||||
cursorOffset.MoveBy(margin.left, margin.top);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!g_signal_handler_find(
|
|
||||||
gdkWindow, G_SIGNAL_MATCH_FUNC, 0, 0, nullptr,
|
|
||||||
FuncToGpointer(NativeMoveResizeWaylandPopupCallback), this)) {
|
|
||||||
g_signal_connect(gdkWindow, "moved-to-rect",
|
|
||||||
G_CALLBACK(NativeMoveResizeWaylandPopupCallback), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t p2a = AppUnitsPerCSSPixel();
|
|
||||||
LOG((" popup window cursor offset x: %d y: %d\n", cursorOffset.x / p2a,
|
|
||||||
cursorOffset.y / p2a));
|
|
||||||
mWaitingForMoveToRectCB = true;
|
|
||||||
sGdkWindowMoveToRect(gdkWindow, &rect, rectAnchor, menuAnchor, hints,
|
|
||||||
cursorOffset.x / p2a, cursorOffset.y / p2a);
|
|
||||||
|
|
||||||
if (isWidgetVisible) {
|
if (isWidgetVisible) {
|
||||||
// We show the popup with the same configuration so no need to call
|
// We show the popup with the same configuration so no need to call
|
||||||
|
@ -2941,7 +2758,6 @@ void nsWindow::OnSizeAllocate(GtkAllocation* aAllocation) {
|
||||||
|
|
||||||
LayoutDeviceIntSize size = GdkRectToDevicePixels(*aAllocation).Size();
|
LayoutDeviceIntSize size = GdkRectToDevicePixels(*aAllocation).Size();
|
||||||
if (mBounds.Size() == size) {
|
if (mBounds.Size() == size) {
|
||||||
LOG((" Already the same size"));
|
|
||||||
// We were already resized at nsWindow::OnConfigureEvent() so skip it.
|
// We were already resized at nsWindow::OnConfigureEvent() so skip it.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4728,10 +4544,6 @@ void nsWindow::NativeResize() {
|
||||||
MOZ_ASSERT(size.width > 0 && size.height > 0,
|
MOZ_ASSERT(size.width > 0 && size.height > 0,
|
||||||
"Can't resize window smaller than 1x1.");
|
"Can't resize window smaller than 1x1.");
|
||||||
gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
|
gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
|
||||||
if (mWaitingForMoveToRectCB) {
|
|
||||||
LOG(("Waiting for move to rect, schedulling "));
|
|
||||||
mPendingSizeRect = mBounds;
|
|
||||||
}
|
|
||||||
} else if (mContainer) {
|
} else if (mContainer) {
|
||||||
GtkWidget* widget = GTK_WIDGET(mContainer);
|
GtkWidget* widget = GTK_WIDGET(mContainer);
|
||||||
GtkAllocation allocation, prev_allocation;
|
GtkAllocation allocation, prev_allocation;
|
||||||
|
@ -4929,9 +4741,6 @@ void nsWindow::NativeShow(bool aAction) {
|
||||||
gdk_window_show_unraised(mGdkWindow);
|
gdk_window_show_unraised(mGdkWindow);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// There's a chance that when the popup will be shown again it might be
|
|
||||||
// resized because parent could be moved meanwhile.
|
|
||||||
mPreferredPopupRect = nsRect(0, 0, 0, 0);
|
|
||||||
if (!mIsX11Display) {
|
if (!mIsX11Display) {
|
||||||
WaylandStopVsync();
|
WaylandStopVsync();
|
||||||
if (IsWaylandPopup() && IsMainMenuWindow()) {
|
if (IsWaylandPopup() && IsMainMenuWindow()) {
|
||||||
|
|
|
@ -427,12 +427,6 @@ class nsWindow final : public nsBaseWidget {
|
||||||
static bool TitlebarCanUseShapeMask();
|
static bool TitlebarCanUseShapeMask();
|
||||||
#ifdef MOZ_WAYLAND
|
#ifdef MOZ_WAYLAND
|
||||||
virtual nsresult GetScreenRect(LayoutDeviceIntRect* aRect) override;
|
virtual nsresult GetScreenRect(LayoutDeviceIntRect* aRect) override;
|
||||||
virtual nsRect GetPreferredPopupRect() override {
|
|
||||||
return mPreferredPopupRect;
|
|
||||||
};
|
|
||||||
virtual void FlushPreferredPopupRect() override {
|
|
||||||
mPreferredPopupRect = nsRect(0, 0, 0, 0);
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
bool IsRemoteContent() { return HasRemoteContent(); }
|
bool IsRemoteContent() { return HasRemoteContent(); }
|
||||||
static void HideWaylandOpenedPopups();
|
static void HideWaylandOpenedPopups();
|
||||||
|
@ -700,9 +694,6 @@ class nsWindow final : public nsBaseWidget {
|
||||||
GtkWindow* GetCurrentWindow();
|
GtkWindow* GetCurrentWindow();
|
||||||
GtkWindow* GetTopmostWindow();
|
GtkWindow* GetTopmostWindow();
|
||||||
bool IsWidgetOverflowWindow();
|
bool IsWidgetOverflowWindow();
|
||||||
nsRect mPreferredPopupRect;
|
|
||||||
bool mWaitingForMoveToRectCB;
|
|
||||||
LayoutDeviceIntRect mPendingSizeRect;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* |mIMContext| takes all IME related stuff.
|
* |mIMContext| takes all IME related stuff.
|
||||||
|
|
|
@ -1730,15 +1730,6 @@ class nsIWidget : public nsISupports {
|
||||||
virtual nsresult GetScreenRect(LayoutDeviceIntRect* aRect) {
|
virtual nsresult GetScreenRect(LayoutDeviceIntRect* aRect) {
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
virtual nsRect GetPreferredPopupRect() {
|
|
||||||
NS_WARNING("GetPreferredPopupRect implemented only for wayland");
|
|
||||||
return nsRect(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
virtual void FlushPreferredPopupRect() {
|
|
||||||
NS_WARNING("FlushPreferredPopupRect implemented only for wayland");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче