зеркало из https://github.com/mozilla/gecko-dev.git
Bug 566480 - Make dragging the menubar drag the window on GTK themes where that should work (and also fix GTK resize drags to initialize drag better). r=karlt,dbaron,enn,dao
This commit is contained in:
Родитель
fba699e63b
Коммит
6e287b8de2
|
@ -1706,6 +1706,7 @@ GK_ATOM(windows_compositor, "windows-compositor")
|
|||
GK_ATOM(windows_classic, "windows-classic")
|
||||
GK_ATOM(touch_enabled, "touch-enabled")
|
||||
GK_ATOM(maemo_classic, "maemo-classic")
|
||||
GK_ATOM(menubar_drag, "menubar-drag")
|
||||
|
||||
// And the same again, as media query keywords.
|
||||
GK_ATOM(_moz_scrollbar_start_backward, "-moz-scrollbar-start-backward")
|
||||
|
@ -1721,3 +1722,4 @@ GK_ATOM(_moz_windows_compositor, "-moz-windows-compositor")
|
|||
GK_ATOM(_moz_windows_classic, "-moz-windows-classic")
|
||||
GK_ATOM(_moz_touch_enabled, "-moz-touch-enabled")
|
||||
GK_ATOM(_moz_maemo_classic, "-moz-maemo-classic")
|
||||
GK_ATOM(_moz_menubar_drag, "-moz-menubar-drag")
|
||||
|
|
|
@ -9433,6 +9433,25 @@ nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount)
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
||||
if (!widget) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(aMouseDownEvent);
|
||||
NS_ENSURE_TRUE(privEvent, NS_ERROR_FAILURE);
|
||||
nsEvent *internalEvent = privEvent->GetInternalNSEvent();
|
||||
NS_ENSURE_TRUE(internalEvent &&
|
||||
internalEvent->eventStructType == NS_MOUSE_EVENT,
|
||||
NS_ERROR_FAILURE);
|
||||
nsMouseEvent *mouseEvent = static_cast<nsMouseEvent*>(internalEvent);
|
||||
|
||||
return widget->BeginMoveDrag(mouseEvent);
|
||||
}
|
||||
|
||||
//Note: This call will lock the cursor, it will not change as it moves.
|
||||
//To unlock, the cursor must be set back to CURSOR_AUTO.
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -40,9 +40,10 @@
|
|||
|
||||
interface nsIBrowserDOMWindow;
|
||||
interface nsIDOMElement;
|
||||
interface nsIDOMEvent;
|
||||
interface nsIChromeFrameMessageManager;
|
||||
|
||||
[scriptable, uuid(adf6b19f-459f-4892-93eb-71c527bae2af)]
|
||||
[scriptable, uuid(ec38cbaf-372f-4874-bc7a-dbf1f0b3d755)]
|
||||
interface nsIDOMChromeWindow : nsISupports
|
||||
{
|
||||
const unsigned short STATE_MAXIMIZED = 1;
|
||||
|
@ -76,4 +77,15 @@ interface nsIDOMChromeWindow : nsISupports
|
|||
void notifyDefaultButtonLoaded(in nsIDOMElement defaultButton);
|
||||
|
||||
readonly attribute nsIChromeFrameMessageManager messageManager;
|
||||
|
||||
/**
|
||||
* On some operating systems, we must allow the window manager to
|
||||
* handle window dragging. This function tells the window manager to
|
||||
* start dragging the window. This function will fail unless called
|
||||
* while the left mouse button is held down, callers must check this.
|
||||
*
|
||||
* Returns NS_ERROR_NOT_IMPLEMENTED (and thus throws in JS) if the OS
|
||||
* doesn't support this.
|
||||
*/
|
||||
void beginWindowMove(in nsIDOMEvent mouseDownEvent);
|
||||
};
|
||||
|
|
|
@ -1000,6 +1000,11 @@ InitSystemMetrics()
|
|||
sSystemMetrics->AppendElement(nsGkAtoms::images_in_buttons);
|
||||
}
|
||||
|
||||
lookAndFeel->GetMetric(nsILookAndFeel::eMetric_MenuBarDrag, metricResult);
|
||||
if (metricResult) {
|
||||
sSystemMetrics->AppendElement(nsGkAtoms::menubar_drag);
|
||||
}
|
||||
|
||||
rv = lookAndFeel->GetMetric(nsILookAndFeel::eMetric_WindowsDefaultTheme, metricResult);
|
||||
if (NS_SUCCEEDED(rv) && metricResult) {
|
||||
sSystemMetrics->AppendElement(nsGkAtoms::windows_default_theme);
|
||||
|
|
|
@ -468,6 +468,13 @@ nsMediaFeatures::features[] = {
|
|||
{ &nsGkAtoms::maemo_classic },
|
||||
GetSystemMetric
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::_moz_menubar_drag,
|
||||
nsMediaFeature::eMinMaxNotAllowed,
|
||||
nsMediaFeature::eBoolInteger,
|
||||
{ &nsGkAtoms::menubar_drag },
|
||||
GetSystemMetric
|
||||
},
|
||||
|
||||
// Null-mName terminator:
|
||||
{
|
||||
|
|
|
@ -88,20 +88,28 @@ WindowDraggingElement.prototype = {
|
|||
if (!this.shouldDrag(aEvent))
|
||||
return;
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
// On GTK, there is a toolkit-level function which handles
|
||||
// window dragging, which must be used.
|
||||
this._window.beginWindowMove(aEvent);
|
||||
#else
|
||||
this._deltaX = aEvent.screenX - this._window.screenX;
|
||||
this._deltaY = aEvent.screenY - this._window.screenY;
|
||||
this._draggingWindow = true;
|
||||
this._window.addEventListener("mousemove", this, false);
|
||||
this._window.addEventListener("mouseup", this, false);
|
||||
#endif
|
||||
break;
|
||||
case "mousemove":
|
||||
if (this._draggingWindow)
|
||||
this._window.moveTo(aEvent.screenX - this._deltaX, aEvent.screenY - this._deltaY);
|
||||
break;
|
||||
case "mouseup":
|
||||
this._draggingWindow = false;
|
||||
this._window.removeEventListener("mousemove", this, false);
|
||||
this._window.removeEventListener("mouseup", this, false);
|
||||
if (this._draggingWindow) {
|
||||
this._draggingWindow = false;
|
||||
this._window.removeEventListener("mousemove", this, false);
|
||||
this._window.removeEventListener("mouseup", this, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -67,6 +67,10 @@ progressmeter[mode="undetermined"] {
|
|||
-moz-binding: url("chrome://global/content/bindings/progressmeter.xml#progressmeter-undetermined");
|
||||
}
|
||||
|
||||
toolbar[type="menubar"]:not(-moz-lwtheme):-moz-system-metric(menubar-drag) {
|
||||
-moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
|
||||
}
|
||||
|
||||
/* ::::: root elements ::::: */
|
||||
|
||||
window,
|
||||
|
|
|
@ -322,7 +322,11 @@ public:
|
|||
/**
|
||||
* If this metric != 0, show icons in buttons.
|
||||
*/
|
||||
eMetric_ImagesInButtons
|
||||
eMetric_ImagesInButtons,
|
||||
/**
|
||||
* If this metric != 0, support window dragging on the menubar.
|
||||
*/
|
||||
eMetric_MenuBarDrag
|
||||
} nsMetricID;
|
||||
|
||||
enum {
|
||||
|
|
|
@ -110,9 +110,10 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
|
|||
#define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
|
||||
#endif
|
||||
|
||||
// b7ec5f61-57df-4355-81f3-41ced52e8026
|
||||
#define NS_IWIDGET_IID \
|
||||
{ 0x271ac413, 0xa202, 0x46dc, \
|
||||
{ 0xbc, 0xd5, 0x67, 0xa1, 0xfb, 0x58, 0x89, 0x7f } }
|
||||
{ 0xb7ec5f61, 0x57df, 0x4355, \
|
||||
{ 0x81, 0xf3, 0x41, 0xce, 0xd5, 0x2e, 0x80, 0x26 } }
|
||||
|
||||
/*
|
||||
* Window shadow styles
|
||||
|
@ -965,6 +966,11 @@ class nsIWidget : public nsISupports {
|
|||
*/
|
||||
NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical) = 0;
|
||||
|
||||
/**
|
||||
* Begin a window moving drag, based on the event passed in.
|
||||
*/
|
||||
NS_IMETHOD BeginMoveDrag(nsMouseEvent* aEvent) = 0;
|
||||
|
||||
enum Modifiers {
|
||||
CAPS_LOCK = 0x01, // when CapsLock is active
|
||||
NUM_LOCK = 0x02, // when NumLock is active
|
||||
|
|
|
@ -70,6 +70,7 @@ nscolor nsLookAndFeel::sComboBoxText = 0;
|
|||
nscolor nsLookAndFeel::sComboBoxBackground = 0;
|
||||
PRUnichar nsLookAndFeel::sInvisibleCharacter = PRUnichar('*');
|
||||
float nsLookAndFeel::sCaretRatio = 0;
|
||||
PRBool nsLookAndFeel::sMenuSupportsDrag = PR_FALSE;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -631,6 +632,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
|
|||
case eMetric_ImagesInButtons:
|
||||
aMetric = moz_gtk_images_in_buttons();
|
||||
break;
|
||||
case eMetric_MenuBarDrag:
|
||||
aMetric = sMenuSupportsDrag;
|
||||
break;
|
||||
default:
|
||||
aMetric = 0;
|
||||
res = NS_ERROR_FAILURE;
|
||||
|
@ -797,6 +801,13 @@ nsLookAndFeel::InitLookAndFeel()
|
|||
sMenuBarHoverText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_SELECTED]);
|
||||
}
|
||||
|
||||
// Some themes have a unified menu bar, and support window dragging on it
|
||||
gboolean supports_menubar_drag = FALSE;
|
||||
gtk_widget_style_get(menuBar,
|
||||
"window-dragging", &supports_menubar_drag,
|
||||
NULL);
|
||||
sMenuSupportsDrag = supports_menubar_drag;
|
||||
|
||||
// GTK's guide to fancy odd row background colors:
|
||||
// 1) Check if a theme explicitly defines an odd row color
|
||||
// 2) If not, check if it defines an even row color, and darken it
|
||||
|
|
|
@ -78,6 +78,7 @@ protected:
|
|||
static nscolor sComboBoxBackground;
|
||||
static PRUnichar sInvisibleCharacter;
|
||||
static float sCaretRatio;
|
||||
static PRBool sMenuSupportsDrag;
|
||||
|
||||
static void InitLookAndFeel();
|
||||
void InitWidget() {
|
||||
|
|
|
@ -6737,21 +6737,83 @@ nsWindow::GetThebesSurface()
|
|||
return mThebesSurface;
|
||||
}
|
||||
|
||||
// Code shared begin BeginMoveDrag and BeginResizeDrag
|
||||
PRBool
|
||||
nsWindow::GetDragInfo(nsMouseEvent* aMouseEvent,
|
||||
GdkWindow** aWindow, gint* aButton,
|
||||
gint* aRootX, gint* aRootY)
|
||||
{
|
||||
if (aMouseEvent->button != nsMouseEvent::eLeftButton) {
|
||||
// we can only begin a move drag with the left mouse button
|
||||
return PR_FALSE;
|
||||
}
|
||||
*aButton = 1;
|
||||
|
||||
// get the gdk window for this widget
|
||||
GdkWindow* gdk_window = mGdkWindow;
|
||||
if (!gdk_window) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(GDK_IS_WINDOW(gdk_window), "must really be window");
|
||||
|
||||
// find the top-level window
|
||||
gdk_window = gdk_window_get_toplevel(gdk_window);
|
||||
NS_ABORT_IF_FALSE(gdk_window,
|
||||
"gdk_window_get_toplevel should not return null");
|
||||
*aWindow = gdk_window;
|
||||
|
||||
if (!aMouseEvent->widget) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// FIXME: It would be nice to have the widget position at the time
|
||||
// of the event, but it's relatively unlikely that the widget has
|
||||
// moved since the mousedown. (On the other hand, it's quite likely
|
||||
// that the mouse has moved, which is why we use the mouse position
|
||||
// from the event.)
|
||||
nsIntPoint offset = aMouseEvent->widget->WidgetToScreenOffset();
|
||||
*aRootX = aMouseEvent->refPoint.x + offset.x;
|
||||
*aRootY = aMouseEvent->refPoint.y + offset.y;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindow::BeginMoveDrag(nsMouseEvent* aEvent)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aEvent, "must have event");
|
||||
NS_ABORT_IF_FALSE(aEvent->eventStructType == NS_MOUSE_EVENT,
|
||||
"event must have correct struct type");
|
||||
|
||||
GdkWindow *gdk_window;
|
||||
gint button, screenX, screenY;
|
||||
if (!GetDragInfo(aEvent, &gdk_window, &button, &screenX, &screenY)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// tell the window manager to start the move
|
||||
gdk_window_begin_move_drag(gdk_window, button, screenX, screenY,
|
||||
aEvent->time);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEvent);
|
||||
|
||||
if (aEvent->eventStructType != NS_MOUSE_EVENT) {
|
||||
// you can only begin a resize drag with a mouse event
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
// you can only begin a resize drag with a mouse event
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsMouseEvent* mouse_event = static_cast<nsMouseEvent*>(aEvent);
|
||||
|
||||
if (mouse_event->button != nsMouseEvent::eLeftButton) {
|
||||
// you can only begin a resize drag with the left mouse button
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
GdkWindow *gdk_window;
|
||||
gint button, screenX, screenY;
|
||||
if (!GetDragInfo(mouse_event, &gdk_window, &button, &screenX, &screenY)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// work out what GdkWindowEdge we're talking about
|
||||
|
@ -6782,39 +6844,9 @@ nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVert
|
|||
}
|
||||
}
|
||||
|
||||
// get the gdk window for this widget
|
||||
GdkWindow* gdk_window = mGdkWindow;
|
||||
if (!GDK_IS_WINDOW(gdk_window)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// find the top-level window
|
||||
gdk_window = gdk_window_get_toplevel(gdk_window);
|
||||
if (!GDK_IS_WINDOW(gdk_window)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// get the current (default) display
|
||||
GdkDisplay* display = gdk_display_get_default();
|
||||
if (!GDK_IS_DISPLAY(display)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// get the current pointer position and button state
|
||||
GdkScreen* screen = NULL;
|
||||
gint screenX, screenY;
|
||||
GdkModifierType mask;
|
||||
gdk_display_get_pointer(display, &screen, &screenX, &screenY, &mask);
|
||||
|
||||
// we only support resizing with button 1
|
||||
if (!(mask & GDK_BUTTON1_MASK)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// tell the window manager to start the resize
|
||||
gdk_window_begin_resize_drag(gdk_window, window_edge, 1,
|
||||
screenX, screenY, aEvent->time);
|
||||
gdk_window_begin_resize_drag(gdk_window, window_edge, button,
|
||||
screenX, screenY, aEvent->time);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -302,7 +302,8 @@ public:
|
|||
static guint32 sLastButtonPressTime;
|
||||
static guint32 sLastButtonReleaseTime;
|
||||
|
||||
NS_IMETHOD BeginResizeDrag (nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
|
||||
NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
|
||||
NS_IMETHOD BeginMoveDrag(nsMouseEvent* aEvent);
|
||||
|
||||
MozContainer* GetMozContainer() { return mContainer; }
|
||||
GdkWindow* GetGdkWindow() { return mGdkWindow; }
|
||||
|
@ -376,6 +377,9 @@ private:
|
|||
PRBool DispatchCommandEvent(nsIAtom* aCommand);
|
||||
void SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
|
||||
PRBool aIntersectWithExisting);
|
||||
PRBool GetDragInfo(nsMouseEvent* aMouseEvent,
|
||||
GdkWindow** aWindow, gint* aButton,
|
||||
gint* aRootX, gint* aRootY);
|
||||
|
||||
GtkWidget *mShell;
|
||||
MozContainer *mContainer;
|
||||
|
|
|
@ -1041,6 +1041,12 @@ nsBaseWidget::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 a
|
|||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseWidget::BeginMoveDrag(nsMouseEvent* aEvent)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
|
@ -132,6 +132,7 @@ public:
|
|||
virtual PRBool ShowsResizeIndicator(nsIntRect* aResizerRect);
|
||||
virtual void FreeNativeData(void * data, PRUint32 aDataType) {}
|
||||
NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
|
||||
NS_IMETHOD BeginMoveDrag(nsMouseEvent* aEvent);
|
||||
virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
virtual nsresult ForceUpdateNativeMenuAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
NS_IMETHOD ResetInputState() { return NS_OK; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче