huge cleanup, support for SetSizeLimits, support for truncating strings, numerous decorator bug fixes, Layer does not draw when view color is B_TRANSPARENT_COLOR, cleaner dispatching of mouse events to the WinBorder in RootLayer, commented the char map selection in the font server, as it seems glyph lookup by unicode index works much better with the default map

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12945 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2005-06-03 19:50:30 +00:00
parent e4f0f510a9
commit 59345e264f
20 changed files with 2489 additions and 1717 deletions

View File

@ -0,0 +1,22 @@
/*
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License.
*
* a helper function to truncate strings
*
*/
#ifndef TRUNCATE_STRING_H
#define TRUNCATE_STRING_H
#include <SupportDefs.h>
// truncated_string
void
truncate_string(const char* string,
uint32 mode, float width, char* result,
const float* escapementArray, float fontSize,
float ellipsisWidth, int32 length, int32 numChars);
#endif // STRING_TRUNCATION_H

View File

@ -1,5 +1,5 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, Haiku, Inc.
// Copyright (c) 2001-2005, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
@ -21,119 +21,164 @@
//
// File Name: Decorator.h
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Base class for window decorators
//
//------------------------------------------------------------------------------
#ifndef _DECORATOR_H_
#define _DECORATOR_H_
#include <SupportDefs.h>
#include <Rect.h>
#include <Region.h>
#include <String.h>
#include <Window.h>
#include "LayerData.h"
#include "ColorSet.h"
#include "LayerData.h"
class DisplayDriver;
class ServerFont;
class BRegion;
typedef enum { DEC_NONE=0, DEC_ZOOM, DEC_CLOSE, DEC_MINIMIZE,
DEC_TAB, DEC_DRAG, DEC_MOVETOBACK, DEC_MOVETOFRONT, DEC_SLIDETAB,
typedef enum {
DEC_NONE = 0,
DEC_ZOOM,
DEC_CLOSE,
DEC_MINIMIZE,
DEC_TAB,
DEC_DRAG,
DEC_MOVETOBACK,
DEC_MOVETOFRONT,
DEC_SLIDETAB,
DEC_RESIZE, CLICK_RESIZE_L, CLICK_RESIZE_T,
CLICK_RESIZE_R, CLICK_RESIZE_B, CLICK_RESIZE_LT, CLICK_RESIZE_RT,
CLICK_RESIZE_LB, CLICK_RESIZE_RB } click_type;
DEC_RESIZE,
CLICK_RESIZE_L,
CLICK_RESIZE_T,
CLICK_RESIZE_R,
CLICK_RESIZE_B,
CLICK_RESIZE_LT,
CLICK_RESIZE_RT,
CLICK_RESIZE_LB,
CLICK_RESIZE_RB
} click_type;
class Decorator
{
public:
Decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags);
virtual ~Decorator(void);
class Decorator {
public:
Decorator(BRect rect,
int32 wlook,
int32 wfeel,
int32 wflags);
virtual ~Decorator();
void SetColors(const ColorSet &cset);
void SetDriver(DisplayDriver *driver);
void SetFlags(int32 wflags);
void SetFeel(int32 wfeel);
void SetFont(ServerFont *font);
void SetLook(int32 wlook);
void SetColors(const ColorSet &cset);
void SetDriver(DisplayDriver *driver);
void SetFlags(int32 wflags);
void SetFeel(int32 wfeel);
void SetFont(ServerFont *font);
void SetLook(int32 wlook);
void SetClose(bool is_down);
void SetMinimize(bool is_down);
void SetZoom(bool is_down);
virtual void SetTitle(const char *string);
int32 GetLook() const;
int32 GetFeel() const;
int32 GetFlags() const;
const char* GetTitle() const;
// we need to know its border(frame). WinBorder's _frame rect
// must expand to include Decorator borders. Otherwise we can't
// draw the border. We also add GetTabRect because I feel we'll need it
BRect GetBorderRect() const;
BRect GetTabRect() const;
bool GetClose();
bool GetMinimize();
bool GetZoom();
virtual void GetSizeLimits(float* minWidth, float* minHeight,
float* maxWidth, float* maxHeight) const;
void SetFocus(bool is_active);
bool GetFocus()
{ return fIsFocused; };
ColorSet GetColors()
{ return (_colors) ? *_colors : ColorSet(); }
void SetClose(bool is_down);
void SetMinimize(bool is_down);
void SetZoom(bool is_down);
virtual void SetTitle(const char *string);
virtual void GetFootprint(BRegion *region);
virtual click_type Clicked(BPoint pt, int32 buttons,
int32 modifiers);
int32 GetLook(void);
int32 GetFeel(void);
int32 GetFlags(void);
const char *GetTitle(void);
// we need to know its border(frame). WinBorder's _frame rect
// must expand to include Decorator borders. Otherwise we can't
// draw the border. We also add GetTabRect because I feel we'll need it
BRect GetBorderRect(void);
BRect GetTabRect(void);
virtual void MoveBy(float x, float y);
virtual void MoveBy(BPoint pt);
virtual BRect SlideTab(float dx, float dy = 0);
virtual void ResizeBy(float x, float y);
virtual void ResizeBy(BPoint pt);
bool GetClose(void);
bool GetMinimize(void);
bool GetZoom(void);
void SetFocus(bool is_active);
bool GetFocus(void) { return _has_focus; };
ColorSet GetColors(void) { return (_colors)?*_colors:ColorSet(); }
virtual void Draw(BRect r);
virtual void Draw();
virtual void DrawClose();
virtual void DrawFrame();
virtual void DrawMinimize();
virtual void DrawTab();
virtual void DrawTitle();
virtual void DrawZoom();
virtual BRect SlideTab(float dx, float dy=0);
virtual void GetFootprint(BRegion *region);
virtual click_type Clicked(BPoint pt, int32 buttons, int32 modifiers);
virtual void MoveBy(float x, float y);
virtual void MoveBy(BPoint pt);
virtual void ResizeBy(float x, float y);
virtual void ResizeBy(BPoint pt);
virtual void Draw(BRect r);
virtual void Draw(void);
virtual void DrawClose(void);
virtual void DrawFrame(void);
virtual void DrawMinimize(void);
virtual void DrawTab(void);
virtual void DrawTitle(void);
virtual void DrawZoom(void);
protected:
int32 _ClipTitle(float width);
protected:
int32 _ClipTitle(float width);
/*!
\brief Returns the number of characters in the title
\return The title character count
*/
int32 _TitleWidth(void) { return (_title_string)?_title_string->CountChars():0; }
virtual void _DrawClose(BRect r);
virtual void _DrawFrame(BRect r);
virtual void _DrawMinimize(BRect r);
virtual void _DrawTab(BRect r);
virtual void _DrawTitle(BRect r);
virtual void _DrawZoom(BRect r);
virtual void _SetFocus(void);
virtual void _DoLayout(void);
virtual void _SetColors(void);
ColorSet *_colors;
DisplayDriver *_driver;
DrawData _drawdata;
int32 _look, _feel, _flags;
BRect _zoomrect,_closerect,_minimizerect,_tabrect,_frame,
_resizerect,_borderrect;
int32 _TitleWidth() const
{ return fTitle.CountChars(); }
private:
bool _close_state, _zoom_state, _minimize_state;
bool _has_focus;
BString *_title_string;
virtual void _DoLayout();
virtual void _DrawFrame(BRect r);
virtual void _DrawTab(BRect r);
virtual void _DrawClose(BRect r);
virtual void _DrawTitle(BRect r);
virtual void _DrawZoom(BRect r);
virtual void _DrawMinimize(BRect r);
virtual void _SetFocus();
virtual void _SetColors();
ColorSet* _colors;
DisplayDriver* _driver;
DrawData _drawdata;
int32 _look;
int32 _feel;
int32 _flags;
BRect _zoomrect;
BRect _closerect;
BRect _minimizerect;
BRect _tabrect;
BRect _frame;
BRect _resizerect;
BRect _borderrect;
private:
bool fClosePressed;
bool fZoomPressed;
bool fMinimizePressed;
bool fIsFocused;
BString fTitle;
};
// add-on stuff
typedef float get_version(void);
typedef Decorator *create_decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags);
typedef Decorator* create_decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags);
#endif

View File

@ -48,7 +48,7 @@ class FontServer
public:
FontServer(void);
~FontServer(void);
void Lock(void);
bool Lock(void);
void Unlock(void);
/*!

View File

@ -108,10 +108,12 @@ class DrawData {
inline const ServerFont& Font() const
{ return fFont; }
// TODO: remove (is contained in SeverFont::Flags())
void SetFontAntiAliasing(bool antiAliasing);
inline bool FontAntiAliasing() const
{ return fFontAntiAliasing; }
// TODO: remove (should be part of DisplayDriver::DrawString() as in BView)
void SetEscapementDelta(escapement_delta delta);
inline escapement_delta EscapementDelta() const
{ return fEscapementDelta; }

View File

@ -27,10 +27,14 @@
#ifndef SERVERFONT_H_
#define SERVERFONT_H_
#include <Rect.h>
#include <Font.h>
#include <Rect.h>
#include "FontFamily.h"
class BShape;
class BString;
class ServerFont {
public:
ServerFont();
@ -48,6 +52,9 @@ class ServerFont {
{ return fStyle ? B_OK : B_NO_INIT; }
ServerFont &operator=(const ServerFont& font);
font_direction Direction() const
{ return fDirection; }
uint32 Encoding() const
@ -70,11 +77,24 @@ class ServerFont {
{ return fStyle->GlyphCount(); }
int32 CountTuned();
font_file_format FileFormat();
const char* GetStyle() const;
const char* GetFamily() const;
const char* GetPath() const
{ return fStyle->GetPath(); }
status_t SetFamilyAndStyle(const uint16& familyID,
const uint16& styleID);
status_t SetFamilyAndStyle(const uint32& fontID);
status_t SetFamilyAndStyle(uint16 familyID,
uint16 styleID);
status_t SetFamilyAndStyle(uint32 fontID);
uint16 StyleID() const
{ return fStyle->GetID(); }
uint16 FamilyID() const
{ return fStyle->Family()->GetID(); }
uint32 GetFamilyAndStyle() const;
void SetDirection(const font_direction& dir)
{ fDirection = dir; }
@ -109,6 +129,7 @@ class ServerFont {
{ return fStyle->GlyphCount(); }
uint16 CharMapCount() const
{ return fStyle->CharMapCount(); }
BShape** GetGlyphShapes(const char charArray[],
int32 numChars) const;
@ -125,24 +146,17 @@ class ServerFont {
FT_Face GetFTFace() const
{ return fStyle->GetFTFace(); };
const char* GetStyle() const;
const char* GetFamily() const;
const char* GetPath() const
{ return fStyle->GetPath(); }
uint16 StyleID() const
{ return fStyle->GetID(); }
uint16 FamilyID() const
{ return fStyle->Family()->GetID(); }
uint32 GetFamilyAndStyle() const;
BRect BoundingBox();
void Height(font_height* fh);
void Height(font_height* fh) const;
void TruncateString(BString* inOut,
uint32 mode,
float width) const;
ServerFont &operator=(const ServerFont& font);
protected:
friend class FontStyle;
void _SetStyle(FontStyle* style);
FontStyle* fStyle;
edge_info fEdges;
@ -152,8 +166,8 @@ protected:
BRect fBounds;
uint32 fFlags;
uint32 fSpacing;
uint16 fFace;
font_direction fDirection;
uint16 fFace;
uint32 fEncoding;
};

View File

@ -35,6 +35,7 @@
#include <String.h>
#include <moreUTF8.h>
#include <truncate_string.h>
#include <Font.h>
@ -765,115 +766,69 @@ BFont::GetTunedInfo(int32 index, tuned_font_info *info) const
link.Read<tuned_font_info>(info);
}
// TruncateString
void
BFont::TruncateString(BString *inOut, uint32 mode, float width) const
{
if(!inOut)
return;
if(width<=0)
{
*inOut="";
return;
}
int32 code;
BPrivate::BAppServerLink link;
link.StartMessage(AS_GET_TRUNCATED_STRINGS);
link.Attach<uint32>(mode);
link.Attach<float>(width);
link.Attach<int32>(1);
link.AttachString(inOut->String());
link.FlushWithReply(&code);
if(code!=SERVER_TRUE)
return;
char *string;
link.ReadString(&string);
*inOut=string;
free(string);
// NOTE: Careful, we cannot directly use "inOut->String()" as result
// array, because the string length increases by 3 bytes in the worst case scenario.
const char* array[1];
array[0] = inOut->String();
GetTruncatedStrings(array, 1, mode, width, inOut);
}
// GetTruncatedStrings
void
BFont::GetTruncatedStrings(const char *stringArray[], int32 numStrings,
uint32 mode, float width, BString resultArray[]) const
{
if(!stringArray || numStrings<1 || !resultArray)
return;
if (stringArray && resultArray && numStrings > 0) {
// allocate storage, see BeBook for "+ 3"
char** truncatedStrings = new char*[numStrings];
for (int32 i = 0; i < numStrings; i++) {
truncatedStrings[i] = new char[strlen(stringArray[i]) + 3];
}
int32 code;
BPrivate::BAppServerLink link;
GetTruncatedStrings(stringArray, numStrings, mode, width, truncatedStrings);
link.StartMessage(AS_GET_TRUNCATED_STRINGS);
link.Attach<uint32>(mode);
link.Attach<float>(width);
link.Attach<int32>(numStrings);
for(int32 i=0; i<numStrings; i++)
link.AttachString(stringArray[i]);
link.FlushWithReply(&code);
if(code!=SERVER_TRUE)
return;
for(int32 i=0; i<numStrings; i++)
{
char *string;
link.ReadString(&string);
resultArray[i].SetTo(string);
free(string);
// copy the strings into the BString array and free each one
for (int32 i = 0; i < numStrings; i++) {
resultArray[i].SetTo(truncatedStrings[i]);
delete[] truncatedStrings[i];
}
delete[] truncatedStrings;
}
}
// GetTruncatedStrings
void
BFont::GetTruncatedStrings(const char *stringArray[], int32 numStrings,
uint32 mode, float width, char *resultArray[]) const
{
if(!stringArray || numStrings<1 || !resultArray)
return;
int32 code;
BPrivate::BAppServerLink link;
link.StartMessage(AS_GET_TRUNCATED_STRINGS);
link.Attach<uint32>(mode);
link.Attach<float>(width);
link.Attach<int32>(numStrings);
for(int32 i=0; i<numStrings; i++)
link.AttachString(stringArray[i]);
link.FlushWithReply(&code);
if(code!=SERVER_TRUE)
return;
// TODO: Look into a possible BPortLink::ReadIntoString() method to speed things
// like this up, along with the other string truncation functions
for(int32 i=0; i<numStrings; i++)
{
char *string;
link.ReadString(&string);
strcpy(resultArray[i],string);
free(string);
if (stringArray && numStrings > 0) {
// the width of the "…" glyph
float ellipsisWidth = StringWidth(B_UTF8_ELLIPSIS);
for (int32 i = 0; i < numStrings; i++) {
int32 length = strlen(stringArray[i]);
// count the individual glyphs
int32 numChars = UTF8CountChars(stringArray[i], length);
// get the escapement of each glyph in font units
float* escapementArray = new float[numChars];
GetEscapements(stringArray[i], numChars, NULL, escapementArray);
truncate_string(stringArray[i], mode, width, resultArray[i],
escapementArray, fSize, ellipsisWidth, length, numChars);
delete[] escapementArray;
}
}
}
// StringWidth
float
BFont::StringWidth(const char *string) const
{
int32 length=strlen(string);
int32 length = strlen(string);
return StringWidth(string, length);
}
@ -881,7 +836,7 @@ BFont::StringWidth(const char *string) const
float
BFont::StringWidth(const char *string, int32 length) const
{
if(!string || length<1)
if (!string || length < 1)
return 0.0;
int32 code;
@ -896,7 +851,7 @@ BFont::StringWidth(const char *string, int32 length) const
link.Attach<uint8>(fSpacing);
link.FlushWithReply(&code);
if(code!=SERVER_TRUE)
if (code != SERVER_TRUE)
return 0.0;
float width;

View File

@ -34,6 +34,8 @@
#include <TextView.h>
#include <stdlib.h>
// TODO: remove this header
#include <stdio.h>
// Private definitions not placed in public headers
extern "C" void _init_global_fonts();
@ -45,6 +47,10 @@ extern "C" status_t _fini_interface_kit_();
#include <ServerProtocol.h>
#include <WidthBuffer.h>
#include <string.h>
#include <Font.h>
#include "moreUTF8.h"
#include "truncate_string.h"
using namespace BPrivate;
@ -729,5 +735,172 @@ do_minimize_team(BRect zoomRect, team_id team, bool zoom)
// ToDo: implement me, needed for Deskbar!
}
// copy_from_start
static char*
copy_from_start(const char* src, char* dst, uint32 numChars,
const float* escapementArray, float width, float ellipsisWidth, float size)
{
//printf("copy_from_start: %.1f\n", width);
float currentWidth = 0.0;
for (uint32 c = 0; c < numChars; c++) {
//printf("forward: %c (%ld) (%.1f + %.1f = %.1f)\n", *src, c, currentWidth, escapementArray[c] * size, currentWidth + escapementArray[c] * size);
currentWidth += escapementArray[c] * size;
if (currentWidth > width) {
//*dst = *src;
// ups, we definitely don't fit. go back until the ellipsis fits
currentWidth += ellipsisWidth;
for (int32 c2 = c; c2 >= 0; c2--) {
//printf(" backward: %c (%ld) (%.1f - %.1f = %.1f)\n", *dst, c2, currentWidth, escapementArray[c2] * size, currentWidth - escapementArray[c2] * size);
currentWidth -= escapementArray[c2] * size;
do {
dst--;
} while (IsInsideGlyph(*dst));
// see if we went back enough
if (currentWidth <= width)
break;
}
// dst needs to point behind the last glyph we want to use
dst++;
break;
} else {
// copy one glyph
do {
*dst++ = *src++;
} while (IsInsideGlyph(*src));
}
}
return dst;
}
// copy_from_end
static char*
copy_from_end(const char* src, char* dst, uint32 numChars, uint32 length,
const float* escapementArray, float width, float ellipsisWidth, float size)
{
const char* originalStart = src;
src += length - 1;
float currentWidth = 0.0;
for (int32 c = numChars - 1; c > 0; c--) {
currentWidth += escapementArray[c] * size;
if (currentWidth > width) {
// ups, we definitely don't fit. go back until the ellipsis fits
currentWidth += ellipsisWidth;
// go forward again until ellipsis fits (already beyond the target)
for (int32 c2 = c; c2 < numChars; c2++) {
//printf(" backward: %c (%ld) (%.1f - %.1f = %.1f)\n", *dst, c2, currentWidth, escapementArray[c2] * size, currentWidth - escapementArray[c2] * size);
currentWidth -= escapementArray[c2] * size;
do {
src++;
} while (IsInsideGlyph(*src));
// see if we went back enough
if (currentWidth <= width)
break;
}
break;
} else {
// go back one glyph
do {
src--;
} while (IsInsideGlyph(*src));
}
}
// copy from the end of the string
uint32 bytesToCopy = originalStart + length - src;
memcpy(dst, src, bytesToCopy);
dst += bytesToCopy;
return dst;
}
static char*
write_ellipsis(char* dst)
{
strcpy(dst, B_UTF8_ELLIPSIS);
//strcpy(dst, "...");
return dst + 3;
}
// truncated_string
void
truncate_string(const char* string,
uint32 mode, float width, char* result,
const float* escapementArray, float fontSize,
float ellipsisWidth, int32 length, int32 numChars)
{
if (string) {
// skip calculation if we don't even have enough room for that
if (width >= ellipsisWidth) {
// iterate over glyphs and copy source into result string
// one glyph at a time as long as we have room for the "…" yet
char* dst = result;
const char* src = string;
switch (mode) {
case B_TRUNCATE_BEGINNING: {
dst = copy_from_end(src, dst, numChars, length,
escapementArray, width, ellipsisWidth, fontSize);
// "dst" points to the position behind the last glyph that
// was copied.
int32 dist = dst - result;
// we didn't terminate yet
*dst = 0;
if (dist < length) {
// TODO: Is there a smarter way?
char* temp = new char[dist + 4];
char* t = temp;
// append "…"
t = write_ellipsis(t);
// shuffle arround strings so that "…" is prepended
strcpy(t, result);
strcpy(result, temp);
delete[] temp;
/* char t = result[3];
memmove(&result[3], result, dist + 1);
write_ellipsis(result);
result[3] = t;*/
}
break;
}
case B_TRUNCATE_END:
dst = copy_from_start(src, dst, numChars,
escapementArray, width, ellipsisWidth, fontSize);
// "dst" points to the position behind the last glyph that
// was copied.
if (dst - result < length) {
// append "…" and terminate with 0
write_ellipsis(dst);
} else {
*dst = 0;
}
break;
case B_TRUNCATE_SMART:
// TODO: implement, though it was never implemented on R5
// FALL THROUGH (at least do something)
case B_TRUNCATE_MIDDLE:
float halfWidth = width / 2.0;
dst = copy_from_start(src, dst, numChars,
escapementArray, halfWidth, ellipsisWidth, fontSize);
// insert "…"
dst = write_ellipsis(dst);
dst = copy_from_end(src, dst, numChars, length,
escapementArray, halfWidth, 0.0, fontSize);
// terminate
*dst = 0;
break;
}
} else {
// we don't have room for a single glyph
strcpy(result, "");
}
}
}
#endif // !COMPILE_FOR_R5

