зеркало из https://github.com/mozilla/gecko-dev.git
Bug 501618: Follow up child widget removal on OS/2, p=dragtext@e-vertise, r=pweilbacher
This commit is contained in:
Родитель
829e02dcea
Коммит
9f9e94acf7
|
@ -79,6 +79,9 @@
|
||||||
|
|
||||||
#include "imgIContainer.h"
|
#include "imgIContainer.h"
|
||||||
|
|
||||||
|
#include "nsTHashtable.h"
|
||||||
|
#include "nsHashKeys.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
@ -2064,80 +2067,117 @@ void nsWindow::FreeNativeData(void * data, PRUint32 aDataType)
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Notify a child window of a coming move by sending it a WM_VRNDISABLED
|
// Configure the child widgets used for plugins
|
||||||
// message. Only do that if it's not one of ours like e.g. plugin windows.
|
|
||||||
//
|
//
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
BOOL nsWindow::NotifyForeignChildWindows(HWND aWnd)
|
|
||||||
{
|
|
||||||
HENUM hEnum = WinBeginEnumWindows(aWnd);
|
|
||||||
HWND hwnd;
|
|
||||||
|
|
||||||
while ((hwnd = WinGetNextWindow(hEnum)) != NULLHANDLE) {
|
// This is _supposed_ to set a clipping region for the child windows used
|
||||||
char className[19];
|
// by plugins. However, on OS/2, clipping regions aren't associated with
|
||||||
WinQueryClassName(hwnd, 19, className);
|
// windows, usually aren't persistent, & have no effect on drawing done
|
||||||
if (strcmp(className, WindowClass()) != 0) {
|
// into children of the clipped window (which is where OS/2 plugins paint).
|
||||||
// This window is not one of our windows so notify it (and wait for
|
// As an alternative, this implementation uses the child windows' dimensions
|
||||||
// the call to return so that the plugin has time to react)
|
// as clipping rectangles, adjusting them to match the bounding boxes of the
|
||||||
WinSendMsg(hwnd, WM_VRNDISABLED, MPVOID, MPVOID);
|
// supplied arrays of rectangles. This should suffice in most situations.
|
||||||
} else {
|
|
||||||
// Recurse starting at this Mozilla child window.
|
nsresult
|
||||||
NotifyForeignChildWindows(hwnd);
|
nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
||||||
}
|
{
|
||||||
|
// for each child window
|
||||||
|
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
||||||
|
const Configuration& configuration = aConfigurations[i];
|
||||||
|
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
||||||
|
NS_ASSERTION(w->GetParent() == this,
|
||||||
|
"Configured widget is not a child");
|
||||||
|
|
||||||
|
// create the bounding box
|
||||||
|
const nsTArray<nsIntRect>& rects = configuration.mClipRegion;
|
||||||
|
nsIntRect r;
|
||||||
|
for (PRUint32 i = 0; i < rects.Length(); ++i)
|
||||||
|
r.UnionRect(r, rects[i]);
|
||||||
|
|
||||||
|
// resize the child; mBounds.x/y contain the child's correct origin;
|
||||||
|
// r.x/y are always <= zero - adding them to r.width/height produces
|
||||||
|
// the actual clipped width/height this window should have
|
||||||
|
w->Resize(configuration.mBounds.x, configuration.mBounds.y,
|
||||||
|
r.width + r.x, r.height + r.y, PR_TRUE);
|
||||||
|
|
||||||
|
// some plugins may shrink their window when the Mozilla widget window
|
||||||
|
// shrinks, then fail to reinflate when the widget window reinflates;
|
||||||
|
// this ensures the plugin's window is always at its full size and is
|
||||||
|
// clipped correctly by the widget's bounds
|
||||||
|
HWND hwnd = WinQueryWindow( w->mWnd, QW_TOP);
|
||||||
|
::WinSetWindowPos(hwnd, 0, 0, 0,
|
||||||
|
configuration.mBounds.width, configuration.mBounds.height,
|
||||||
|
SWP_MOVE | SWP_SIZE);
|
||||||
|
|
||||||
|
// show or hide the window, then save the array of rects
|
||||||
|
// for future reference
|
||||||
|
w->Show(!configuration.mClipRegion.IsEmpty());
|
||||||
|
w->StoreWindowClipRegion(configuration.mClipRegion);
|
||||||
}
|
}
|
||||||
return WinEndEnumWindows(hEnum);
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Force a resize of child windows after a scroll to reset hover positions.
|
|
||||||
//
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
void nsWindow::ScrollChildWindows(PRInt32 aX, PRInt32 aY)
|
|
||||||
{
|
|
||||||
nsIWidget *child = GetFirstChild();
|
|
||||||
while (child) {
|
|
||||||
nsIntRect rect;
|
|
||||||
child->GetBounds(rect);
|
|
||||||
child->Resize(rect.x + aX, rect.y + aY, rect.width, rect.height, PR_FALSE);
|
|
||||||
child = child->GetNextSibling();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Scroll the bits of a window
|
// Scroll the bits of a window
|
||||||
//
|
//
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
NS_METHOD nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect)
|
void nsWindow::Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||||
|
const nsTArray<Configuration>& aConfigurations)
|
||||||
{
|
{
|
||||||
RECTL rcl;
|
// Build the set of widgets that are to be moved by the scroll amount.
|
||||||
|
nsTHashtable<nsPtrHashKey<nsWindow> > scrolledWidgets;
|
||||||
if (nsnull != aClipRect)
|
scrolledWidgets.Init();
|
||||||
{
|
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
||||||
rcl.xLeft = aClipRect->x;
|
const Configuration& configuration = aConfigurations[i];
|
||||||
rcl.yBottom = aClipRect->y + aClipRect->height;
|
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
||||||
rcl.xRight = rcl.xLeft + aClipRect->width;
|
NS_ASSERTION(w->GetParent() == this,
|
||||||
rcl.yTop = rcl.yBottom + aClipRect->height;
|
"Configured widget is not a child");
|
||||||
NS2PM(rcl);
|
if (configuration.mBounds.TopLeft() == w->mBounds.TopLeft() + aDelta)
|
||||||
// this rect is inex
|
scrolledWidgets.PutEntry(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIntRect affectedRect;
|
||||||
|
affectedRect.UnionRect(aSource, aSource + aDelta);
|
||||||
|
ULONG flags = SW_INVALIDATERGN;
|
||||||
|
|
||||||
|
// We can use SW_SCROLLCHILDREN if all the windows that intersect
|
||||||
|
// the affected area are moving by the scroll amount. Check if
|
||||||
|
// any of our children would be affected by SW_SCROLLCHILDREN but
|
||||||
|
// are not supposed to scroll.
|
||||||
|
for (nsWindow* w = static_cast<nsWindow*>(GetFirstChild()); w;
|
||||||
|
w = static_cast<nsWindow*>(w->GetNextSibling())) {
|
||||||
|
if (w->mBounds.Intersects(affectedRect)) {
|
||||||
|
flags |= SW_SCROLLCHILDREN;
|
||||||
|
if (!scrolledWidgets.GetEntry(w)) {
|
||||||
|
flags &= ~SW_SCROLLCHILDREN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RECTL clip;
|
||||||
|
clip.xLeft = affectedRect.x;
|
||||||
|
clip.xRight = affectedRect.x + affectedRect.width;
|
||||||
|
clip.yTop = mBounds.height - affectedRect.y;
|
||||||
|
clip.yBottom = clip.yTop - affectedRect.height;
|
||||||
|
|
||||||
// this prevents screen corruption while scrolling during a
|
// this prevents screen corruption while scrolling during a
|
||||||
// Moz-originated drag - during a native drag, the screen
|
// Moz-originated drag - the hps isn't actually used but
|
||||||
// isn't updated until the drag ends. so there's no corruption
|
// fetching it unlocks the screen so it can be updated
|
||||||
HPS hps = 0;
|
HPS hps = 0;
|
||||||
CheckDragStatus(ACTION_SCROLL, &hps);
|
CheckDragStatus(ACTION_SCROLL, &hps);
|
||||||
|
::WinScrollWindow(mWnd, aDelta.x, -aDelta.y, &clip, &clip, NULL, NULL, flags);
|
||||||
|
|
||||||
NotifyForeignChildWindows(mWnd);
|
// Now make sure all children actually get positioned, sized, and clipped
|
||||||
WinScrollWindow(mWnd, aDx, -aDy, aClipRect ? &rcl : 0, 0, 0,
|
// correctly. If SW_SCROLLCHILDREN was in effect, they may already be.
|
||||||
0, SW_SCROLLCHILDREN | SW_INVALIDATERGN);
|
ConfigureChildren(aConfigurations);
|
||||||
ScrollChildWindows(aDx, aDy);
|
|
||||||
Update();
|
Update();
|
||||||
|
|
||||||
if (hps)
|
if (hps)
|
||||||
ReleaseIfDragHPS(hps);
|
ReleaseIfDragHPS(hps);
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
|
|
@ -172,7 +172,9 @@ class nsWindow : public nsBaseWidget,
|
||||||
NS_IMETHOD Invalidate( PRBool aIsSynchronous);
|
NS_IMETHOD Invalidate( PRBool aIsSynchronous);
|
||||||
NS_IMETHOD Invalidate( const nsIntRect & aRect, PRBool aIsSynchronous);
|
NS_IMETHOD Invalidate( const nsIntRect & aRect, PRBool aIsSynchronous);
|
||||||
NS_IMETHOD Update();
|
NS_IMETHOD Update();
|
||||||
NS_IMETHOD Scroll( PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect);
|
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
|
||||||
|
virtual void Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||||
|
const nsTArray<Configuration>& aConfigurations);
|
||||||
NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState);
|
NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState);
|
||||||
|
|
||||||
// Get a HWND or a HPS.
|
// Get a HWND or a HPS.
|
||||||
|
@ -314,9 +316,6 @@ protected:
|
||||||
HBITMAP CreateTransparencyMask(gfxASurface::gfxImageFormat format,
|
HBITMAP CreateTransparencyMask(gfxASurface::gfxImageFormat format,
|
||||||
PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight);
|
PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight);
|
||||||
|
|
||||||
BOOL NotifyForeignChildWindows(HWND aWnd);
|
|
||||||
void ScrollChildWindows(PRInt32 aX, PRInt32 aY);
|
|
||||||
|
|
||||||
// Enumeration of the methods which are accessible on the PM thread
|
// Enumeration of the methods which are accessible on the PM thread
|
||||||
enum {
|
enum {
|
||||||
CREATE,
|
CREATE,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче