2005-06-17 23:10:15 +04:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2001-2005, Haiku, Inc.
|
|
|
|
* Distributed under the terms of the MIT license.
|
|
|
|
*
|
|
|
|
* Author: DarkWyrm <bpmagic@columbus.rr.com>
|
2005-11-07 22:01:12 +03:00
|
|
|
* Adi Oanca <adioanca@gmail.com>
|
2005-06-17 23:10:15 +04:00
|
|
|
* Stephan Aßmus <superstippi@gmx.de>
|
2005-12-02 18:06:14 +03:00
|
|
|
* Axel Dörfler, axeld@pinc-software.de
|
2005-06-17 23:10:15 +04:00
|
|
|
*/
|
2005-06-24 02:43:11 +04:00
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
#include "WindowLayer.h"
|
2005-06-03 23:50:30 +04:00
|
|
|
|
|
|
|
#include "DebugInfoManager.h"
|
2003-02-14 04:53:53 +03:00
|
|
|
#include "Decorator.h"
|
2005-06-17 23:10:15 +04:00
|
|
|
#include "DecorManager.h"
|
2003-02-14 04:53:53 +03:00
|
|
|
#include "Desktop.h"
|
2005-12-08 15:41:19 +03:00
|
|
|
#include "DrawingEngine.h"
|
2005-06-03 23:50:30 +04:00
|
|
|
#include "MessagePrivate.h"
|
|
|
|
#include "PortLink.h"
|
2005-11-03 20:03:36 +03:00
|
|
|
#include "ServerApp.h"
|
2005-06-03 23:50:30 +04:00
|
|
|
#include "ServerWindow.h"
|
2004-01-13 03:38:42 +03:00
|
|
|
#include "Workspace.h"
|
2005-12-09 20:25:32 +03:00
|
|
|
#include "WorkspacesLayer.h"
|
2003-02-14 04:53:53 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
#include <WindowPrivate.h>
|
|
|
|
|
|
|
|
#include <Debug.h>
|
|
|
|
#include <DirectWindow.h>
|
2005-12-09 18:40:30 +03:00
|
|
|
#include <View.h>
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
#include <new>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2005-11-09 02:26:47 +03:00
|
|
|
|
2005-11-24 20:45:26 +03:00
|
|
|
// Toggle debug output
|
2005-12-08 15:41:19 +03:00
|
|
|
//#define DEBUG_WINDOW_LAYER
|
|
|
|
//#define DEBUG_WINDOW_LAYER_CLICK
|
2003-03-23 23:52:37 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
#ifdef DEBUG_WINDOW_LAYER
|
2003-09-09 02:09:10 +04:00
|
|
|
# define STRACE(x) printf x
|
|
|
|
#else
|
|
|
|
# define STRACE(x) ;
|
2003-03-23 23:52:37 +03:00
|
|
|
#endif
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
#ifdef DEBUG_WINDOW_LAYER_CLICK
|
2003-09-09 02:09:10 +04:00
|
|
|
# define STRACE_CLICK(x) printf x
|
|
|
|
#else
|
|
|
|
# define STRACE_CLICK(x) ;
|
2003-04-05 05:51:35 +04:00
|
|
|
#endif
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// if the background clearing is delayed until
|
|
|
|
// the client draws the view, we have less flickering
|
|
|
|
// when contents have to be redrawn because of resizing
|
|
|
|
// a window or because the client invalidates parts.
|
|
|
|
// when redrawing something that has been exposed from underneath
|
|
|
|
// other windows, the other window will be seen longer at
|
|
|
|
// its previous position though if the exposed parts are not
|
|
|
|
// cleared right away. maybe there ought to be a flag in
|
|
|
|
// the update session, which tells us the cause of the update
|
|
|
|
#define DELAYED_BACKGROUND_CLEARING 0
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
// IMPORTANT: nested LockSingleWindow()s are not supported (by MultiLocker)
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
using std::nothrow;
|
|
|
|
|
2005-12-09 18:40:30 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::WindowLayer(const BRect& frame, const char *name,
|
|
|
|
window_look look, window_feel feel,
|
|
|
|
uint32 flags, uint32 workspaces,
|
|
|
|
::ServerWindow* window,
|
|
|
|
DrawingEngine* drawingEngine)
|
|
|
|
:
|
|
|
|
fTitle(name),
|
|
|
|
fFrame(frame),
|
|
|
|
|
|
|
|
fVisibleRegion(),
|
|
|
|
fVisibleContentRegion(),
|
|
|
|
fVisibleContentRegionValid(false),
|
|
|
|
fDirtyRegion(),
|
|
|
|
|
|
|
|
fBorderRegion(),
|
|
|
|
fBorderRegionValid(false),
|
|
|
|
fContentRegion(),
|
|
|
|
fContentRegionValid(false),
|
|
|
|
fEffectiveDrawingRegion(),
|
|
|
|
fEffectiveDrawingRegionValid(false),
|
|
|
|
|
|
|
|
fIsClosing(false),
|
|
|
|
fIsMinimizing(false),
|
|
|
|
fIsZooming(false),
|
|
|
|
fIsResizing(false),
|
|
|
|
fIsSlidingTab(false),
|
|
|
|
fIsDragging(false),
|
|
|
|
|
|
|
|
fDecorator(NULL),
|
|
|
|
fTopLayer(NULL),
|
|
|
|
fWindow(window),
|
|
|
|
fDrawingEngine(drawingEngine),
|
|
|
|
fDesktop(window->Desktop()),
|
|
|
|
|
|
|
|
fCurrentUpdateSession(),
|
|
|
|
fPendingUpdateSession(),
|
|
|
|
fUpdateRequested(false),
|
|
|
|
fInUpdate(false),
|
|
|
|
|
|
|
|
// windows start hidden
|
|
|
|
fHidden(true),
|
|
|
|
fIsFocus(false),
|
|
|
|
|
|
|
|
fLook(look),
|
|
|
|
fFeel(feel),
|
|
|
|
fWorkspaces(workspaces),
|
|
|
|
fCurrentWorkspace(-1),
|
|
|
|
|
|
|
|
fMinWidth(1),
|
|
|
|
fMaxWidth(32768),
|
|
|
|
fMinHeight(1),
|
|
|
|
fMaxHeight(32768),
|
|
|
|
|
|
|
|
fReadLocked(false)
|
2003-02-14 04:53:53 +03:00
|
|
|
{
|
2005-12-01 18:58:04 +03:00
|
|
|
// make sure our arguments are valid
|
|
|
|
if (!IsValidLook(fLook))
|
|
|
|
fLook = B_TITLED_WINDOW_LOOK;
|
|
|
|
if (!IsValidFeel(fFeel))
|
|
|
|
fFeel = B_NORMAL_WINDOW_FEEL;
|
2005-12-09 17:06:30 +03:00
|
|
|
|
|
|
|
SetFlags(flags, NULL);
|
2005-12-01 18:58:04 +03:00
|
|
|
|
2005-12-01 15:07:28 +03:00
|
|
|
if (fLook != B_NO_BORDER_WINDOW_LOOK) {
|
2005-12-08 15:41:19 +03:00
|
|
|
fDecorator = gDecorManager.AllocateDecorator(fDesktop, frame, name, fLook, fFlags);
|
2005-06-28 06:00:48 +04:00
|
|
|
if (fDecorator)
|
2005-06-03 23:50:30 +04:00
|
|
|
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth, &fMaxHeight);
|
|
|
|
}
|
2004-03-28 18:58:39 +04:00
|
|
|
|
2005-06-28 06:00:48 +04:00
|
|
|
// do we need to change our size to let the decorator fit?
|
|
|
|
// _ResizeBy() will adapt the frame for validity before resizing
|
2005-07-06 00:28:40 +04:00
|
|
|
if (feel == kDesktopWindowFeel) {
|
|
|
|
// the desktop window spans over the whole screen
|
|
|
|
// ToDo: this functionality should be moved somewhere else (so that it
|
|
|
|
// is always used when the workspace is changed)
|
|
|
|
uint16 width, height;
|
|
|
|
uint32 colorSpace;
|
|
|
|
float frequency;
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fDesktop->ScreenAt(0)) {
|
|
|
|
fDesktop->ScreenAt(0)->GetMode(width, height, colorSpace, frequency);
|
2005-11-09 23:14:52 +03:00
|
|
|
// TODO: MOVE THIS AWAY!!! RemoveBy contains calls to virtual methods! Also, there is not TopLayer()!
|
2005-11-29 02:36:59 +03:00
|
|
|
fFrame.OffsetTo(B_ORIGIN);
|
2005-12-08 15:41:19 +03:00
|
|
|
// ResizeBy(width - frame.Width(), height - frame.Height(), NULL);
|
2005-11-04 18:23:54 +03:00
|
|
|
}
|
2005-11-07 04:16:12 +03:00
|
|
|
}
|
2005-06-28 06:00:48 +04:00
|
|
|
|
2005-11-24 20:45:26 +03:00
|
|
|
STRACE(("WindowLayer %p, %s:\n", this, Name()));
|
2005-07-18 14:34:25 +04:00
|
|
|
STRACE(("\tFrame: (%.1f, %.1f, %.1f, %.1f)\n", fFrame.left, fFrame.top,
|
|
|
|
fFrame.right, fFrame.bottom));
|
2005-06-28 06:00:48 +04:00
|
|
|
STRACE(("\tWindow %s\n", window ? window->Title() : "NULL"));
|
2003-02-14 04:53:53 +03:00
|
|
|
}
|
2004-06-11 06:46:48 +04:00
|
|
|
|
2005-12-09 18:40:30 +03:00
|
|
|
|
2005-11-24 20:45:26 +03:00
|
|
|
WindowLayer::~WindowLayer()
|
2003-02-14 04:53:53 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
delete fTopLayer;
|
2005-06-03 23:50:30 +04:00
|
|
|
delete fDecorator;
|
2003-02-14 04:53:53 +03:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
WindowLayer::ReadLockWindows()
|
|
|
|
{
|
|
|
|
if (fDesktop)
|
2005-12-12 13:41:31 +03:00
|
|
|
fReadLocked = fDesktop->LockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
else
|
|
|
|
fReadLocked = true;
|
|
|
|
|
|
|
|
return fReadLocked;
|
2003-02-14 04:53:53 +03:00
|
|
|
}
|
2004-06-11 06:46:48 +04:00
|
|
|
|
2005-12-09 18:40:30 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
WindowLayer::ReadUnlockWindows()
|
|
|
|
{
|
|
|
|
if (fReadLocked) {
|
|
|
|
if (fDesktop)
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
fReadLocked = false;
|
|
|
|
}
|
|
|
|
}
|
2005-11-14 20:39:33 +03:00
|
|
|
|
2005-12-12 00:46:35 +03:00
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
|
2003-02-14 04:53:53 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// this function is only called from the Desktop thread
|
2005-11-09 23:14:52 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// start from full region (as if the window was fully visible)
|
|
|
|
GetFullRegion(&fVisibleRegion);
|
|
|
|
// clip to region still available on screen
|
|
|
|
fVisibleRegion.IntersectWith(stillAvailableOnScreen);
|
|
|
|
|
|
|
|
fVisibleContentRegionValid = false;
|
|
|
|
fEffectiveDrawingRegionValid = false;
|
|
|
|
|
2005-12-12 00:46:35 +03:00
|
|
|
// TODO: review this!
|
|
|
|
fWindow->HandleDirectConnection(B_DIRECT_MODIFY | B_CLIPPING_MODIFIED);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
2005-12-12 00:46:35 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
WindowLayer::GetFullRegion(BRegion* region)
|
|
|
|
{
|
|
|
|
// TODO: if someone needs to call this from
|
|
|
|
// the outside, the clipping needs to be readlocked!
|
2005-11-11 03:10:03 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
GetBorderRegion(region);
|
2005-11-11 03:10:03 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// start from the frame, extend to include decorator border
|
|
|
|
region->Include(fFrame);
|
2005-11-11 03:10:03 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-11-11 03:10:03 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// GetBorderRegion
|
|
|
|
void
|
|
|
|
WindowLayer::GetBorderRegion(BRegion* region)
|
|
|
|
{
|
|
|
|
// TODO: if someone needs to call this from
|
|
|
|
// the outside, the clipping needs to be readlocked!
|
|
|
|
|
|
|
|
if (!fBorderRegionValid) {
|
|
|
|
// TODO: checkup Decorator::GetFootPrint() to see if it is as fast as this:
|
|
|
|
/* fBorderRegion.Set(BRect(fFrame.left - 4, fFrame.top - 20,
|
|
|
|
(fFrame.left + fFrame.right) / 2, fFrame.top - 5));
|
|
|
|
fBorderRegion.Include(BRect(fFrame.left - 4, fFrame.top - 4,
|
|
|
|
fFrame.right + 4, fFrame.top - 1));
|
|
|
|
fBorderRegion.Include(BRect(fFrame.left - 4, fFrame.top,
|
|
|
|
fFrame.left - 1, fFrame.bottom));
|
|
|
|
fBorderRegion.Include(BRect(fFrame.right + 1, fFrame.top,
|
|
|
|
fFrame.right + 4, fFrame.bottom - 11));
|
|
|
|
fBorderRegion.Include(BRect(fFrame.left - 4, fFrame.bottom + 1,
|
|
|
|
fFrame.right - 11, fFrame.bottom + 4));
|
|
|
|
fBorderRegion.Include(BRect(fFrame.right - 10, fFrame.bottom - 10,
|
|
|
|
fFrame.right + 4, fFrame.bottom + 4));*/
|
|
|
|
|
|
|
|
// TODO: remove and use Decorator::GetFootPrint()
|
|
|
|
// start from the frame, extend to include decorator border
|
|
|
|
if (fDecorator) {
|
|
|
|
fDecorator->GetFootprint(&fBorderRegion);
|
2005-11-11 03:10:03 +03:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
fBorderRegionValid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
*region = fBorderRegion;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::GetContentRegion(BRegion* region)
|
|
|
|
{
|
|
|
|
// TODO: if someone needs to call this from
|
|
|
|
// the outside, the clipping needs to be readlocked!
|
|
|
|
|
|
|
|
if (!fContentRegionValid) {
|
|
|
|
_UpdateContentRegion();
|
|
|
|
}
|
|
|
|
|
|
|
|
*region = fContentRegion;
|
|
|
|
}
|
2005-11-24 20:12:32 +03:00
|
|
|
|
2005-11-09 23:14:52 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
BRegion&
|
|
|
|
WindowLayer::VisibleContentRegion()
|
|
|
|
{
|
|
|
|
// TODO: if someone needs to call this from
|
|
|
|
// the outside, the clipping needs to be readlocked!
|
|
|
|
|
|
|
|
// regions expected to be locked
|
|
|
|
if (!fVisibleContentRegionValid) {
|
|
|
|
GetContentRegion(&fVisibleContentRegion);
|
|
|
|
fVisibleContentRegion.IntersectWith(&fVisibleRegion);
|
2005-11-09 23:14:52 +03:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
return fVisibleContentRegion;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-12-09 17:06:30 +03:00
|
|
|
void
|
|
|
|
WindowLayer::_PropagatePosition()
|
|
|
|
{
|
|
|
|
if ((fFlags & B_SAME_POSITION_IN_ALL_WORKSPACES) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int32 i = 0; i < kListCount; i++) {
|
|
|
|
Anchor(i).position = fFrame.LeftTop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
WindowLayer::MoveBy(int32 x, int32 y)
|
|
|
|
{
|
|
|
|
// this function is only called from the desktop thread
|
|
|
|
|
|
|
|
if ((x == 0 && y == 0) || !ReadLockWindows())
|
|
|
|
return;
|
|
|
|
|
|
|
|
fWindow->HandleDirectConnection(B_DIRECT_STOP);
|
|
|
|
|
|
|
|
fFrame.OffsetBy(x, y);
|
2005-12-09 17:06:30 +03:00
|
|
|
_PropagatePosition();
|
2005-12-09 16:17:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fWindow->HandleDirectConnection(B_DIRECT_START | B_BUFFER_MOVED);
|
|
|
|
|
|
|
|
// take along the dirty region which have not
|
|
|
|
// processed yet
|
|
|
|
fDirtyRegion.OffsetBy(x, y);
|
|
|
|
|
|
|
|
if (fBorderRegionValid)
|
|
|
|
fBorderRegion.OffsetBy(x, y);
|
|
|
|
if (fContentRegionValid)
|
|
|
|
fContentRegion.OffsetBy(x, y);
|
|
|
|
|
|
|
|
if (fCurrentUpdateSession.IsUsed())
|
|
|
|
fCurrentUpdateSession.MoveBy(x, y);
|
|
|
|
if (fPendingUpdateSession.IsUsed())
|
|
|
|
fPendingUpdateSession.MoveBy(x, y);
|
|
|
|
|
|
|
|
fEffectiveDrawingRegionValid = false;
|
|
|
|
|
|
|
|
if (fDecorator)
|
|
|
|
fDecorator->MoveBy(x, y);
|
|
|
|
|
|
|
|
if (fTopLayer != NULL)
|
|
|
|
fTopLayer->MoveBy(x, y, NULL);
|
|
|
|
|
|
|
|
// the desktop will take care of dirty regions
|
2005-11-09 23:14:52 +03:00
|
|
|
|
|
|
|
// dispatch a message to the client informing about the changed size
|
|
|
|
BMessage msg(B_WINDOW_MOVED);
|
2005-12-08 15:41:19 +03:00
|
|
|
msg.AddInt64("when", system_time());
|
|
|
|
msg.AddPoint("where", fFrame.LeftTop());
|
|
|
|
fWindow->SendMessageToClient(&msg);
|
|
|
|
|
|
|
|
ReadUnlockWindows();
|
2003-02-14 04:53:53 +03:00
|
|
|
}
|
2004-06-11 06:46:48 +04:00
|
|
|
|
2005-06-28 06:00:48 +04:00
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
|
2005-06-28 06:00:48 +04:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// this function is only called from the desktop thread
|
|
|
|
|
|
|
|
int32 wantWidth = fFrame.IntegerWidth() + x;
|
|
|
|
int32 wantHeight = fFrame.IntegerHeight() + y;
|
2005-06-03 23:50:30 +04:00
|
|
|
|
|
|
|
// enforce size limits
|
|
|
|
if (wantWidth < fMinWidth)
|
|
|
|
wantWidth = fMinWidth;
|
|
|
|
if (wantWidth > fMaxWidth)
|
|
|
|
wantWidth = fMaxWidth;
|
|
|
|
|
|
|
|
if (wantHeight < fMinHeight)
|
|
|
|
wantHeight = fMinHeight;
|
|
|
|
if (wantHeight > fMaxHeight)
|
|
|
|
wantHeight = fMaxHeight;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
x = wantWidth - fFrame.IntegerWidth();
|
|
|
|
y = wantHeight - fFrame.IntegerHeight();
|
2005-06-03 23:50:30 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if ((x == 0 && y == 0) || !ReadLockWindows())
|
2005-11-09 23:14:52 +03:00
|
|
|
return;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fWindow->HandleDirectConnection(B_DIRECT_STOP);
|
2005-11-09 23:14:52 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fFrame.right += x;
|
|
|
|
fFrame.bottom += y;
|
2005-11-09 23:14:52 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fWindow->HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESIZED);
|
2005-11-09 23:14:52 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// put the previous border region into the dirty region as well
|
|
|
|
// to handle the part that was overlapping a layer
|
|
|
|
if (dirtyRegion)
|
|
|
|
dirtyRegion->Include(&fBorderRegion);
|
2005-11-24 20:12:32 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fBorderRegionValid = false;
|
|
|
|
fContentRegionValid = false;
|
|
|
|
fEffectiveDrawingRegionValid = false;
|
2005-06-03 23:50:30 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fDecorator)
|
|
|
|
fDecorator->ResizeBy(x, y);
|
|
|
|
|
|
|
|
// the border is dirty, put it into
|
|
|
|
// dirtyRegion for a start
|
|
|
|
BRegion newBorderRegion;
|
|
|
|
GetBorderRegion(&newBorderRegion);
|
|
|
|
if (dirtyRegion) {
|
|
|
|
dirtyRegion->Include(&newBorderRegion);
|
2005-11-09 23:14:52 +03:00
|
|
|
}
|
2005-06-22 00:11:44 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fTopLayer != NULL)
|
|
|
|
fTopLayer->ResizeBy(x, y, dirtyRegion);
|
|
|
|
|
2005-12-20 00:16:23 +03:00
|
|
|
//if (dirtyRegion)
|
|
|
|
//fDrawingEngine->FillRegion(*dirtyRegion, RGBColor(0, 255, 255, 255));
|
|
|
|
|
2005-11-09 23:14:52 +03:00
|
|
|
// send a message to the client informing about the changed size
|
|
|
|
BRect frame(Frame());
|
|
|
|
BMessage msg(B_WINDOW_RESIZED);
|
|
|
|
msg.AddInt64("when", system_time());
|
|
|
|
msg.AddInt32("width", frame.IntegerWidth());
|
|
|
|
msg.AddInt32("height", frame.IntegerHeight());
|
2005-12-08 15:41:19 +03:00
|
|
|
fWindow->SendMessageToClient(&msg);
|
|
|
|
|
|
|
|
ReadUnlockWindows();
|
2003-02-14 04:53:53 +03:00
|
|
|
}
|
2004-06-11 06:46:48 +04:00
|
|
|
|
2005-11-14 20:39:33 +03:00
|
|
|
|
offscreen bitmaps work, tested on Haiku as well, supports all colorspaces that BBitmap::ImportBits() supports. It uses a fallback for non-B_RGB(A)32 bitmaps. Added support for B_SUB_PIXEL_PRECISION view flags, though it is a bit hacky, since I had to add it to LayerData, even though it is not a true part of stack data. Added Layer::SetFlags() to enforce code path and update fLayerData. Cleaned up DisplayDriverPainter and DisplayDriver API (changed some const BRect& rect to simply BRect rect in order to be able to reuse it in the code), moved Painter.h, the test environment only draws the changed part of the frame buffer again - this causes a lot less CPU overhead, Painter special cases stroke width of 1.0 to use square caps, which is similar to R5 implementation and removes a lot of problems with non-straight line drawing, ServerWindow uses the DisplayDriver from it's WinBorder instead of the one from the Desktop (needed for offscreen windows, which have their own DisplayDriverPainter), it also checks for GetRootLayer() == NULL, because offscreen layers are not attached to a RootLayer, there was a fix for scrolling which worked at least in the test environment, it is now defunced, because Adi moved _CopyBits to Layer... I need to reenable it later, LayerData has no more fEscapementDelta, also fixed fFontAliasing (which was thought to overriding the font flags, and now works as such again), Desktop initialises the menu_info and scroll_bar_info stuff, which makes ScrollBars work actually... hope I didn't forget something.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13448 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-07-05 20:17:16 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::ScrollViewBy(ViewLayer* view, int32 dx, int32 dy)
|
offscreen bitmaps work, tested on Haiku as well, supports all colorspaces that BBitmap::ImportBits() supports. It uses a fallback for non-B_RGB(A)32 bitmaps. Added support for B_SUB_PIXEL_PRECISION view flags, though it is a bit hacky, since I had to add it to LayerData, even though it is not a true part of stack data. Added Layer::SetFlags() to enforce code path and update fLayerData. Cleaned up DisplayDriverPainter and DisplayDriver API (changed some const BRect& rect to simply BRect rect in order to be able to reuse it in the code), moved Painter.h, the test environment only draws the changed part of the frame buffer again - this causes a lot less CPU overhead, Painter special cases stroke width of 1.0 to use square caps, which is similar to R5 implementation and removes a lot of problems with non-straight line drawing, ServerWindow uses the DisplayDriver from it's WinBorder instead of the one from the Desktop (needed for offscreen windows, which have their own DisplayDriverPainter), it also checks for GetRootLayer() == NULL, because offscreen layers are not attached to a RootLayer, there was a fix for scrolling which worked at least in the test environment, it is now defunced, because Adi moved _CopyBits to Layer... I need to reenable it later, LayerData has no more fEscapementDelta, also fixed fFontAliasing (which was thought to overriding the font flags, and now works as such again), Desktop initialises the menu_info and scroll_bar_info stuff, which makes ScrollBars work actually... hope I didn't forget something.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13448 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-07-05 20:17:16 +04:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// this can be executed from any thread, but if the
|
|
|
|
// desktop thread is executing this, it should have
|
|
|
|
// the write lock, otherwise it is not prevented
|
|
|
|
// from executing this at the same time as the window
|
|
|
|
// is doing something else here!
|
offscreen bitmaps work, tested on Haiku as well, supports all colorspaces that BBitmap::ImportBits() supports. It uses a fallback for non-B_RGB(A)32 bitmaps. Added support for B_SUB_PIXEL_PRECISION view flags, though it is a bit hacky, since I had to add it to LayerData, even though it is not a true part of stack data. Added Layer::SetFlags() to enforce code path and update fLayerData. Cleaned up DisplayDriverPainter and DisplayDriver API (changed some const BRect& rect to simply BRect rect in order to be able to reuse it in the code), moved Painter.h, the test environment only draws the changed part of the frame buffer again - this causes a lot less CPU overhead, Painter special cases stroke width of 1.0 to use square caps, which is similar to R5 implementation and removes a lot of problems with non-straight line drawing, ServerWindow uses the DisplayDriver from it's WinBorder instead of the one from the Desktop (needed for offscreen windows, which have their own DisplayDriverPainter), it also checks for GetRootLayer() == NULL, because offscreen layers are not attached to a RootLayer, there was a fix for scrolling which worked at least in the test environment, it is now defunced, because Adi moved _CopyBits to Layer... I need to reenable it later, LayerData has no more fEscapementDelta, also fixed fFontAliasing (which was thought to overriding the font flags, and now works as such again), Desktop initialises the menu_info and scroll_bar_info stuff, which makes ScrollBars work actually... hope I didn't forget something.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13448 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-07-05 20:17:16 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (!view || view == fTopLayer || (dx == 0 && dy == 0))
|
|
|
|
return;
|
offscreen bitmaps work, tested on Haiku as well, supports all colorspaces that BBitmap::ImportBits() supports. It uses a fallback for non-B_RGB(A)32 bitmaps. Added support for B_SUB_PIXEL_PRECISION view flags, though it is a bit hacky, since I had to add it to LayerData, even though it is not a true part of stack data. Added Layer::SetFlags() to enforce code path and update fLayerData. Cleaned up DisplayDriverPainter and DisplayDriver API (changed some const BRect& rect to simply BRect rect in order to be able to reuse it in the code), moved Painter.h, the test environment only draws the changed part of the frame buffer again - this causes a lot less CPU overhead, Painter special cases stroke width of 1.0 to use square caps, which is similar to R5 implementation and removes a lot of problems with non-straight line drawing, ServerWindow uses the DisplayDriver from it's WinBorder instead of the one from the Desktop (needed for offscreen windows, which have their own DisplayDriverPainter), it also checks for GetRootLayer() == NULL, because offscreen layers are not attached to a RootLayer, there was a fix for scrolling which worked at least in the test environment, it is now defunced, because Adi moved _CopyBits to Layer... I need to reenable it later, LayerData has no more fEscapementDelta, also fixed fFontAliasing (which was thought to overriding the font flags, and now works as such again), Desktop initialises the menu_info and scroll_bar_info stuff, which makes ScrollBars work actually... hope I didn't forget something.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13448 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-07-05 20:17:16 +04:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
if (fDesktop && fDesktop->LockSingleWindow()) {
|
2005-12-08 15:41:19 +03:00
|
|
|
BRegion dirty;
|
|
|
|
view->ScrollBy(dx, dy, &dirty);
|
offscreen bitmaps work, tested on Haiku as well, supports all colorspaces that BBitmap::ImportBits() supports. It uses a fallback for non-B_RGB(A)32 bitmaps. Added support for B_SUB_PIXEL_PRECISION view flags, though it is a bit hacky, since I had to add it to LayerData, even though it is not a true part of stack data. Added Layer::SetFlags() to enforce code path and update fLayerData. Cleaned up DisplayDriverPainter and DisplayDriver API (changed some const BRect& rect to simply BRect rect in order to be able to reuse it in the code), moved Painter.h, the test environment only draws the changed part of the frame buffer again - this causes a lot less CPU overhead, Painter special cases stroke width of 1.0 to use square caps, which is similar to R5 implementation and removes a lot of problems with non-straight line drawing, ServerWindow uses the DisplayDriver from it's WinBorder instead of the one from the Desktop (needed for offscreen windows, which have their own DisplayDriverPainter), it also checks for GetRootLayer() == NULL, because offscreen layers are not attached to a RootLayer, there was a fix for scrolling which worked at least in the test environment, it is now defunced, because Adi moved _CopyBits to Layer... I need to reenable it later, LayerData has no more fEscapementDelta, also fixed fFontAliasing (which was thought to overriding the font flags, and now works as such again), Desktop initialises the menu_info and scroll_bar_info stuff, which makes ScrollBars work actually... hope I didn't forget something.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13448 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-07-05 20:17:16 +04:00
|
|
|
|
2005-12-20 00:16:23 +03:00
|
|
|
//fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 255, 255));
|
|
|
|
//snooze(2000);
|
|
|
|
|
|
|
|
_TriggerContentRedraw(dirty);
|
2005-11-11 14:03:33 +03:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
offscreen bitmaps work, tested on Haiku as well, supports all colorspaces that BBitmap::ImportBits() supports. It uses a fallback for non-B_RGB(A)32 bitmaps. Added support for B_SUB_PIXEL_PRECISION view flags, though it is a bit hacky, since I had to add it to LayerData, even though it is not a true part of stack data. Added Layer::SetFlags() to enforce code path and update fLayerData. Cleaned up DisplayDriverPainter and DisplayDriver API (changed some const BRect& rect to simply BRect rect in order to be able to reuse it in the code), moved Painter.h, the test environment only draws the changed part of the frame buffer again - this causes a lot less CPU overhead, Painter special cases stroke width of 1.0 to use square caps, which is similar to R5 implementation and removes a lot of problems with non-straight line drawing, ServerWindow uses the DisplayDriver from it's WinBorder instead of the one from the Desktop (needed for offscreen windows, which have their own DisplayDriverPainter), it also checks for GetRootLayer() == NULL, because offscreen layers are not attached to a RootLayer, there was a fix for scrolling which worked at least in the test environment, it is now defunced, because Adi moved _CopyBits to Layer... I need to reenable it later, LayerData has no more fEscapementDelta, also fixed fFontAliasing (which was thought to overriding the font flags, and now works as such again), Desktop initialises the menu_info and scroll_bar_info stuff, which makes ScrollBars work actually... hope I didn't forget something.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13448 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-07-05 20:17:16 +04:00
|
|
|
}
|
|
|
|
}
|
2005-06-28 06:00:48 +04:00
|
|
|
|
2005-11-14 20:39:33 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
//! Takes care of invalidating parts that could not be copied
|
2005-06-25 17:09:19 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset)
|
2005-06-25 17:09:19 +04:00
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!fHidden && fDesktop && fDesktop->LockSingleWindow()) {
|
2005-12-08 15:41:19 +03:00
|
|
|
BRegion newDirty(*region);
|
|
|
|
|
|
|
|
// clip the region to the visible contents at the
|
|
|
|
// source and destination location (not that VisibleContentRegion()
|
|
|
|
// is used once to make sure it is valid, then fVisibleContentRegion
|
|
|
|
// is used directly)
|
|
|
|
region->IntersectWith(&VisibleContentRegion());
|
|
|
|
if (region->CountRects() > 0) {
|
|
|
|
region->OffsetBy(xOffset, yOffset);
|
|
|
|
region->IntersectWith(&fVisibleContentRegion);
|
|
|
|
if (region->CountRects() > 0) {
|
|
|
|
// if the region still contains any rects
|
|
|
|
// offset to source location again
|
|
|
|
region->OffsetBy(-xOffset, -yOffset);
|
|
|
|
// the part which we can copy is not dirty
|
|
|
|
newDirty.Exclude(region);
|
|
|
|
|
2005-12-09 01:15:12 +03:00
|
|
|
fDrawingEngine->CopyRegion(region, xOffset, yOffset);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
// move along the already dirty regions that are common
|
|
|
|
// with the region that we could copy
|
|
|
|
_ShiftPartOfRegion(&fDirtyRegion, region, xOffset, yOffset);
|
|
|
|
if (fPendingUpdateSession.IsUsed())
|
|
|
|
_ShiftPartOfRegion(&fPendingUpdateSession.DirtyRegion(), region, xOffset, yOffset);
|
2005-12-10 11:05:25 +03:00
|
|
|
|
|
|
|
if (fCurrentUpdateSession.IsUsed()) {
|
|
|
|
// if there are parts in the current update session
|
|
|
|
// that intersect with the copied region, we cannot
|
|
|
|
// simply shift them as with the other dirty regions
|
|
|
|
// - we cannot change the update rect already told to the
|
|
|
|
// client, that's why we transfer those parts to the
|
|
|
|
// new dirty region instead
|
|
|
|
BRegion common(*region);
|
|
|
|
// see if there is a common part at all
|
|
|
|
common.IntersectWith(&fCurrentUpdateSession.DirtyRegion());
|
|
|
|
if (common.CountRects() > 0) {
|
|
|
|
// cut the common part from the region
|
|
|
|
fCurrentUpdateSession.DirtyRegion().Exclude(&common);
|
|
|
|
newDirty.Include(&common);
|
|
|
|
}
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// what is left visible from the original region
|
|
|
|
// at the destination after the region which could be
|
|
|
|
// copied has been excluded, is considered dirty
|
|
|
|
// NOTE: it may look like dirty regions are not moved
|
|
|
|
// if no region could be copied, but that's alright,
|
|
|
|
// since these parts will now be in newDirty anyways
|
|
|
|
// (with the right offset)
|
|
|
|
newDirty.OffsetBy(xOffset, yOffset);
|
|
|
|
newDirty.IntersectWith(&fVisibleContentRegion);
|
|
|
|
if (newDirty.CountRects() > 0)
|
|
|
|
ProcessDirtyRegion(newDirty);
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-06-25 17:09:19 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-06-25 17:09:19 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::SetTopLayer(ViewLayer* topLayer)
|
2005-06-25 17:09:19 +04:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// the top layer is special, it has a coordinate system
|
|
|
|
// as if it was attached directly to the desktop, therefor,
|
|
|
|
// the coordinate conversion through the layer tree works
|
|
|
|
// as expected, since the top layer has no "parent" but has
|
|
|
|
// fFrame as if it had
|
2005-06-25 17:09:19 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fTopLayer = topLayer;
|
2005-06-25 17:09:19 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// make sure the location of the top layer on screen matches ours
|
|
|
|
fTopLayer->MoveBy(fFrame.left - fTopLayer->Frame().left,
|
|
|
|
fFrame.top - fTopLayer->Frame().top, NULL);
|
2005-06-25 17:09:19 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// make sure the size of the top layer matches ours
|
|
|
|
fTopLayer->ResizeBy(fFrame.Width() - fTopLayer->Frame().Width(),
|
|
|
|
fFrame.Height() - fTopLayer->Frame().Height(), NULL);
|
|
|
|
|
|
|
|
fTopLayer->AttachedToWindow(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ViewLayer*
|
|
|
|
WindowLayer::ViewAt(const BPoint& where)
|
|
|
|
{
|
|
|
|
ViewLayer* view = NULL;
|
|
|
|
|
|
|
|
if (ReadLockWindows()) {
|
|
|
|
if (!fContentRegionValid)
|
|
|
|
_UpdateContentRegion();
|
|
|
|
|
|
|
|
view = fTopLayer->ViewAt(where, &fContentRegion);
|
|
|
|
|
|
|
|
ReadUnlockWindows();
|
2005-11-08 00:24:53 +03:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
return view;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
window_anchor&
|
|
|
|
WindowLayer::Anchor(int32 index)
|
|
|
|
{
|
|
|
|
return fAnchor[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
WindowLayer*
|
|
|
|
WindowLayer::NextWindow(int32 index)
|
|
|
|
{
|
|
|
|
return fAnchor[index].next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
WindowLayer*
|
|
|
|
WindowLayer::PreviousWindow(int32 index)
|
|
|
|
{
|
|
|
|
return fAnchor[index].previous;
|
2005-11-08 00:24:53 +03:00
|
|
|
}
|
2005-11-11 01:30:43 +03:00
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-11-08 00:24:53 +03:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::GetEffectiveDrawingRegion(ViewLayer* layer, BRegion& region)
|
2005-11-11 01:30:43 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (!fEffectiveDrawingRegionValid) {
|
|
|
|
fEffectiveDrawingRegion = VisibleContentRegion();
|
|
|
|
if (fInUpdate) {
|
|
|
|
// enforce the dirty region of the update session
|
|
|
|
fEffectiveDrawingRegion.IntersectWith(&fCurrentUpdateSession.DirtyRegion());
|
|
|
|
} else {
|
|
|
|
// not in update, the view can draw everywhere
|
2005-12-20 00:16:23 +03:00
|
|
|
//printf("WindowLayer(%s)::GetEffectiveDrawingRegion(for %s) - outside update\n", Title(), layer->Name());
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fEffectiveDrawingRegionValid = true;
|
2005-06-25 17:09:19 +04:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
// TODO: this is a region that needs to be cached later in the server
|
|
|
|
// when the current layer in ServerWindow is set, and we are currently
|
|
|
|
// in an update (fInUpdate), than we can set this region and remember
|
|
|
|
// it for the comming drawing commands until the current layer changes
|
|
|
|
// again or fEffectiveDrawingRegionValid is suddenly false.
|
|
|
|
region = fEffectiveDrawingRegion;
|
|
|
|
if (!fContentRegionValid)
|
|
|
|
_UpdateContentRegion();
|
|
|
|
|
|
|
|
region.IntersectWith(&layer->ScreenClipping(&fContentRegion));
|
|
|
|
}
|
|
|
|
|
2005-12-09 18:40:30 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
bool
|
|
|
|
WindowLayer::DrawingRegionChanged(ViewLayer* layer) const
|
|
|
|
{
|
|
|
|
return !fEffectiveDrawingRegionValid || !layer->IsScreenClippingValid();
|
2005-06-25 17:09:19 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::ProcessDirtyRegion(BRegion& region)
|
2004-08-08 00:30:58 +04:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// if this is exectuted in the desktop thread,
|
|
|
|
// it means that the window thread currently
|
|
|
|
// blocks to get the read lock, if it is
|
|
|
|
// executed from the window thread, it should
|
|
|
|
// have the read lock and the desktop thread
|
|
|
|
// is blocking to get the write lock. IAW, this
|
|
|
|
// is only executed in one thread.
|
|
|
|
if (fDirtyRegion.CountRects() == 0) {
|
|
|
|
// the window needs to be informed
|
|
|
|
// when the dirty region was empty.
|
|
|
|
// NOTE: when the window thread has processed
|
|
|
|
// the dirty region in MessageReceived(),
|
|
|
|
// it will make the region empty again,
|
|
|
|
// when it is empty here, we need to send
|
|
|
|
// the message to initiate the next update round.
|
|
|
|
// Until the message is processed in the window
|
|
|
|
// thread, the desktop thread can add parts to
|
|
|
|
// the region as it likes.
|
2005-12-12 16:14:21 +03:00
|
|
|
ServerWindow()->RequestRedraw();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-06-03 23:50:30 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// this is executed from the desktop thread
|
|
|
|
fDirtyRegion.Include(®ion);
|
|
|
|
}
|
2005-06-03 23:50:30 +04:00
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
WindowLayer::RedrawDirtyRegion()
|
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!fDesktop || !fDesktop->LockSingleWindow())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
2005-06-03 23:50:30 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (IsVisible()) {
|
|
|
|
_DrawBorder();
|
2005-12-20 00:16:23 +03:00
|
|
|
|
|
|
|
BRegion dirtyContentRegion(VisibleContentRegion());
|
|
|
|
dirtyContentRegion.IntersectWith(&fDirtyRegion);
|
|
|
|
|
|
|
|
_TriggerContentRedraw(dirtyContentRegion);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-06-03 23:50:30 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// reset the dirty region, since
|
|
|
|
// we're fully clean. If the desktop
|
|
|
|
// thread wanted to mark something
|
|
|
|
// dirty in the mean time, it was
|
|
|
|
// blocking on the global region lock to
|
|
|
|
// get write access, since we held the
|
|
|
|
// read lock for the whole time.
|
|
|
|
fDirtyRegion.MakeEmpty();
|
2005-06-28 06:00:48 +04:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-06-28 06:00:48 +04:00
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
WindowLayer::MarkDirty(BRegion& regionOnScreen)
|
|
|
|
{
|
|
|
|
// for marking any part of the desktop dirty
|
|
|
|
// this will get write access to the global
|
|
|
|
// region lock, and result in ProcessDirtyRegion()
|
|
|
|
// to be called for any windows affected
|
|
|
|
if (fDesktop)
|
|
|
|
fDesktop->MarkDirty(regionOnScreen);
|
|
|
|
}
|
2005-06-03 23:50:30 +04:00
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
WindowLayer::MarkContentDirty(BRegion& regionOnScreen)
|
|
|
|
{
|
|
|
|
// for triggering AS_REDRAW
|
|
|
|
// since this won't affect other windows, read locking
|
|
|
|
// is sufficient. If there was no dirty region before,
|
|
|
|
// an update message is triggered
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!fHidden && fDesktop && fDesktop->LockSingleWindow()) {
|
2005-12-08 15:41:19 +03:00
|
|
|
regionOnScreen.IntersectWith(&VisibleContentRegion());
|
2005-12-20 00:16:23 +03:00
|
|
|
_TriggerContentRedraw(regionOnScreen);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-06-03 23:50:30 +04:00
|
|
|
}
|
|
|
|
|
2005-10-31 14:05:52 +03:00
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::InvalidateView(ViewLayer* layer, BRegion& layerRegion)
|
2005-06-03 23:50:30 +04:00
|
|
|
{
|
2005-12-12 13:41:31 +03:00
|
|
|
if (layer && !fHidden && fDesktop && fDesktop->LockSingleWindow()) {
|
2005-12-08 15:41:19 +03:00
|
|
|
if (!layer->IsVisible()) {
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!fContentRegionValid)
|
|
|
|
_UpdateContentRegion();
|
|
|
|
|
|
|
|
layer->ConvertToScreen(&layerRegion);
|
2005-12-20 00:16:23 +03:00
|
|
|
layerRegion.IntersectWith(&fVisibleRegion);
|
|
|
|
if (layerRegion.CountRects() > 0) {
|
|
|
|
layerRegion.IntersectWith(&layer->ScreenClipping(&fContentRegion));
|
|
|
|
|
|
|
|
//fDrawingEngine->FillRegion(layerRegion, RGBColor(255, 255, 0, 255));
|
|
|
|
//snooze(2000);
|
|
|
|
|
|
|
|
_TriggerContentRedraw(layerRegion);
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// EnableUpdateRequests
|
|
|
|
void
|
|
|
|
WindowLayer::EnableUpdateRequests()
|
|
|
|
{
|
|
|
|
// fUpdateRequestsEnabled = true;
|
|
|
|
/* if (fCumulativeRegion.CountRects() > 0) {
|
|
|
|
GetRootLayer()->MarkForRedraw(fCumulativeRegion);
|
|
|
|
GetRootLayer()->TriggerRedraw();
|
|
|
|
}*/
|
2004-08-08 00:30:58 +04:00
|
|
|
}
|
|
|
|
|
2005-10-31 14:05:52 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-09-08 20:53:42 +04:00
|
|
|
void
|
2005-12-09 20:25:32 +03:00
|
|
|
WindowLayer::MouseDown(BMessage* message, BPoint where, int32* _viewToken)
|
2005-09-08 20:53:42 +04:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// TODO: move into Decorator
|
|
|
|
if (!fBorderRegionValid)
|
|
|
|
GetBorderRegion(&fBorderRegion);
|
2005-11-29 02:36:59 +03:00
|
|
|
|
2005-11-24 20:45:26 +03:00
|
|
|
// default action is to drag the WindowLayer
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fBorderRegion.Contains(where)) {
|
2005-11-24 20:45:26 +03:00
|
|
|
// clicking WindowLayer visible area
|
2005-09-19 02:43:31 +04:00
|
|
|
|
2005-11-24 00:52:36 +03:00
|
|
|
click_type action = DEC_DRAG;
|
2005-09-19 02:43:31 +04:00
|
|
|
|
2005-11-24 00:52:36 +03:00
|
|
|
if (fDecorator)
|
2005-12-09 20:25:32 +03:00
|
|
|
action = _ActionFor(message);
|
2005-11-24 00:52:36 +03:00
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
// deactivate border buttons on first click (select)
|
|
|
|
if (!IsFocus() && action != DEC_MOVETOBACK
|
2005-11-24 00:52:36 +03:00
|
|
|
&& action != DEC_RESIZE && action != DEC_SLIDETAB)
|
|
|
|
action = DEC_DRAG;
|
|
|
|
|
|
|
|
// set decorator internals
|
|
|
|
switch (action) {
|
|
|
|
case DEC_CLOSE:
|
|
|
|
fIsClosing = true;
|
|
|
|
fDecorator->SetClose(true);
|
|
|
|
STRACE_CLICK(("===> DEC_CLOSE\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEC_ZOOM:
|
|
|
|
fIsZooming = true;
|
|
|
|
fDecorator->SetZoom(true);
|
|
|
|
STRACE_CLICK(("===> DEC_ZOOM\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEC_MINIMIZE:
|
|
|
|
fIsMinimizing = true;
|
|
|
|
fDecorator->SetMinimize(true);
|
|
|
|
STRACE_CLICK(("===> DEC_MINIMIZE\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEC_DRAG:
|
|
|
|
fIsDragging = true;
|
|
|
|
fLastMousePosition = where;
|
|
|
|
STRACE_CLICK(("===> DEC_DRAG\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEC_RESIZE:
|
|
|
|
fIsResizing = true;
|
|
|
|
fLastMousePosition = where;
|
|
|
|
STRACE_CLICK(("===> DEC_RESIZE\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEC_SLIDETAB:
|
|
|
|
fIsSlidingTab = true;
|
|
|
|
fLastMousePosition = where;
|
|
|
|
STRACE_CLICK(("===> DEC_SLIDETAB\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2005-11-12 20:49:05 +03:00
|
|
|
|
2005-12-09 01:15:12 +03:00
|
|
|
// redraw decoratpr
|
|
|
|
BRegion visibleBorder;
|
|
|
|
GetBorderRegion(&visibleBorder);
|
|
|
|
visibleBorder.IntersectWith(&VisibleRegion());
|
|
|
|
|
|
|
|
fDrawingEngine->Lock();
|
|
|
|
fDrawingEngine->ConstrainClippingRegion(&visibleBorder);
|
|
|
|
|
|
|
|
if (fIsZooming) {
|
|
|
|
fDecorator->SetZoom(true);
|
|
|
|
} else if (fIsClosing) {
|
|
|
|
fDecorator->SetClose(true);
|
|
|
|
} else if (fIsMinimizing) {
|
|
|
|
fDecorator->SetMinimize(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
fDrawingEngine->Unlock();
|
|
|
|
|
2005-11-24 00:52:36 +03:00
|
|
|
// based on what the Decorator returned, properly place this window.
|
|
|
|
if (action == DEC_MOVETOBACK) {
|
2005-12-08 15:41:19 +03:00
|
|
|
fDesktop->SendWindowBehind(this);
|
2005-11-24 00:52:36 +03:00
|
|
|
} else {
|
2005-12-08 15:41:19 +03:00
|
|
|
fDesktop->SetMouseEventWindow(this);
|
|
|
|
fDesktop->ActivateWindow(this);
|
2005-11-24 00:52:36 +03:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
} else {
|
|
|
|
if (ViewLayer* view = ViewAt(where)) {
|
|
|
|
// clicking a simple ViewLayer
|
|
|
|
if (!IsFocus()) {
|
|
|
|
DesktopSettings desktopSettings(fDesktop);
|
|
|
|
|
2005-12-09 18:40:30 +03:00
|
|
|
// Activate window in case it doesn't accept first click, and
|
|
|
|
// we're not in FFM mode
|
|
|
|
if ((Flags() & B_WILL_ACCEPT_FIRST_CLICK) == 0
|
|
|
|
&& desktopSettings.MouseMode() == B_NORMAL_MOUSE)
|
2005-12-08 15:41:19 +03:00
|
|
|
fDesktop->ActivateWindow(this);
|
|
|
|
|
|
|
|
// eat the click if we don't accept first click
|
2005-12-09 20:25:32 +03:00
|
|
|
if ((Flags() & (B_WILL_ACCEPT_FIRST_CLICK | B_AVOID_FOCUS)) == 0)
|
|
|
|
return;
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-12-09 20:25:32 +03:00
|
|
|
|
|
|
|
// fill out view token for the view under the mouse
|
|
|
|
*_viewToken = view->Token();
|
|
|
|
|
|
|
|
// TODO: that's not really a clean solution - maybe move that
|
|
|
|
// functionality back into the ViewLayer class
|
|
|
|
if (WorkspacesLayer* layer = dynamic_cast<WorkspacesLayer*>(view))
|
|
|
|
layer->MouseDown(message, where);
|
2005-11-11 01:30:43 +03:00
|
|
|
}
|
2005-09-19 02:43:31 +04:00
|
|
|
}
|
2005-09-08 20:53:42 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-09-08 20:53:42 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::MouseUp(BMessage* msg, BPoint where, int32* _viewToken)
|
2005-09-08 20:53:42 +04:00
|
|
|
{
|
2005-10-03 01:55:45 +04:00
|
|
|
bool invalidate = false;
|
2005-09-16 09:10:21 +04:00
|
|
|
if (fDecorator) {
|
2005-10-25 22:42:10 +04:00
|
|
|
click_type action = _ActionFor(msg);
|
2005-12-09 01:15:12 +03:00
|
|
|
|
|
|
|
// redraw decoratpr
|
|
|
|
BRegion visibleBorder;
|
|
|
|
GetBorderRegion(&visibleBorder);
|
|
|
|
visibleBorder.IntersectWith(&VisibleRegion());
|
|
|
|
|
|
|
|
fDrawingEngine->Lock();
|
|
|
|
fDrawingEngine->ConstrainClippingRegion(&visibleBorder);
|
|
|
|
|
|
|
|
if (fIsZooming) {
|
|
|
|
fDecorator->SetZoom(true);
|
|
|
|
} else if (fIsClosing) {
|
|
|
|
fDecorator->SetClose(true);
|
|
|
|
} else if (fIsMinimizing) {
|
|
|
|
fDecorator->SetMinimize(true);
|
|
|
|
}
|
|
|
|
|
2005-09-16 09:10:21 +04:00
|
|
|
if (fIsZooming) {
|
|
|
|
fIsZooming = false;
|
|
|
|
fDecorator->SetZoom(false);
|
2005-10-03 01:55:45 +04:00
|
|
|
if (action == DEC_ZOOM) {
|
|
|
|
invalidate = true;
|
2005-12-08 15:41:19 +03:00
|
|
|
fWindow->NotifyZoom();
|
2005-10-03 01:55:45 +04:00
|
|
|
}
|
2005-09-16 09:10:21 +04:00
|
|
|
}
|
|
|
|
if (fIsClosing) {
|
|
|
|
fIsClosing = false;
|
|
|
|
fDecorator->SetClose(false);
|
2005-10-03 01:55:45 +04:00
|
|
|
if (action == DEC_CLOSE) {
|
|
|
|
invalidate = true;
|
2005-12-08 15:41:19 +03:00
|
|
|
fWindow->NotifyQuitRequested();
|
2005-10-03 01:55:45 +04:00
|
|
|
}
|
2005-09-16 09:10:21 +04:00
|
|
|
}
|
|
|
|
if (fIsMinimizing) {
|
|
|
|
fIsMinimizing = false;
|
|
|
|
fDecorator->SetMinimize(false);
|
2005-10-03 01:55:45 +04:00
|
|
|
if (action == DEC_MINIMIZE) {
|
|
|
|
invalidate = true;
|
2005-12-08 15:41:19 +03:00
|
|
|
fWindow->NotifyMinimize(true);
|
2005-10-03 01:55:45 +04:00
|
|
|
}
|
2005-09-16 09:10:21 +04:00
|
|
|
}
|
2005-12-09 01:15:12 +03:00
|
|
|
|
|
|
|
fDrawingEngine->Unlock();
|
2005-09-16 09:10:21 +04:00
|
|
|
}
|
|
|
|
fIsDragging = false;
|
|
|
|
fIsResizing = false;
|
|
|
|
fIsSlidingTab = false;
|
2005-11-24 19:04:29 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (ViewLayer* view = ViewAt(where))
|
|
|
|
*_viewToken = view->Token();
|
2005-09-08 20:53:42 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-09-08 20:53:42 +04:00
|
|
|
void
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken)
|
2005-09-08 20:53:42 +04:00
|
|
|
{
|
2005-09-16 09:10:21 +04:00
|
|
|
if (fDecorator) {
|
2005-12-09 01:15:12 +03:00
|
|
|
|
|
|
|
BRegion visibleBorder;
|
|
|
|
GetBorderRegion(&visibleBorder);
|
|
|
|
visibleBorder.IntersectWith(&VisibleRegion());
|
|
|
|
|
|
|
|
fDrawingEngine->Lock();
|
|
|
|
fDrawingEngine->ConstrainClippingRegion(&visibleBorder);
|
|
|
|
|
2005-09-16 09:10:21 +04:00
|
|
|
if (fIsZooming) {
|
2005-10-25 22:42:10 +04:00
|
|
|
fDecorator->SetZoom(_ActionFor(msg) == DEC_ZOOM);
|
2005-09-16 09:10:21 +04:00
|
|
|
} else if (fIsClosing) {
|
2005-10-25 22:42:10 +04:00
|
|
|
fDecorator->SetClose(_ActionFor(msg) == DEC_CLOSE);
|
2005-09-16 09:10:21 +04:00
|
|
|
} else if (fIsMinimizing) {
|
2005-10-25 22:42:10 +04:00
|
|
|
fDecorator->SetMinimize(_ActionFor(msg) == DEC_MINIMIZE);
|
2005-09-16 09:10:21 +04:00
|
|
|
}
|
2005-12-09 01:15:12 +03:00
|
|
|
|
|
|
|
fDrawingEngine->Unlock();
|
2005-09-16 09:10:21 +04:00
|
|
|
}
|
2005-10-03 01:55:45 +04:00
|
|
|
|
2005-12-09 01:15:12 +03:00
|
|
|
if (fIsDragging && !(Flags() & B_NOT_MOVABLE)) {
|
2005-10-25 22:42:10 +04:00
|
|
|
BPoint delta = where - fLastMousePosition;
|
2005-12-08 15:41:19 +03:00
|
|
|
fDesktop->MoveWindowBy(this, delta.x, delta.y);
|
2005-09-16 09:10:21 +04:00
|
|
|
}
|
2005-12-09 01:15:12 +03:00
|
|
|
if (fIsResizing && !(Flags() & B_NOT_RESIZABLE)) {
|
2005-10-25 22:42:10 +04:00
|
|
|
BPoint delta = where - fLastMousePosition;
|
2005-12-08 15:41:19 +03:00
|
|
|
if (Flags() & B_NOT_V_RESIZABLE)
|
2005-12-02 13:35:01 +03:00
|
|
|
delta.y = 0;
|
2005-12-08 15:41:19 +03:00
|
|
|
if (Flags() & B_NOT_H_RESIZABLE)
|
2005-12-02 13:35:01 +03:00
|
|
|
delta.x = 0;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fDesktop->ResizeWindowBy(this, delta.x, delta.y);
|
2005-09-16 09:10:21 +04:00
|
|
|
}
|
|
|
|
if (fIsSlidingTab) {
|
|
|
|
// TODO: implement
|
|
|
|
}
|
2005-10-03 01:55:45 +04:00
|
|
|
|
2005-10-25 22:42:10 +04:00
|
|
|
fLastMousePosition = where;
|
2005-11-24 00:52:36 +03:00
|
|
|
|
|
|
|
// change focus in FFM mode
|
2005-12-08 15:41:19 +03:00
|
|
|
DesktopSettings desktopSettings(fDesktop);
|
2005-11-29 02:36:59 +03:00
|
|
|
|
Have I said input event handling is done?
* didn't realize that mouse events always go to the view under the mouse, not
only if its the focus window (FFM can really do harm, after all :-)).
* removed a TODO from the list: EventDispatcher::Target is now a public
class EventTarget, and every ServerWindow has one.
* as a result, EventDispatcher no longer manages targets itself, it
just maintains a list of them. You no longer set messengers, you
only set targets.
* customization of the message filters, they no longer inherit from
BMessageFilter (but EventFilter).
* a message target is no longer set explicetly anywhere, it's only
changed in the message filters if needed.
* therefore, no more locking mess in the EventDispatcher needed.
* this also made the EventDispatcher::fLastFocus stuff superfluous.
* moved the RootLayer::MouseEventHandler() into the message filter.
* Replaced RootLayer::_ChildAt() with WindowAt().
* WindowLayer now has an idea if it has focus or not, it no longer needs
to query the RootLayer for this - maybe we should rename "focus" to
"active", though (as far as layers are concerned).
* the "_view_token" data is now added from the EventDispatcher, not
the (Window)Layer class anymore.
* removed Layer::MouseWheelChanged() as we currently don't need it
(if the need arises, we can add it back later again)
* there is still no mouse moved message sent when opening a window
under the cursor, though...
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15228 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-11-29 19:01:41 +03:00
|
|
|
if (desktopSettings.MouseMode() != B_NORMAL_MOUSE && !IsFocus())
|
2005-12-08 15:41:19 +03:00
|
|
|
fDesktop->SetFocusWindow(this);
|
2005-11-24 19:04:29 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (ViewLayer* view = ViewAt(where))
|
|
|
|
*_viewToken = view->Token();
|
2005-09-08 20:53:42 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-09-29 01:12:38 +04:00
|
|
|
void
|
2005-11-24 20:45:26 +03:00
|
|
|
WindowLayer::WorkspaceActivated(int32 index, bool active)
|
2005-09-29 01:12:38 +04:00
|
|
|
{
|
|
|
|
BMessage activatedMsg(B_WORKSPACE_ACTIVATED);
|
2005-12-08 15:41:19 +03:00
|
|
|
activatedMsg.AddInt64("when", system_time());
|
2005-09-29 01:12:38 +04:00
|
|
|
activatedMsg.AddInt32("workspace", index);
|
|
|
|
activatedMsg.AddBool("active", active);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
ServerWindow()->SendMessageToClient(&activatedMsg);
|
2005-09-29 01:12:38 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-10-01 14:03:43 +04:00
|
|
|
void
|
2005-11-24 20:45:26 +03:00
|
|
|
WindowLayer::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces)
|
2005-10-01 14:03:43 +04:00
|
|
|
{
|
|
|
|
fWorkspaces = newWorkspaces;
|
|
|
|
|
|
|
|
BMessage changedMsg(B_WORKSPACES_CHANGED);
|
2005-12-08 15:41:19 +03:00
|
|
|
changedMsg.AddInt64("when", system_time());
|
2005-10-01 14:03:43 +04:00
|
|
|
changedMsg.AddInt32("old", oldWorkspaces);
|
|
|
|
changedMsg.AddInt32("new", newWorkspaces);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
ServerWindow()->SendMessageToClient(&changedMsg);
|
2005-10-01 14:03:43 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-10-29 15:15:47 +04:00
|
|
|
void
|
2005-11-24 20:45:26 +03:00
|
|
|
WindowLayer::Activated(bool active)
|
2005-10-29 15:15:47 +04:00
|
|
|
{
|
|
|
|
BMessage msg(B_WINDOW_ACTIVATED);
|
2005-11-15 04:42:58 +03:00
|
|
|
msg.AddBool("active", active);
|
2005-12-08 15:41:19 +03:00
|
|
|
ServerWindow()->SendMessageToClient(&msg);
|
2005-10-29 15:15:47 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
//# pragma mark -
|
2005-06-16 16:32:42 +04:00
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
2005-12-09 01:15:12 +03:00
|
|
|
WindowLayer::SetTitle(const char* name, BRegion& dirty)
|
2005-06-16 16:32:42 +04:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// rebuild the clipping for the title area
|
|
|
|
// and redraw it.
|
2005-06-16 16:32:42 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fTitle = name;
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fDecorator) {
|
2005-12-09 01:15:12 +03:00
|
|
|
fDecorator->SetTitle(name, &dirty);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2005-12-09 01:15:12 +03:00
|
|
|
fBorderRegionValid = false;
|
|
|
|
// the border very likely changed
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2005-06-16 16:32:42 +04:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::SetFocus(bool focus)
|
2003-02-24 18:47:06 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// executed from Desktop thread
|
|
|
|
// it holds the clipping write lock,
|
|
|
|
// so the window thread cannot be
|
|
|
|
// accessing fIsFocus
|
|
|
|
|
|
|
|
BRegion dirty(fBorderRegion);
|
|
|
|
dirty.IntersectWith(&fVisibleRegion);
|
|
|
|
fDesktop->MarkDirty(dirty);
|
|
|
|
|
|
|
|
fIsFocus = focus;
|
|
|
|
if (fDecorator)
|
|
|
|
fDecorator->SetFocus(focus);
|
|
|
|
|
|
|
|
Activated(focus);
|
2003-02-24 18:47:06 +03:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::SetHidden(bool hidden)
|
2003-02-24 18:47:06 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// the desktop takes care of dirty regions
|
|
|
|
if (fHidden != hidden) {
|
|
|
|
fHidden = hidden;
|
|
|
|
|
|
|
|
fTopLayer->SetHidden(hidden);
|
|
|
|
|
|
|
|
// TODO: anything else?
|
|
|
|
}
|
2003-02-24 18:47:06 +03:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
bool
|
|
|
|
WindowLayer::IsVisible() const
|
2003-02-24 18:47:06 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (IsOffscreenWindow())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (IsHidden())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (fVisibleRegion.CountRects() == 0)
|
|
|
|
return false;
|
|
|
|
*/
|
|
|
|
return fCurrentWorkspace >= 0 && fCurrentWorkspace < kWorkingList;
|
2003-02-24 18:47:06 +03:00
|
|
|
}
|
|
|
|
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::SetSizeLimits(int32 minWidth, int32 maxWidth,
|
|
|
|
int32 minHeight, int32 maxHeight)
|
2003-02-24 18:47:06 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (minWidth < 0)
|
|
|
|
minWidth = 0;
|
2005-02-28 23:23:51 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (minHeight < 0)
|
|
|
|
minHeight = 0;
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fMinWidth = minWidth;
|
|
|
|
fMaxWidth = maxWidth;
|
|
|
|
fMinHeight = minHeight;
|
|
|
|
fMaxHeight = maxHeight;
|
2005-12-02 18:42:28 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// give the Decorator a say in this too
|
|
|
|
if (fDecorator) {
|
|
|
|
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight,
|
|
|
|
&fMaxWidth, &fMaxHeight);
|
|
|
|
}
|
2005-12-02 18:42:28 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
_ObeySizeLimits();
|
|
|
|
}
|
2005-12-02 18:42:28 +03:00
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
WindowLayer::GetSizeLimits(int32* minWidth, int32* maxWidth,
|
|
|
|
int32* minHeight, int32* maxHeight) const
|
|
|
|
{
|
|
|
|
*minWidth = fMinWidth;
|
|
|
|
*maxWidth = fMaxWidth;
|
|
|
|
*minHeight = fMinHeight;
|
|
|
|
*maxHeight = fMaxHeight;
|
2005-12-02 18:42:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
WindowLayer::SetTabLocation(float location)
|
2005-11-29 02:36:59 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fDecorator)
|
|
|
|
fDecorator->SetTabLocation(location);
|
|
|
|
}
|
2005-11-29 02:36:59 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
float
|
|
|
|
WindowLayer::TabLocation() const
|
|
|
|
{
|
|
|
|
if (fDecorator)
|
|
|
|
return fDecorator->TabLocation();
|
|
|
|
return 0.0;
|
2005-11-29 02:36:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-01 16:59:04 +03:00
|
|
|
void
|
|
|
|
WindowLayer::SetLook(window_look look, BRegion* updateRegion)
|
|
|
|
{
|
2005-12-01 17:56:01 +03:00
|
|
|
if (fDecorator == NULL && look != B_NO_BORDER_WINDOW_LOOK) {
|
|
|
|
// we need a new decorator
|
2005-12-08 15:41:19 +03:00
|
|
|
fDecorator = gDecorManager.AllocateDecorator(fDesktop, Frame(),
|
|
|
|
Title(), fLook, fFlags);
|
2005-12-01 17:56:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fLook = look;
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
fBorderRegionValid = false;
|
|
|
|
// the border very likely changed
|
|
|
|
fContentRegionValid = false;
|
|
|
|
// mabye a resize handle was added...
|
|
|
|
fEffectiveDrawingRegionValid = false;
|
|
|
|
// ...and therefor the drawing region is
|
|
|
|
// likely not valid anymore either
|
2005-12-01 17:56:01 +03:00
|
|
|
|
|
|
|
if (fDecorator != NULL) {
|
2005-12-08 15:41:19 +03:00
|
|
|
DesktopSettings settings(fDesktop);
|
2005-12-01 17:56:01 +03:00
|
|
|
fDecorator->SetLook(settings, look, updateRegion);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// we might need to resize the window!
|
|
|
|
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth, &fMaxHeight);
|
|
|
|
_ObeySizeLimits();
|
2005-12-01 17:56:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (look == B_NO_BORDER_WINDOW_LOOK) {
|
|
|
|
// we don't need a decorator for this window
|
|
|
|
delete fDecorator;
|
|
|
|
fDecorator = NULL;
|
|
|
|
}
|
2005-12-01 16:59:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-03 23:50:30 +04:00
|
|
|
void
|
2005-12-01 15:07:28 +03:00
|
|
|
WindowLayer::SetFeel(window_feel feel)
|
2005-02-28 23:23:51 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// if the subset list is no longer needed, clear it
|
|
|
|
if ((fFeel == B_MODAL_SUBSET_WINDOW_FEEL || fFeel == B_FLOATING_SUBSET_WINDOW_FEEL)
|
|
|
|
&& (feel != B_MODAL_SUBSET_WINDOW_FEEL && feel != B_FLOATING_SUBSET_WINDOW_FEEL))
|
|
|
|
fSubsets.MakeEmpty();
|
|
|
|
|
2005-04-21 22:57:34 +04:00
|
|
|
fFeel = feel;
|
|
|
|
|
2005-12-02 13:35:01 +03:00
|
|
|
// having modal windows with B_AVOID_FRONT or B_AVOID_FOCUS doesn't
|
|
|
|
// make that much sense, so we filter those flags out on demand
|
2005-12-09 17:06:30 +03:00
|
|
|
fFlags = fOriginalFlags;
|
|
|
|
fFlags &= ValidWindowFlags(fFeel);
|
2005-12-09 16:17:43 +03:00
|
|
|
|
2005-12-09 17:06:30 +03:00
|
|
|
if (!IsNormal()) {
|
2005-12-09 16:17:43 +03:00
|
|
|
fFlags |= B_SAME_POSITION_IN_ALL_WORKSPACES;
|
2005-12-09 17:06:30 +03:00
|
|
|
_PropagatePosition();
|
|
|
|
}
|
2005-06-03 23:50:30 +04:00
|
|
|
}
|
|
|
|
|
2005-11-14 20:39:33 +03:00
|
|
|
|
2005-12-01 16:59:04 +03:00
|
|
|
void
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::SetFlags(uint32 flags, BRegion* updateRegion)
|
2005-12-01 16:59:04 +03:00
|
|
|
{
|
2005-12-09 17:06:30 +03:00
|
|
|
fOriginalFlags = flags;
|
|
|
|
fFlags = flags & ValidWindowFlags(fFeel);
|
|
|
|
if (!IsNormal())
|
|
|
|
fFlags |= B_SAME_POSITION_IN_ALL_WORKSPACES;
|
|
|
|
|
|
|
|
if ((fFlags & B_SAME_POSITION_IN_ALL_WORKSPACES) != 0)
|
|
|
|
_PropagatePosition();
|
2005-12-01 18:02:11 +03:00
|
|
|
|
|
|
|
if (fDecorator == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fDecorator->SetFlags(flags, updateRegion);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fBorderRegionValid = false;
|
|
|
|
// the border might have changed (smaller/larger tab)
|
|
|
|
|
|
|
|
// we might need to resize the window!
|
|
|
|
if (fDecorator) {
|
|
|
|
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth, &fMaxHeight);
|
|
|
|
_ObeySizeLimits();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-09 18:40:30 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
/*!
|
|
|
|
\brief Returns wether or not the window is visible on the specified
|
|
|
|
workspace.
|
|
|
|
|
|
|
|
A modal or floating window may be visible on a workscreen if one
|
|
|
|
of its subset windows is visible there.
|
|
|
|
*/
|
|
|
|
bool
|
2005-12-09 16:17:43 +03:00
|
|
|
WindowLayer::InWorkspace(int32 index) const
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
2005-12-09 16:17:43 +03:00
|
|
|
if (IsNormal())
|
|
|
|
return (fWorkspaces & (1UL << index)) != 0;
|
|
|
|
|
|
|
|
if (fFeel == B_MODAL_ALL_WINDOW_FEEL
|
2005-12-08 15:41:19 +03:00
|
|
|
|| fFeel == B_FLOATING_ALL_WINDOW_FEEL)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (fFeel == B_MODAL_APP_WINDOW_FEEL
|
|
|
|
|| fFeel == B_FLOATING_APP_WINDOW_FEEL)
|
2005-12-09 16:17:43 +03:00
|
|
|
return ServerWindow()->App()->InWorkspace(index);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
if (fFeel == B_MODAL_SUBSET_WINDOW_FEEL
|
|
|
|
|| fFeel == B_FLOATING_SUBSET_WINDOW_FEEL) {
|
|
|
|
for (int32 i = 0; i < fSubsets.CountItems(); i++) {
|
|
|
|
WindowLayer* window = fSubsets.ItemAt(i);
|
2005-12-09 16:17:43 +03:00
|
|
|
if (window->InWorkspace(index))
|
2005-12-08 15:41:19 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
WindowLayer::SupportsFront()
|
|
|
|
{
|
|
|
|
if (fFeel == kDesktopWindowFeel)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
2005-12-01 16:59:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-02 13:35:01 +03:00
|
|
|
bool
|
|
|
|
WindowLayer::IsModal() const
|
|
|
|
{
|
|
|
|
return IsModalFeel(fFeel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
WindowLayer::IsFloating() const
|
|
|
|
{
|
|
|
|
return IsFloatingFeel(fFeel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
bool
|
|
|
|
WindowLayer::IsNormal() const
|
|
|
|
{
|
|
|
|
return !IsFloatingFeel(fFeel) && !IsModalFeel(fFeel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Returns the windows that's in behind of the backmost position
|
|
|
|
this window can get.
|
|
|
|
Returns NULL is this window can be the backmost window.
|
|
|
|
*/
|
|
|
|
WindowLayer*
|
|
|
|
WindowLayer::Backmost(WindowLayer* window, int32 workspace)
|
|
|
|
{
|
|
|
|
if (workspace == -1)
|
|
|
|
workspace = fCurrentWorkspace;
|
|
|
|
|
|
|
|
if (fFeel == kDesktopWindowFeel)
|
|
|
|
return NULL;
|
|
|
|
else if (fFeel == B_FLOATING_ALL_WINDOW_FEEL)
|
|
|
|
return window ? window : PreviousWindow(workspace);
|
|
|
|
|
|
|
|
if (window == NULL)
|
|
|
|
window = PreviousWindow(workspace);
|
|
|
|
|
|
|
|
for (; window != NULL; window = window->PreviousWindow(workspace)) {
|
|
|
|
if (window->IsHidden() || window == this)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (HasInSubset(window))
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-02 18:06:14 +03:00
|
|
|
/*!
|
|
|
|
\brief Returns the windows that's in front of the frontmost position
|
|
|
|
this window can get.
|
|
|
|
Returns NULL is this window can be the frontmost window.
|
|
|
|
*/
|
|
|
|
WindowLayer*
|
2005-12-08 15:41:19 +03:00
|
|
|
WindowLayer::Frontmost(WindowLayer* first, int32 workspace)
|
2005-12-02 18:06:14 +03:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (workspace == -1)
|
|
|
|
workspace = fCurrentWorkspace;
|
|
|
|
|
|
|
|
if (fFeel == kDesktopWindowFeel)
|
|
|
|
return first ? first : NextWindow(workspace);
|
|
|
|
|
2005-12-02 18:06:14 +03:00
|
|
|
if (fFeel == B_FLOATING_ALL_WINDOW_FEEL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (first == NULL)
|
2005-12-08 15:41:19 +03:00
|
|
|
first = NextWindow(workspace);
|
2005-12-02 18:06:14 +03:00
|
|
|
|
|
|
|
for (WindowLayer* window = first; window != NULL;
|
2005-12-08 15:41:19 +03:00
|
|
|
window = window->NextWindow(workspace)) {
|
|
|
|
if (window->IsHidden() || window == this)
|
2005-12-02 18:06:14 +03:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// no one can be in front of a floating all window
|
|
|
|
if (window->Feel() == B_FLOATING_ALL_WINDOW_FEEL)
|
|
|
|
return window;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (window->HasInSubset(this))
|
2005-12-02 18:06:14 +03:00
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
WindowLayer::AddToSubset(WindowLayer* window)
|
|
|
|
{
|
|
|
|
return fSubsets.AddItem(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::RemoveFromSubset(WindowLayer* window)
|
|
|
|
{
|
|
|
|
fSubsets.RemoveItem(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
WindowLayer::HasInSubset(WindowLayer* window)
|
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fFeel == B_MODAL_APP_WINDOW_FEEL && window->Feel() == B_MODAL_ALL_WINDOW_FEEL
|
|
|
|
|| fFeel == B_NORMAL_WINDOW_FEEL
|
|
|
|
|| fFeel == window->Feel())
|
|
|
|
return false;
|
|
|
|
|
2005-12-02 18:06:14 +03:00
|
|
|
if (fFeel == B_FLOATING_ALL_WINDOW_FEEL
|
|
|
|
|| fFeel == B_MODAL_ALL_WINDOW_FEEL)
|
|
|
|
return true;
|
|
|
|
|
2005-12-02 18:48:21 +03:00
|
|
|
if (fFeel == B_FLOATING_APP_WINDOW_FEEL
|
|
|
|
|| fFeel == B_MODAL_APP_WINDOW_FEEL)
|
2005-12-08 15:41:19 +03:00
|
|
|
return window->ServerWindow()->App() == ServerWindow()->App();
|
2005-12-02 18:48:21 +03:00
|
|
|
|
2005-12-02 18:06:14 +03:00
|
|
|
return fSubsets.HasItem(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
bool
|
|
|
|
WindowLayer::SameSubset(WindowLayer* window)
|
2005-06-03 23:50:30 +04:00
|
|
|
{
|
2005-12-08 15:41:19 +03:00
|
|
|
// TODO: this is probably not needed at all, but it doesn't hurt to have it in svn
|
|
|
|
if (fFeel == B_MODAL_ALL_WINDOW_FEEL || window->Feel() == B_MODAL_ALL_WINDOW_FEEL)
|
|
|
|
return fFeel == window->Feel();
|
2005-06-03 23:50:30 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fFeel == B_MODAL_APP_WINDOW_FEEL || window->Feel() == B_MODAL_APP_WINDOW_FEEL)
|
|
|
|
return ServerWindow()->App() == window->ServerWindow()->App();
|
2005-11-11 01:30:43 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fFeel == B_MODAL_SUBSET_WINDOW_FEEL) {
|
|
|
|
// we basically need to check if the subsets have anything in common
|
|
|
|
for (int32 i = fSubsets.CountItems(); i-- > 0;) {
|
|
|
|
if (window->HasInSubset(fSubsets.ItemAt(i)))
|
|
|
|
return true;
|
|
|
|
}
|
2005-06-22 00:11:44 +04:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
if (window->Feel() == B_MODAL_SUBSET_WINDOW_FEEL) {
|
|
|
|
for (int32 i = window->fSubsets.CountItems(); i-- > 0;) {
|
|
|
|
if (HasInSubset(window->fSubsets.ItemAt(i)))
|
|
|
|
return true;
|
2005-11-06 20:47:06 +03:00
|
|
|
}
|
|
|
|
}
|
offscreen bitmaps work, tested on Haiku as well, supports all colorspaces that BBitmap::ImportBits() supports. It uses a fallback for non-B_RGB(A)32 bitmaps. Added support for B_SUB_PIXEL_PRECISION view flags, though it is a bit hacky, since I had to add it to LayerData, even though it is not a true part of stack data. Added Layer::SetFlags() to enforce code path and update fLayerData. Cleaned up DisplayDriverPainter and DisplayDriver API (changed some const BRect& rect to simply BRect rect in order to be able to reuse it in the code), moved Painter.h, the test environment only draws the changed part of the frame buffer again - this causes a lot less CPU overhead, Painter special cases stroke width of 1.0 to use square caps, which is similar to R5 implementation and removes a lot of problems with non-straight line drawing, ServerWindow uses the DisplayDriver from it's WinBorder instead of the one from the Desktop (needed for offscreen windows, which have their own DisplayDriverPainter), it also checks for GetRootLayer() == NULL, because offscreen layers are not attached to a RootLayer, there was a fix for scrolling which worked at least in the test environment, it is now defunced, because Adi moved _CopyBits to Layer... I need to reenable it later, LayerData has no more fEscapementDelta, also fixed fFontAliasing (which was thought to overriding the font flags, and now works as such again), Desktop initialises the menu_info and scroll_bar_info stuff, which makes ScrollBars work actually... hope I didn't forget something.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13448 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-07-05 20:17:16 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
return false;
|
2005-11-24 20:54:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-09 16:17:43 +03:00
|
|
|
uint32
|
|
|
|
WindowLayer::SubsetWorkspaces() const
|
|
|
|
{
|
|
|
|
if (fFeel == B_MODAL_ALL_WINDOW_FEEL
|
|
|
|
|| fFeel == B_FLOATING_ALL_WINDOW_FEEL)
|
|
|
|
return B_ALL_WORKSPACES;
|
|
|
|
|
|
|
|
if (fFeel == B_MODAL_APP_WINDOW_FEEL
|
|
|
|
|| fFeel == B_FLOATING_APP_WINDOW_FEEL)
|
|
|
|
return ServerWindow()->App()->Workspaces();
|
|
|
|
|
|
|
|
if (fFeel == B_MODAL_SUBSET_WINDOW_FEEL
|
|
|
|
|| fFeel == B_FLOATING_SUBSET_WINDOW_FEEL) {
|
|
|
|
uint32 workspaces = 0;
|
|
|
|
for (int32 i = 0; i < fSubsets.CountItems(); i++) {
|
|
|
|
WindowLayer* window = fSubsets.ItemAt(i);
|
|
|
|
|
|
|
|
if (!window->IsHidden())
|
|
|
|
workspaces |= window->Workspaces();
|
|
|
|
}
|
|
|
|
|
|
|
|
return workspaces;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// #pragma mark - static
|
offscreen bitmaps work, tested on Haiku as well, supports all colorspaces that BBitmap::ImportBits() supports. It uses a fallback for non-B_RGB(A)32 bitmaps. Added support for B_SUB_PIXEL_PRECISION view flags, though it is a bit hacky, since I had to add it to LayerData, even though it is not a true part of stack data. Added Layer::SetFlags() to enforce code path and update fLayerData. Cleaned up DisplayDriverPainter and DisplayDriver API (changed some const BRect& rect to simply BRect rect in order to be able to reuse it in the code), moved Painter.h, the test environment only draws the changed part of the frame buffer again - this causes a lot less CPU overhead, Painter special cases stroke width of 1.0 to use square caps, which is similar to R5 implementation and removes a lot of problems with non-straight line drawing, ServerWindow uses the DisplayDriver from it's WinBorder instead of the one from the Desktop (needed for offscreen windows, which have their own DisplayDriverPainter), it also checks for GetRootLayer() == NULL, because offscreen layers are not attached to a RootLayer, there was a fix for scrolling which worked at least in the test environment, it is now defunced, because Adi moved _CopyBits to Layer... I need to reenable it later, LayerData has no more fEscapementDelta, also fixed fFontAliasing (which was thought to overriding the font flags, and now works as such again), Desktop initialises the menu_info and scroll_bar_info stuff, which makes ScrollBars work actually... hope I didn't forget something.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13448 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-07-05 20:17:16 +04:00
|
|
|
|
2005-12-01 18:58:04 +03:00
|
|
|
|
|
|
|
/*static*/
|
|
|
|
bool
|
|
|
|
WindowLayer::IsValidLook(window_look look)
|
|
|
|
{
|
|
|
|
return look == B_TITLED_WINDOW_LOOK
|
|
|
|
|| look == B_DOCUMENT_WINDOW_LOOK
|
|
|
|
|| look == B_MODAL_WINDOW_LOOK
|
|
|
|
|| look == B_FLOATING_WINDOW_LOOK
|
|
|
|
|| look == B_BORDERED_WINDOW_LOOK
|
|
|
|
|| look == B_NO_BORDER_WINDOW_LOOK
|
|
|
|
|| look == kDesktopWindowLook
|
|
|
|
|| look == kLeftTitledWindowLook;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*static*/
|
|
|
|
bool
|
|
|
|
WindowLayer::IsValidFeel(window_feel feel)
|
|
|
|
{
|
|
|
|
return feel == B_NORMAL_WINDOW_FEEL
|
|
|
|
|| feel == B_MODAL_SUBSET_WINDOW_FEEL
|
|
|
|
|| feel == B_MODAL_APP_WINDOW_FEEL
|
|
|
|
|| feel == B_MODAL_ALL_WINDOW_FEEL
|
|
|
|
|| feel == B_FLOATING_SUBSET_WINDOW_FEEL
|
|
|
|
|| feel == B_FLOATING_APP_WINDOW_FEEL
|
|
|
|
|| feel == B_FLOATING_ALL_WINDOW_FEEL
|
|
|
|
|| feel == kDesktopWindowFeel
|
|
|
|
|| feel == kMenuWindowFeel
|
|
|
|
|| feel == kWindowScreenFeel;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-02 13:35:01 +03:00
|
|
|
/*static*/
|
|
|
|
bool
|
|
|
|
WindowLayer::IsModalFeel(window_feel feel)
|
|
|
|
{
|
|
|
|
return feel == B_MODAL_SUBSET_WINDOW_FEEL
|
|
|
|
|| feel == B_MODAL_APP_WINDOW_FEEL
|
|
|
|
|| feel == B_MODAL_ALL_WINDOW_FEEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*static*/
|
|
|
|
bool
|
|
|
|
WindowLayer::IsFloatingFeel(window_feel feel)
|
|
|
|
{
|
|
|
|
return feel == B_FLOATING_SUBSET_WINDOW_FEEL
|
|
|
|
|| feel == B_FLOATING_APP_WINDOW_FEEL
|
|
|
|
|| feel == B_FLOATING_ALL_WINDOW_FEEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-01 18:58:04 +03:00
|
|
|
/*static*/
|
|
|
|
uint32
|
|
|
|
WindowLayer::ValidWindowFlags()
|
|
|
|
{
|
|
|
|
return B_NOT_MOVABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE
|
|
|
|
| B_NOT_MINIMIZABLE | B_NOT_RESIZABLE
|
|
|
|
| B_NOT_H_RESIZABLE | B_NOT_V_RESIZABLE
|
|
|
|
| B_AVOID_FRONT | B_AVOID_FOCUS
|
|
|
|
| B_WILL_ACCEPT_FIRST_CLICK | B_OUTLINE_RESIZE
|
|
|
|
| B_NO_WORKSPACE_ACTIVATION
|
|
|
|
| B_NOT_ANCHORED_ON_ACTIVATE
|
|
|
|
| B_ASYNCHRONOUS_CONTROLS
|
|
|
|
| B_QUIT_ON_WINDOW_CLOSE
|
2005-12-09 17:06:30 +03:00
|
|
|
| B_SAME_POSITION_IN_ALL_WORKSPACES
|
2005-12-01 18:58:04 +03:00
|
|
|
| kWorkspacesWindowFlag
|
|
|
|
| kWindowScreenFlag;
|
|
|
|
}
|
|
|
|
|
2005-12-02 13:35:01 +03:00
|
|
|
|
|
|
|
/*static*/
|
|
|
|
uint32
|
|
|
|
WindowLayer::ValidWindowFlags(window_feel feel)
|
|
|
|
{
|
|
|
|
uint32 flags = ValidWindowFlags();
|
|
|
|
if (IsModalFeel(feel))
|
|
|
|
return flags & ~(B_AVOID_FOCUS | B_AVOID_FRONT);
|
|
|
|
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark - private
|
|
|
|
|
|
|
|
// _ShiftPartOfRegion
|
|
|
|
void
|
|
|
|
WindowLayer::_ShiftPartOfRegion(BRegion* region, BRegion* regionToShift,
|
|
|
|
int32 xOffset, int32 yOffset)
|
|
|
|
{
|
|
|
|
BRegion common(*regionToShift);
|
|
|
|
// see if there is a common part at all
|
|
|
|
common.IntersectWith(region);
|
|
|
|
if (common.CountRects() > 0) {
|
|
|
|
// cut the common part from the region,
|
|
|
|
// offset that to destination and include again
|
|
|
|
region->Exclude(&common);
|
|
|
|
common.OffsetBy(xOffset, yOffset);
|
|
|
|
region->Include(&common);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2005-12-20 00:16:23 +03:00
|
|
|
WindowLayer::_TriggerContentRedraw(BRegion& dirtyContentRegion)
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
|
|
|
if (dirtyContentRegion.CountRects() > 0) {
|
|
|
|
// send UPDATE message to the client
|
2005-12-10 11:05:25 +03:00
|
|
|
_TransferToUpdateSession(&dirtyContentRegion);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
if (!fContentRegionValid)
|
|
|
|
_UpdateContentRegion();
|
|
|
|
|
|
|
|
if (fDrawingEngine->Lock()) {
|
|
|
|
fDrawingEngine->ConstrainClippingRegion(&dirtyContentRegion);
|
|
|
|
#if DELAYED_BACKGROUND_CLEARING
|
|
|
|
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
|
|
|
|
&fContentRegion, false);
|
|
|
|
#else
|
|
|
|
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
|
|
|
|
&fContentRegion, true);
|
|
|
|
#endif
|
|
|
|
fDrawingEngine->Unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::_DrawBorder()
|
|
|
|
{
|
|
|
|
// this is executed in the window thread, but only
|
|
|
|
// in respond to a REDRAW message having been received, the
|
|
|
|
// clipping lock is held for reading
|
|
|
|
|
|
|
|
if (!fDecorator)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// construct the region of the border that needs redrawing
|
|
|
|
BRegion dirtyBorderRegion;
|
|
|
|
GetBorderRegion(&dirtyBorderRegion);
|
|
|
|
// intersect with our visible region
|
|
|
|
dirtyBorderRegion.IntersectWith(&fVisibleRegion);
|
|
|
|
// intersect with the dirty region
|
|
|
|
dirtyBorderRegion.IntersectWith(&fDirtyRegion);
|
|
|
|
|
|
|
|
if (dirtyBorderRegion.CountRects() > 0) {
|
|
|
|
// TODO: decorator drawing with update region...
|
|
|
|
fDrawingEngine->ConstrainClippingRegion(&dirtyBorderRegion);
|
|
|
|
fDecorator->Draw(dirtyBorderRegion.Frame());
|
|
|
|
fDrawingEngine->ConstrainClippingRegion(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
pre: the clipping is readlocked (this function is
|
|
|
|
only called from _TriggerContentRedraw()), which
|
|
|
|
in turn is only called from MessageReceived() with
|
|
|
|
the clipping lock held
|
|
|
|
*/
|
|
|
|
void
|
2005-12-10 11:05:25 +03:00
|
|
|
WindowLayer::_TransferToUpdateSession(BRegion* contentDirtyRegion)
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
|
|
|
if (contentDirtyRegion->CountRects() <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// add to pending
|
|
|
|
fPendingUpdateSession.SetUsed(true);
|
|
|
|
fPendingUpdateSession.Include(contentDirtyRegion);
|
|
|
|
|
|
|
|
// clip pending update session from current
|
|
|
|
// update session, it makes no sense to draw stuff
|
|
|
|
// already needing a redraw anyways. Theoretically,
|
|
|
|
// this could be done smarter (clip layers from pending
|
|
|
|
// that have not yet been redrawn in the current update
|
|
|
|
// session)
|
|
|
|
if (fCurrentUpdateSession.IsUsed()) {
|
|
|
|
fCurrentUpdateSession.Exclude(contentDirtyRegion);
|
|
|
|
fEffectiveDrawingRegionValid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fUpdateRequested) {
|
|
|
|
// send this to client
|
|
|
|
_SendUpdateMessage();
|
|
|
|
// as long as we have not received
|
|
|
|
// the "begin update" command, the
|
|
|
|
// pending session does not become the
|
|
|
|
// current
|
|
|
|
// TODO: problem: since we sent the update regions frame,
|
|
|
|
// we should not add to the pending session after we
|
|
|
|
// sent the update message!!!
|
|
|
|
} else {
|
|
|
|
if (!fCurrentUpdateSession.IsUsed())
|
2005-12-10 11:05:25 +03:00
|
|
|
fprintf(stderr, "WindowLayer(%s)::_TransferToUpdateSession() - pending region changed before BeginUpdate()!\n", Title());
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// _SendUpdateMessage
|
|
|
|
void
|
|
|
|
WindowLayer::_SendUpdateMessage()
|
|
|
|
{
|
|
|
|
BMessage message(_UPDATE_);
|
|
|
|
BRect updateRect = fPendingUpdateSession.DirtyRegion().Frame();
|
|
|
|
updateRect.OffsetBy(-fFrame.left, -fFrame.top);
|
|
|
|
message.AddRect("_rect", updateRect);
|
|
|
|
ServerWindow()->SendMessageToClient(&message);
|
2005-12-20 00:16:23 +03:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fUpdateRequested = true;
|
|
|
|
|
|
|
|
// TODO: the toggling between the update sessions is too
|
|
|
|
// expensive, optimize with some pointer tricks
|
|
|
|
fCurrentUpdateSession = fPendingUpdateSession;
|
|
|
|
fPendingUpdateSession.SetUsed(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::BeginUpdate()
|
|
|
|
{
|
|
|
|
// NOTE: since we might "shift" parts of the
|
|
|
|
// internal dirty regions from the desktop thread
|
|
|
|
// in response to WindowLayer::ResizeBy(), which
|
|
|
|
// might move arround views, this function needs to block
|
|
|
|
// on the global clipping lock so that the internal
|
|
|
|
// dirty regions are not messed with from the Desktop thread
|
|
|
|
// and ServerWindow thread at the same time.
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!fDesktop->LockSingleWindow())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (fUpdateRequested && fCurrentUpdateSession.IsUsed()) {
|
|
|
|
// all drawing command from the client
|
|
|
|
// will have the dirty region from the update
|
|
|
|
// session enforced
|
|
|
|
fInUpdate = true;
|
|
|
|
fEffectiveDrawingRegionValid = false;
|
|
|
|
}
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::EndUpdate()
|
|
|
|
{
|
|
|
|
// NOTE: see comment in _BeginUpdate()
|
2005-12-12 13:41:31 +03:00
|
|
|
if (!fDesktop->LockSingleWindow())
|
2005-12-08 15:41:19 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (fInUpdate) {
|
|
|
|
fCurrentUpdateSession.SetUsed(false);
|
|
|
|
|
|
|
|
fInUpdate = false;
|
|
|
|
fEffectiveDrawingRegionValid = false;
|
|
|
|
}
|
|
|
|
if (fPendingUpdateSession.IsUsed()) {
|
|
|
|
// send this to client
|
|
|
|
_SendUpdateMessage();
|
|
|
|
} else {
|
|
|
|
fUpdateRequested = false;
|
|
|
|
}
|
|
|
|
|
2005-12-12 13:41:31 +03:00
|
|
|
fDesktop->UnlockSingleWindow();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::_UpdateContentRegion()
|
|
|
|
{
|
|
|
|
// TODO: speed up by avoiding "Exclude()"
|
|
|
|
// start from the frame, extend to include decorator border
|
|
|
|
fContentRegion.Set(fFrame);
|
|
|
|
|
|
|
|
// resize handle
|
|
|
|
if (fDecorator) {
|
|
|
|
if (!fBorderRegionValid)
|
|
|
|
GetBorderRegion(&fBorderRegion);
|
|
|
|
|
|
|
|
fContentRegion.Exclude(&fBorderRegion);
|
|
|
|
}
|
|
|
|
|
|
|
|
fContentRegionValid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
click_type
|
|
|
|
WindowLayer::_ActionFor(const BMessage* msg) const
|
|
|
|
{
|
|
|
|
BPoint where(0, 0);
|
|
|
|
int32 buttons = 0;
|
|
|
|
int32 modifiers = 0;
|
|
|
|
|
|
|
|
msg->FindPoint("where", &where);
|
|
|
|
msg->FindInt32("buttons", &buttons);
|
|
|
|
msg->FindInt32("modifiers", &modifiers);
|
|
|
|
|
|
|
|
if (fDecorator)
|
|
|
|
return fDecorator->Clicked(where, buttons, modifiers);
|
|
|
|
|
|
|
|
return DEC_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// _ObeySizeLimits
|
|
|
|
void
|
|
|
|
WindowLayer::_ObeySizeLimits()
|
|
|
|
{
|
|
|
|
// make sure we even have valid size limits
|
|
|
|
if (fMaxWidth < fMinWidth)
|
|
|
|
fMaxWidth = fMinWidth;
|
|
|
|
|
|
|
|
if (fMaxHeight < fMinHeight)
|
|
|
|
fMaxHeight = fMinHeight;
|
|
|
|
|
|
|
|
// Automatically resize the window to fit these new limits
|
|
|
|
// if it does not already.
|
|
|
|
|
|
|
|
// On R5, Windows don't automatically resize, but since
|
|
|
|
// BWindow::ResizeTo() even honors the limits, I would guess
|
|
|
|
// this is a bug that we don't have to adopt.
|
|
|
|
// Note that most current apps will do unnecessary resizing
|
|
|
|
// after having set the limits, but the overhead is neglible.
|
|
|
|
|
|
|
|
float minWidthDiff = fMinWidth - fFrame.Width();
|
|
|
|
float minHeightDiff = fMinHeight - fFrame.Height();
|
|
|
|
float maxWidthDiff = fMaxWidth - fFrame.Width();
|
|
|
|
float maxHeightDiff = fMaxHeight - fFrame.Height();
|
|
|
|
|
|
|
|
float xDiff = 0.0;
|
|
|
|
if (minWidthDiff > 0.0) // we're currently smaller than minWidth
|
|
|
|
xDiff = minWidthDiff;
|
|
|
|
else if (maxWidthDiff < 0.0) // we're currently larger than maxWidth
|
|
|
|
xDiff = maxWidthDiff;
|
|
|
|
|
|
|
|
float yDiff = 0.0;
|
|
|
|
if (minHeightDiff > 0.0) // we're currently smaller than minHeight
|
|
|
|
yDiff = minHeightDiff;
|
|
|
|
else if (maxHeightDiff < 0.0) // we're currently larger than maxHeight
|
|
|
|
yDiff = maxHeightDiff;
|
|
|
|
|
|
|
|
if (fDesktop)
|
|
|
|
fDesktop->ResizeWindowBy(this, xDiff, yDiff);
|
|
|
|
else
|
|
|
|
ResizeBy(xDiff, yDiff, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// #pragma mark - UpdateSession
|
|
|
|
|
|
|
|
// constructor
|
|
|
|
WindowLayer::UpdateSession::UpdateSession()
|
|
|
|
: fDirtyRegion(),
|
|
|
|
fInUse(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// destructor
|
|
|
|
WindowLayer::UpdateSession::~UpdateSession()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Include
|
|
|
|
void
|
|
|
|
WindowLayer::UpdateSession::Include(BRegion* additionalDirty)
|
|
|
|
{
|
|
|
|
fDirtyRegion.Include(additionalDirty);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::UpdateSession::Exclude(BRegion* dirtyInNextSession)
|
|
|
|
{
|
|
|
|
fDirtyRegion.Exclude(dirtyInNextSession);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::UpdateSession::MoveBy(int32 x, int32 y)
|
|
|
|
{
|
|
|
|
fDirtyRegion.OffsetBy(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WindowLayer::UpdateSession::SetUsed(bool used)
|
|
|
|
{
|
|
|
|
fInUse = used;
|
|
|
|
if (!fInUse)
|
|
|
|
fDirtyRegion.MakeEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
WindowLayer::UpdateSession&
|
|
|
|
WindowLayer::UpdateSession::operator=(const WindowLayer::UpdateSession& other)
|
|
|
|
{
|
|
|
|
fDirtyRegion = other.fDirtyRegion;
|
|
|
|
fInUse = other.fInUse;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|