зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
310a492571
|
@ -1,6 +1,6 @@
|
|||
<html lang="en" dir="ltr">
|
||||
<body>
|
||||
<div id="maindiv">Hello World!</div>
|
||||
<div id="maindiv" style="padding-top:50px">Hello World!</div>
|
||||
</body>
|
||||
<script>
|
||||
const cpmm = SpecialPowers.Services.cpmm;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html lang="en" dir="ltr">
|
||||
<body>
|
||||
<div id="maindiv">Hello World!</div>
|
||||
<div id="maindiv" style="padding-top:50px">Hello World!</div>
|
||||
</body>
|
||||
<script>
|
||||
var number = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<html lang="en" dir="ltr">
|
||||
<body>
|
||||
<div id="maindiv">Hello World!</div>
|
||||
<div id="maindiv" style="padding-top:50px">Hello World!</div>
|
||||
</body>
|
||||
<script>
|
||||
const cpmm = SpecialPowers.Services.cpmm;
|
||||
|
|
|
@ -28,7 +28,7 @@ function isPaused({ getMessage, pausedExecutionPoint }) {
|
|||
const message = getMessage();
|
||||
return pausedExecutionPoint
|
||||
&& message.executionPoint
|
||||
&& pausedExecutionPoint.checkpoint === message.executionPoint.checkpoint;
|
||||
&& pausedExecutionPoint.progress === message.executionPoint.progress;
|
||||
}
|
||||
|
||||
class MessageContainer extends Component {
|
||||
|
|
|
@ -14,15 +14,117 @@
|
|||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function updateWindow(window, buffer, width, height, hadFailure) {
|
||||
// Make sure the window has a canvas filling the screen.
|
||||
let canvas = window.middlemanCanvas;
|
||||
if (!canvas) {
|
||||
canvas = window.document.createElement("canvas");
|
||||
window.document.body.style.margin = "0px";
|
||||
window.document.body.insertBefore(canvas, window.document.body.firstChild);
|
||||
window.middlemanCanvas = canvas;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
// Create a sandbox with the resources we need. require() doesn't work here.
|
||||
const sandbox = Cu.Sandbox(CC("@mozilla.org/systemprincipal;1", "nsIPrincipal")());
|
||||
Cu.evalInSandbox(
|
||||
"Components.utils.import('resource://gre/modules/jsdebugger.jsm');" +
|
||||
"addDebuggerToGlobal(this);",
|
||||
sandbox
|
||||
);
|
||||
const RecordReplayControl = sandbox.RecordReplayControl;
|
||||
|
||||
// State for dragging the overlay.
|
||||
let dragx, dragy;
|
||||
|
||||
// Windows in the middleman process are initially set up as about:blank pages.
|
||||
// This method fills them in with a canvas filling the tab, and an overlay that
|
||||
// can be displayed over that canvas.
|
||||
function setupContents(window) {
|
||||
// The middlemanOverlay element is shown when the active child is replaying.
|
||||
const overlay = window.middlemanOverlay = window.document.createElement("div");
|
||||
overlay.style.position = "absolute";
|
||||
overlay.style.border = "medium solid #000000";
|
||||
overlay.style.backgroundColor = "#BBCCCC";
|
||||
|
||||
// The middlemanPosition element is contained in the overlay and shows the
|
||||
// current position in the recording.
|
||||
const position = window.middlemanPosition = window.document.createElement("div");
|
||||
position.innerText = "";
|
||||
position.style.textAlign = "center";
|
||||
position.style.padding = "5px 5px 0px 5px";
|
||||
overlay.appendChild(position);
|
||||
|
||||
// The middlemanProgressBar element is contained in the overlay and shows any
|
||||
// progress made on the current operation.
|
||||
const progressBar =
|
||||
window.middlemanProgressBar = window.document.createElement("canvas");
|
||||
progressBar.width = 100;
|
||||
progressBar.height = 5;
|
||||
progressBar.getContext("2d").fillStyle = "white";
|
||||
progressBar.getContext("2d").fillRect(0, 0, 100, 5);
|
||||
progressBar.style.padding = "5px 5px 5px 5px";
|
||||
|
||||
overlay.appendChild(progressBar);
|
||||
window.document.body.prepend(overlay);
|
||||
|
||||
overlay.onmousedown = window.middlemanMouseDown = function(e) {
|
||||
e.preventDefault();
|
||||
dragx = e.clientX;
|
||||
dragy = e.clientY;
|
||||
window.document.onmouseup = window.middlemanMouseUp;
|
||||
window.document.onmousemove = window.middlemanMouseMove;
|
||||
};
|
||||
|
||||
window.middlemanMouseMove = function(e) {
|
||||
// Compute the new position of the overlay per the current drag operation.
|
||||
// Don't allow the overlay to be dragged outside the window.
|
||||
e.preventDefault();
|
||||
const canvas = window.middlemanCanvas;
|
||||
let diffx = e.clientX - dragx;
|
||||
let diffy = e.clientY - dragy;
|
||||
const newTop = () => overlay.offsetTop + diffy;
|
||||
if (newTop() < 0) {
|
||||
diffy -= newTop();
|
||||
}
|
||||
const maxTop = canvas.height / window.devicePixelRatio;
|
||||
if (newTop() + overlay.offsetHeight >= maxTop) {
|
||||
diffy -= newTop() + overlay.offsetHeight - maxTop;
|
||||
}
|
||||
overlay.style.top = newTop() + "px";
|
||||
const newLeft = () => overlay.offsetLeft + diffx;
|
||||
if (newLeft() < 0) {
|
||||
diffx -= newLeft();
|
||||
}
|
||||
const maxLeft = canvas.width / window.devicePixelRatio;
|
||||
if (newLeft() + overlay.offsetWidth >= maxLeft) {
|
||||
diffx -= newLeft() + overlay.offsetWidth - maxLeft;
|
||||
}
|
||||
overlay.style.left = (overlay.offsetLeft + diffx) + "px";
|
||||
dragx += diffx;
|
||||
dragy += diffy;
|
||||
};
|
||||
|
||||
window.middlemanMouseUp = function(e) {
|
||||
window.document.onmouseup = null;
|
||||
window.document.onmousemove = null;
|
||||
};
|
||||
|
||||
// The middlemanCanvas element fills the tab's contents.
|
||||
const canvas = window.middlemanCanvas = window.document.createElement("canvas");
|
||||
canvas.style.position = "absolute";
|
||||
window.document.body.style.margin = "0px";
|
||||
window.document.body.prepend(canvas);
|
||||
}
|
||||
|
||||
function getOverlay(window) {
|
||||
if (!window.middlemanOverlay) {
|
||||
setupContents(window);
|
||||
}
|
||||
return window.middlemanOverlay;
|
||||
}
|
||||
|
||||
function getCanvas(window) {
|
||||
if (!window.middlemanCanvas) {
|
||||
setupContents(window);
|
||||
}
|
||||
return window.middlemanCanvas;
|
||||
}
|
||||
|
||||
function updateWindowCanvas(window, buffer, width, height, hadFailure) {
|
||||
// Make sure the window has a canvas filling the screen.
|
||||
const canvas = getCanvas(window);
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
@ -53,23 +155,51 @@ function updateWindow(window, buffer, width, height, hadFailure) {
|
|||
|
||||
// Make recording/replaying tabs easier to differentiate from other tabs.
|
||||
window.document.title = "RECORD/REPLAY";
|
||||
|
||||
updateWindowOverlay(window);
|
||||
}
|
||||
|
||||
// Entry point for when we have some new graphics data from the child process
|
||||
// to draw.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function Update(buffer, width, height, hadFailure) {
|
||||
function UpdateCanvas(buffer, width, height, hadFailure) {
|
||||
try {
|
||||
// Paint to all windows we can find. Hopefully there is only one.
|
||||
for (const window of Services.ww.getWindowEnumerator()) {
|
||||
updateWindow(window, buffer, width, height, hadFailure);
|
||||
updateWindowCanvas(window, buffer, width, height, hadFailure);
|
||||
}
|
||||
} catch (e) {
|
||||
dump("Middleman Graphics Update Exception: " + e + "\n");
|
||||
dump("Middleman Graphics UpdateCanvas Exception: " + e + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
function updateWindowOverlay(window) {
|
||||
const overlay = getOverlay(window);
|
||||
|
||||
const position = RecordReplayControl.recordingPosition();
|
||||
if (position === undefined) {
|
||||
overlay.style.visibility = "hidden";
|
||||
} else {
|
||||
overlay.style.visibility = "visible";
|
||||
window.middlemanPosition.innerText = (Math.round(position * 10000) / 100) + "%";
|
||||
}
|
||||
}
|
||||
|
||||
// Entry point for when we need to update the overlay's contents or visibility.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function UpdateOverlay() {
|
||||
try {
|
||||
// Paint to all windows we can find. Hopefully there is only one.
|
||||
for (const window of Services.ww.getWindowEnumerator()) {
|
||||
updateWindowOverlay(window);
|
||||
}
|
||||
} catch (e) {
|
||||
dump("Middleman Graphics UpdateOverlay Exception: " + e + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
var EXPORTED_SYMBOLS = [
|
||||
"Update",
|
||||
"UpdateCanvas",
|
||||
"UpdateOverlay",
|
||||
];
|
||||
|
|
|
@ -1183,7 +1183,14 @@ const browsingContextTargetPrototype = {
|
|||
return;
|
||||
}
|
||||
const windowUtils = this.window.windowUtils;
|
||||
windowUtils.suppressEventHandling(true);
|
||||
|
||||
// Events are not suppressed when running in the middleman, as we are in a
|
||||
// different process from the debuggee and may want to process events in
|
||||
// the middleman for e.g. the overlay drawn when rewinding.
|
||||
if (Debugger.recordReplayProcessKind() != "Middleman") {
|
||||
windowUtils.suppressEventHandling(true);
|
||||
}
|
||||
|
||||
windowUtils.suspendTimeouts();
|
||||
},
|
||||
|
||||
|
@ -1197,7 +1204,9 @@ const browsingContextTargetPrototype = {
|
|||
}
|
||||
const windowUtils = this.window.windowUtils;
|
||||
windowUtils.resumeTimeouts();
|
||||
windowUtils.suppressEventHandling(false);
|
||||
if (Debugger.recordReplayProcessKind() != "Middleman") {
|
||||
windowUtils.suppressEventHandling(false);
|
||||
}
|
||||
},
|
||||
|
||||
_changeTopLevelDocument(window) {
|
||||
|
|
|
@ -432,6 +432,21 @@ Middleman_HadRepaintFailure(JSContext* aCx, unsigned aArgc, Value* aVp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
Middleman_RecordingPosition(JSContext* aCx, unsigned aArgc, Value* aVp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(aArgc, aVp);
|
||||
|
||||
Maybe<double> recordingPosition = parent::GetRecordingPosition();
|
||||
|
||||
if (recordingPosition.isSome()) {
|
||||
args.rval().setNumber(recordingPosition.ref());
|
||||
} else {
|
||||
args.rval().setUndefined();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Devtools Sandbox
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -912,6 +927,7 @@ static const JSFunctionSpec gMiddlemanMethods[] = {
|
|||
JS_FN("maybeSwitchToReplayingChild", Middleman_MaybeSwitchToReplayingChild, 0, 0),
|
||||
JS_FN("hadRepaint", Middleman_HadRepaint, 2, 0),
|
||||
JS_FN("hadRepaintFailure", Middleman_HadRepaintFailure, 0, 0),
|
||||
JS_FN("recordingPosition", Middleman_RecordingPosition, 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
|
|
@ -92,6 +92,14 @@ HandleMessageInMiddleman(ipc::Side aSide, const IPC::Message& aMessage)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Send input events to the middleman when the active child is replaying,
|
||||
// so that UI elements such as the replay overlay can be interacted with.
|
||||
if (!ActiveChildIsRecording() && nsContentUtils::IsMessageInputEvent(aMessage)) {
|
||||
ipc::IProtocol::Result r = dom::ContentChild::GetSingleton()->PContentChild::OnMessageReceived(aMessage);
|
||||
MOZ_RELEASE_ASSERT(r == ipc::IProtocol::MsgProcessed);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The content process has its own compositor, so compositor messages from
|
||||
// the UI process should only be handled in the middleman.
|
||||
if (type >= layers::PCompositorBridge::PCompositorBridgeStart &&
|
||||
|
|
|
@ -153,9 +153,6 @@ UpdateGraphicsInUIProcess(const PaintMessage* aMsg)
|
|||
InitGraphicsSandbox();
|
||||
}
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
JSAutoRealm ar(cx, *gGraphicsSandbox);
|
||||
|
||||
size_t width = gLastPaintWidth;
|
||||
size_t height = gLastPaintHeight;
|
||||
size_t stride = layers::ImageDataSerializer::ComputeRGBStride(gSurfaceFormat, width);
|
||||
|
@ -184,6 +181,9 @@ UpdateGraphicsInUIProcess(const PaintMessage* aMsg)
|
|||
}
|
||||
}
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
JSAutoRealm ar(cx, *gGraphicsSandbox);
|
||||
|
||||
JSObject* bufferObject =
|
||||
JS_NewArrayBufferWithExternalContents(cx, width * height * 4, memory);
|
||||
MOZ_RELEASE_ASSERT(bufferObject);
|
||||
|
@ -196,11 +196,28 @@ UpdateGraphicsInUIProcess(const PaintMessage* aMsg)
|
|||
|
||||
// Call into the graphics module to update the canvas it manages.
|
||||
RootedValue rval(cx);
|
||||
if (!JS_CallFunctionName(cx, *gGraphicsSandbox, "Update", args, &rval)) {
|
||||
if (!JS_CallFunctionName(cx, *gGraphicsSandbox, "UpdateCanvas", args, &rval)) {
|
||||
MOZ_CRASH("UpdateGraphicsInUIProcess");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UpdateGraphicsOverlay()
|
||||
{
|
||||
if (!gLastPaintWidth || !gLastPaintHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
JSAutoRealm ar(cx, *gGraphicsSandbox);
|
||||
|
||||
RootedValue rval(cx);
|
||||
if (!JS_CallFunctionName(cx, *gGraphicsSandbox, "UpdateOverlay",
|
||||
JS::HandleValueArray::empty(), &rval)) {
|
||||
MOZ_CRASH("UpdateGraphicsOverlay");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
MaybeTriggerExplicitPaint()
|
||||
{
|
||||
|
|
|
@ -283,7 +283,7 @@ public:
|
|||
bool
|
||||
ActiveChildIsRecording()
|
||||
{
|
||||
return gActiveChild->IsRecording();
|
||||
return gActiveChild && gActiveChild->IsRecording();
|
||||
}
|
||||
|
||||
ChildProcessInfo*
|
||||
|
@ -611,6 +611,12 @@ SwitchActiveChild(ChildProcessInfo* aChild, bool aRecoverPosition = true)
|
|||
oldActiveChild->RecoverToCheckpoint(oldActiveChild->MostRecentSavedCheckpoint());
|
||||
oldActiveChild->SetRole(MakeUnique<ChildRoleStandby>());
|
||||
}
|
||||
|
||||
// The graphics overlay is affected when we switch between recording and
|
||||
// replaying children.
|
||||
if (aChild->IsRecording() != oldActiveChild->IsRecording()) {
|
||||
UpdateGraphicsOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -857,6 +863,19 @@ MaybeSwitchToReplayingChild()
|
|||
}
|
||||
}
|
||||
|
||||
Maybe<double>
|
||||
GetRecordingPosition()
|
||||
{
|
||||
if (gActiveChild->IsRecording()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// Get the fraction of the recording that the active child has reached so far.
|
||||
double fraction = (gActiveChild->MostRecentCheckpoint() - CheckpointId::First)
|
||||
/ (double) (gCheckpointTimes.length() - CheckpointId::First);
|
||||
return Some(fraction);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Initialization
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1168,6 +1187,10 @@ RecvHitCheckpoint(const HitCheckpointMessage& aMsg)
|
|||
UpdateCheckpointTimes(aMsg);
|
||||
MaybeUpdateGraphicsAtCheckpoint(aMsg.mCheckpointId);
|
||||
|
||||
if (!gActiveChild->IsRecording()) {
|
||||
UpdateGraphicsOverlay();
|
||||
}
|
||||
|
||||
// Resume either forwards or backwards. Break the resume off into a separate
|
||||
// runnable, to avoid starving any code already on the stack and waiting for
|
||||
// the process to pause. Immediately resume if the main thread is blocked.
|
||||
|
|
|
@ -76,6 +76,10 @@ void SetBreakpoint(size_t aId, const js::BreakpointPosition& aPosition);
|
|||
// children cannot process such requests).
|
||||
void MaybeSwitchToReplayingChild();
|
||||
|
||||
// If the active child is replaying, get its fractional (range [0,1]) position
|
||||
// in the recording. If the active child is recording, return Nothing.
|
||||
Maybe<double> GetRecordingPosition();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Graphics
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -90,6 +94,9 @@ void SendGraphicsMemoryToChild();
|
|||
// an unhandled recording divergence.
|
||||
void UpdateGraphicsInUIProcess(const PaintMessage* aMsg);
|
||||
|
||||
// Update the overlay shown over the tab's graphics.
|
||||
void UpdateGraphicsOverlay();
|
||||
|
||||
// If necessary, update graphics after the active child sends a paint message
|
||||
// or reaches a checkpoint.
|
||||
void MaybeUpdateGraphicsAtPaint(const PaintMessage& aMsg);
|
||||
|
|
|
@ -177,6 +177,7 @@ public:
|
|||
struct TextBoxParams {
|
||||
bool disabled = false;
|
||||
bool focused = false;
|
||||
bool borderless = false;
|
||||
};
|
||||
|
||||
struct SearchFieldParams {
|
||||
|
|
|
@ -2022,6 +2022,15 @@ nsNativeThemeCocoa::DrawTextBox(CGContextRef cgContext, const HIRect& inBoxRect,
|
|||
CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0);
|
||||
CGContextFillRect(cgContext, inBoxRect);
|
||||
|
||||
#if DRAW_IN_FRAME_DEBUG
|
||||
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
|
||||
CGContextFillRect(cgContext, inBoxRect);
|
||||
#endif
|
||||
|
||||
if (aParams.borderless) {
|
||||
return;
|
||||
}
|
||||
|
||||
HIThemeFrameDrawInfo fdi;
|
||||
fdi.version = 0;
|
||||
fdi.kind = kHIThemeFrameTextFieldSquare;
|
||||
|
@ -2042,11 +2051,6 @@ nsNativeThemeCocoa::DrawTextBox(CGContextRef cgContext, const HIRect& inBoxRect,
|
|||
drawRect.size.width -= frameOutset * 2;
|
||||
drawRect.size.height -= frameOutset * 2;
|
||||
|
||||
#if DRAW_IN_FRAME_DEBUG
|
||||
CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
|
||||
CGContextFillRect(cgContext, inBoxRect);
|
||||
#endif
|
||||
|
||||
HIThemeDrawFrame(&drawRect, &fdi, cgContext, HITHEME_ORIENTATION);
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
|
@ -3334,15 +3338,14 @@ nsNativeThemeCocoa::ComputeWidgetInfo(nsIFrame* aFrame,
|
|||
case StyleAppearance::Statusbar:
|
||||
return Some(WidgetInfo::StatusBar(IsActive(aFrame, YES)));
|
||||
|
||||
case StyleAppearance::Menulist:
|
||||
case StyleAppearance::MenulistTextfield: {
|
||||
case StyleAppearance::Menulist: {
|
||||
ControlParams controlParams = ComputeControlParams(aFrame, eventState);
|
||||
controlParams.focused = controlParams.focused || IsFocused(aFrame);
|
||||
controlParams.pressed = IsOpenButton(aFrame);
|
||||
DropdownParams params;
|
||||
params.controlParams = controlParams;
|
||||
params.pullsDown = false;
|
||||
params.editable = aWidgetType == StyleAppearance::MenulistTextfield;
|
||||
params.editable = false;
|
||||
return Some(WidgetInfo::Dropdown(params));
|
||||
}
|
||||
|
||||
|
@ -3355,6 +3358,7 @@ nsNativeThemeCocoa::ComputeWidgetInfo(nsIFrame* aFrame,
|
|||
case StyleAppearance::Groupbox:
|
||||
return Some(WidgetInfo::GroupBox());
|
||||
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::Textfield:
|
||||
case StyleAppearance::NumberInput: {
|
||||
bool isFocused = eventState.HasState(NS_EVENT_STATE_FOCUS);
|
||||
|
@ -3368,7 +3372,10 @@ nsNativeThemeCocoa::ComputeWidgetInfo(nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
bool isDisabled = IsDisabled(aFrame, eventState) || IsReadOnly(aFrame);
|
||||
return Some(WidgetInfo::TextBox(TextBoxParams{isDisabled, isFocused}));
|
||||
bool borderless =
|
||||
(aWidgetType == StyleAppearance::MenulistTextfield && !isFocused);
|
||||
return Some(WidgetInfo::TextBox(TextBoxParams{isDisabled, isFocused,
|
||||
borderless}));
|
||||
}
|
||||
|
||||
case StyleAppearance::Searchfield:
|
||||
|
@ -4064,9 +4071,6 @@ nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext,
|
|||
break;
|
||||
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
result = DirectionAwareMargin(kAquaComboboxBorder, aFrame);
|
||||
break;
|
||||
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
{
|
||||
|
@ -4330,6 +4334,7 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsPresContext* aPresContext,
|
|||
break;
|
||||
}
|
||||
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
case StyleAppearance::TextfieldMultiline:
|
||||
|
@ -4645,7 +4650,6 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a
|
|||
case StyleAppearance::MenulistButton:
|
||||
case StyleAppearance::MozMenulistButton:
|
||||
case StyleAppearance::MenulistText:
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
if (aFrame && aFrame->GetWritingMode().IsVertical()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4709,6 +4713,7 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a
|
|||
case StyleAppearance::Treeheadersortarrow:
|
||||
case StyleAppearance::Treeitem:
|
||||
case StyleAppearance::Treeline:
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::MozMacSourceList:
|
||||
case StyleAppearance::MozMacSourceListSelection:
|
||||
case StyleAppearance::MozMacActiveSourceListSelection:
|
||||
|
@ -4803,7 +4808,6 @@ nsNativeThemeCocoa::ThemeDrawsFocusForWidget(WidgetType aWidgetType)
|
|||
}
|
||||
|
||||
if (aWidgetType == StyleAppearance::Menulist ||
|
||||
aWidgetType == StyleAppearance::MenulistTextfield ||
|
||||
aWidgetType == StyleAppearance::Button ||
|
||||
aWidgetType == StyleAppearance::MozMacHelpButton ||
|
||||
aWidgetType == StyleAppearance::MozMacDisclosureButtonOpen ||
|
||||
|
@ -4843,6 +4847,7 @@ nsNativeThemeCocoa::WidgetAppearanceDependsOnWindowFocus(WidgetType aWidgetType)
|
|||
case StyleAppearance::SpinnerDownbutton:
|
||||
case StyleAppearance::Separator:
|
||||
case StyleAppearance::Toolbox:
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
case StyleAppearance::Treeview:
|
||||
|
|
|
@ -778,6 +778,9 @@ CreateHeaderBar()
|
|||
static GtkWidget*
|
||||
CreateWidget(WidgetNodeType aWidgetType)
|
||||
{
|
||||
MOZ_ASSERT(aWidgetType != MOZ_GTK_DROPDOWN_ENTRY,
|
||||
"Callers should be passing MOZ_GTK_ENTRY");
|
||||
|
||||
switch (aWidgetType) {
|
||||
case MOZ_GTK_WINDOW:
|
||||
return CreateWindowWidget();
|
||||
|
@ -1509,6 +1512,10 @@ GtkStyleContext*
|
|||
GetStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection,
|
||||
GtkStateFlags aStateFlags, StyleFlags aFlags)
|
||||
{
|
||||
if (aNodeType == MOZ_GTK_DROPDOWN_ENTRY) {
|
||||
aNodeType = MOZ_GTK_ENTRY;
|
||||
}
|
||||
|
||||
GtkStyleContext* style;
|
||||
if (gtk_check_version(3, 20, 0) != nullptr) {
|
||||
style = GetWidgetStyleInternal(aNodeType);
|
||||
|
|
|
@ -1247,7 +1247,8 @@ moz_gtk_vpaned_paint(cairo_t *cr, GdkRectangle* rect,
|
|||
static gint
|
||||
moz_gtk_entry_paint(cairo_t *cr, GdkRectangle* rect,
|
||||
GtkWidgetState* state,
|
||||
GtkStyleContext* style)
|
||||
GtkStyleContext* style,
|
||||
WidgetNodeType widget)
|
||||
{
|
||||
gint x = rect->x, y = rect->y, width = rect->width, height = rect->height;
|
||||
int draw_focus_outline_only = state->depressed; // StyleAppearance::FocusOutline
|
||||
|
@ -1265,7 +1266,11 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRectangle* rect,
|
|||
} else {
|
||||
gtk_render_background(style, cr, x, y, width, height);
|
||||
}
|
||||
gtk_render_frame(style, cr, x, y, width, height);
|
||||
|
||||
// Paint the border, except for 'menulist-textfield' that isn't focused:
|
||||
if (widget != MOZ_GTK_DROPDOWN_ENTRY || state->focused) {
|
||||
gtk_render_frame(style, cr, x, y, width, height);
|
||||
}
|
||||
|
||||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
|
@ -2415,8 +2420,9 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top,
|
|||
return MOZ_GTK_SUCCESS;
|
||||
}
|
||||
case MOZ_GTK_ENTRY:
|
||||
case MOZ_GTK_DROPDOWN_ENTRY:
|
||||
{
|
||||
style = GetStyleContext(MOZ_GTK_ENTRY);
|
||||
style = GetStyleContext(widget);
|
||||
|
||||
// XXX: Subtract 1 pixel from the padding to account for the default
|
||||
// padding in forms.css. See bug 1187385.
|
||||
|
@ -2449,9 +2455,6 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top,
|
|||
case MOZ_GTK_TREE_HEADER_SORTARROW:
|
||||
w = GetWidget(MOZ_GTK_TREE_HEADER_SORTARROW);
|
||||
break;
|
||||
case MOZ_GTK_DROPDOWN_ENTRY:
|
||||
w = GetWidget(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA);
|
||||
break;
|
||||
case MOZ_GTK_DROPDOWN_ARROW:
|
||||
w = GetWidget(MOZ_GTK_COMBOBOX_ENTRY_BUTTON);
|
||||
break;
|
||||
|
@ -3307,7 +3310,7 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr,
|
|||
GtkStyleContext* style =
|
||||
GetStyleContext(MOZ_GTK_SPINBUTTON_ENTRY, direction,
|
||||
GetStateFlagsFromGtkWidgetState(state));
|
||||
gint ret = moz_gtk_entry_paint(cr, rect, state, style);
|
||||
gint ret = moz_gtk_entry_paint(cr, rect, state, style, widget);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
@ -3334,11 +3337,12 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr,
|
|||
(GtkExpanderStyle) flags, direction);
|
||||
break;
|
||||
case MOZ_GTK_ENTRY:
|
||||
case MOZ_GTK_DROPDOWN_ENTRY:
|
||||
{
|
||||
GtkStyleContext* style =
|
||||
GetStyleContext(MOZ_GTK_ENTRY, direction,
|
||||
GetStyleContext(widget, direction,
|
||||
GetStateFlagsFromGtkWidgetState(state));
|
||||
gint ret = moz_gtk_entry_paint(cr, rect, state, style);
|
||||
gint ret = moz_gtk_entry_paint(cr, rect, state, style, widget);
|
||||
return ret;
|
||||
}
|
||||
case MOZ_GTK_TEXT_VIEW:
|
||||
|
@ -3351,15 +3355,6 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr,
|
|||
return moz_gtk_combo_box_entry_button_paint(cr, rect,
|
||||
state, flags, direction);
|
||||
break;
|
||||
case MOZ_GTK_DROPDOWN_ENTRY:
|
||||
{
|
||||
GtkStyleContext* style =
|
||||
GetStyleContext(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA, direction,
|
||||
GetStateFlagsFromGtkWidgetState(state));
|
||||
gint ret = moz_gtk_entry_paint(cr, rect, state, style);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case MOZ_GTK_CHECKBUTTON_CONTAINER:
|
||||
case MOZ_GTK_RADIOBUTTON_CONTAINER:
|
||||
return moz_gtk_container_paint(cr, rect, state, widget, direction);
|
||||
|
|
|
@ -1741,6 +1741,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
|
|||
}
|
||||
break;
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
{
|
||||
|
@ -1927,7 +1928,6 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
|
|||
// Combobox dropdowns don't support native theming in vertical mode.
|
||||
case StyleAppearance::Menulist:
|
||||
case StyleAppearance::MenulistText:
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
if (aFrame && aFrame->GetWritingMode().IsVertical()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1989,6 +1989,7 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
|
|||
case StyleAppearance::ScrollbartrackVertical:
|
||||
case StyleAppearance::ScrollbarthumbHorizontal:
|
||||
case StyleAppearance::ScrollbarthumbVertical:
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
case StyleAppearance::TextfieldMultiline:
|
||||
|
|
|
@ -45,6 +45,7 @@ HeadlessThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
|
|||
result.left = 7;
|
||||
break;
|
||||
case StyleAppearance::FocusOutline:
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
result.top = 5;
|
||||
|
@ -101,12 +102,6 @@ HeadlessThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
|
|||
result.bottom = 1;
|
||||
result.left = 0;
|
||||
break;
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
result.top = 1;
|
||||
result.right = 0;
|
||||
result.bottom = 1;
|
||||
result.left = 1;
|
||||
break;
|
||||
case StyleAppearance::Menuitem:
|
||||
case StyleAppearance::Checkmenuitem:
|
||||
case StyleAppearance::Radiomenuitem:
|
||||
|
@ -251,6 +246,7 @@ HeadlessThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
|
|||
aResult->width = 14;
|
||||
aResult->height = 26;
|
||||
break;
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
aResult->width = 0;
|
||||
|
|
|
@ -105,7 +105,8 @@ nsNativeTheme::GetContentState(nsIFrame* aFrame, StyleAppearance aWidgetType)
|
|||
// focus something in the window.
|
||||
#if defined(XP_MACOSX)
|
||||
// Mac always draws focus rings for textboxes and lists.
|
||||
if (aWidgetType == StyleAppearance::NumberInput ||
|
||||
if (aWidgetType == StyleAppearance::MenulistTextfield ||
|
||||
aWidgetType == StyleAppearance::NumberInput ||
|
||||
aWidgetType == StyleAppearance::Textfield ||
|
||||
aWidgetType == StyleAppearance::TextfieldMultiline ||
|
||||
aWidgetType == StyleAppearance::Searchfield ||
|
||||
|
@ -347,6 +348,7 @@ nsNativeTheme::IsWidgetStyled(nsPresContext* aPresContext, nsIFrame* aFrame,
|
|||
|
||||
return (aWidgetType == StyleAppearance::NumberInput ||
|
||||
aWidgetType == StyleAppearance::Button ||
|
||||
aWidgetType == StyleAppearance::MenulistTextfield ||
|
||||
aWidgetType == StyleAppearance::Textfield ||
|
||||
aWidgetType == StyleAppearance::TextfieldMultiline ||
|
||||
aWidgetType == StyleAppearance::Listbox ||
|
||||
|
|
|
@ -730,6 +730,7 @@ mozilla::Maybe<nsUXThemeClass> nsNativeThemeWin::GetThemeClass(WidgetType aWidge
|
|||
case StyleAppearance::Checkbox:
|
||||
case StyleAppearance::Groupbox:
|
||||
return Some(eUXButton);
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
case StyleAppearance::TextfieldMultiline:
|
||||
|
@ -951,6 +952,7 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, WidgetType aWidgetType,
|
|||
// same as GBS_NORMAL don't bother supporting GBS_DISABLED.
|
||||
return NS_OK;
|
||||
}
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
case StyleAppearance::TextfieldMultiline: {
|
||||
|
@ -1869,11 +1871,16 @@ RENDER_AGAIN:
|
|||
DrawThemeBGRTLAware(theme, hdc, part, state,
|
||||
&widgetRect, &clipRect, IsFrameRTL(aFrame));
|
||||
}
|
||||
else if (aWidgetType == StyleAppearance::NumberInput ||
|
||||
else if (aWidgetType == StyleAppearance::MenulistTextfield ||
|
||||
aWidgetType == StyleAppearance::NumberInput ||
|
||||
aWidgetType == StyleAppearance::Textfield ||
|
||||
aWidgetType == StyleAppearance::TextfieldMultiline) {
|
||||
DrawThemeBackground(theme, hdc, part, state, &widgetRect, &clipRect);
|
||||
if (state == TFS_EDITBORDER_DISABLED) {
|
||||
// Paint the border, except for 'menulist-textfield' that isn't focused:
|
||||
if (aWidgetType != StyleAppearance::MenulistTextfield ||
|
||||
state == TFS_EDITBORDER_FOCUSED) {
|
||||
DrawThemeBackground(theme, hdc, part, state, &widgetRect, &clipRect);
|
||||
}
|
||||
if (state == TFS_EDITBORDER_DISABLED) {
|
||||
InflateRect(&widgetRect, -1, -1);
|
||||
::FillRect(hdc, &widgetRect, reinterpret_cast<HBRUSH>(COLOR_BTNFACE+1));
|
||||
}
|
||||
|
@ -2099,7 +2106,8 @@ nsNativeThemeWin::GetWidgetBorder(nsDeviceContext* aContext,
|
|||
result.left = 0;
|
||||
}
|
||||
|
||||
if (aFrame && (aWidgetType == StyleAppearance::NumberInput ||
|
||||
if (aFrame && (aWidgetType == StyleAppearance::MenulistTextfield ||
|
||||
aWidgetType == StyleAppearance::NumberInput ||
|
||||
aWidgetType == StyleAppearance::Textfield ||
|
||||
aWidgetType == StyleAppearance::TextfieldMultiline)) {
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
|
@ -2199,7 +2207,8 @@ nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext,
|
|||
return ok;
|
||||
}
|
||||
|
||||
if (aWidgetType == StyleAppearance::NumberInput ||
|
||||
if (aWidgetType == StyleAppearance::MenulistTextfield ||
|
||||
aWidgetType == StyleAppearance::NumberInput ||
|
||||
aWidgetType == StyleAppearance::Textfield ||
|
||||
aWidgetType == StyleAppearance::TextfieldMultiline ||
|
||||
aWidgetType == StyleAppearance::Menulist)
|
||||
|
@ -2216,7 +2225,8 @@ nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext,
|
|||
* Instead, we add 2px padding for the contents and fix this. (Used to be 1px
|
||||
* added, see bug 430212)
|
||||
*/
|
||||
if (aWidgetType == StyleAppearance::NumberInput ||
|
||||
if (aWidgetType == StyleAppearance::MenulistTextfield ||
|
||||
aWidgetType == StyleAppearance::NumberInput ||
|
||||
aWidgetType == StyleAppearance::Textfield ||
|
||||
aWidgetType == StyleAppearance::TextfieldMultiline) {
|
||||
aResult->top = aResult->bottom = 2;
|
||||
|
@ -2358,6 +2368,7 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
|
|||
|
||||
switch (aWidgetType) {
|
||||
case StyleAppearance::Groupbox:
|
||||
case StyleAppearance::MenulistTextfield:
|
||||
case StyleAppearance::NumberInput:
|
||||
case StyleAppearance::Textfield:
|
||||
case StyleAppearance::Toolbox:
|
||||
|
@ -3812,8 +3823,12 @@ RENDER_AGAIN:
|
|||
case StyleAppearance::Listbox:
|
||||
case StyleAppearance::Menulist:
|
||||
case StyleAppearance::MenulistTextfield: {
|
||||
// Draw inset edge
|
||||
::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
|
||||
// Paint the border, except for 'menulist-textfield' that isn't focused:
|
||||
if (aWidgetType != StyleAppearance::MenulistTextfield || focused) {
|
||||
// Draw inset edge
|
||||
::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
|
||||
}
|
||||
|
||||
EventStates eventState = GetContentState(aFrame, aWidgetType);
|
||||
|
||||
// Fill in background
|
||||
|
|
Загрузка…
Ссылка в новой задаче