View File

@ -1026,27 +1026,29 @@ void
BWindow::SetSizeLimits(float minWidth, float maxWidth,
float minHeight, float maxHeight)
{
int32 rCode;
if (minWidth > maxWidth
|| minHeight > maxHeight)
if (minWidth > maxWidth || minHeight > maxHeight)
return;
Lock();
fLink->StartMessage(AS_SET_SIZE_LIMITS);
fLink->Attach<float>(fMinWindWidth);
fLink->Attach<float>(fMaxWindWidth);
fLink->Attach<float>(fMinWindHeight);
fLink->Attach<float>(fMaxWindHeight);
fLink->Flush();
fLink->GetNextReply(&rCode);
Unlock();
if (Lock()) {
fLink->StartMessage(AS_SET_SIZE_LIMITS);
fLink->Attach<float>(minWidth);
fLink->Attach<float>(maxWidth);
fLink->Attach<float>(minHeight);
fLink->Attach<float>(maxHeight);
fLink->Flush();
if (rCode == SERVER_TRUE) {
fMinWindHeight = minHeight;
fMinWindWidth = minWidth;
fMaxWindHeight = maxHeight;
fMaxWindWidth = maxWidth;
int32 rCode;
fLink->GetNextReply(&rCode);
if (rCode == SERVER_TRUE) {
// read the values that were really enforced on
// the server side
fLink->Read<float>(&fMinWindWidth);
fLink->Read<float>(&fMaxWindWidth);
fLink->Read<float>(&fMinWindHeight);
fLink->Read<float>(&fMaxWindHeight);
}
Unlock();
}
}
@ -1055,16 +1057,18 @@ void
BWindow::GetSizeLimits(float *minWidth, float *maxWidth,
float *minHeight, float *maxHeight)
{
*minHeight = fMinWindHeight;
*minWidth = fMinWindWidth;
*maxHeight = fMaxWindHeight;
*maxWidth = fMaxWindWidth;
// TODO: What about locking?!?
*minHeight = fMinWindHeight;
*minWidth = fMinWindWidth;
*maxHeight = fMaxWindHeight;
*maxWidth = fMaxWindWidth;
}
void
BWindow::SetZoomLimits(float maxWidth, float maxHeight)
{
// TODO: What about locking?!?
if (maxWidth > fMaxWindWidth)
maxWidth = fMaxWindWidth;
else
@ -1090,6 +1094,8 @@ BWindow::Zoom(BPoint rec_position, float rec_width, float rec_height)
void
BWindow::Zoom()
{
// TODO: broken.
// TODO: What about locking?!?
float minWidth, minHeight;
BScreen screen;
@ -1142,6 +1148,7 @@ BWindow::ScreenChanged(BRect screen_size, color_space depth)
void
BWindow::SetPulseRate(bigtime_t rate)
{
// TODO: What about locking?!?
if (rate < 0)
return;
@ -1170,6 +1177,7 @@ BWindow::SetPulseRate(bigtime_t rate)
bigtime_t
BWindow::PulseRate() const
{
// TODO: What about locking?!?
return fPulseRate;
}
@ -1192,6 +1200,7 @@ void
BWindow::AddShortcut(uint32 key, uint32 modifiers, BMessage *msg, BHandler *target)
{
// NOTE: I'm not sure if it is OK to use 'key'
// TODO: What about locking?!?
if (msg == NULL)
return;
@ -1224,6 +1233,7 @@ BWindow::AddShortcut(uint32 key, uint32 modifiers, BMessage *msg, BHandler *targ
void
BWindow::RemoveShortcut(uint32 key, uint32 modifiers)
{
// TODO: What about locking?!?
int32 index = findShortcut(key, modifiers | B_COMMAND_KEY);
if (index >=0) {
_BCmdKey *cmdKey = (_BCmdKey *)accelList.ItemAt(index);
@ -1239,6 +1249,7 @@ BWindow::RemoveShortcut(uint32 key, uint32 modifiers)
BButton *
BWindow::DefaultButton() const
{
// TODO: What about locking?!?
return fDefaultButton;
}
@ -1246,6 +1257,7 @@ BWindow::DefaultButton() const
void
BWindow::SetDefaultButton(BButton *button)
{
// TODO: What about locking?!?
if (fDefaultButton == button)
return;
@ -1268,6 +1280,7 @@ BWindow::SetDefaultButton(BButton *button)
bool
BWindow::NeedsUpdate() const
{
// TODO: What about locking?!?
int32 rCode;
const_cast<BWindow *>(this)->Lock();
@ -1283,6 +1296,7 @@ BWindow::NeedsUpdate() const
void
BWindow::UpdateIfNeeded()
{
// TODO: What about locking?!?
// works only from this thread
if (find_thread(NULL) != Thread())
return;
@ -1317,6 +1331,7 @@ BWindow::UpdateIfNeeded()
BView *
BWindow::FindView(const char *viewName) const
{
// TODO: What about locking?!?
return findView(top_view, viewName);
}
@ -1324,12 +1339,14 @@ BWindow::FindView(const char *viewName) const
BView *
BWindow::FindView(BPoint point) const
{
// TODO: What about locking?!?
return findView(top_view, point);
}
BView *BWindow::CurrentFocus() const
{
// TODO: What about locking?!?
return fFocus;
}
@ -1337,6 +1354,7 @@ BView *BWindow::CurrentFocus() const
void
BWindow::Activate(bool active)
{
// TODO: What about locking?!?
if (IsHidden())
return;

View File

@ -1,5 +1,5 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, Haiku, Inc.
// Copyright (c) 2001-2005, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
@ -21,6 +21,7 @@
//
// File Name: Decorator.cpp
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Base class for window decorators
//
//------------------------------------------------------------------------------
@ -41,36 +42,28 @@
object.
*/
Decorator::Decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags)
: _colors(new ColorSet()),
_driver(NULL),
_drawdata(),
_look(wlook),
_feel(wfeel),
_flags(wflags),
_zoomrect(),
_closerect(),
_minimizerect(),
_tabrect(),
_frame(rect),
_resizerect(),
_borderrect(),
fClosePressed(false),
fZoomPressed(false),
fMinimizePressed(false),
fIsFocused(false),
fTitle("")
{
_close_state=false;
_minimize_state=false;
_zoom_state=false;
_has_focus=false;
_title_string=new BString;
_driver=NULL;
/// xxx.Set(0,0,1,1) produces a rectangle 2 pixels wide, that
// WILL be drawn on screen. We so not want that... so...
// [ A BRect when instantiated is made invalid, so, no need for: ]
/*
_closerect.Set( 0, 0, -1, -1);
_zoomrect.Set( 0, 0, -1, -1);
_minimizerect.Set( 0, 0, -1, -1);
_resizerect.Set( 0, 0, -1, -1);
*/
_frame=rect;
// rect rectangle MUST remain intact - it is top_view's area
// Decorator drawing MUST be done arround that area
//_tabrect.Set(rect.left,rect.top,rect.right, rect.top+((rect.bottom-rect.top)/4));
// [ A BRect when instantiated is made invalid, so, no need for: ]
// _tabrect.Set( 0, 0, -1, -1 );
_look=wlook;
_feel=wfeel;
_flags=wflags;
_colors=new ColorSet();
}
/*!
@ -78,22 +71,17 @@ Decorator::Decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags)
Frees the color set and the title string
*/
Decorator::~Decorator(void)
Decorator::~Decorator()
{
if(_colors!=NULL)
{
delete _colors;
_colors=NULL;
}
if(_title_string)
delete _title_string;
delete _colors;
}
/*!
\brief Updates the decorator's color set
\param cset The color set to update from
*/
void Decorator::SetColors(const ColorSet &cset)
void
Decorator::SetColors(const ColorSet &cset)
{
_colors->SetColors(cset);
_SetColors();
@ -103,48 +91,15 @@ void Decorator::SetColors(const ColorSet &cset)
\brief Assigns a display driver to the decorator
\param driver A valid DisplayDriver object
*/
void Decorator::SetDriver(DisplayDriver *driver)
void
Decorator::SetDriver(DisplayDriver *driver)
{
_driver = driver;
// lots of subclasses will depend on the driver for text support, so call
// _DoLayout() after this
_driver=driver;
_DoLayout();
}
/*!
\brief Sets the close button's value.
\param is_down Whether the button is down or not
Note that this does not update the button's look - it just updates the
internal button value
*/
void Decorator::SetClose(bool is_down)
{
_close_state=is_down;
}
/*!
\brief Sets the minimize button's value.
\param is_down Whether the button is down or not
Note that this does not update the button's look - it just updates the
internal button value
*/
void Decorator::SetMinimize(bool is_down)
{
_zoom_state=is_down;
}
/*!
\brief Sets the zoom button's value.
\param is_down Whether the button is down or not
Note that this does not update the button's look - it just updates the
internal button value
*/
void Decorator::SetZoom(bool is_down)
{
_minimize_state=is_down;
// _DoLayout() after we have it
if (_driver) {
_DoLayout();
}
}
/*!
@ -154,9 +109,10 @@ void Decorator::SetZoom(bool is_down)
While this call will not update the screen, it will affect how future
updates work and immediately affects input handling.
*/
void Decorator::SetFlags(int32 wflags)
void
Decorator::SetFlags(int32 wflags)
{
_flags=wflags;
_flags = wflags;
}
/*!
@ -166,21 +122,22 @@ void Decorator::SetFlags(int32 wflags)
While this call will not update the screen, it will affect how future
updates work and immediately affects input handling.
*/
void Decorator::SetFeel(int32 wfeel)
void
Decorator::SetFeel(int32 wfeel)
{
_feel=wfeel;
_feel = wfeel;
}
/*
\brief Sets the decorator's font
\param font The new font object to copy from
*/
void Decorator::SetFont(ServerFont *font)
void
Decorator::SetFont(ServerFont *font)
{
if(!font)
return;
_drawdata.SetFont(*font);
if (font) {
_drawdata.SetFont(*font);
}
}
/*!
@ -190,43 +147,79 @@ void Decorator::SetFont(ServerFont *font)
While this call will not update the screen, it will affect how future
updates work and immediately affects input handling.
*/
void Decorator::SetLook(int32 wlook)
void
Decorator::SetLook(int32 wlook)
{
_look=wlook;
_look = wlook;
// TODO: relayout and redraw, no?
}
/*!
\brief Returns the value of the close button
\return true if down, false if up
\brief Sets the close button's value.
\param is_down Whether the button is down or not
Note that this does not update the button's look - it just updates the
internal button value
*/
bool Decorator::GetClose(void)
void
Decorator::SetClose(bool is_down)
{
return _close_state;
if (is_down != fClosePressed) {
fClosePressed = is_down;
DrawClose();
}
}
/*!
\brief Returns the value of the minimize button
\return true if down, false if up
\brief Sets the minimize button's value.
\param is_down Whether the button is down or not
Note that this does not update the button's look - it just updates the
internal button value
*/
bool Decorator::GetMinimize(void)
void
Decorator::SetMinimize(bool is_down)
{
return _minimize_state;
if (is_down != fMinimizePressed) {
fMinimizePressed = is_down;
DrawMinimize();
}
}
/*!
\brief Returns the value of the zoom button
\return true if down, false if up
\brief Sets the zoom button's value.
\param is_down Whether the button is down or not
Note that this does not update the button's look - it just updates the
internal button value
*/
bool Decorator::GetZoom(void)
void
Decorator::SetZoom(bool is_down)
{
return _zoom_state;
if (is_down != fZoomPressed) {
fZoomPressed = is_down;
DrawZoom();
}
}
/*!
\brief Updates the value of the decorator title
\param string New title value
*/
void
Decorator::SetTitle(const char *string)
{
fTitle.SetTo(string);
_DoLayout();
// TODO: redraw?
}
/*!
\brief Returns the decorator's window look
\return the decorator's window look
*/
int32 Decorator::GetLook(void)
int32
Decorator::GetLook() const
{
return _look;
}
@ -235,7 +228,8 @@ int32 Decorator::GetLook(void)
\brief Returns the decorator's window feel
\return the decorator's window feel
*/
int32 Decorator::GetFeel(void)
int32
Decorator::GetFeel() const
{
return _feel;
}
@ -244,28 +238,20 @@ int32 Decorator::GetFeel(void)
\brief Returns the decorator's window flags
\return the decorator's window flags
*/
int32 Decorator::GetFlags(void)
int32
Decorator::GetFlags() const
{
return _flags;
}
/*!
\brief Updates the value of the decorator title
\param string New title value
*/
void Decorator::SetTitle(const char *string)
{
_title_string->SetTo(string);
_DoLayout();
}
/*!
\brief Returns the decorator's title
\return the decorator's title
*/
const char *Decorator::GetTitle(void)
const char*
Decorator::GetTitle() const
{
return _title_string->String();
return fTitle.String();
}
/*!
@ -273,7 +259,9 @@ const char *Decorator::GetTitle(void)
\return the decorator's border rectangle
*/
BRect Decorator::GetBorderRect(void){
BRect
Decorator::GetBorderRect() const
{
return _borderrect;
}
@ -282,10 +270,49 @@ BRect Decorator::GetBorderRect(void){
\return the decorator's tab rectangle
*/
BRect Decorator::GetTabRect(void){
BRect
Decorator::GetTabRect() const
{
return _tabrect;
}
/*!
\brief Returns the value of the close button
\return true if down, false if up
*/
bool
Decorator::GetClose()
{
return fClosePressed;
}
/*!
\brief Returns the value of the minimize button
\return true if down, false if up
*/
bool
Decorator::GetMinimize()
{
return fMinimizePressed;
}
/*!
\brief Returns the value of the zoom button
\return true if down, false if up
*/
bool
Decorator::GetZoom()
{
return fZoomPressed;
}
// GetSizeLimits
void
Decorator::GetSizeLimits(float* minWidth, float* minHeight,
float* maxWidth, float* maxHeight) const
{
}
/*!
\brief Changes the focus value of the decorator
\param is_active True if active, false if not
@ -293,258 +320,26 @@ BRect Decorator::GetTabRect(void){
While this call will not update the screen, it will affect how future
updates work.
*/
void Decorator::SetFocus(bool is_active)
void
Decorator::SetFocus(bool is_active)
{
_has_focus=is_active;
fIsFocused = is_active;
_SetFocus();
}
/*!
\brief Provides the number of characters that will fit in the given width
\param width Maximum number of pixels the title can be
\return the number of characters that will fit in the given width
*/
int32 Decorator::_ClipTitle(float width)
{
if(_driver)
{
int32 strlength=_title_string->CountChars();
float pixwidth=_driver->StringWidth(_title_string->String(),strlength,&_drawdata);
while(strlength>=0)
{
if(pixwidth<width)
return strlength;
strlength--;
pixwidth=_driver->StringWidth(_title_string->String(),strlength,&_drawdata);
}
}
return 0;
// TODO: maybe it would be cleaner to handle the redraw here.
}
//-------------------------------------------------------------------------
// Virtual Methods
//-------------------------------------------------------------------------
/*!
\brief Moves the decorator frame and all default rectangles
\param x X Offset
\param y y Offset
If a subclass implements this method, be sure to call Decorator::MoveBy
to ensure that internal members are also updated. All members of the Decorator
class are automatically moved in this method
*/
void Decorator::MoveBy(float x, float y)
{
_zoomrect.OffsetBy(x,y);
_closerect.OffsetBy(x,y);
_minimizerect.OffsetBy(x,y);
_minimizerect.OffsetBy(x,y);
_tabrect.OffsetBy(x,y);
_frame.OffsetBy(x,y);
_resizerect.OffsetBy(x,y);
_borderrect.OffsetBy(x,y);
}
/*!
\brief Moves the decorator frame and all default rectangles
\param pt Point containing the offsets
If a subclass implements this method, be sure to call Decorator::MoveBy
to ensure that internal members are also updated. All members of the Decorator
class are automatically moved in this method
*/
void Decorator::MoveBy(BPoint pt)
{
MoveBy(pt.x,pt.y);
}
/*!
\brief Moves the tab by the specified amount
\param dx x offset
\param dy y offset
\return The new tab rectangle.
Slides the tab by the x or y value. This function is not required to be
implemented by subclasses. Note that the tab rectangle returned does not
necessarily reflect _tabrect offset by the amount given - few people want to
slide a tab right off the window - that would be a Bad Thing (TM).
*/
BRect Decorator::SlideTab(float dx, float dy)
{
return BRect(0,0,0,0);
}
/*!
\brief Resizes the decorator frame
\param dx x offset
\param dy y offset
This is a required function for subclasses to implement - the default does nothing.
Note that window resize flags should be followed and _frame should be resized
accordingly. It would also be a wise idea to ensure that the window's rectangles
are not inverted.
*/
void Decorator::ResizeBy(float x, float y)
{
}
/*!
\brief Resizes the decorator frame
\param pt Point containing the offsets
This is a required function for subclasses to implement - the default does nothing.
Note that window resize flags should be followed and _frame should be resized
accordingly. It would also be a wise idea to ensure that the window's rectangles
are not inverted.
*/
void Decorator::ResizeBy(BPoint pt)
{
}
/*!
\brief Updates the decorator's look in the area r
\param r The area to update.
The default version updates all areas which intersect the frame and tab.
*/
void Decorator::Draw(BRect r)
{
_DrawTab(r & _tabrect);
_DrawFrame(r & _frame);
}
//! Forces a complete decorator update
void Decorator::Draw(void)
{
_DrawTab(_tabrect);
_DrawFrame(_frame);
}
//! Draws the close button
void Decorator::DrawClose(void)
{
_DrawClose(_closerect);
}
//! draws the frame
void Decorator::DrawFrame(void)
{
_DrawFrame(_frame);
}
//! draws the minimize button
void Decorator::DrawMinimize(void)
{
_DrawTab(_minimizerect);
}
//! draws the tab, title, and buttons
void Decorator::DrawTab(void)
{
_DrawTab(_tabrect);
_DrawZoom(_zoomrect);
_DrawMinimize(_minimizerect);
_DrawTitle(_tabrect);
_DrawClose(_closerect);
}
// draws the title
void Decorator::DrawTitle(void)
{
_DrawTitle(_tabrect);
}
//! draws the zoom button
void Decorator::DrawZoom(void)
{
_DrawZoom(_zoomrect);
}
/*!
\brief Actually draws the close button
\param r Area of the button to update
Unless a subclass has a particularly large button, it is probably unnecessary
to check the update rectangle.
*/
void Decorator::_DrawClose(BRect r)
{
}
/*!
\brief Actually draws the frame
\param r Area of the frame to update
*/
void Decorator::_DrawFrame(BRect r)
{
}
/*!
\brief Actually draws the minimize button
\param r Area of the button to update
Unless a subclass has a particularly large button, it is probably unnecessary
to check the update rectangle.
*/
void Decorator::_DrawMinimize(BRect r)
{
}
/*!
\brief Actually draws the tab
\param r Area of the tab to update
This function is called when the tab itself needs drawn. Other items, like the
window title or buttons, should not be drawn here.
*/
void Decorator::_DrawTab(BRect r)
{
}
/*!
\brief Actually draws the title
\param r area of the title to update
The main tasks for this function are to ensure that the decorator draws the title
only in its own area and drawing the title itself. Using B_OP_COPY for drawing
the title is recommended because of the marked performance hit of the other
drawing modes, but it is not a requirement.
*/
void Decorator::_DrawTitle(BRect r)
{
}
/*!
\brief Actually draws the zoom button
\param r Area of the button to update
Unless a subclass has a particularly large button, it is probably unnecessary
to check the update rectangle.
*/
void Decorator::_DrawZoom(BRect r)
{
}
/*!
\brief Hook function for when the color set is updated
This function is called after the decorator's color set is updated. Quite useful
if the decorator uses colors based on those in the system.
*/
void Decorator::_SetColors(void)
{
}
/*!
\brief Returns the "footprint" of the entire window, including decorator
\param region Region to be changed to represent the window's screen footprint
This function is required by all subclasses.
*/
void Decorator::GetFootprint(BRegion *region)
void
Decorator::GetFootprint(BRegion *region)
{
}
@ -581,18 +376,278 @@ void Decorator::GetFootprint(BRegion *region)
This function is required by all subclasses.
*/
click_type Decorator::Clicked(BPoint pt, int32 buttons, int32 modifiers)
click_type
Decorator::Clicked(BPoint pt, int32 buttons, int32 modifiers)
{
return DEC_NONE;
}
//! Hook function called when the decorator changes focus
void Decorator::_SetFocus(void)
/*!
\brief Moves the decorator frame and all default rectangles
\param x X Offset
\param y y Offset
If a subclass implements this method, be sure to call Decorator::MoveBy
to ensure that internal members are also updated. All members of the Decorator
class are automatically moved in this method
*/
void
Decorator::MoveBy(float x, float y)
{
_zoomrect.OffsetBy(x, y);
_closerect.OffsetBy(x, y);
_minimizerect.OffsetBy(x, y);
_minimizerect.OffsetBy(x, y);
_tabrect.OffsetBy(x, y);
_frame.OffsetBy(x, y);
_resizerect.OffsetBy(x, y);
_borderrect.OffsetBy(x, y);
}
/*!
\brief Moves the decorator frame and all default rectangles
\param pt Point containing the offsets
If a subclass implements this method, be sure to call Decorator::MoveBy
to ensure that internal members are also updated. All members of the Decorator
class are automatically moved in this method
*/
void
Decorator::MoveBy(BPoint pt)
{
MoveBy(pt.x, pt.y);
}
/*!
\brief Moves the tab by the specified amount
\param dx x offset
\param dy y offset
\return The new tab rectangle.
Slides the tab by the x or y value. This function is not required to be
implemented by subclasses. Note that the tab rectangle returned does not
necessarily reflect _tabrect offset by the amount given - few people want to
slide a tab right off the window - that would be a Bad Thing (TM).
*/
BRect
Decorator::SlideTab(float dx, float dy)
{
return BRect(0, 0, 0, 0);
}
/*!
\brief Resizes the decorator frame
\param dx x offset
\param dy y offset
This is a required function for subclasses to implement - the default does nothing.
Note that window resize flags should be followed and _frame should be resized
accordingly. It would also be a wise idea to ensure that the window's rectangles
are not inverted.
*/
void
Decorator::ResizeBy(float x, float y)
{
}
//! Function for calculating layout for the decorator
void Decorator::_DoLayout(void)
{
/*!
\brief Resizes the decorator frame
\param pt Point containing the offsets
This is a required function for subclasses to implement - the default does nothing.
Note that window resize flags should be followed and _frame should be resized
accordingly. It would also be a wise idea to ensure that the window's rectangles
are not inverted.
*/
void
Decorator::ResizeBy(BPoint pt)
{
}
/*!
\brief Updates the decorator's look in the area r
\param r The area to update.
The default version updates all areas which intersect the frame and tab.
*/
void
Decorator::Draw(BRect r)
{
_DrawFrame(r & _frame);
_DrawTab(r & _tabrect);
}
//! Forces a complete decorator update
void
Decorator::Draw()
{
_DrawFrame(_frame);
_DrawTab(_tabrect);
}
//! Draws the close button
void
Decorator::DrawClose()
{
_DrawClose(_closerect);
}
//! draws the frame
void
Decorator::DrawFrame()
{
_DrawFrame(_frame);
}
//! draws the minimize button
void
Decorator::DrawMinimize(void)
{
_DrawTab(_minimizerect);
}
//! draws the tab, title, and buttons
void
Decorator::DrawTab()
{
_DrawTab(_tabrect);
_DrawZoom(_zoomrect);
_DrawMinimize(_minimizerect);
_DrawTitle(_tabrect);
_DrawClose(_closerect);
}
// draws the title
void
Decorator::DrawTitle()
{
_DrawTitle(_tabrect);
}
//! draws the zoom button
void
Decorator::DrawZoom(void)
{
_DrawZoom(_zoomrect);
}
/*!
\brief Provides the number of characters that will fit in the given width
\param width Maximum number of pixels the title can be
\return the number of characters that will fit in the given width
*/
int32
Decorator::_ClipTitle(float width)
{
// TODO: eventually, use ServerFont::TruncateString()
// when it exists (if it doesn't already)
if (_driver) {
int32 strlength = fTitle.CountChars();
float pixwidth=_driver->StringWidth(fTitle.String(),strlength,&_drawdata);
while (strlength >= 0) {
if (pixwidth < width)
return strlength;
strlength--;
pixwidth=_driver->StringWidth(fTitle.String(), strlength, &_drawdata);
}
}
return 0;
}
//! Function for calculating layout for the decorator
void
Decorator::_DoLayout()
{
}
/*!
\brief Actually draws the frame
\param r Area of the frame to update
*/
void
Decorator::_DrawFrame(BRect r)
{
}
/*!
\brief Actually draws the tab
\param r Area of the tab to update
This function is called when the tab itself needs drawn. Other items, like the
window title or buttons, should not be drawn here.
*/
void
Decorator::_DrawTab(BRect r)
{
}
/*!
\brief Actually draws the close button
\param r Area of the button to update
Unless a subclass has a particularly large button, it is probably unnecessary
to check the update rectangle.
*/
void
Decorator::_DrawClose(BRect r)
{
}
/*!
\brief Actually draws the title
\param r area of the title to update
The main tasks for this function are to ensure that the decorator draws the title
only in its own area and drawing the title itself. Using B_OP_COPY for drawing
the title is recommended because of the marked performance hit of the other
drawing modes, but it is not a requirement.
*/
void
Decorator::_DrawTitle(BRect r)
{
}
/*!
\brief Actually draws the zoom button
\param r Area of the button to update
Unless a subclass has a particularly large button, it is probably unnecessary
to check the update rectangle.
*/
void
Decorator::_DrawZoom(BRect r)
{
}
/*!
\brief Actually draws the minimize button
\param r Area of the button to update
Unless a subclass has a particularly large button, it is probably unnecessary
to check the update rectangle.
*/
void
Decorator::_DrawMinimize(BRect r)
{
}
//! Hook function called when the decorator changes focus
void
Decorator::_SetFocus()
{
}
/*!
\brief Hook function for when the color set is updated
This function is called after the decorator's color set is updated. Quite useful
if the decorator uses colors based on those in the system.
*/
void
Decorator::_SetColors()
{
}

File diff suppressed because it is too large Load Diff

View File

@ -30,52 +30,74 @@
#include "Decorator.h"
#include <Region.h>
class DefaultDecorator: public Decorator
{
public:
DefaultDecorator(BRect frame, int32 wlook, int32 wfeel, int32 wflags);
virtual ~DefaultDecorator(void);
class DefaultDecorator: public Decorator {
public:
DefaultDecorator(BRect frame,
int32 look,
int32 feel,
int32 flags);
virtual ~DefaultDecorator();
virtual void MoveBy(float x, float y);
virtual void MoveBy(BPoint pt);
virtual void ResizeBy(float x, float y);
virtual void ResizeBy(BPoint pt);
virtual void MoveBy(float x, float y);
virtual void MoveBy(BPoint pt);
virtual void ResizeBy(float x, float y);
virtual void ResizeBy(BPoint pt);
virtual void Draw(BRect r);
virtual void Draw(void);
virtual void GetFootprint(BRegion *region);
virtual BRect SlideTab(float dx, float dy);
virtual click_type Clicked(BPoint pt, int32 buttons, int32 modifiers);
virtual void Draw(BRect r);
virtual void Draw();
virtual void GetSizeLimits(float* minWidth, float* minHeight,
float* maxWidth, float* maxHeight) const;
virtual void GetFootprint(BRegion *region);
virtual BRect SlideTab(float dx, float dy);
virtual click_type Clicked(BPoint pt, int32 buttons,
int32 modifiers);
protected:
virtual void _DrawClose(BRect r);
virtual void _DrawFrame(BRect r);
virtual void _DrawTab(BRect r);
virtual void _DrawTitle(BRect r);
virtual void _DrawZoom(BRect r);
virtual void _DoLayout(void);
virtual void _SetFocus(void);
virtual void _SetColors(void);
void DrawBlendedRect(BRect r, bool down);
uint32 taboffset;
virtual void _DoLayout();
RGBColor tab_highcol, tab_lowcol;
RGBColor button_highcol, button_lowcol;
RGBColor frame_highcol, frame_midcol, frame_lowcol, frame_highercol,
frame_lowercol;
RGBColor textcol;
virtual void _DrawFrame(BRect r);
virtual void _DrawTab(BRect r);
RGBColor *framecolors;
virtual void _DrawClose(BRect r);
virtual void _DrawTitle(BRect r);
virtual void _DrawZoom(BRect r);
virtual void _SetFocus();
virtual void _SetColors();
private:
void _DrawBlendedRect(BRect r, bool down);
void _GetButtonSizeAndOffset(const BRect& tabRect,
float* offset, float*size) const;
void _LayoutTabItems(const BRect& tabRect);
RGBColor fButtonHighColor;
RGBColor fButtonLowColor;
RGBColor fTextColor;
RGBColor fTabColor;
RGBColor* fFrameColors;
// Individual rects for handling window frame rendering the proper way
BRect rightborder,leftborder,topborder,bottomborder;
uint64 solidhigh, solidlow;
int32 borderwidth;
// Individual rects for handling window frame
// rendering the proper way
BRect fRightBorder;
BRect fLeftBorder;
BRect fTopBorder;
BRect fBottomBorder;
bool slidetab;
int textoffset;
float titlepixelwidth;
int32 fBorderWidth;
// bool fSlidingTab;
// uint32 fTabOffset;
float fTextOffset;
float fMinTabWidth;
float fMaxTabWidth;
BString fTruncatedTitle;
int32 fTruncatedTitleLength;
};
#endif

View File

@ -70,7 +70,7 @@ FontServer::FontServer(void)
&& init)
init=false;
families=new BList(0);
families=new BList(20);
plain=NULL;
bold=NULL;
fixed=NULL;
@ -86,9 +86,10 @@ FontServer::~FontServer(void)
}
//! Locks access to the font server
void FontServer::Lock(void)
bool
FontServer::Lock(void)
{
acquire_sem(lock);
return acquire_sem(lock) >= B_OK;
}
//! Unlocks access to the font server
@ -248,15 +249,21 @@ status_t FontServer::ScanDirectory(const char *fontspath)
if (error!=0)
continue;
charmap=_GetSupportedCharmap(face);
// TODO: Commenting this out makes my "Unicode glyph lookup"
// work with our default fonts. The real fix is to select the
// Unicode char map (if supported), and/or adjust the
// utf8 -> glyph-index mapping everywhere to handle other
// char maps. We could also ignore fonts that don't support
// the Unicode lookup as a temporary "solution".
/* charmap=_GetSupportedCharmap(face);
if(!charmap)
{
FT_Done_Face(face);
continue;
}
face->charmap=charmap;
face->charmap=charmap;*/
family=GetFamily(face->family_name);

View File

@ -847,19 +847,13 @@ Layer::Redraw(const BRegion& reg, Layer *startFrom)
void
Layer::Draw(const BRect &r)
{
// TODO/NOTE: this should be an empty method! the next lines are for testing only
#ifdef DEBUG_LAYER
printf("Layer(%s)::Draw: ", GetName());
r.PrintToStream();
#endif
// TODO: don't do this if ViewColor() is B_TRANSPARENT_COLOR
fDriver->FillRect(r, fLayerData->ViewColor());
// RGBColor c(rand()%255,rand()%255,rand()%255);
// fDriver->FillRect(r, c);
// empty HOOK function.
if (!fLayerData->ViewColor().IsTransparentMagic())
fDriver->FillRect(r, fLayerData->ViewColor());
}
// EmptyGlobals

View File

@ -61,41 +61,68 @@
#endif
static RGBColor kDefaultWorkspaceColor = RGBColor(51, 102, 152);
static int32 kMaxWorkspaceCount = 32;
RootLayer::RootLayer(const char *name, int32 workspaceCount,
Desktop *desktop, DisplayDriver *driver)
: Layer(BRect(0,0,0,0), name, 0, B_FOLLOW_ALL, B_WILL_DRAW, driver)
RootLayer::RootLayer(const char *name, int32 workspaceCount,
Desktop *desktop, DisplayDriver *driver)
: Layer(BRect(0, 0, 0, 0), name, 0, B_FOLLOW_ALL, B_WILL_DRAW, driver),
fDesktop(desktop),
fDragMessage(NULL),
fLastMouseMoved(this),
fMouseTargetWinBorder(NULL),
fViewAction(B_ENTERED_VIEW),
fEventMaskLayer(NULL),
fCursorManager(),
fAllRegionsLock("root layer region lock"),
fThreadID(B_ERROR),
fListenPort(-1),
fScreenPtrList(32),
fRows(0),
fColumns(0),
fScreenWidth(0),
fScreenHeight(0),
fColorSpace(B_RGB32),
fFrequency(60.0),
fButtons(0),
fLastMousePosition(0.0, 0.0),
// fMovingWindow(false),
// fResizingWindow(false),
fHaveWinBorderList(false),
fActiveWksIndex(0),
fWsCount(0),
fWorkspace(new Workspace*[kMaxWorkspaceCount]),
fWinBorderListLength(64),
fWinBorderList2((WinBorder**)malloc(fWinBorderListLength * sizeof(WinBorder*))),
fWinBorderList((WinBorder**)malloc(fWinBorderListLength * sizeof(WinBorder*))),
fWinBorderCount(0),
fWinBorderIndex(0),
fScreenShotIndex(1),
#if ON_SCREEN_DEBUGGING_INFO
fQuiting(false),
fDebugInfo("")
#else
fQuiting(false)
#endif
{
fDesktop = desktop;
fWinBorderListLength = 64;
fWinBorderList2 = (WinBorder**)malloc(fWinBorderListLength * sizeof(WinBorder*));
fWinBorderList = (WinBorder**)malloc(fWinBorderListLength * sizeof(WinBorder*));
fWinBorderCount = 0;
fWinBorderIndex = 0;
fWsCount = 0;
fMovingWindow = false;
fResizingWindow = false;
fHaveWinBorderList = false;
fLastMouseMoved = this;
fViewAction = B_ENTERED_VIEW;
fEventMaskLayer = NULL;
fDragMessage = NULL;
fScreenShotIndex = 1;
fQuiting = false;
//NOTE: be careful about this one.
fRootLayer = this;
fRows = 0;
fColumns = 0;
// easy way to identify this class.
fClassID = AS_ROOTLAYER_CLASS;
fHidden = false;
memset(&fWorkspace[0], 0, sizeof(Workspace*)*32);
memset(fWorkspace, 0, sizeof(Workspace*) * kMaxWorkspaceCount);
SetWorkspaceCount(workspaceCount);
// TODO: this should eventually be replaced by a method to convert the monitor
@ -103,13 +130,12 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
// ReadWorkspaceData(WORKSPACE_DATA_LIST);
// TODO: read these 4 from a configuration file.
fScreenWidth = 0;
fScreenHeight = 0;
fColorSpace = B_RGB32;
fFrequency = 60.f;
// fScreenWidth = 0;
// fScreenHeight = 0;
// fColorSpace = B_RGB32;
// fFrequency = 60.f;
// init the first, default workspace
fActiveWksIndex = 0;
fWorkspace[fActiveWksIndex] = new Workspace(fActiveWksIndex, 0xFF00FF00,
kDefaultWorkspaceColor);
fLayerData->SetHighColor(RGBColor(255, 255, 255));
@ -121,7 +147,6 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
fListenPort = find_port(SERVER_INPUT_PORT);
if (fListenPort == B_NAME_NOT_FOUND) {
fListenPort = -1;
return;
}
#if ON_SCREEN_DEBUGGING_INFO
DebugInfoManager::Default()->SetRootLayer(this);
@ -131,20 +156,24 @@ RootLayer::RootLayer(const char *name, int32 workspaceCount,
RootLayer::~RootLayer()
{
int32 exitValue;
fQuiting = true;
BPortLink msg(fListenPort, -1);
fQuiting = true;
BPortLink msg(fListenPort, -1);
msg.StartMessage(B_QUIT_REQUESTED);
msg.EndMessage();
msg.Flush();
wait_for_thread(fThreadID, &exitValue);
status_t dummy;
wait_for_thread(fThreadID, &dummy);
delete fDragMessage;
for (int32 i = 0; i < fWsCount; i++)
delete fWorkspace[i];
delete[] fWorkspace;
free(fWinBorderList2);
free(fWinBorderList);
// RootLayer object just uses Screen objects, it is not allowed to delete them.
}
@ -303,7 +332,7 @@ int32 RootLayer::WorkingThread(void *data)
break;
}
default:
STRACE(("RootLayer(%s)::WorkingThread received unexpected code %lx\n",oneRootLayer->GetName(), code));
printf("RootLayer(%s)::WorkingThread received unexpected code %lx\n", oneRootLayer->GetName(), code);
break;
}
@ -551,9 +580,12 @@ bool RootLayer::SetActiveWorkspace(int32 index)
if (index >= fWsCount || index == fActiveWksIndex || index < 0)
return false;
// you cannot switch workspaces on R5 if there is an event mask layer
if (fEventMaskLayer)
return false;
// if fWorkspace[index] object does not exist, create and add allowed WinBorders
if (!fWorkspace[index])
{
if (!fWorkspace[index]) {
// TODO: we NEED datas from a file!!!
fWorkspace[index] = new Workspace(index, 0xFF00FF00, kDefaultWorkspaceColor);
@ -565,10 +597,8 @@ bool RootLayer::SetActiveWorkspace(int32 index)
int32 ptrCount = windowList.CountItems();
WinBorder **ptrWin = (WinBorder**)windowList.Items();
for (int32 i = 0; i < ptrCount; i++)
{
if (ptrWin[i]->Workspaces() & (0x00000001UL << index))
{
for (int32 i = 0; i < ptrCount; i++) {
if (ptrWin[i]->Workspaces() & (0x00000001UL << index)) {
fWorkspace[index]->AddWinBorder(ptrWin[i]);
if (!ptrWin[i]->IsHidden())
fWorkspace[index]->ShowWinBorder(ptrWin[i]);
@ -577,6 +607,7 @@ bool RootLayer::SetActiveWorkspace(int32 index)
fDesktop->Unlock();
}
// adjust our DrawData to workspace colors
rgb_color bg = fWorkspace[index]->BGColor().GetColor32();
if ((bg.red + bg.green + bg.blue) / 3 > 128)
fLayerData->SetHighColor(RGBColor(0, 0, 0));
@ -584,10 +615,11 @@ bool RootLayer::SetActiveWorkspace(int32 index)
fLayerData->SetHighColor(RGBColor(255, 255, 255));
fLayerData->SetLowColor(fWorkspace[index]->BGColor());
int32 exIndex = ActiveWorkspaceIndex();
int32 exIndex = ActiveWorkspaceIndex();
// send the workspace changed message for the old workspace
{
BMessage activatedMsg(B_WORKSPACE_ACTIVATED);
BMessage activatedMsg(B_WORKSPACE_ACTIVATED);
activatedMsg.AddInt64("when", real_time_clock_usecs());
activatedMsg.AddInt32("workspace", fActiveWksIndex);
activatedMsg.AddBool("active", false);
@ -596,48 +628,49 @@ bool RootLayer::SetActiveWorkspace(int32 index)
fWinBorderList[i]->Window()->SendMessageToClient(&activatedMsg, B_NULL_TOKEN, false);
}
fActiveWksIndex = index;
fActiveWksIndex = index;
if (fMovingWindow && fEventMaskLayer)
{
WinBorder *movingWinBorder = (WinBorder*)fEventMaskLayer;
if (fMouseTargetWinBorder) {
// if (fMovingWindow && fEventMaskLayer) {
// WinBorder *movingWinBorder = (WinBorder*)fEventMaskLayer;
movingWinBorder->MouseUp(DEC_NONE);
// movingWinBorder->MouseUp(DEC_NONE);
// NOTE: DO NOT reset these 2 members! We still want to move our window in the new workspace
//fEventMaskLayer = NULL;
//fMovingWindow = false;
fResizingWindow = false;
// fResizingWindow = false;
// Take the WinBorder we're currently dragging with us to the new workspace
// NOTE: The code looks broken for WinBorders that show on multiple workspaces
// at the same time.
// only normal windows can change workspaces
if (movingWinBorder->Feel() == B_NORMAL_WINDOW_FEEL
&& !ActiveWorkspace()->HasWinBorder(movingWinBorder))
{
if (fMouseTargetWinBorder->Feel() == B_NORMAL_WINDOW_FEEL
&& !ActiveWorkspace()->HasWinBorder(fMouseTargetWinBorder)) {
// Workspace class expects a window to be hidden when it's about to be removed.
// As we surely know this windows is visible, we simply set fHidden to true and then
// change it back when adding winBorder to the current workspace.
movingWinBorder->fHidden = true;
fWorkspace[exIndex]->HideWinBorder(movingWinBorder);
fWorkspace[exIndex]->RemoveWinBorder(movingWinBorder);
fMouseTargetWinBorder->fHidden = true;
fWorkspace[exIndex]->HideWinBorder(fMouseTargetWinBorder);
fWorkspace[exIndex]->RemoveWinBorder(fMouseTargetWinBorder);
movingWinBorder->fHidden = false;
ActiveWorkspace()->AddWinBorder(movingWinBorder);
ActiveWorkspace()->ShowWinBorder(movingWinBorder);
fMouseTargetWinBorder->fHidden = false;
ActiveWorkspace()->AddWinBorder(fMouseTargetWinBorder);
ActiveWorkspace()->ShowWinBorder(fMouseTargetWinBorder);
// TODO: can you call SetWinBorderWorskpaces() instead of this?
uint32 wks = movingWinBorder->Workspaces();
BMessage changedMsg(B_WORKSPACES_CHANGED);
uint32 wks = fMouseTargetWinBorder->Workspaces();
BMessage changedMsg(B_WORKSPACES_CHANGED);
changedMsg.AddInt64("when", real_time_clock_usecs());
changedMsg.AddInt32("old", wks);
wks &= ~(0x00000001 << exIndex);
wks |= (0x00000001 << fActiveWksIndex);
wks &= ~(0x00000001 << exIndex);
wks |= (0x00000001 << fActiveWksIndex);
changedMsg.AddInt32("new", wks);
movingWinBorder->QuietlySetWorkspaces(wks);
movingWinBorder->Window()->SendMessageToClient(&changedMsg, B_NULL_TOKEN, false);
fMouseTargetWinBorder->QuietlySetWorkspaces(wks);
fMouseTargetWinBorder->Window()->SendMessageToClient(&changedMsg, B_NULL_TOKEN, false);
}
}
else if (fEventMaskLayer)
{
}/* else if (fEventMaskLayer) {
// is this a WinBorder object?
if (!fEventMaskLayer->fOwner)
{
@ -648,11 +681,12 @@ bool RootLayer::SetActiveWorkspace(int32 index)
fEventMaskLayer = NULL;
fMovingWindow = false;
fResizingWindow = false;
}
}*/
fHaveWinBorderList = true;
get_workspace_windows();
// send the workspace changed message for the new workspace
{
BMessage activatedMsg(B_WORKSPACE_ACTIVATED);
activatedMsg.AddInt64("when", real_time_clock_usecs());
@ -707,7 +741,7 @@ void RootLayer::SetWinBorderWorskpaces(WinBorder *winBorder, uint32 oldWksIndex,
}
else
{
// do nothing. winBorder was, and it's still is a member of this workspace
// do nothing. winBorder was, and it still is a member of this workspace
// OR, winBorder wasn't and it will not be in this workspace
}
@ -716,6 +750,7 @@ void RootLayer::SetWinBorderWorskpaces(WinBorder *winBorder, uint32 oldWksIndex,
}
}
// TODO: look into this...
if (fEventMaskLayer)
{
WinBorder *wb = fEventMaskLayer->fOwner?
@ -723,12 +758,12 @@ void RootLayer::SetWinBorderWorskpaces(WinBorder *winBorder, uint32 oldWksIndex,
(WinBorder*)fEventMaskLayer;
if (!fWorkspace[fActiveWksIndex]->HasWinBorder(wb))
{
if (wb == fEventMaskLayer)
/* if (wb == fEventMaskLayer)
{
fMovingWindow = false;
fResizingWindow = false;
wb->MouseUp(DEC_NONE);
}
}*/
fEventMaskLayer = NULL;
}
}
@ -744,23 +779,20 @@ void RootLayer::SetWinBorderWorskpaces(WinBorder *winBorder, uint32 oldWksIndex,
show_final_scene(exFocus, exActive);
}
void RootLayer::SetWorkspaceCount(int32 wksCount)
void
RootLayer::SetWorkspaceCount(int32 wksCount)
{
if (wksCount < 1)
wksCount = 1;
if (wksCount > 32)
wksCount = 32;
if (wksCount > kMaxWorkspaceCount)
wksCount = kMaxWorkspaceCount;
for (int32 i = wksCount; i < fWsCount; i++)
{
if (fWorkspace[i])
{
delete fWorkspace[i];
fWorkspace[i] = NULL;
}
for (int32 i = wksCount; i < fWsCount; i++) {
delete fWorkspace[i];
fWorkspace[i] = NULL;
}
fWsCount = wksCount;
fWsCount = wksCount;
}
void RootLayer::ReadWorkspaceData(const char *path)
@ -946,13 +978,12 @@ RootLayer::SetScreenMode(int32 width, int32 height, uint32 colorSpace, float fre
//---------------------------------------------------------------------------
// Input related methods
//---------------------------------------------------------------------------
inline
void RootLayer::MouseEventHandler(int32 code, BPortLink& msg)
inline void
RootLayer::MouseEventHandler(int32 code, BPortLink& msg)
{
switch(code)
{
case B_MOUSE_DOWN:
{
switch(code) {
case B_MOUSE_DOWN: {
//printf("RootLayer::MouseEventHandler(B_MOUSE_DOWN)\n");
// Attached data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
@ -970,7 +1001,7 @@ void RootLayer::MouseEventHandler(int32 code, BPortLink& msg)
msg.Read<int32>(&evt.buttons);
msg.Read<int32>(&evt.clicks);
if (fLastMousePossition != evt.where) {
if (fLastMousePosition != evt.where) {
// TODO: a B_MOUSE_MOVED message might have to be generated in order to
// correctly trigger entered/exited view transits.
// Commented for now, since it is not _that_ critical and happens frequently with the Haiku
@ -978,11 +1009,15 @@ void RootLayer::MouseEventHandler(int32 code, BPortLink& msg)
// CRITICAL("mouse position changed in B_MOUSE_DOWN from last B_MOUSE_MOVED\n");
// update on screen mouse pos
GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y);
fLastMousePossition = evt.where;
fLastMousePosition = evt.where;
}
// We'll need this so that GetMouse can query for which buttons
// are down.
fButtons = evt.buttons;
if (fLastMouseMoved == NULL) {
CRITICAL("RootLayer: fLastMouseMoved is null!\n");
CRITICAL("RootLayer::MouseEventHandler(B_MOUSE_DOWN) fLastMouseMoved is null!\n");
break;
}
@ -991,21 +1026,16 @@ void RootLayer::MouseEventHandler(int32 code, BPortLink& msg)
// we are clicking a WinBorder
click_type action;
bool invalidate;
bool sendMessage = true;
WinBorder *exActive = ActiveWinBorder();
WinBorder *exFocus = FocusWinBorder();
WinBorder *target = fLastMouseMoved->fOwner?
fLastMouseMoved->fOwner:
(WinBorder*)fLastMouseMoved;
WinBorder* exActive = ActiveWinBorder();
WinBorder* exFocus = FocusWinBorder();
WinBorder* target = fLastMouseMoved->fOwner ? fLastMouseMoved->fOwner
: (WinBorder*)fLastMouseMoved;
action = target->TellWhat(evt);
click_type action = target->MouseDown(evt);
if (action == DEC_MOVETOBACK)
invalidate = ActiveWorkspace()->MoveToBack(target);
else
invalidate = ActiveWorkspace()->MoveToFront(target);
// TODO: only move to front if *not* in Focus Follows Mouse mode!
bool invalidate = action == DEC_MOVETOBACK ? ActiveWorkspace()->MoveToBack(target)
: ActiveWorkspace()->MoveToFront(target);
// Performance: MoveToFront() often returns true although it shouldn't do that.
// This is because internaly it calls Workspace::ShowWinBorder() and this imposes
@ -1014,55 +1044,57 @@ void RootLayer::MouseEventHandler(int32 code, BPortLink& msg)
if (invalidate)
show_final_scene(exFocus, exActive);
if (action == DEC_DRAG)
{
fMovingWindow = true;
}
else if (action == DEC_RESIZE)
{
fResizingWindow = true;
}
else if (action != DEC_NONE && action != DEC_MOVETOBACK)
{
target->MouseDown(action);
}
else if (action != DEC_MOVETOBACK)
{
// we are inside WinBorder
// some of the actions are handled by the WinBorder itself,
// others are handled by RootLayer
fMouseTargetWinBorder = NULL;
switch (action) {
case DEC_MOVETOBACK:
// TODO: handle here once we support FFM...
// now it is handled above
break;
case DEC_NONE: {
// TODO: bring to front if not in FFM...
// now it is handled above
bool sendMessage = true;
// supress mouse down events if the window has no focus or
// does not accept first clicks
if (target != FocusWinBorder())
sendMessage = false;
else if (exFocus != FocusWinBorder()
&& !(target->WindowFlags() & B_WILL_ACCEPT_FIRST_CLICK))
sendMessage = false;
if (sendMessage && fLastMouseMoved != target->fTopLayer) {
BMessage msg;
msg.what = B_MOUSE_DOWN;
msg.AddInt64("when", evt.when);
msg.AddPoint("where", evt.where);
msg.AddInt32("modifiers", evt.modifiers);
msg.AddInt32("buttons", evt.buttons);
msg.AddInt32("clicks", evt.clicks);
target->Window()->SendMessageToClient(&msg, fLastMouseMoved->fViewToken, false);
}
if (target != FocusWinBorder())
sendMessage = false;
else if (exFocus != FocusWinBorder()
&& !(target->WindowFlags() & B_WILL_ACCEPT_FIRST_CLICK))
sendMessage = false;
if (sendMessage && fLastMouseMoved != target->fTopLayer)
{
BMessage msg;
msg.what = B_MOUSE_DOWN;
msg.AddInt64("when", evt.when);
msg.AddPoint("where", evt.where);
msg.AddInt32("modifiers", evt.modifiers);
msg.AddInt32("buttons", evt.buttons);
msg.AddInt32("clicks", evt.clicks);
target->Window()->SendMessageToClient(&msg, fLastMouseMoved->fViewToken, false);
if (fLastMouseMoved->EventMask() & B_POINTER_EVENTS) {
fEventMaskLayer = fLastMouseMoved;
}
break;
}
}
if (fLastMouseMoved->EventMask() & B_POINTER_EVENTS)
{
fEventMaskLayer = fLastMouseMoved;
case DEC_DRAG:
case DEC_RESIZE:
default:
// TODO: bring to front if not in FFM...
// now it is handled above
fMouseTargetWinBorder = target;
break;
}
// We'll need this so that GetMouse can query for which buttons
// are down.
fButtons=evt.buttons;
break;
}
case B_MOUSE_UP:
{
case B_MOUSE_UP: {
//printf("RootLayer::MouseEventHandler(B_MOUSE_UP)\n");
// Attached data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
@ -1076,42 +1108,41 @@ void RootLayer::MouseEventHandler(int32 code, BPortLink& msg)
msg.Read<float>(&evt.where.y);
msg.Read<int32>(&evt.modifiers);
if (fLastMousePossition != evt.where) {
if (fLastMouseMoved == NULL) {
CRITICAL("RootLayer::MouseEventHandler(B_MOUSE_UP) fLastMouseMoved is null!\n");
break;
}
if (fLastMousePosition != evt.where) {
// TODO: a B_MOUSE_MOVED message might have to be generated in order to
// correctly trigger entered/exited view transits.
fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_MOUSE_MOVED (%.1f, %.1f)!",
evt.where.x, evt.where.y, fLastMousePossition.x, fLastMousePossition.y);
fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_MOUSE_MOVED (%.1f, %.1f)!\n",
evt.where.x, evt.where.y, fLastMousePosition.x, fLastMousePosition.y);
// update on screen mouse pos
GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y);
fLastMousePossition = evt.where;
fLastMousePosition = evt.where;
}
// TODO: what if 'fEventMaskLayer' is deleted in the mean time.
if (fEventMaskLayer)
{
if (fEventMaskLayer) {
// if this is a regular Layer, sent message to counterpart BView.
if (fEventMaskLayer->fOwner)
{
if (fEventMaskLayer->fOwner) {
BMessage upmsg(B_MOUSE_UP);
upmsg.AddInt64("when",evt.when);
upmsg.AddPoint("where",evt.where);
upmsg.AddInt32("modifiers",evt.modifiers);
fEventMaskLayer->Window()->SendMessageToClient(&upmsg, fEventMaskLayer->fViewToken, false);
}
// this surely is a WinBorder
else
{
((WinBorder*)fEventMaskLayer)->MouseUp(((WinBorder*)fEventMaskLayer)->TellWhat(evt));
} else {
// this surely is a WinBorder
// TODO: This code is too confusing. There should be a clear separation.
// ((WinBorder*)fEventMaskLayer)->MouseUp(((WinBorder*)fEventMaskLayer)->TellWhat(evt));
}
fEventMaskLayer = NULL;
}
else
{
} else {
// NOTE: focus may be NULL
if (fLastMouseMoved->Window() && fLastMouseMoved->fOwner == FocusWinBorder())
{
if (fLastMouseMoved->Window() && fLastMouseMoved->fOwner == FocusWinBorder()) {
// send B_MOUSE_UP for regular Layers/BViews
BMessage upmsg(B_MOUSE_UP);
upmsg.AddInt64("when",evt.when);
@ -1119,17 +1150,19 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
upmsg.AddInt32("modifiers",evt.modifiers);
fLastMouseMoved->Window()->SendMessageToClient(&upmsg, fLastMouseMoved->fViewToken, false);
}
else
{
} else {
// WinBorders don't need _UP_ messages unless they received _DOWN_ messages,
// and that case is threated above - WinBorders use Layer::fEventMask to
// capture the mouse.
}
}
fMovingWindow = false;
fResizingWindow = false;
// fMovingWindow = false;
// fResizingWindow = false;
if (fMouseTargetWinBorder) {
fMouseTargetWinBorder->MouseUp(evt);
fMouseTargetWinBorder = NULL;
}
STRACE(("MOUSE UP: at (%f, %f)\n", evt.where.x, evt.where.y));
@ -1139,8 +1172,8 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
break;
}
case B_MOUSE_MOVED:
{
case B_MOUSE_MOVED: {
//printf("RootLayer::MouseEventHandler(B_MOUSE_MOVED)\n");
// Attached data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
@ -1156,12 +1189,26 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
GetDisplayDriver()->MoveCursorTo(evt.where.x, evt.where.y);
fLastMousePosition = evt.where;
// NOTE: The mouse does NOT have to be over the fMouseTargetWinBorder for
// it to be still the valid target of the event. In fact, it is
// the only valid target until MOUSE_UP. So don't move this block farther
// down.
if (fMouseTargetWinBorder) {
fMouseTargetWinBorder->MouseMoved(evt);
fLastMouseMoved = fMouseTargetWinBorder;
break;
}
// TODO: lock ServerWindow here! Don't forget, you need to add/remove Layers
// from within RootLayer's thread!!!
Layer *target = LayerAt(evt.where);
if (target == NULL)
CRITICAL("RootLayer::MouseEventHandler: 'target' can't be null.\n");
WinBorder *winBorderUnder = NULL;
Layer* target = LayerAt(evt.where);
if (target == NULL) {
CRITICAL("RootLayer::MouseEventHandler(B_MOUSE_MOVED) 'target' can't be null.\n");
break;
}
WinBorder* winBorderUnder = NULL;
// TODO: I think that windows created without the B_ASYNCHRONOUS_CONTROLS flag
// don't receive B_MOUSE_MOVED events after a B_MOUSE_DOWN. Test.
@ -1169,53 +1216,40 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
// is very hard.
// fEventMaskLayer is always != this
if (fEventMaskLayer)
{
if (fEventMaskLayer == target)
{
if (fEventMaskLayer) {
if (fEventMaskLayer == target) {
if (target == fLastMouseMoved)
{
fViewAction = B_INSIDE_VIEW;
}
else
{
fViewAction = B_ENTERED_VIEW;
}
}
else if (fEventMaskLayer == fLastMouseMoved)
{
} else if (fEventMaskLayer == fLastMouseMoved) {
fViewAction = B_EXITED_VIEW;
}
else
{
} else {
fViewAction = B_OUTSIDE_VIEW;
}
if (fEventMaskLayer->fOwner)
{
if (fEventMaskLayer->fOwner) {
// top layer does not have B_POINTER_EVENTS in its event mask
BMessage movemsg(B_MOUSE_MOVED);
movemsg.AddInt64("when",evt.when);
movemsg.AddPoint("where",evt.where);
movemsg.AddInt32("buttons",evt.buttons);
movemsg.AddInt64("when", evt.when);
movemsg.AddPoint("where", evt.where);
movemsg.AddInt32("buttons", evt.buttons);
movemsg.AddInt32("transit", fViewAction);
fEventMaskLayer->Window()->SendMessageToClient(&movemsg, fEventMaskLayer->fViewToken, false);
}
else
{
} else {
winBorderUnder = (WinBorder*)fEventMaskLayer;
}
}
else
{
if (fLastMouseMoved != target)
{
} else {
if (fLastMouseMoved != target) {
fViewAction = B_EXITED_VIEW;
if (fLastMouseMoved->fOwner)
{
if (fLastMouseMoved != fLastMouseMoved->fOwner->fTopLayer)
{
if (fLastMouseMoved->fOwner) {
if (fLastMouseMoved != fLastMouseMoved->fOwner->fTopLayer) {
BMessage movemsg(B_MOUSE_MOVED);
movemsg.AddInt64("when",evt.when);
movemsg.AddPoint("where",evt.where);
@ -1223,21 +1257,16 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
movemsg.AddInt32("transit",fViewAction);
fLastMouseMoved->Window()->SendMessageToClient(&movemsg, fLastMouseMoved->fViewToken, false);
}
}
else if (fLastMouseMoved != this)
((WinBorder*)fLastMouseMoved)->MouseMoved(DEC_NONE);
}// else if (fLastMouseMoved != this)
// ((WinBorder*)fLastMouseMoved)->MouseMoved(DEC_NONE);
fViewAction = B_ENTERED_VIEW;
}
else
{
} else {
fViewAction = B_INSIDE_VIEW;
}
if (target->fOwner)
{
if (target != target->fOwner->fTopLayer)
{
if (target->fOwner) {
if (target != target->fOwner->fTopLayer) {
BMessage movemsg(B_MOUSE_MOVED);
movemsg.AddInt64("when",evt.when);
movemsg.AddPoint("where",evt.where);
@ -1245,16 +1274,14 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
movemsg.AddInt32("transit",fViewAction);
target->Window()->SendMessageToClient(&movemsg, target->fViewToken, false);
}
}
else if (target != this)
{
} else if (target != this) {
winBorderUnder = (WinBorder*)target;
}
}
if (winBorderUnder) {
/* if (winBorderUnder) {
BPoint delta = evt.where - fLastMousePossition;
BPoint delta = evt.where - fLastMousePosition;
if (fMovingWindow) {
@ -1280,15 +1307,14 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
} else {
winBorderUnder->MouseMoved(winBorderUnder->TellWhat(evt));
}
}
}*/
fLastMouseMoved = target;
fLastMousePossition = evt.where;
fLastMouseMoved = target;
break;
}
case B_MOUSE_WHEEL_CHANGED:
{
case B_MOUSE_WHEEL_CHANGED: {
//printf("RootLayer::MouseEventHandler(B_MOUSE_WHEEL_CHANGED)\n");
// FEATURE: This is a tentative change: mouse wheel messages are always sent to the window
// under the cursor. It's pretty stupid to send it to the active window unless a particular
// view has locked focus via SetMouseEventMask
@ -1299,12 +1325,9 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
msg.Read<float>(&evt.wheel_delta_x);
msg.Read<float>(&evt.wheel_delta_y);
if (fLastMouseMoved != this)
{
if (fLastMouseMoved->fOwner) // is a Layer object not a WinBorder one
{
if (fLastMouseMoved->fOwner->fTopLayer != fLastMouseMoved) // must not be the top_view's counterpart
{
if (fLastMouseMoved && fLastMouseMoved != this) {
if (fLastMouseMoved->fOwner) { // is a Layer object not a WinBorder one
if (fLastMouseMoved->fOwner->fTopLayer != fLastMouseMoved) { // must not be the top_view's counterpart
BMessage wheelmsg(B_MOUSE_WHEEL_CHANGED);
wheelmsg.AddInt64("when", evt.when);
wheelmsg.AddFloat("be:wheel_delta_x",evt.wheel_delta_x);
@ -1312,9 +1335,7 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
fLastMouseMoved->Window()->SendMessageToClient(&wheelmsg, fLastMouseMoved->fViewToken, false);
}
}
else
{
} else {
// TODO: WinBorder::MouseWheel() should dissapear or get other params!
// ((WinBorder*)fLastMouseMoved)->MouseWheel(...)
}
@ -1323,7 +1344,7 @@ fprintf(stderr, "mouse position changed in B_MOUSE_UP (%.1f, %.1f) from last B_M
}
default:
{
printf("\nDesktop::MouseEventHandler(): WARNING: unknown message\n\n");
printf("RootLayer::MouseEventHandler(): WARNING: unknown message\n");
break;
}
}
@ -1430,6 +1451,7 @@ void RootLayer::KeyboardEventHandler(int32 code, BPortLink& msg)
{
fScreenShotIndex++;
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
entry.SetTo(filename);
}
fScreenShotIndex++;
GetDisplayDriver()->DumpToFile(filename);
@ -1512,6 +1534,7 @@ void RootLayer::KeyboardEventHandler(int32 code, BPortLink& msg)
{
fScreenShotIndex++;
sprintf(filename,"/boot/home/screen%ld.png",fScreenShotIndex);
entry.SetTo(filename);
}
fScreenShotIndex++;
@ -1897,7 +1920,8 @@ void RootLayer::change_winBorder_feel(WinBorder *winBorder, int32 newFeel)
{
if (fEventMaskLayer)
{
WinBorder *wb = fEventMaskLayer->fOwner?
// TODO: What was this supposed to do?!?
/* WinBorder *wb = fEventMaskLayer->fOwner?
fEventMaskLayer->fOwner:
(WinBorder*)fEventMaskLayer;
if (wb == fEventMaskLayer)
@ -1905,7 +1929,7 @@ void RootLayer::change_winBorder_feel(WinBorder *winBorder, int32 newFeel)
fMovingWindow = false;
fResizingWindow = false;
wb->MouseUp(DEC_NONE);
}
}*/
fEventMaskLayer = NULL;
}
@ -1970,18 +1994,17 @@ bool RootLayer::get_workspace_windows()
return aChange;
}
void RootLayer::draw_window_tab(WinBorder *exFocus)
void
RootLayer::draw_window_tab(WinBorder *exFocus)
{
WinBorder *focus = FocusWinBorder();
if (exFocus || focus)
{
if (exFocus || focus) {
if (exFocus && exFocus != focus && exFocus->fDecorator)
exFocus->fDecorator->SetFocus(false);
if (focus && exFocus != focus && focus->fDecorator)
focus->fDecorator->SetFocus(true);
if (exFocus && focus != exFocus)
{
if (exFocus && focus != exFocus) {
// TODO: this line is a hack, decorator is drawn twice.
BRegion reg(exFocus->fVisible);
if (focus)
@ -1991,8 +2014,8 @@ void RootLayer::draw_window_tab(WinBorder *exFocus)
}
}
inline
void RootLayer::empty_visible_regions(Layer *layer)
inline void
RootLayer::empty_visible_regions(Layer *layer)
{
// TODO: optimize by avoiding recursion?
// NOTE: first 'layer' must be a WinBorder
@ -2002,36 +2025,32 @@ void RootLayer::empty_visible_regions(Layer *layer)
layer->fVisible.MakeEmpty();
child = layer->VirtualBottomChild();
while(child)
{
while(child) {
empty_visible_regions(child);
child = layer->VirtualUpperSibling();
}
}
inline
void RootLayer::winborder_activation(WinBorder* exActive)
inline void
RootLayer::winborder_activation(WinBorder* exActive)
{
if (exActive && (FocusWinBorder() != exActive || FrontWinBorder() != exActive))
{
BMessage msg(B_WINDOW_ACTIVATED);
if (exActive && (FocusWinBorder() != exActive || FrontWinBorder() != exActive)) {
BMessage msg(B_WINDOW_ACTIVATED);
msg.AddBool("active", false);
exActive->Window()->SendMessageToClient(&msg, B_NULL_TOKEN, false);
}
if (FocusWinBorder() == FrontWinBorder()
&& FrontWinBorder() != NULL && FrontWinBorder() != exActive)
{
BMessage msg(B_WINDOW_ACTIVATED);
&& FrontWinBorder() != NULL && FrontWinBorder() != exActive) {
BMessage msg(B_WINDOW_ACTIVATED);
msg.AddBool("active", true);
FrontWinBorder()->Window()->SendMessageToClient(&msg, B_NULL_TOKEN, false);
}
}
inline
void RootLayer::show_final_scene(WinBorder *exFocus, WinBorder *exActive)
inline void
RootLayer::show_final_scene(WinBorder *exFocus, WinBorder *exActive)
{
if(fHaveWinBorderList || get_workspace_windows())
{
if (fHaveWinBorderList || get_workspace_windows()) {
// next call should call get_workspace_windows()
fHaveWinBorderList = false;
// TODO: should it be improved by calling with region of hidden windows
@ -2050,12 +2069,15 @@ void RootLayer::show_final_scene(WinBorder *exFocus, WinBorder *exActive)
// the same mouse position with B_ENTERD_VIEW??? Same when changing workspaces!!!
// INVESTIGATE, INVESTIGATE, INVESTIGATE!!!
// NOTE: the following 3 lines are here for safety reasons!
fLastMouseMoved = LayerAt(fLastMousePossition);
if (fLastMouseMoved == NULL)
CRITICAL("RootLayer::KeyboardEventHandler: 'fLastMouseMoved' can't be null.\n");
fLastMouseMoved = LayerAt(fLastMousePosition);
if (fLastMouseMoved == NULL) {
CRITICAL("RootLayer::show_final_scene: 'fLastMouseMoved' can't be null.\n");
fLastMouseMoved = this;
}
}
void RootLayer::Draw(const BRect &r)
void
RootLayer::Draw(const BRect &r)
{
fDriver->FillRect(r, fWorkspace[fActiveWksIndex]->BGColor());
#ifdef APPSERVER_ROOTLAYER_SHOW_WORKSPACE_NUMBER

View File

@ -164,12 +164,15 @@ friend class Desktop;
void MouseEventHandler(int32 code, BPortLink& link);
void KeyboardEventHandler(int32 code, BPortLink& link);
Desktop *fDesktop;
BMessage *fDragMessage;
Layer *fLastMouseMoved;
Desktop* fDesktop;
BMessage* fDragMessage;
Layer* fLastMouseMoved;
WinBorder* fMouseTargetWinBorder;
int32 fViewAction;
Layer *fEventMaskLayer;
Layer* fEventMaskLayer;
CursorManager fCursorManager;
BLocker fAllRegionsLock;
thread_id fThreadID;
@ -185,19 +188,20 @@ friend class Desktop;
float fFrequency;
int32 fButtons;
BPoint fLastMousePossition;
BPoint fLastMousePosition;
bool fMovingWindow;
bool fResizingWindow;
bool fHaveWinBorderList;
int32 fActiveWksIndex;
int32 fWsCount;
Workspace* fWorkspace[32];
Workspace** fWorkspace;
int32 fWinBorderListLength;
WinBorder** fWinBorderList2;
WinBorder** fWinBorderList;
int32 fWinBorderCount;
mutable int32 fWinBorderIndex;
int32 fWinBorderListLength;
int32 fScreenShotIndex;
bool fQuiting;

View File

@ -1220,12 +1220,12 @@ ServerApp::DispatchMessage(int32 code, LinkMsgReader &msg)
replylink.Attach<float>(width);
replylink.Flush();
free(string);
} else {
replylink.StartMessage(SERVER_FALSE);
replylink.Flush();
}
free(string);
break;
}
@ -1875,6 +1875,84 @@ ServerApp::DispatchMessage(int32 code, LinkMsgReader &msg)
break;
}
/* case AS_GET_TRUNCATED_STRINGS:
{
// Attached data
// 1) uint16 family id
// 2) uint16 style id
// 3) float size
// 4) uint8 spacing
// 5) uint32 mode - B_TRUNCATE_END...
// 6) float width - desired width
// 7) int32 count - count of attached strings
// 8) strings
// Returns:
// 1) strings - as many strings as requested, all of "width" maximum width
// font attribs
uint16 family;
uint16 style;
float size;
uint8 spacing;
msg.Read<uint16>(&family);
msg.Read<uint16>(&style);
msg.Read<float>(&size);
msg.Read<uint8>(&spacing);
// params
uint32 mode;
float width;
int32 count;
msg.Read<uint32>(&mode);
msg.Read<float>(&width);
msg.Read<int32>(&count);
char** strings = NULL;
bool success = false;
if (count > 0) {
strings = new char*[count];
for (int32 i = 0; i < count; i++) {
msg.ReadString(&strings[i]);
}
// TODO: truncate strings here
ServerFont font;
if (font.SetFamilyAndStyle(family, style) >= B_OK) {
font.SetSize(size);
// TODO: implement: font.SetSpacing(spacing);
success = font.GetTruncatedStrings(strings, count, width, mode);
}
}
int32 replyport;
msg.Read<int32>(&replyport);
replylink.SetSendPort(replyport);
if (success) {
replylink.StartMessage(SERVER_TRUE);
for (int32 i = 0; i < count; i++) {
replylink.AttachString(strings[i]);
}
} else {
replylink.StartMessage(SERVER_FALSE);
}
replylink.Flush();
// free used resources
if (count > 0) {
for (int32 i = 0; i < count; i++)
free(strings[i]);
}
delete[] strings;
break;
}*/
case AS_SCREEN_GET_MODE:
{
// Attached data
@ -1944,12 +2022,20 @@ ServerApp::DispatchMessage(int32 code, LinkMsgReader &msg)
replylink.Flush();
break;
}
default:
{
STRACE(("ServerApp %s received unhandled message code offset %s\n",fSignature.String(),
MsgCodeToBString(code).String()));
printf("ServerApp %s received unhandled message code offset %s\n", fSignature.String(),
MsgCodeToBString(code).String());
// TODO: completely broken. The reply port seems to be unkown!
// It is in the data, but the position is unkown. Man, I find
// this comm stuff really clumsy. -Stephan)
// And BTW: the client is now blocking and waiting for a reply!
/*replylink.SetSendPort(msg.GetPort());
replylink.StartMessage(SERVER_FALSE);
replylink.Flush();
*/
break;
}
}

View File

@ -26,11 +26,13 @@
//------------------------------------------------------------------------------
#include <ByteOrder.h>
#include <Shape.h>
#include <String.h>
#include <UTF8.h>
#include "Angle.h"
#include "FontServer.h"
#include "moreUTF8.h"
#include "truncate_string.h"
#include FT_FREETYPE_H
#include FT_OUTLINE_H
@ -47,20 +49,22 @@
\param flags Style flags as defined in <Font.h>
\param spacing String spacing flag as defined in <Font.h>
*/
ServerFont::ServerFont(FontStyle *style, float size, float rotation, float shear,
uint16 flags, uint8 spacing)
ServerFont::ServerFont(FontStyle *style, float size,
float rotation, float shear,
uint16 flags, uint8 spacing)
: fStyle(style),
fSize(size),
fRotation(rotation),
fShear(shear),
fBounds(0, 0, 0, 0),
fFlags(flags),
fSpacing(spacing),
fDirection(B_FONT_LEFT_TO_RIGHT),
fFace(B_REGULAR_FACE),
fEncoding(B_UNICODE_UTF8)
{
fStyle=style;
fSize=size;
fRotation=rotation;
fShear=shear;
fFlags=flags;
fSpacing=spacing;
fDirection=B_FONT_LEFT_TO_RIGHT;
fFace=B_REGULAR_FACE;
fEncoding=B_UNICODE_UTF8;
fBounds.Set(0,0,0,0);
if(fStyle)
if (fStyle)
fStyle->AddDependent();
}
@ -68,18 +72,18 @@ ServerFont::ServerFont(FontStyle *style, float size, float rotation, float shear
// constructor, that initializes without actually interfacing with
// freetype, so that a ServerFont can be guaranteed to be "valid".
ServerFont::ServerFont(void)
ServerFont::ServerFont()
: fStyle(NULL),
fSize(0.0),
fRotation(0.0),
fShear(90.0),
fBounds(0, 0, 0, 0),
fFlags(0),
fSpacing(B_STRING_SPACING),
fDirection(B_FONT_LEFT_TO_RIGHT),
fFace(B_REGULAR_FACE),
fEncoding(B_UNICODE_UTF8)
{
fStyle=NULL;
fSize=0.0;
fRotation=0.0;
fShear=90.0;
fFlags=0;
fSpacing=B_STRING_SPACING;
fDirection=B_FONT_LEFT_TO_RIGHT;
fFace=B_REGULAR_FACE;
fEncoding=B_UNICODE_UTF8;
fBounds.Set(0,0,0,0);
}
/*!
@ -87,27 +91,27 @@ ServerFont::ServerFont(void)
\param font ServerFont to copy
*/
ServerFont::ServerFont(const ServerFont &font)
: fStyle(font.fStyle),
fSize(font.fSize),
fRotation(font.fRotation),
fShear(font.fShear),
fBounds(0, 0, 0, 0),
fFlags(font.fFlags),
fSpacing(font.fSpacing),
fDirection(font.fDirection),
fFace(font.fFace),
fEncoding(font.fEncoding)
{
fStyle=font.fStyle;
fSize=font.fSize;
fRotation=font.fRotation;
fShear=font.fShear;
fFlags=font.fFlags;
fSpacing=font.fSpacing;
fDirection=font.fDirection;
fFace=font.fFace;
fEncoding=font.fEncoding;
fBounds.Set(0,0,0,0);
if(fStyle)
if (fStyle)
fStyle->AddDependent();
}
/*!
\brief Removes itself as a dependency of its owning style.
*/
ServerFont::~ServerFont(void)
ServerFont::~ServerFont()
{
if(fStyle)
if (fStyle)
fStyle->RemoveDependent();
}
@ -116,19 +120,21 @@ ServerFont::~ServerFont(void)
\param The font to copy from.
\return A copy of the specified font
*/
ServerFont& ServerFont::operator=(const ServerFont& font){
fStyle = font.fStyle;
ServerFont&
ServerFont::operator=(const ServerFont& font)
{
fSize = font.fSize;
fRotation = font.fRotation;
fShear = font.fShear;
fFlags = font.fFlags;
fSpacing = font.fSpacing;
fDirection = B_FONT_LEFT_TO_RIGHT;
fFace = B_REGULAR_FACE;
fEncoding = B_UNICODE_UTF8;
fBounds.Set(0,0,0,0);
if(fStyle)
fStyle->AddDependent();
fDirection = font.fDirection;
fFace = font.fFace;
fEncoding = font.fEncoding;
fBounds = font.fBounds;
_SetStyle(font.fStyle);
return *this;
}
@ -136,10 +142,11 @@ ServerFont& ServerFont::operator=(const ServerFont& font){
\brief Returns the number of strikes in the font
\return The number of strikes in the font
*/
int32 ServerFont::CountTuned(void)
int32
ServerFont::CountTuned()
{
if(fStyle)
fStyle->TunedCount();
if (fStyle)
return fStyle->TunedCount();
return 0;
}
@ -148,42 +155,77 @@ int32 ServerFont::CountTuned(void)
\brief Returns the file format of the font. Currently unimplemented.
\return B_TRUETYPE_WINDOWS
*/
font_file_format ServerFont::FileFormat(void)
font_file_format
ServerFont::FileFormat()
{
// TODO: implement ServerFont::FileFormat
return B_TRUETYPE_WINDOWS;
}
/*!
\brief Returns a BRect which encloses the entire font
\return A BRect which encloses the entire font
const char*
ServerFont::GetStyle() const
{
if (fStyle)
return fStyle->Name();
return NULL;
}
const char*
ServerFont::GetFamily() const
{
if (fStyle)
return fStyle->Family()->Name();
return NULL;
}
/*!
\brief Sets the ServerFont instance to whatever font is specified
\param familyID ID number of the family to set
\param styleID ID number of the style to set
\return B_OK if successful, B_ERROR if not
*/
BRect ServerFont::BoundingBox(void)
status_t
ServerFont::SetFamilyAndStyle(uint16 familyID, uint16 styleID)
{
return fBounds;
FontStyle* style = NULL;
if (fontserver->Lock()) {
style = fontserver->GetStyle(familyID, styleID);
fontserver->Unlock();
}
if (!style)
return B_ERROR;
_SetStyle(style);
return B_OK;
}
const char *ServerFont::GetStyle(void) const
{
return fStyle->Name();
}
const char *ServerFont::GetFamily(void) const
{
return fStyle->Family()->Name();
}
/*!
\brief Obtains the height values for characters in the font in its current state
\param fh pointer to a font_height object to receive the values for the font
/*!
\brief Sets the ServerFont instance to whatever font is specified
\param fontID the combination of family and style ID numbers
\return B_OK if successful, B_ERROR if not
*/
void ServerFont::Height(font_height *fh)
status_t
ServerFont::SetFamilyAndStyle(uint32 fontID)
{
if(!fh)
return;
uint16 style = fontID & 0xFFFF;
uint16 family = (fontID & 0xFFFF0000) >> 16;
if(fStyle)
*fh=fStyle->GetHeight(fSize);
return SetFamilyAndStyle(family, style);
}
/*!
\brief Gets the ID values for the ServerFont instance in one shot
\return the combination of family and style ID numbers
*/
uint32
ServerFont::GetFamilyAndStyle(void) const
{
return (FamilyID() << 16) | StyleID();
}
// functions needed to convert a freetype vector graphics to a BShape
@ -295,7 +337,7 @@ BPoint*
ServerFont::GetEscapements(const char charArray[], int32 numChars,
BPoint offsetArray[]) const
{
if (!charArray || numChars <= 0 || !offsetArray)
if (!fStyle || !charArray || numChars <= 0 || !offsetArray)
return NULL;
FT_Face face = fStyle->GetFTFace();
@ -349,7 +391,7 @@ inline bool
is_white_space(uint16 glyph)
{
// TODO: handle them all!
if (glyph == ' ')
if (glyph == ' ' || glyph == B_TAB)
return true;
return false;
}
@ -359,7 +401,7 @@ bool
ServerFont::GetEscapements(const char charArray[], int32 numChars,
float widthArray[], escapement_delta delta) const
{
if (!charArray || numChars <= 0)
if (!fStyle || !charArray || numChars <= 0)
return false;
FT_Face face = fStyle->GetFTFace();
@ -404,7 +446,7 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars,
float
ServerFont::StringWidth(const char* string, int32 numBytes) const
{
if (!string || numBytes <= 0)
if (!fStyle || !string || numBytes <= 0)
return 0.0;
FT_Face face = fStyle->GetFTFace();
@ -439,55 +481,69 @@ ServerFont::StringWidth(const char* string, int32 numBytes) const
return width;
}
/*!
\brief Sets the ServerFont instance to whatever font is specified
\param familyID ID number of the family to set
\param styleID ID number of the style to set
\return B_OK if successful, B_ERROR if not
/*!
\brief Returns a BRect which encloses the entire font
\return A BRect which encloses the entire font
*/
status_t ServerFont::SetFamilyAndStyle(const uint16 &familyID,const uint16 &styleID)
BRect
ServerFont::BoundingBox()
{
fontserver->Lock();
FontStyle *sty=fontserver->GetStyle(familyID,styleID);
fontserver->Unlock();
if(!sty)
return B_ERROR;
fStyle=sty;
return B_OK;
// TODO: fBounds is nowhere calculated!
return fBounds;
}
/*!
\brief Sets the ServerFont instance to whatever font is specified
\param fontID the combination of family and style ID numbers
\return B_OK if successful, B_ERROR if not
/*!
\brief Obtains the height values for characters in the font in its current state
\param fh pointer to a font_height object to receive the values for the font
*/
status_t ServerFont::SetFamilyAndStyle(const uint32 &fontID)
void
ServerFont::Height(font_height *fh) const
{
uint16 style = fontID & 0xFFFF;
uint16 family = (fontID & 0xFFFF0000) >> 16;
fontserver->Lock();
FontStyle *sty=fontserver->GetStyle(family,style);
fontserver->Unlock();
if(!sty)
return B_ERROR;
fStyle=sty;
return B_OK;
if (fh && fStyle)
*fh = fStyle->GetHeight(fSize);
}
/*!
\brief Gets the ID values for the ServerFont instance in one shot
\return the combination of family and style ID numbers
*/
uint32 ServerFont::GetFamilyAndStyle(void) const
// TruncateString
void
ServerFont::TruncateString(BString* inOut, uint32 mode, float width) const
{
uint32 famsty=0;
famsty|=FamilyID() << 16;
famsty|=StyleID();
return famsty;
if (inOut) {
// the width of the "…" glyph
float ellipsisWidth = StringWidth(B_UTF8_ELLIPSIS, 3);
const char* string = inOut->String();
int32 length = strlen(string);
// temporary array to hold result
char* result = new char[length + 3];
// count the individual glyphs
int32 numChars = UTF8CountChars(string, length);
// get the escapement of each glyph in font units
float* escapementArray = new float[numChars];
static escapement_delta delta = (escapement_delta){ 0.0, 0.0 };
GetEscapements(string, numChars, escapementArray, delta);
truncate_string(string, mode, width, result,
escapementArray, fSize, ellipsisWidth, length, numChars);
inOut->SetTo(result);
delete[] escapementArray;
delete[] result;
}
}
// _SetStyle
void
ServerFont::_SetStyle(FontStyle* style)
{
if (style != fStyle) {
// detach from old style
if (fStyle)
fStyle->RemoveDependent();
fStyle = style;
// attach to new style
if (fStyle)
fStyle->AddDependent();
}
}

View File

@ -22,6 +22,7 @@
// File Name: ServerWindow.cpp
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Adi Oanca <adioanca@mymail.ro>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Shadow BWindow class
//
//------------------------------------------------------------------------------
@ -74,7 +75,6 @@
# define DTRACE(x) ;
#endif
// #pragma mark -
/*!
@ -230,7 +230,7 @@ ServerWindow::Minimize(bool status)
//! Sends a message to the client to perform a Zoom
void
ServerWindow::Zoom(void)
ServerWindow::Zoom()
{
// NOTE: if you do something else, other than sending a port message, PLEASE lock
BMessage msg(B_ZOOM);
@ -259,7 +259,7 @@ ServerWindow::ScreenModeChanged(const BRect frame, const color_space colorSpace)
\return B_OK if everything is ok, B_ERROR if something went wrong
*/
status_t
ServerWindow::Lock(void)
ServerWindow::Lock()
{
STRACE(("\nServerWindow %s: Lock\n", fName));
@ -268,7 +268,7 @@ ServerWindow::Lock(void)
//! Unlocks the window
void
ServerWindow::Unlock(void)
ServerWindow::Unlock()
{
STRACE(("ServerWindow %s: Unlock\n\n", fName));
@ -280,7 +280,7 @@ ServerWindow::Unlock(void)
\return True if locked, false if not.
*/
bool
ServerWindow::IsLocked(void) const
ServerWindow::IsLocked() const
{
return fLocker.IsLocked();
}
@ -289,8 +289,7 @@ ServerWindow::IsLocked(void) const
\brief Sets the font state for a layer
\param layer The layer to set the font
*/
inline
void
inline void
ServerWindow::SetLayerFontState(Layer *layer, LinkMsgReader &link)
{
STRACE(("ServerWindow %s: SetLayerFontStateMessage for layer %s\n",
@ -301,8 +300,7 @@ ServerWindow::SetLayerFontState(Layer *layer, LinkMsgReader &link)
}
inline
void
inline void
ServerWindow::SetLayerState(Layer *layer, LinkMsgReader &link)
{
STRACE(("ServerWindow %s: SetLayerState for layer %s\n",fName,
@ -314,8 +312,7 @@ ServerWindow::SetLayerState(Layer *layer, LinkMsgReader &link)
}
inline
Layer *
inline Layer*
ServerWindow::CreateLayerTree(Layer *localRoot, LinkMsgReader &link)
{
// NOTE: no need to check for a lock. This is a private method.
@ -991,8 +988,11 @@ ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link)
link.Read<BRect>(&invalRect);
BRect converted(fCurrentLayer->ConvertToTop(invalRect.LeftTop()),
fCurrentLayer->ConvertToTop(invalRect.RightBottom()));
BRegion invalidRegion(converted);
// invalidRegion.IntersectWith(&fCurrentLayer->fVisible);
myRootLayer->GoRedraw(fWinBorder, BRegion(converted));
myRootLayer->GoRedraw(fWinBorder, invalidRegion);
// myRootLayer->RequestDraw(invalidRegion, fWinBorder);
break;
}
case AS_LAYER_INVAL_REGION:
@ -1236,17 +1236,29 @@ ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link)
// 3) float minimum height
// 4) float maximum height
float wmin,wmax,hmin,hmax;
float minWidth;
float maxWidth;
float minHeight;
float maxHeight;
link.Read<float>(&wmin);
link.Read<float>(&wmax);
link.Read<float>(&hmin);
link.Read<float>(&hmax);
fWinBorder->SetSizeLimits(wmin,wmax,hmin,hmax);
link.Read<float>(&minWidth);
link.Read<float>(&maxWidth);
link.Read<float>(&minHeight);
link.Read<float>(&maxHeight);
fWinBorder->SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight);
// and now, sync the client to the limits that we were able to enforce
fWinBorder->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
fMsgSender->StartMessage(SERVER_TRUE);
fMsgSender->Attach<float>(minWidth);
fMsgSender->Attach<float>(maxWidth);
fMsgSender->Attach<float>(minHeight);
fMsgSender->Attach<float>(maxHeight);
fMsgSender->Flush();
break;
}
case B_MINIMIZE:
@ -2061,7 +2073,8 @@ ServerWindow::_CopyBits(RootLayer* rootLayer, Layer* layer,
layer->GetDisplayDriver()->CopyRegion(&copyRegion, xOffset, yOffset);
// trigger the redraw
rootLayer->GoRedraw(fWinBorder, invalidRegion);
// rootLayer->GoRedraw(fWinBorder, invalidRegion);
rootLayer->RequestDraw(invalidRegion, fWinBorder);
}

View File

@ -22,27 +22,31 @@
// File Name: WinBorder.cpp
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Adi Oanca <adioanca@cotty.iren.ro>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Layer subclass which handles window management
//
//------------------------------------------------------------------------------
#include <Locker.h>
#include <Region.h>
#include <String.h>
#include <Locker.h>
#include <View.h> // for mouse button defines
#include <Debug.h>
#include "PortLink.h"
#include "View.h" // for mouse button defines
#include "MessagePrivate.h"
#include "ServerWindow.h"
#include "Decorator.h"
#include "DisplayDriver.h"
#include "Desktop.h"
#include "WinBorder.h"
#include "DebugInfoManager.h"
#include "AppServer.h" // for new_decorator()
#include "TokenHandler.h"
#include "Decorator.h"
#include "Desktop.h"
#include "Globals.h"
#include "MessagePrivate.h"
#include "PortLink.h"
#include "RootLayer.h"
#include "ServerWindow.h"
#include "TokenHandler.h"
#include "Workspace.h"
#include "WinBorder.h"
// Toggle general function call output
//#define DEBUG_WINBORDER
@ -71,80 +75,89 @@
# define STRACE_CLICK(x) ;
#endif
//! TokenHandler object used to provide IDs for all WinBorder objects
TokenHandler border_token_handler;
bool gMouseDown = false;
WinBorder::WinBorder( const BRect &r,
const char *name,
const uint32 wlook,
const uint32 wfeel,
const uint32 wflags,
const uint32 wwksindex,
ServerWindow *win,
DisplayDriver *driver)
WinBorder::WinBorder(const BRect &r,
const char *name,
const uint32 wlook,
const uint32 wfeel,
const uint32 wflags,
const uint32 wwksindex,
ServerWindow *win,
DisplayDriver *driver)
: Layer(r, name, B_NULL_TOKEN, B_FOLLOW_NONE, 0UL, driver),
fLook(wlook),
fLevel(-100),
fWindowFlags(wflags),
fWorkspaces(wwksindex)
fDecorator(NULL),
fTopLayer(NULL),
zUpdateReg(),
yUpdateReg(),
fUpdateReg(),
fMouseButtons(0),
fKeyModifiers(0),
fLastMousePosition(-1.0, -1.0),
fIsClosing(false),
fIsMinimizing(false),
fIsZooming(false),
fIsDragging(false),
fBringToFrontOnRelease(false),
fIsResizing(false),
fInUpdate(false),
fRequestSent(false),
fLook(wlook),
fFeel(-1),
fLevel(-100),
fWindowFlags(wflags),
fWorkspaces(wwksindex),
fMinWidth(1.0),
fMaxWidth(10000.0),
fMinHeight(1.0),
fMaxHeight(10000.0),
cnt(0) // for debugging
{
// unlike BViews, windows start off as hidden
fHidden = true;
fInUpdate = false;
fRequestSent = false;
fServerWin = win;
fClassID = AS_WINBORDER_CLASS;
cnt = 0; // for debugging
fMouseButtons = 0;
fKeyModifiers = 0;
fDecorator = NULL;
fTopLayer = NULL;
fAdFlags = fAdFlags | B_LAYER_CHILDREN_DEPENDANT;
fFlags = B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE;
fEventMask = B_POINTER_EVENTS;
fIsClosing = false;
fIsMinimizing = false;
fIsZooming = false;
fLastMousePosition.Set(-1,-1);
QuietlySetFeel(wfeel);
if (fFeel != B_NO_BORDER_WINDOW_LOOK)
if (fFeel != B_NO_BORDER_WINDOW_LOOK) {
fDecorator = new_decorator(r, name, fLook, fFeel, fWindowFlags, fDriver);
if (fDecorator)
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight, &fMaxWidth, &fMaxHeight);
}
RebuildFullRegion();
gDesktop->AddWinBorder(this);
STRACE(("WinBorder %s:\n",GetName()));
STRACE(("\tFrame: (%.1f,%.1f,%.1f,%.1f)\n",r.left,r.top,r.right,r.bottom));
STRACE(("\tWindow %s\n",win?win->Title():"NULL"));
STRACE(("WinBorder %s:\n", GetName()));
STRACE(("\tFrame: (%.1f, %.1f, %.1f, %.1f)\n", r.left, r.top, r.right, r.bottom));
STRACE(("\tWindow %s\n",win ? win->Title() : "NULL"));
}
WinBorder::~WinBorder(void)
WinBorder::~WinBorder()
{
STRACE(("WinBorder(%s)::~WinBorder()\n",GetName()));
gDesktop->RemoveWinBorder(this);
if (fTopLayer){
delete fTopLayer;
fTopLayer = NULL;
}
if (fDecorator)
{
delete fDecorator;
fDecorator = NULL;
}
delete fTopLayer;
delete fDecorator;
}
//! Rebuilds the WinBorder's "fully-visible" region based on info from the decorator
void WinBorder::RebuildFullRegion(void)
void
WinBorder::RebuildFullRegion()
{
STRACE(("WinBorder(%s)::RebuildFullRegion()\n",GetName()));
@ -155,16 +168,6 @@ void WinBorder::RebuildFullRegion(void)
fDecorator->GetFootprint(&fFull);
}
click_type WinBorder::TellWhat(PointerEvent& evt) const
{
if (fTopLayer->fFullVisible.Contains(evt.where))
return DEC_NONE;
else if (fDecorator)
return fDecorator->Clicked(evt.where, evt.buttons, evt.modifiers);
else
return DEC_NONE;
}
/*!
\brief Handles B_MOUSE_DOWN events and takes appropriate actions
\param evt PointerEvent object containing the info from the last B_MOUSE_DOWN message
@ -174,41 +177,51 @@ click_type WinBorder::TellWhat(PointerEvent& evt) const
or frame. If it is not, the message is passed on to the appropriate view in the client
BWindow. If the WinBorder is the target, then the proper action flag is set.
*/
void WinBorder::MouseDown(click_type action)
click_type
WinBorder::MouseDown(const PointerEvent& event)
{
// find out where user clicked in Decorator
switch(action)
{
case DEC_CLOSE:
{
fIsClosing = true;
fDecorator->SetClose(true);
fDecorator->DrawClose();
STRACE_CLICK(("===> DEC_CLOSE\n"));
break;
}
case DEC_ZOOM:
{
fIsZooming = true;
fDecorator->SetZoom(true);
fDecorator->DrawZoom();
STRACE_CLICK(("===> DEC_ZOOM\n"));
break;
}
case DEC_MINIMIZE:
{
fIsMinimizing = true;
fDecorator->SetMinimize(true);
fDecorator->DrawMinimize();
STRACE_CLICK(("===> DEC_MINIMIZE\n"));
break;
}
default:
{
debugger("WinBorder::MouseDown - default case - not allowed!\n");
break;
click_type action = _ActionFor(event);
if (fDecorator) {
// find out where user clicked in Decorator
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;
fBringToFrontOnRelease = true;
fLastMousePosition = event.where;
STRACE_CLICK(("===> DEC_DRAG\n"));
break;
case DEC_RESIZE:
fIsResizing = true;
fLastMousePosition = event.where;
fResizingClickOffset = event.where - fFrame.RightBottom();
STRACE_CLICK(("===> DEC_RESIZE\n"));
break;
default:
break;
}
}
return action;
}
/*!
@ -219,25 +232,32 @@ void WinBorder::MouseDown(click_type action)
or check to see if the user clicked on a tab button (close, zoom, etc.) and then moused
away to prevent the operation from occurring
*/
void WinBorder::MouseMoved(click_type action)
void
WinBorder::MouseMoved(const PointerEvent& event)
{
if (fIsZooming && action!=DEC_ZOOM)
{
fDecorator->SetZoom(false);
fDecorator->DrawZoom();
if (fDecorator) {
if (fIsZooming) {
fDecorator->SetZoom(_ActionFor(event) == DEC_ZOOM);
} else if (fIsClosing) {
fDecorator->SetClose(_ActionFor(event) == DEC_CLOSE);
} else if (fIsMinimizing) {
fDecorator->SetMinimize(_ActionFor(event) == DEC_MINIMIZE);
}
}
else
if (fIsClosing && action!=DEC_CLOSE)
{
fDecorator->SetClose(false);
fDecorator->DrawClose();
if (fIsDragging) {
// we will not come to front if we ever actually moved
fBringToFrontOnRelease = false;
BPoint delta = event.where - fLastMousePosition;
MoveBy(delta.x, delta.y);
}
else
if(fIsMinimizing && action!=DEC_MINIMIZE)
{
fDecorator->SetMinimize(false);
fDecorator->DrawMinimize();
if (fIsResizing) {
BRect frame(fFrame.LeftTop(), event.where - fResizingClickOffset);
BPoint delta = frame.RightBottom() - fFrame.RightBottom();
ResizeBy(delta.x, delta.y);
}
fLastMousePosition = event.where;
}
/*!
@ -248,46 +268,57 @@ void WinBorder::MouseMoved(click_type action)
button click flag, takes the appropriate action (i.e. clearing the close button flag also
takes steps to close the window).
*/
void WinBorder::MouseUp(click_type action)
void
WinBorder::MouseUp(const PointerEvent& event)
{
if (fIsZooming)
{
fIsZooming = false;
fDecorator->SetZoom(false);
fDecorator->DrawZoom();
if(action==DEC_ZOOM)
Window()->Zoom();
return;
if (fDecorator) {
click_type action = _ActionFor(event);
if (fIsZooming) {
fIsZooming = false;
fDecorator->SetZoom(false);
if (action == DEC_ZOOM)
Window()->Zoom();
return;
}
if (fIsClosing) {
fIsClosing = false;
fDecorator->SetClose(false);
if (action == DEC_CLOSE)
Window()->Quit();
return;
}
if (fIsMinimizing) {
fIsMinimizing = false;
fDecorator->SetMinimize(false);
if (action == DEC_MINIMIZE)
Window()->Minimize(true);
return;
}
}
if(fIsClosing)
{
fIsClosing = false;
fDecorator->SetClose(false);
fDecorator->DrawClose();
if(action==DEC_CLOSE)
Window()->Quit();
return;
}
if(fIsMinimizing)
{
fIsMinimizing = false;
fDecorator->SetMinimize(false);
fDecorator->DrawMinimize();
if(action==DEC_MINIMIZE)
Window()->Minimize(true);
return;
if (fBringToFrontOnRelease) {
// TODO: We would have dragged the window if
// the mouse would have moved, but it didn't
// move -> This will bring the window to the
// front on R5 in FFM mode!
}
fIsDragging = false;
fIsResizing = false;
fBringToFrontOnRelease = false;
}
//! Sets the decorator focus to active or inactive colors
void WinBorder::HighlightDecorator(const bool &active)
void
WinBorder::HighlightDecorator(const bool &active)
{
STRACE(("Decorator->Highlight\n"));
fDecorator->SetFocus(active);
if (fDecorator)
fDecorator->SetFocus(active);
}
//! redraws a certain section of the window border
void WinBorder::Draw(const BRect &r)
void
WinBorder::Draw(const BRect &r)
{
#ifdef DEBUG_WINBORDER
printf("WinBorder(%s)::Draw() : ", GetName());
@ -295,10 +326,9 @@ void WinBorder::Draw(const BRect &r)
#endif
// if we have a visible region, it is decorator's one.
if(fDecorator)
{
WinBorder *wb = GetRootLayer()->FocusWinBorder();
if (wb && wb == this)
if (fDecorator) {
WinBorder* wb = GetRootLayer()->FocusWinBorder();
if (wb == this)
fDecorator->SetFocus(true);
else
fDecorator->SetFocus(false);
@ -307,10 +337,14 @@ void WinBorder::Draw(const BRect &r)
}
//! Moves the winborder with redraw
void WinBorder::MoveBy(float x, float y)
void
WinBorder::MoveBy(float x, float y)
{
if (x == 0.0 && y == 0.0)
return;
STRACE(("WinBorder(%s)::MoveBy(%.1f, %.1f) fDecorator: %p\n", GetName(), x, y, fDecorator));
if(fDecorator)
if (fDecorator)
fDecorator->MoveBy(x,y);
// NOTE: I moved this here from Layer::move_layer()
@ -343,78 +377,159 @@ fUpdateReg.OffsetBy(x, y);
} else {
move_layer(x, y);
}
if (Window()) {
// dispatch a message to the client informing about the changed size
BMessage msg(B_WINDOW_MOVED);
msg.AddPoint("where", fFrame.LeftTop());
Window()->SendMessageToClient(&msg, B_NULL_TOKEN, false);
}
}
//! Resizes the winborder with redraw
void WinBorder::ResizeBy(float x, float y)
void
WinBorder::ResizeBy(float x, float y)
{
// TODO: account for size limits
// NOTE: size limits are also regarded in BWindow::ResizeXX()
STRACE(("WinBorder(%s)::ResizeBy()\n", GetName()));
if(fDecorator)
fDecorator->ResizeBy(x,y);
resize_layer(x,y);
float wantWidth = fFrame.Width() + x;
float wantHeight = fFrame.Height() + y;
// enforce size limits
if (wantWidth < fMinWidth)
wantWidth = fMinWidth;
if (wantWidth > fMaxWidth)
wantWidth = fMaxWidth;
if (wantHeight < fMinHeight)
wantHeight = fMinHeight;
if (wantHeight > fMaxHeight)
wantHeight = fMaxHeight;
x = wantWidth - fFrame.Width();
y = wantHeight - fFrame.Height();
if (x != 0.0 || y != 0.0) {
if (fDecorator)
fDecorator->ResizeBy(x, y);
resize_layer(x, y);
if (Window()) {
// send a message to the client informing about the changed size
BRect frame(fTopLayer->Frame());
BMessage msg(B_WINDOW_RESIZED);
msg.AddInt32("width", frame.Width());
msg.AddInt32("height", frame.Height());
Window()->SendMessageToClient(&msg, B_NULL_TOKEN, false);
}
}
}
//! Sets the minimum and maximum sizes of the window
void WinBorder::SetSizeLimits(float minwidth, float maxwidth, float minheight, float maxheight)
void
WinBorder::SetSizeLimits(float minWidth, float maxWidth,
float minHeight, float maxHeight)
{
if(minwidth<0)
minwidth=0;
if (minWidth < 0)
minWidth = 0;
if(minheight<0)
minheight=0;
if(maxwidth<=minwidth)
maxwidth=minwidth+1;
if(maxheight<=minheight)
maxheight=minheight+1;
fMinWidth=minwidth;
fMaxWidth=maxwidth;
fMinHeight=minheight;
fMaxHeight=maxheight;
if (minHeight < 0)
minHeight = 0;
fMinWidth = minWidth;
fMaxWidth = maxWidth;
fMinHeight = minHeight;
fMaxHeight = maxHeight;
// give the Decorator a say in this too
if (fDecorator)
fDecorator->GetSizeLimits(&fMinWidth, &fMinHeight,
&fMaxWidth, &fMaxHeight);
if (fMaxWidth < fMinWidth)
fMaxWidth = fMinWidth;
if (fMaxHeight < fMinHeight)
fMaxHeight = fMinHeight;
#if 0 // On R5, Windows don't automatically resize
// Automatically resize the window to fit these new limits
// if it does not already.
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;
ResizeBy(xDiff, yDiff);
#endif
}
// GetSizeLimits
void
WinBorder::GetSizeLimits(float* minWidth, float* maxWidth,
float* minHeight, float* maxHeight) const
{
*minWidth = fMinWidth;
*maxWidth = fMaxWidth;
*minHeight = fMinHeight;
*maxHeight = fMaxHeight;
}
//! Returns true if the point is in the WinBorder's screen area
bool WinBorder::HasPoint(const BPoint& pt) const
bool
WinBorder::HasPoint(const BPoint& pt) const
{
return fFullVisible.Contains(pt);
}
// Unimplemented. Hook function for handling when system GUI colors change
void WinBorder::UpdateColors(void)
void
WinBorder::UpdateColors()
{
STRACE(("WinBorder %s: UpdateColors unimplemented\n",GetName()));
}
// Unimplemented. Hook function for handling when the system decorator changes
void WinBorder::UpdateDecorator(void)
void
WinBorder::UpdateDecorator()
{
STRACE(("WinBorder %s: UpdateDecorator unimplemented\n",GetName()));
}
// Unimplemented. Hook function for handling when a system font changes
void WinBorder::UpdateFont(void)
void
WinBorder::UpdateFont()
{
STRACE(("WinBorder %s: UpdateFont unimplemented\n",GetName()));
}
// Unimplemented. Hook function for handling when the screen resolution changes
void WinBorder::UpdateScreen(void)
void
WinBorder::UpdateScreen()
{
STRACE(("WinBorder %s: UpdateScreen unimplemented\n",GetName()));
}
void WinBorder::QuietlySetFeel(int32 feel)
// QuietlySetFeel
void
WinBorder::QuietlySetFeel(int32 feel)
{
fFeel = feel;
switch(fFeel)
{
switch(fFeel) {
case B_FLOATING_SUBSET_WINDOW_FEEL:
case B_FLOATING_APP_WINDOW_FEEL:
fLevel = B_FLOATING_APP;
@ -452,8 +567,7 @@ void WinBorder::QuietlySetFeel(int32 feel)
// floating and modal windows must appear in every workspace where
// their main window is present. Thus their wksIndex will be set to
// '0x0' and they will be made visible when needed.
switch (fFeel)
{
switch (fFeel) {
case B_MODAL_APP_WINDOW_FEEL:
break;
case B_MODAL_SUBSET_WINDOW_FEEL:
@ -470,4 +584,18 @@ void WinBorder::QuietlySetFeel(int32 feel)
case B_NORMAL_WINDOW_FEEL:
break;
}
}
}
// _ActionFor
click_type
WinBorder::_ActionFor(const PointerEvent& event) const
{
if (fTopLayer->fFullVisible.Contains(event.where))
return DEC_NONE;
else if (fDecorator)
return fDecorator->Clicked(event.where, event.buttons, event.modifiers);
else
return DEC_NONE;
}

View File

@ -1,5 +1,5 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, Haiku, Inc.
// Copyright (c) 2001-2005, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
@ -22,6 +22,7 @@
// File Name: WinBorder.h
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Adi Oanca <adioanca@mymail.ro>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Layer subclass which handles window management
//
//------------------------------------------------------------------------------
@ -36,13 +37,15 @@
// these are used by window manager to properly place window.
enum {
B_SYSTEM_LAST = -10L,
B_FLOATING_APP = 0L,
B_MODAL_APP = 1L,
B_NORMAL = 2L,
B_FLOATING_ALL = 3L,
B_MODAL_ALL = 4L,
B_SYSTEM_FIRST = 10L,
B_SYSTEM_LAST = -10L,
B_FLOATING_APP = 0L,
B_MODAL_APP = 1L,
B_NORMAL = 2L,
B_FLOATING_ALL = 3L,
B_MODAL_ALL = 4L,
B_SYSTEM_FIRST = 10L,
};
class ServerWindow;
@ -50,64 +53,66 @@ class Decorator;
class DisplayDriver;
class Desktop;
class PointerEvent
{
public:
int32 code; //B_MOUSE_UP, B_MOUSE_DOWN, B_MOUSE_MOVED
//B_MOUSE_WHEEL_CHANGED
bigtime_t when;
BPoint where;
float wheel_delta_x;
float wheel_delta_y;
int32 modifiers;
int32 buttons; //B_PRIMARY_MOUSE_BUTTON, B_SECONDARY_MOUSE_BUTTON
//B_TERTIARY_MOUSE_BUTTON
int32 clicks;
class PointerEvent {
public:
int32 code; // B_MOUSE_UP, B_MOUSE_DOWN, B_MOUSE_MOVED,
// B_MOUSE_WHEEL_CHANGED
bigtime_t when;
BPoint where;
float wheel_delta_x;
float wheel_delta_y;
int32 modifiers;
int32 buttons; // B_PRIMARY_MOUSE_BUTTON, B_SECONDARY_MOUSE_BUTTON
// B_TERTIARY_MOUSE_BUTTON
int32 clicks;
};
class WinBorder : public Layer
{
public:
WinBorder( const BRect &r,
const char *name,
const uint32 wlook,
const uint32 wfeel,
const uint32 wflags,
const uint32 wwksindex,
ServerWindow *win,
DisplayDriver *driver);
virtual ~WinBorder(void);
class WinBorder : public Layer {
public:
WinBorder(const BRect &r,
const char *name,
const uint32 wlook,
const uint32 wfeel,
const uint32 wflags,
const uint32 wwksindex,
ServerWindow *win,
DisplayDriver *driver);
virtual ~WinBorder();
virtual void Draw(const BRect &r);
virtual void MoveBy(float x, float y);
virtual void ResizeBy(float x, float y);
virtual void RebuildFullRegion(void);
virtual void RebuildFullRegion();
void SetSizeLimits( float minwidth,
float maxwidth,
float minheight,
float maxheight);
void SetSizeLimits(float minWidth,
float maxWidth,
float minHeight,
float maxHeight);
click_type TellWhat(PointerEvent& evt) const;
void MouseDown(click_type action);
void MouseMoved(click_type action);
void MouseUp(click_type action);
void GetSizeLimits(float* minWidth,
float* maxWidth,
float* minHeight,
float* maxHeight) const;
click_type MouseDown(const PointerEvent& evt);
void MouseMoved(const PointerEvent& evt);
void MouseUp(const PointerEvent& evt);
void UpdateColors(void);
void UpdateDecorator(void);
void UpdateFont(void);
void UpdateScreen(void);
void UpdateColors();
void UpdateDecorator();
void UpdateFont();
void UpdateScreen();
virtual bool HasClient(void) { return false; }
inline Decorator* GetDecorator(void) const { return fDecorator; }
virtual bool HasClient() { return false; }
inline Decorator* GetDecorator() const { return fDecorator; }
inline int32 Look(void) const { return fLook; }
inline int32 Feel(void) const { return fFeel; }
inline int32 Look() const { return fLook; }
inline int32 Feel() const { return fFeel; }
inline int32 Level() const { return fLevel; }
inline uint32 WindowFlags(void) const { return fWindowFlags; }
inline uint32 Workspaces(void) const { return fWorkspaces; }
inline uint32 WindowFlags() const { return fWindowFlags; }
inline uint32 Workspaces() const { return fWorkspaces; }
void HighlightDecorator(const bool &active);
@ -118,11 +123,13 @@ public:
FMWList fFMWList;
protected:
protected:
friend class Layer;
friend class ServerWindow;
friend class RootLayer;
click_type _ActionFor(const PointerEvent& evt) const;
Decorator* fDecorator;
Layer* fTopLayer;
@ -133,11 +140,17 @@ protected:
int32 fMouseButtons;
int32 fKeyModifiers;
BPoint fLastMousePosition;
BPoint fResizingClickOffset;
bool fIsClosing;
bool fIsMinimizing;
bool fIsZooming;
bool fIsDragging;
bool fBringToFrontOnRelease;
bool fIsResizing;
bool fInUpdate;
bool fRequestSent;
@ -147,10 +160,10 @@ protected:
int32 fWindowFlags;
uint32 fWorkspaces;
float fMinWidth,
fMaxWidth;
float fMinHeight,
fMaxHeight;
float fMinWidth;
float fMaxWidth;
float fMinHeight;
float fMaxHeight;
int cnt; // for debugging
};