From b9fb06417a515edc14195906032cdf69cfeb9a7e Mon Sep 17 00:00:00 2001 From: "cbiesinger%web.de" Date: Sun, 18 Jan 2004 20:49:45 +0000 Subject: [PATCH] Bug 227733 Live resize is possible for BeOS widget implementation. patch by sergei_d@fi.tartu.ee (Sergei Dolgov), r=biesi, no sr needed (beos only) --- widget/src/beos/nsWindow.cpp | 296 +++++++++++++++-------------------- widget/src/beos/nsWindow.h | 17 +- 2 files changed, 136 insertions(+), 177 deletions(-) diff --git a/widget/src/beos/nsWindow.cpp b/widget/src/beos/nsWindow.cpp index 0cc11d2a09a..2faa94ffb97 100644 --- a/widget/src/beos/nsWindow.cpp +++ b/widget/src/beos/nsWindow.cpp @@ -431,7 +431,7 @@ nsresult nsWindow::StandardWindowCreate(nsIWidget *aParent, window_feel feel = B_NORMAL_WINDOW_FEEL; // Set all windows to use outline resize, since currently, the redraw of the window during resize // is very "choppy" - uint32 flags = B_ASYNCHRONOUS_CONTROLS | B_OUTLINE_RESIZE; + uint32 flags = B_ASYNCHRONOUS_CONTROLS | B_FRAME_EVENTS; #ifdef MOZ_DEBUG_WINDOW_CREATE printf("%s\n", (mWindowType == eWindowType_popup) ? "popup" : @@ -459,8 +459,8 @@ nsresult nsWindow::StandardWindowCreate(nsIWidget *aParent, case eWindowType_toplevel: case eWindowType_invisible: { - // This was never documented, so I'm not sure why we do it, yet - winrect.OffsetBy( 10, 30 ); + // This was never documented, so I'm not sure why we did it + //winrect.OffsetBy( 10, 30 ); #ifdef MOZ_DEBUG_WINDOW_CREATE printf("\tBorder Style : "); @@ -598,7 +598,7 @@ NS_METHOD nsWindow::Create(nsNativeWidget aParent, BView *nsWindow::CreateBeOSView() { - return new nsViewBeOS(this, BRect(0, 0, 0, 0), "", 0, B_WILL_DRAW); + return new nsViewBeOS(this, BRect(0,0,0,0), "", 0, B_WILL_DRAW | B_FRAME_EVENTS); } //------------------------------------------------------------------------- @@ -1004,18 +1004,24 @@ nsresult nsWindow::Move(PRInt32 aX, PRInt32 aY) havewindow = true; if(mView->Parent() || ! havewindow) + { mView->MoveTo(aX, aY); + } else - mView->Window()->MoveTo(aX, aY); - + { + mView->Window()->MoveTo(aX, aY); + } if(mustunlock) mView->UnlockLooper(); } + else + OnMove(aX,aY); return NS_OK; } + //------------------------------------------------------------------------- // // Resize this component @@ -1044,20 +1050,18 @@ NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) if(mView->Parent() || ! havewindow) mView->ResizeTo(aWidth-1, GetHeight(aHeight)-1); else - ((nsWindowBeOS *)mView->Window())->ResizeToWithoutEvent(aWidth-1, GetHeight(aHeight)-1); + ((nsWindowBeOS *)mView->Window())->ResizeTo(aWidth-1, GetHeight(aHeight)-1); - if (aRepaint) - mView->Invalidate(); + //This caused senseless blinking on page reload. Do we need it? + //if (aRepaint && mustunlock) + // mView->Invalidate(); if(mustunlock) mView->UnlockLooper(); - - //inform the xp layer of the change in size - OnResize(mBounds); - } else { + //inform the xp layer of the change in size OnResize(mBounds); } @@ -1076,7 +1080,6 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRBool aRepaint) { Move(aX,aY); - // Resize will unlock the looper when the above leaves it locked, so it must go last Resize(aWidth,aHeight,aRepaint); return NS_OK; } @@ -1745,19 +1748,25 @@ bool nsWindow::CallMethod(MethodInfo *info) if (!mEnabled) return false; DispatchFocus(NS_GOTFOCUS); - if(mJustGotActivate) - { - mJustGotActivate = PR_FALSE; - DispatchFocus(NS_ACTIVATE); - } + + //Old hack borrowed from MS Windows code. Will test how good it works without hack. + //Same for all further occurencies of mJustGot variables + + //if(mJustGotActivate) + //if(mJustGotActivate) + //{ + // mJustGotActivate = PR_FALSE; + // DispatchFocus(NS_ACTIVATE); + //} break; case nsWindow::KILL_FOCUS: NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod"); - if(mJustGotDeactivate) - { - DispatchFocus(NS_DEACTIVATE); - } + //This was old hack borrowed from MS Windows code. + //if(mJustGotDeactivate) + //{ + // DispatchFocus(NS_DEACTIVATE); + //} DispatchFocus(NS_LOSTFOCUS); break; @@ -1856,19 +1865,12 @@ bool nsWindow::CallMethod(MethodInfo *info) nsViewBeOS *bv = dynamic_cast(mView); if(bv && bv->GetPaintRegion(®) && reg.Frame().IsValid()) { - int32 rects = reg.CountRects(); - for(int32 i = 0; i < rects; ++i) - { - nsRect r; - BRect br = reg.RectAt(i); - r.x = (nscoord)br.left; - r.y = (nscoord)br.top; - r.width = (nscoord)br.IntegerWidth() + 1; - r.height = (nscoord)br.IntegerHeight() + 1; - OnPaint(r); - } + //TODO: provide region for OnPaint(). Not only rect. + BRect br = reg.Frame(); + nsRect r(nscoord(br.left), nscoord(br.top), + nscoord(br.IntegerWidth() + 1), nscoord(br.IntegerHeight() + 1)); + OnPaint(r); } - } break; @@ -1903,8 +1905,10 @@ bool nsWindow::CallMethod(MethodInfo *info) break; case nsWindow::ONACTIVATE: - NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod"); - if (!mEnabled || eWindowType_popup == mWindowType) + NS_ASSERTION(info->nArgs == 2, "Wrong number of arguments to CallMethod"); + if (!mEnabled || eWindowType_popup == mWindowType || 0 == mView->Window()) + return false; + if((BWindow *)info->args[1] != mView->Window()) return false; if (*mEventCallback || eWindowType_child == mWindowType) { @@ -1915,16 +1919,17 @@ bool nsWindow::CallMethod(MethodInfo *info) eWindowType_toplevel == mWindowType) DealWithPopups(ONACTIVATE,nsPoint(0,0)); DispatchFocus(NS_DEACTIVATE); - mJustGotDeactivate = PR_TRUE; + //mJustGotDeactivate = PR_TRUE; } else { DispatchFocus(NS_ACTIVATE); - mJustGotActivate = PR_TRUE; + //mJustGotActivate = PR_TRUE; if (mView && mView->Window()) gLastActiveWindow = mView->Window(); - if(mWindowType == eWindowType_dialog) - SetFocus(PR_TRUE); + //Old hack. It seems no need for this at moment, but who knows. + //if(mWindowType == eWindowType_dialog) + // SetFocus(PR_TRUE); } } break; @@ -2589,19 +2594,14 @@ nsIWidget *nsIWidgetStore::GetMozillaWidget(void) nsWindowBeOS::nsWindowBeOS( nsIWidget *aWidgetWindow, BRect aFrame, const char *aName, window_look aLook, window_feel aFeel, int32 aFlags, int32 aWorkspace ) : BWindow( aFrame, aName, aLook, aFeel, aFlags, aWorkspace ), - nsIWidgetStore( aWidgetWindow ), - resizeRunner(NULL) + nsIWidgetStore( aWidgetWindow ) { - //note that the window will be resized (and FrameResized() - //will be called) if aFrame isn't a valid window size - lastWidth=aFrame.Width(); - lastHeight=aFrame.Height(); + //placeholder for initialization } nsWindowBeOS::~nsWindowBeOS() { - //clean up - delete resizeRunner; + //placeholder for clean up } bool nsWindowBeOS::QuitRequested( void ) @@ -2613,7 +2613,7 @@ bool nsWindowBeOS::QuitRequested( void ) { MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, nsWindow::CLOSEWINDOW))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); NS_RELEASE(t); } return false; @@ -2621,25 +2621,8 @@ bool nsWindowBeOS::QuitRequested( void ) void nsWindowBeOS::MessageReceived(BMessage *msg) { - switch (msg->what) - { - case 'RESZ': - { - // this is the message generated by the resizeRunner - it - // has now served its purpose - delete resizeRunner; - resizeRunner=NULL; - - - //kick off the xp resizing stuff - DoFrameResized(); - } - break; - - default : - BWindow::MessageReceived(msg); - break; - } + //Placeholder for possible improvements, e.g. DND and quitting + BWindow::MessageReceived(msg); } // This function calls KeyDown() for Alt+whatever instead of app_server @@ -2656,117 +2639,45 @@ void nsWindowBeOS::DispatchMessage(BMessage *msg, BHandler *handler) BWindow::DispatchMessage(msg, handler); } +//This method serves single purpose here - allows Mozilla to save current window position, +//and restore position on new start. void nsWindowBeOS::FrameMoved(BPoint origin) { + //determine if the window position actually changed - if (origin.x == lastpoint.x && origin.x == lastpoint.x) { + if (origin.x == lastWindowPoint.x && origin.x == lastWindowPoint.x) + { //it didn't - don't bother return; } - lastpoint.x = origin.x; - lastpoint.y = origin.y; + lastWindowPoint = origin; nsWindow *w = (nsWindow *)GetMozillaWidget(); nsToolkit *t; - if(w && (t = w->GetToolkit()) != 0) { + if(w && (t = w->GetToolkit()) != 0) + { uint32 args[2]; args[0] = (uint32)origin.x; args[1] = (uint32)origin.y; MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, nsWindow::ONMOVE, 2, args))) - t->CallMethodAsync(info); - NS_RELEASE(t); - } -} - -void nsWindowBeOS::FrameResized(float width, float height) -{ - //determine if the window size actually changed - if (width==lastWidth && height==lastHeight) { - //it didn't - don't bother - return; - } - - //remember new size - lastWidth=width; - lastHeight=height; - - // TODO: This should be removed/commented out, since we are using an outline view - - // while the user resizes the window, a large number of - // B_WINDOW_RESIZED events are generated. because - // the layout/drawing code invoked during a resize isn't - // terribly fast, these events can "back up" (new ones are - // delivered before old ones are processed), causing mozilla - // to act sluggish (even on a fast machine, the re-layouts - // and redraws performed in response to the B_WINDOW_RESIZED - // events usually don't finish until long after the user is - // done resizing the window), and possibly even overflow the - // window's event queue. to stop this from happening, we will - // consolidate all B_WINDOW_RESIZED messages generated within - // 1/10 seconds of each other into a single resize event (i.e., - // the views won't be resized/redrawn until the user finishes - // resizing the window) - const bigtime_t timerLen=100000LL; - if (resizeRunner==NULL) { - //this is the first B_WINDOW_RESIZE event in this interval - - //start the timer - BMessage msg('RESZ'); - resizeRunner=new BMessageRunner(BMessenger(this), &msg, timerLen, 1); - - } else { - //this is not the first B_WINDOW_RESIZE event in the - //current interval - reset the timer - resizeRunner->SetInterval(timerLen); - } -} - -void nsWindowBeOS::ResizeToWithoutEvent(float width, float height) -{ - //this method is just a wrapper for BWindow::ResizeTo(), except - //it will attempt to keep the B_FRAME_RESIZED event resulting - //from the ResizeTo() call from being passed to the xp layout - //engine (OnResize() will already have been called for this - //resize by nsWindow::Resize() above) - lastWidth=width; - lastHeight=height; - ResizeTo(width, height); -} - -void nsWindowBeOS::DoFrameResized() -{ - //let the layout engine know the window has changed size, - //so it can resize the window's views - nsWindow *w = (nsWindow *)GetMozillaWidget(); - nsToolkit *t; - if(w && (t = w->GetToolkit()) != 0) - { - //the window's new size needs to be passed to OnResize() - - //note that the values passed to FrameResized() are the - //dimensions as reported by Bounds().Width() and - //Bounds().Height(), which are one pixel smaller than the - //window's true size - uint32 args[2]; - args[0]=(uint32)lastWidth+1; - args[1]=(uint32)lastHeight+1; - MethodInfo *info = nsnull; - if(nsnull != (info = new MethodInfo(w, w, nsWindow::ONRESIZE, 2, args))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); NS_RELEASE(t); } } void nsWindowBeOS::WindowActivated(bool active) { -// Calls method ONACTIVATE to handle mJustGotActivated | mJustGotDeactivated +// Calls method ONACTIVATE to dispatch focus ACTIVATE messages nsWindow *w = (nsWindow *)GetMozillaWidget(); nsToolkit *t; if(w && (t = w->GetToolkit()) != 0) { - uint32 args[1]; + uint32 args[2]; args[0] = (uint32)active; + args[1] = (uint32)this; MethodInfo *info = nsnull; - if(nsnull != (info = new MethodInfo(w, w, nsWindow::ONACTIVATE, 1, args))) - t->CallMethodAsync(info); + if(nsnull != (info = new MethodInfo(w, w, nsWindow::ONACTIVATE, 2, args))) + t->CallMethodAsync(info); NS_RELEASE(t); } } @@ -2784,7 +2695,7 @@ void nsWindowBeOS::WorkspacesChanged(uint32 oldworkspace, uint32 newworkspace) args[1] = oldworkspace; MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, nsWindow::ONWORKSPACE, 2, args))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); NS_RELEASE(t); } } @@ -2800,6 +2711,8 @@ nsViewBeOS::nsViewBeOS(nsIWidget *aWidgetWindow, BRect aFrame, const char *aName void nsViewBeOS::AttachedToWindow() { + lastViewWidth = Bounds().Width(); + lastViewHeight = Bounds().Height(); nsWindow *w = (nsWindow *)GetMozillaWidget(); SetHighColor(255, 255, 255); FillRect(Bounds()); @@ -2817,11 +2730,13 @@ void nsViewBeOS::DrawAfterChildren(BRect updateRect) { //Stub for B_DRAW_ON_CHILDREN flags //If some problem appears, line below may be uncommented. -// DoDraw(updateRect); + + //DoDraw(updateRect); } void nsViewBeOS::DoDraw(BRect updateRect) { + //Collecting update rects here in paintregion paintregion.Include(updateRect); nsWindow *w = (nsWindow *)GetMozillaWidget(); nsToolkit *t; @@ -2835,6 +2750,7 @@ void nsViewBeOS::DoDraw(BRect updateRect) } } +// Method to get update rects for asynchronous drawing. bool nsViewBeOS::GetPaintRegion(BRegion *r) { if(paintregion.CountRects() == 0) @@ -2868,7 +2784,7 @@ void nsViewBeOS::MouseDown(BPoint point) args[4] = modifiers(); MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, nsWindow::BTNCLICK, 5, args))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); } NS_RELEASE(t); } @@ -2890,20 +2806,20 @@ void nsViewBeOS::MouseMoved(BPoint point, uint32 transit, const BMessage *msg) args[0] = NS_MOUSE_ENTER; MethodInfo *enterInfo = nsnull; if(nsnull != (enterInfo = new MethodInfo(w, w, nsWindow::ONMOUSE, 4, args))) - t->CallMethodAsync(enterInfo); + t->CallMethodAsync(enterInfo); } args[0] = NS_MOUSE_MOVE; MethodInfo *moveInfo = nsnull; if(nsnull != (moveInfo = new MethodInfo(w, w, nsWindow::ONMOUSE, 4, args))) - t->CallMethodAsync(moveInfo); + t->CallMethodAsync(moveInfo); if(transit == B_EXITED_VIEW) { args[0] = NS_MOUSE_EXIT; MethodInfo *exitInfo = nsnull; if(nsnull != (exitInfo = new MethodInfo(w, w, nsWindow::ONMOUSE, 4, args))) - t->CallMethodAsync(exitInfo); + t->CallMethodAsync(exitInfo); } NS_RELEASE(t); } @@ -2928,7 +2844,7 @@ void nsViewBeOS::MouseUp(BPoint point) args[4] = modifiers(); MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, nsWindow::BTNCLICK, 5, args))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); } NS_RELEASE(t); } @@ -2971,7 +2887,7 @@ void nsViewBeOS::MessageReceived(BMessage *msg) args[0] = (uint32)-3; MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, nsWindow::ONWHEEL, 1, args))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); NS_RELEASE(t); } } @@ -3011,7 +2927,7 @@ void nsViewBeOS::KeyDown(const char *bytes, int32 numBytes) args[5] = rawcode; MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, nsWindow::ONKEY, 6, args))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); NS_RELEASE(t); } } @@ -3043,7 +2959,7 @@ void nsViewBeOS::KeyUp(const char *bytes, int32 numBytes) args[5] = rawcode; MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, nsWindow::ONKEY, 6, args))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); NS_RELEASE(t); } } @@ -3061,12 +2977,58 @@ void nsViewBeOS::MakeFocus(bool focused) args[0]=(uint32)Window(); MethodInfo *info = nsnull; if(nsnull != (info = new MethodInfo(w, w, (focused)? nsWindow::GOT_FOCUS : nsWindow::KILL_FOCUS,1,args))) - t->CallMethodAsync(info); + t->CallMethodAsync(info); NS_RELEASE(t); } } void nsViewBeOS::FrameResized(float width, float height) { - // do nothing + //determine if the window size actually changed + if (width==lastViewWidth && height==lastViewHeight) + { + //it didn't - don't bother + return; + } + //remember new size + lastViewWidth=width; + lastViewHeight=height; + nsWindow *w = (nsWindow *)GetMozillaWidget(); + nsToolkit *t; + if(w && (t = w->GetToolkit()) != 0) + { + //the window's new size needs to be passed to OnResize() - + //note that the values passed to FrameResized() are the + //dimensions as reported by Bounds().Width() and + //Bounds().Height(), which are one pixel smaller than the + //window's true size + uint32 args[2]; + args[0]=(uint32)width+1; + args[1]=(uint32)height+1; + + MethodInfo *info = 0; + if (nsnull != (info = new MethodInfo(w, w, nsWindow::ONRESIZE, 2, args))) + t->CallMethodAsync(info); + NS_RELEASE(t); + } +} +void nsViewBeOS::FrameMoved(BPoint origin) +{ + //determine if the window position actually changed + if (origin.x == lastViewPoint.x && origin.x == lastViewPoint.x) + return; + lastViewPoint.x = origin.x; + lastViewPoint.y = origin.y; + nsWindow *w = (nsWindow *)GetMozillaWidget(); + nsToolkit *t; + if(w && (t = w->GetToolkit()) != 0) + { + uint32 args[2]; + args[0] = (uint32)origin.x; + args[1] = (uint32)origin.y; + MethodInfo *info = 0; + if (nsnull != (info = new MethodInfo(w, w, nsWindow::ONMOVE, 2, args))) + t->CallMethodAsync(info); + NS_RELEASE(t); + } } diff --git a/widget/src/beos/nsWindow.h b/widget/src/beos/nsWindow.h index fa14440d76f..e907d352182 100644 --- a/widget/src/beos/nsWindow.h +++ b/widget/src/beos/nsWindow.h @@ -298,19 +298,11 @@ public: virtual void MessageReceived(BMessage *msg); virtual void DispatchMessage(BMessage *msg, BHandler *handler); virtual void WindowActivated(bool active); - virtual void FrameResized(float width, float height); virtual void FrameMoved(BPoint origin); virtual void WorkspacesChanged(uint32 oldworkspace, uint32 newworkspace); - - void ResizeToWithoutEvent(float width, float height); - private: - void DoFrameResized(); - - float lastWidth, lastHeight; - BPoint lastpoint; - BMessageRunner *resizeRunner; + BPoint lastWindowPoint; }; // @@ -335,14 +327,19 @@ public: uint32 transit, const BMessage *message); virtual void MouseUp(BPoint point); - bool GetPaintRegion(/*nsRect &r*/BRegion *breg); + bool GetPaintRegion(BRegion *breg); void KeyDown(const char *bytes, int32 numBytes); void KeyUp(const char *bytes, int32 numBytes); virtual void MakeFocus(bool focused); virtual void MessageReceived(BMessage *msg); virtual void FrameResized(float width, float height); + virtual void FrameMoved(BPoint origin); + private: void DoDraw(BRect updateRect); + float lastViewWidth; + float lastViewHeight; + BPoint lastViewPoint; }; //