Compare commits

...

8 Commits

Author SHA1 Message Date
Pascal Abresch cf60bfdbc0 WIP: very WIP webpositive tab stuff. 2021-12-29 21:14:51 +01:00
Pascal Abresch aff45ca380 WebPositive: add nephele to about box 2021-12-29 21:14:51 +01:00
Alexander von Gluck IV 65ed50c713 graphics/edid: Add support for digital display info; solves #17462
* We pack the first 8 bits into a union for the raw
  edid since alignment matters.
* Handing the raw_edid is a bit ugly, so in the edid struct
  we drop the input_type from the union since packing doesn't
  matter as much.

Change-Id: I32dbfe9484f9eb83cf491a44d30a32ca36d65b7b
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4775
Reviewed-by: Alex von Gluck IV <kallisti5@unixzen.com>
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
2021-12-18 15:21:30 +00:00
Lt-Henry 6a9aea9dfd input: implemented B_GET_DEVICE_NAME ioctl on both usb and i2c input devices
Change-Id: Ie1eb0a958b4d60e6fa673cf8fe72bdfe924baf51
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4798
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
2021-12-18 14:51:19 +00:00
Alex Hitech 370623a923 Russian keymap: the Rouble currency sign was mistakenly on the Capslock key, and vice versa.
Change-Id: I3d907da00cfc0d5092ef04bfa50f413ba261e5e6
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4822
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
2021-12-18 09:39:47 +00:00
Augustin Cavalier e0842c10af kernel/condition_variable: Pause between iterations.
Should hopefully resolve the remaining problem in #17455.

Change-Id: I6e00286508c069705e07c9a0b59af2cf5e15e427
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4819
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
2021-12-18 07:52:47 +00:00
Jérôme Duval 101dc0ba83 strace: fix revents output for poll syscall
each poll_fd struct should be checked, valid when not -1 and revents not zero.

Change-Id: Ia624ad1369ad1a6066c9970a47cfac63fa773702
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4821
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
2021-12-17 20:40:55 +00:00
Jérôme Duval 3285dcae22 tcp: reset receive.low_water_mark when nothing to read anymore
the socket interface module checks the receive.low_water_mark to automatically
notify a read event. available_data will be zero, thus enabling the notification.

fixes the test poll_nm in NSPR.

Change-Id: I5354faec439df96671506550cdb144a45f6082b1
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4820
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
2021-12-17 20:40:55 +00:00
30 changed files with 283 additions and 2210 deletions

View File

@ -25,18 +25,30 @@ typedef struct {
uint8 revision;
} edid1_version;
// analog input parameters
typedef struct {
uint8 input_voltage; // 0=0.7V/0.3V, 1=0.714V/0.286,
// 2=1V/0.4V, 3=0.7V/0V
bool setup; // true if voltage configurable
bool sep_sync;
bool comp_sync;
bool sync_on_green;
bool sync_serr;
} edid1_analog_params;
// digital input parameters
typedef struct {
uint8 bit_depth;
uint8 interface;
} edid1_digital_params;
// display info
typedef struct {
BBITFIELD8_7 (
input_type : 1, // 1 : digital
input_voltage : 2, // 0=0.7V/0.3V, 1=0.714V/0.286,
// 2=1V/0.4V, 3=0.7V/0V
setup : 1, // true if voltage configurable
sep_sync : 1,
comp_sync : 1,
sync_on_green : 1,
sync_serr : 1
);
uint8 input_type;
edid1_analog_params analog_params;
edid1_digital_params digital_params;
uint8 h_size;
uint8 v_size;
uint8 gamma; // (x+100)/100

View File

@ -61,11 +61,11 @@ typedef struct _PACKED {
} edid1_version_raw;
// display info
// analog input parameters
typedef struct _PACKED {
BBITFIELD8_7 (
input_type : 1, // 1 : digital
input_voltage : 2, // 0=0.7V/0.3V, 1=0.714V/0.286,
BBITFIELD8_7 (
input_type : 1, // 0 : analog, 1 : digital
input_voltage : 2, // 0=0.7V/0.3V, 1=0.714V/0.286,
// 2=1V/0.4V, 3=0.7V/0V
setup : 1, // true if voltage configurable
sep_sync : 1,
@ -73,6 +73,26 @@ typedef struct _PACKED {
sync_on_green : 1,
sync_serr : 1
);
} edid1_analog_params_raw;
// digital input parameters
typedef struct _PACKED {
BBITFIELD8_3 (
input_type : 1, // 0 : analog, 1 : digital
bit_depth : 3, // 0=undefined, 1=6,2=8,3=10,4=12,5=14,6=16,7=reserved
interface : 4 // 0=undefined, 2=HDMIa, 3=HDMIb
// 4=MDDI, 5=DisplayPort
);
} edid1_digital_params_raw;
// display info
typedef struct _PACKED {
union {
edid1_analog_params_raw analog_params;
edid1_digital_params_raw digital_params;
};
uint8 h_size;
uint8 v_size;
uint8 gamma; // (x+100)/100

View File

@ -43,20 +43,33 @@ static void
decode_version(edid1_version *version, const edid1_version_raw *raw)
{
version->version = raw->version;
version->revision = raw->revision;
version->revision = raw->revision;
}
static void
decode_display(edid1_display *display, const edid1_display_raw *raw)
{
display->input_type = raw->input_type;
display->input_voltage = raw->input_voltage;
display->setup = raw->setup;
display->sep_sync = raw->sep_sync;
display->comp_sync = raw->comp_sync;
display->sync_on_green = raw->sync_on_green;
display->sync_serr = raw->sync_serr;
{
// We need to dig into one of the union to get the first
// bit which should always align. then we can pick the right
// data structure to parse.
display->input_type = raw->analog_params.input_type;
if (display->input_type != 0) {
// digital
display->digital_params.bit_depth = 0;
if (raw->digital_params.bit_depth > 0 && raw->digital_params.bit_depth < 7)
display->digital_params.bit_depth = raw->digital_params.bit_depth * 2 + 4;
display->digital_params.interface = raw->digital_params.interface;
} else {
// analog
display->analog_params.input_voltage = raw->analog_params.input_voltage;
display->analog_params.setup = raw->analog_params.setup;
display->analog_params.sep_sync = raw->analog_params.sep_sync;
display->analog_params.comp_sync = raw->analog_params.comp_sync;
display->analog_params.sync_on_green = raw->analog_params.sync_on_green;
display->analog_params.sync_serr = raw->analog_params.sync_serr;
}
display->h_size = raw->h_size;
display->v_size = raw->v_size;

View File

@ -4,12 +4,6 @@
*/
/*!
Part of DDC driver
Dumps EDID content
*/
#include "edid.h"
#if !defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
# include "ddc_int.h"
@ -23,20 +17,23 @@ edid_dump(edid1_info *edid)
{
int i, j;
dprintf("Vendor: %s\n", edid->vendor.manufacturer);
dprintf("Product ID: %d\n", (int)edid->vendor.prod_id);
dprintf("Serial #: %d\n", (int)edid->vendor.serial);
dprintf("Produced in week/year: %d/%d\n", edid->vendor.week,
dprintf("EDID info:\n");
dprintf(" Vendor: %s\n", edid->vendor.manufacturer);
dprintf(" Product ID: %d\n", (int)edid->vendor.prod_id);
dprintf(" Serial #: %d\n", (int)edid->vendor.serial);
dprintf(" Produced in week/year: %d/%d\n", edid->vendor.week,
edid->vendor.year);
dprintf("EDID version: %d.%d\n", edid->version.version,
dprintf(" EDID version: %d.%d\n", edid->version.version,
edid->version.revision);
dprintf("Type: %s\n", edid->display.input_type ? "Digital" : "Analog");
dprintf("Size: %d cm x %d cm\n", edid->display.h_size,
dprintf(" Type: %s\n", edid->display.input_type != 0 ? "Digital" : "Analog");
if (edid->display.input_type != 0)
dprintf(" Digtial Bit Depth: %d\n", edid->display.digital_params.bit_depth);
dprintf(" Size: %d cm x %d cm\n", edid->display.h_size,
edid->display.v_size);
dprintf("Gamma=%.3f\n", (edid->display.gamma + 100) / 100.0);
dprintf("White (X,Y)=(%.3f,%.3f)\n", edid->display.white_x / 1024.0,
dprintf(" Gamma=%.3f\n", (edid->display.gamma + 100) / 100.0);
dprintf(" White (X,Y)=(%.3f,%.3f)\n", edid->display.white_x / 1024.0,
edid->display.white_y / 1024.0);
dprintf("Supported Future Video Modes:\n");

View File

@ -267,6 +267,12 @@ JoystickProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
size_t length)
{
switch (op) {
case B_GET_DEVICE_NAME:
{
const char name[] = DEVICE_NAME" Joystick";
return IOGetDeviceName(name, buffer, length);
}
case B_JOYSTICK_SET_DEVICE_MODULE:
{
if (length < sizeof(joystick_module_info))

View File

@ -343,6 +343,12 @@ KeyboardProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
size_t length)
{
switch (op) {
case B_GET_DEVICE_NAME:
{
const char name[] = DEVICE_NAME" Keyboard";
return IOGetDeviceName(name,buffer,length);
}
case KB_READ:
{
if (*cookie == 0) {

View File

@ -131,6 +131,13 @@ MouseProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
size_t length)
{
switch (op) {
case B_GET_DEVICE_NAME:
{
const char name[] = DEVICE_NAME" Mouse";
return IOGetDeviceName(name,buffer,length);
}
case MS_READ:
{
if (length < sizeof(mouse_movement))

View File

@ -6,6 +6,7 @@
#include <stdlib.h>
#include <ring_buffer.h>
#include <kernel.h>
#include "Driver.h"
#include "HIDCollection.h"
@ -187,3 +188,16 @@ ProtocolHandler::SetNextHandler(ProtocolHandler *nextHandler)
{
fNextHandler = nextHandler;
}
status_t
ProtocolHandler::IOGetDeviceName(const char *name, void *buffer, size_t length)
{
if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS;
if (user_strlcpy((char *)buffer, name, length) > 0)
return B_OK;
return B_ERROR;
}

View File

@ -54,6 +54,9 @@ public:
void SetNextHandler(ProtocolHandler *next);
ProtocolHandler * NextHandler() { return fNextHandler; };
status_t IOGetDeviceName(const char *name, void *buffer,
size_t length);
protected:
status_t fStatus;

View File

@ -182,6 +182,13 @@ TabletProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
size_t length)
{
switch (op) {
case B_GET_DEVICE_NAME:
{
const char name[] = DEVICE_NAME" Tablet";
return IOGetDeviceName(name,buffer,length);
}
case MS_READ:
{
if (length < sizeof(tablet_movement))

View File

@ -15,7 +15,7 @@
#define DRIVER_NAME "i2c_hid"
#define DEVICE_PATH_SUFFIX "i2c"
#define DEVICE_NAME "I2C"
extern DeviceList *gDeviceList;

View File

@ -16,6 +16,7 @@
#define DRIVER_NAME "usb_hid"
#define DEVICE_PATH_SUFFIX "usb"
#define DEVICE_NAME "USB"
#define USB_INTERFACE_CLASS_HID 3
#define USB_INTERFACE_SUBCLASS_HID_BOOT 1

View File

@ -1011,6 +1011,9 @@ TCPEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
TRACE(" ReadData(): %" B_PRIuSIZE " bytes kept.",
fReceiveQueue.Available());
if (fReceiveQueue.Available() == 0 && fState == FINISH_RECEIVED)
socket->receive.low_water_mark = 0;
// if we are opening the window, check if we should send an ACK
if (!clone)
SendAcknowledge(false);
@ -1438,7 +1441,7 @@ TCPEndpoint::_ShouldReceive() const
return false;
return fState == ESTABLISHED || fState == FINISH_SENT
|| fState == FINISH_ACKNOWLEDGED;
|| fState == FINISH_ACKNOWLEDGED || fState == FINISH_RECEIVED;
}

View File

@ -429,7 +429,7 @@ add_tcp_header(net_address_module_info* addressModule,
optionsLength);
}
TRACE(("add_tcp_header(): buffer %p, flags 0x%x, seq %lu, ack %lu, up %u, "
TRACE(("add_tcp_header(): buffer %p, flags 0x%x, seq %" B_PRIu32 ", ack %" B_PRIu32 ", up %u, "
"win %u\n", buffer, segment.flags, segment.sequence,
segment.acknowledge, segment.urgent_offset, segment.advertised_window));

View File

@ -138,6 +138,7 @@ BrowserApp::AboutRequested()
// create the about window
const char* authors[] = {
"Pascal R. G. Abresch",
"Andrea Anzani",
"Stephan Aßmus",
"Alexandre Deckner",
@ -276,7 +277,7 @@ BrowserApp::ReadyToRun()
for (int j = 1; archivedWindow.FindString("tab", j, &url)
== B_OK; j++) {
printf("Create %d:%d\n", i, j);
_CreateNewTab(window, url, false);
_CreateWebView(window, url, false);
pagesCreated++;
}
}
@ -310,7 +311,7 @@ BrowserApp::MessageReceived(BMessage* message)
_CreateNewWindow(url);
break;
}
case NEW_TAB: {
case CREATE_VIEW: {
BrowserWindow* window;
if (message->FindPointer("window",
reinterpret_cast<void**>(&window)) != B_OK)
@ -319,7 +320,7 @@ BrowserApp::MessageReceived(BMessage* message)
message->FindString("url", &url);
bool select = false;
message->FindBool("select", &select);
_CreateNewTab(window, url, select);
_CreateWebView(window, url, select);
break;
}
case WINDOW_OPENED:
@ -513,7 +514,7 @@ BrowserApp::_CreateNewPage(const BString& url, BrowserWindow* webWindow,
if (url.Length() != 0)
webWindow->CurrentWebView()->LoadURL(url);
} else
webWindow->CreateNewTab(url, true);
webWindow->CreateWebView(url, true);
webWindow->Activate();
webWindow->CurrentWebView()->MakeFocus(true);
webWindow->Unlock();
@ -535,7 +536,7 @@ BrowserApp::_CreateNewPage(const BString& url, BrowserWindow* webWindow,
if (url.Length() != 0)
webWindow->CurrentWebView()->LoadURL(url);
} else
webWindow->CreateNewTab(url, true);
webWindow->CreateWebView(url, true);
webWindow->Activate();
webWindow->CurrentWebView()->MakeFocus(true);
loadedInWindowOnCurrentWorkspace = true;
@ -571,12 +572,12 @@ BrowserApp::_CreateNewWindow(const BString& url, bool fullscreen)
void
BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url,
BrowserApp::_CreateWebView(BrowserWindow* window, const BString& url,
bool select)
{
if (!window->Lock())
return;
window->CreateNewTab(url, select);
window->CreateWebView(url, select);
window->Unlock();
}

View File

@ -66,7 +66,7 @@ private:
bool useBlankTab = true);
BrowserWindow* _CreateNewWindow(const BString& url,
bool fullscreen = false);
void _CreateNewTab(BrowserWindow* window,
void _CreateWebView(BrowserWindow* window,
const BString& url, bool select);
void _ShowWindow(const BMessage* message,
BWindow* window);

View File

@ -84,11 +84,11 @@
#include "NavMenu.h"
#include "SettingsKeys.h"
#include "SettingsMessage.h"
#include "TabManager.h"
#include "URLInputGroup.h"
#include "WebPage.h"
#include "WebView.h"
#include "WebViewConstants.h"
#include "WebViewListItem.h"
#include "WindowIcon.h"
@ -382,18 +382,13 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
kDefaultSearchPageURL);
// Create the interface elements
BMessage* newTabMessage = new BMessage(NEW_TAB);
newTabMessage->AddString("url", "");
newTabMessage->AddPointer("window", this);
newTabMessage->AddBool("select", true);
fTabManager = new TabManager(BMessenger(this), newTabMessage);
BMessage* createWebViewMessage = new BMessage(CREATE_VIEW);
createWebViewMessage->AddString("url", "");
createWebViewMessage->AddPointer("window", this);
createWebViewMessage->AddBool("select", true);
// Menu
#if INTEGRATE_MENU_INTO_TAB_BAR
BMenu* mainMenu = fTabManager->Menu();
#else
BMenu* mainMenu = new BMenuBar("Main menu");
#endif
BMenu* menu = new BMenu(B_TRANSLATE("Window"));
BMessage* newWindowMessage = new BMessage(NEW_WINDOW);
newWindowMessage->AddString("url", "");
@ -402,7 +397,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
menu->AddItem(newItem);
newItem->SetTarget(be_app);
newItem = new BMenuItem(B_TRANSLATE("New tab"),
new BMessage(*newTabMessage), 'T');
new BMessage(*createWebViewMessage), 'T');
menu->AddItem(newItem);
newItem->SetTarget(be_app);
menu->AddItem(new BMenuItem(B_TRANSLATE("Open location"),
@ -411,7 +406,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
menu->AddItem(new BMenuItem(B_TRANSLATE("Close window"),
new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY));
menu->AddItem(new BMenuItem(B_TRANSLATE("Close tab"),
new BMessage(CLOSE_TAB), 'W'));
new BMessage(CLOSE_VIEW), 'W'));
menu->AddItem(new BMenuItem(B_TRANSLATE("Save page as" B_UTF8_ELLIPSIS),
new BMessage(SAVE_PAGE), 'S'));
menu->AddSeparatorItem();
@ -626,14 +621,11 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
// Layout
BGroupView* topView = new BGroupView(B_VERTICAL, 0.0);
#if !INTEGRATE_MENU_INTO_TAB_BAR
topView->AddChild(menuBarGroup);
#endif
topView->AddChild(fTabManager->TabGroup());
topView->AddChild(navigationGroup);
if (fBookmarkBar != NULL)
topView->AddChild(fBookmarkBar);
topView->AddChild(fTabManager->ContainerView());
//TODO NEPHELE
topView->AddChild(findGroup);
topView->AddChild(statusGroup);
@ -642,7 +634,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
fURLInputGroup->MakeFocus(true);
fMenuGroup = menuBarGroup;
fTabGroup = fTabManager->TabGroup()->GetLayout();
//fTabGroup = fTabManager->TabGroup()->GetLayout();
fNavigationGroup = navigationGroup;
fFindGroup = findGroup;
fStatusGroup = statusGroup;
@ -651,7 +643,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
fFindGroup->SetVisible(false);
fToggleFullscreenButton->SetVisible(false);
CreateNewTab(url, true, webView);
CreateWebView(url, true, webView);
_ShowInterface(true);
_SetAutoHideInterfaceInFullscreen(fAppSettings->GetValue(
kSettingsKeyAutoHideInterfaceInFullscreenMode,
@ -695,7 +687,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
BrowserWindow::~BrowserWindow()
{
fAppSettings->RemoveListener(BMessenger(this));
delete fTabManager;
//delete fTabManager;
delete fPulseRunner;
delete fSavePanel;
}
@ -1088,39 +1080,22 @@ BrowserWindow::MessageReceived(BMessage* message)
be_app->PostMessage(message);
break;
case CLOSE_TAB:
if (fTabManager->CountTabs() > 1) {
case CLOSE_VIEW:
if (fWebViewList->CountItems() > 1) {
int32 index;
if (message->FindInt32("tab index", &index) != B_OK)
index = fTabManager->SelectedTabIndex();
_ShutdownTab(index);
_UpdateTabGroupVisibility();
_CloseView(index);
} else
PostMessage(B_QUIT_REQUESTED);
break;
case SELECT_TAB:
{
int32 index;
if (message->FindInt32("tab index", &index) == B_OK
&& fTabManager->SelectedTabIndex() != index
&& fTabManager->CountTabs() > index) {
fTabManager->SelectTab(index);
case SELECT_VIEW:
void* view;
if (message->FindPointer("WebView", &view) == B_OK) {
fWebViewList->Select(fWebViewList->IndexOf((BListItem*)view));
SetCurrentWebView((BWebView*)view);
}
break;
}
case TAB_CHANGED:
{
// This message may be received also when the last tab closed,
// i.e. with index == -1.
int32 index;
if (message->FindInt32("tab index", &index) != B_OK)
index = -1;
_TabChanged(index);
break;
}
case SETTINGS_VALUE_CHANGED:
{
@ -1134,7 +1109,6 @@ BrowserWindow::MessageReceived(BMessage* message)
&& message->FindBool("value", &flag) == B_OK) {
if (fShowTabsIfSinglePageOpen != flag) {
fShowTabsIfSinglePageOpen = flag;
_UpdateTabGroupVisibility();
}
} else if (name == kSettingsKeyAutoHidePointer
&& message->FindBool("value", &flag) == B_OK) {
@ -1185,8 +1159,9 @@ BrowserWindow::Archive(BMessage* archive, bool deep) const
{
status_t ret = archive->AddRect("window frame", Frame());
for (int i = 0; i < fTabManager->CountTabs(); i++) {
BWebView* view = dynamic_cast<BWebView*>(fTabManager->ViewForTab(i));
for (int i = 0; i < fWebViewList->CountItems(); i++) {
WebViewListItem* webViewItem = static_cast<WebViewListItem*>(fWebViewList->ItemAt(i));
BWebView* view = webViewItem->fWebView;
if (view == NULL) {
continue;
}
@ -1210,8 +1185,8 @@ BrowserWindow::QuitRequested()
// Iterate over all tabs to delete all BWebViews.
// Do this here, so WebKit tear down happens earlier.
SetCurrentWebView(NULL);
while (fTabManager->CountTabs() > 0)
_ShutdownTab(0);
while (fWebViewList->CountItems() > 0)
_CloseView(0);
message.AddRect("window frame", WindowFrame());
be_app->PostMessage(&message);
@ -1350,12 +1325,12 @@ BrowserWindow::IsBlankTab() const
return false;
BString requestedURL = CurrentWebView()->MainFrameRequestedURL();
return requestedURL.Length() == 0
|| requestedURL == _NewTabURL(fTabManager->CountTabs() == 1);
|| requestedURL == _NewTabURL(fWebViewList->CountItems() == 1);
}
void
BrowserWindow::CreateNewTab(const BString& _url, bool select,
BrowserWindow::CreateWebView(const BString& _url, bool select,
BWebView* webView)
{
bool applyNewPagePolicy = webView == NULL;
@ -1363,9 +1338,9 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select,
if (webView == NULL)
webView = new BWebView("web view", fContext);
bool isNewWindow = fTabManager->CountTabs() == 0;
fTabManager->AddTab(webView, B_TRANSLATE("New tab"));
bool isNewWindow = fWebViewList->CountItems() == 0;
WebViewListItem* newEntry = new WebViewListItem(webView, B_TRANSLATE("New tab"));
fWebViewList->AddItem(newEntry);
BString url(_url);
if (applyNewPagePolicy && url.Length() == 0)
@ -1375,7 +1350,7 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select,
webView->LoadURL(url.String());
if (select) {
fTabManager->SelectTab(fTabManager->CountTabs() - 1);
fWebViewList->Select(fWebViewList->IndexOf(newEntry));
SetCurrentWebView(webView);
webView->WebPage()->ResendNotifications();
fURLInputGroup->SetPageIcon(NULL);
@ -1384,7 +1359,6 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select,
}
_ShowInterface(true);
_UpdateTabGroupVisibility();
}
@ -1440,7 +1414,7 @@ BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction)
// But our own WebPage may already try to lock us from within
// the application thread -> dead-lock. Thus we can't wait for
// a reply here.
BMessage message(NEW_TAB);
BMessage message(CREATE_VIEW);
message.AddPointer("window", this);
message.AddString("url", url);
message.AddBool("select", primaryAction);
@ -1458,20 +1432,15 @@ BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame,
view);
window->Show();
} else
CreateNewTab(BString(), activate, view);
CreateWebView(BString(), activate, view);
}
void
BrowserWindow::CloseWindowRequested(BWebView* view)
{
int32 index = fTabManager->TabForView(view);
if (index < 0) {
// Tab is already gone.
return;
}
BMessage message(CLOSE_TAB);
message.AddInt32("tab index", index);
BMessage message(CLOSE_VIEW);
message.AddPointer("view pointer", view);
PostMessage(&message, this);
}
@ -1559,10 +1528,11 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view)
NavigationCapabilitiesChanged(fBackButton->IsEnabled(),
fForwardButton->IsEnabled(), false, view);
int32 tabIndex = fTabManager->TabForView(view);
// TODO NEPHELE
/*int32 tabIndex = fTabManager->TabForView(view);
if (tabIndex > 0 && strcmp(B_TRANSLATE("New tab"),
fTabManager->TabLabel(tabIndex)) == 0)
fTabManager->SetTabLabel(tabIndex, url);
fTabManager->SetTabLabel(tabIndex, url);*/
}
@ -1571,7 +1541,7 @@ BrowserWindow::MainDocumentError(const BString& failingURL,
const BString& localizedDescription, BWebView* view)
{
// Make sure we show the page that contains the view.
if (!_ShowPage(view))
if (!_SelectView(view))
return;
// Try delegating the URL to an external app instead.
@ -1603,7 +1573,8 @@ BrowserWindow::MainDocumentError(const BString& failingURL,
void
BrowserWindow::TitleChanged(const BString& title, BWebView* view)
{
{/*
// TODO NEPHELE
int32 tabIndex = fTabManager->TabForView(view);
if (tabIndex < 0)
return;
@ -1613,19 +1584,20 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view)
if (view != CurrentWebView())
return;
_UpdateTitle(title);
_UpdateTitle(title);*/
}
void
BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view)
{
{/*
// TODO NEPHELE
// The view may already be gone, since this notification arrives
// asynchronously.
if (!fTabManager->HasView(view))
return;
_SetPageIcon(view, icon);
_SetPageIcon(view, icon);*/
}
@ -1636,7 +1608,7 @@ BrowserWindow::ResizeRequested(float width, float height, BWebView* view)
return;
// Ignore request when there is more than one BWebView embedded.
if (fTabManager->CountTabs() > 1)
if (fWebViewList->CountItems() > 1)
return;
// Make sure the new frame is not larger than the screen frame minus
@ -1773,7 +1745,7 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser,
}
}
// Switch to the page for which this authentication is required.
if (!_ShowPage(view))
if (!_SelectView(view))
return false;
AuthenticationPanel* panel = new AuthenticationPanel(Frame());
@ -1818,7 +1790,7 @@ BrowserWindow::_UpdateTitle(const BString& title)
SetTitle(windowTitle.String());
}
/*
void
BrowserWindow::_UpdateTabGroupVisibility()
{
@ -1838,27 +1810,22 @@ BrowserWindow::_TabGroupShouldBeVisible() const
&& (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0;
}
*/
void
BrowserWindow::_ShutdownTab(int32 index)
{
BView* view = fTabManager->RemoveTab(index);
BrowserWindow::_CloseView(int32 index)
{/*
// TODO NEPHELE
BView* view = fWebViewList->RemoveItem(index);
BWebView* webView = dynamic_cast<BWebView*>(view);
if (webView == CurrentWebView())
SetCurrentWebView(NULL);
if (webView != NULL)
webView->Shutdown();
else
delete view;
delete view;*/
}
void
BrowserWindow::_TabChanged(int32 index)
{
SetCurrentWebView(dynamic_cast<BWebView*>(fTabManager->ViewForTab(index)));
}
status_t
BrowserWindow::_BookmarkPath(BPath& path) const
@ -2116,7 +2083,8 @@ BrowserWindow::_AddBookmarkURLsRecursively(BDirectory& directory,
void
BrowserWindow::_SetPageIcon(BWebView* view, const BBitmap* icon)
{
{/*
// TODO NEPHELE
PageUserData* userData = static_cast<PageUserData*>(view->GetUserData());
if (userData == NULL) {
userData = new(std::nothrow) PageUserData(NULL);
@ -2129,7 +2097,7 @@ BrowserWindow::_SetPageIcon(BWebView* view, const BBitmap* icon)
userData->SetPageIcon(icon);
fTabManager->SetTabIcon(view, userData->PageIcon());
if (view == CurrentWebView())
fURLInputGroup->SetPageIcon(icon);
fURLInputGroup->SetPageIcon(icon);*/
}
@ -2299,18 +2267,19 @@ BrowserWindow::_UpdateClipboardItems()
bool
BrowserWindow::_ShowPage(BWebView* view)
{
BrowserWindow::_SelectView(BWebView* view)
{/*
// TODO NEPHEL
if (view != CurrentWebView()) {
int32 tabIndex = fTabManager->TabForView(view);
if (tabIndex < 0) {
int32 viewIndex = fWebViewList->IndexOf(<BListItem>*view);
if (viewIndex < 0) {
// Page seems to be gone already?
return false;
}
fTabManager->SelectTab(tabIndex);
_TabChanged(tabIndex);
fWebViewList->Select(viewIndex);
SetCurrentWebView(view);
UpdateIfNeeded();
}
} */
return true;
}
@ -2381,14 +2350,14 @@ BrowserWindow::_ShowInterface(bool show)
fMenuGroup->SetVisible(
(fVisibleInterfaceElements & INTERFACE_ELEMENT_MENU) != 0);
#endif
fTabGroup->SetVisible(_TabGroupShouldBeVisible());
//fTabGroup->SetVisible(_TabGroupShouldBeVisible());
fNavigationGroup->SetVisible(
(fVisibleInterfaceElements & INTERFACE_ELEMENT_NAVIGATION) != 0);
fStatusGroup->SetVisible(
(fVisibleInterfaceElements & INTERFACE_ELEMENT_STATUS) != 0);
} else {
fMenuGroup->SetVisible(false);
fTabGroup->SetVisible(false);
//fTabGroup->SetVisible(false);
fNavigationGroup->SetVisible(false);
fStatusGroup->SetVisible(false);
}

View File

@ -34,6 +34,7 @@
#include <Messenger.h>
#include <String.h>
#include <UrlContext.h>
#include <OutlineListView.h>
class BButton;
class BCheckBox;
@ -52,7 +53,6 @@ class BWebView;
class BookmarkBar;
class SettingsMessage;
class TabManager;
class URLInputGroup;
namespace BPrivate {
@ -84,7 +84,6 @@ enum StartUpPolicy {
enum {
NEW_WINDOW = 'nwnd',
NEW_TAB = 'ntab',
WINDOW_OPENED = 'wndo',
WINDOW_CLOSED = 'wndc',
SHOW_DOWNLOAD_WINDOW = 'sdwd',
@ -93,7 +92,11 @@ enum {
SHOW_COOKIE_WINDOW = 'skwd'
};
#define INTEGRATE_MENU_INTO_TAB_BAR 0
enum {
CLOSE_VIEW = 'clvw',
CREATE_VIEW = 'crvw',
SELECT_VIEW = 'slvw'
};
class BrowserWindow : public BWebWindow {
@ -123,7 +126,7 @@ public:
virtual void SetCurrentWebView(BWebView* view);
bool IsBlankTab() const;
void CreateNewTab(const BString& url, bool select,
void CreateWebView(const BString& url, bool select,
BWebView* webView = 0);
BRect WindowFrame() const;
@ -174,9 +177,7 @@ private:
private:
void _UpdateTitle(const BString &title);
void _UpdateTabGroupVisibility();
bool _TabGroupShouldBeVisible() const;
void _ShutdownTab(int32 index);
void _CloseView(int32 index);
void _TabChanged(int32 index);
status_t _BookmarkPath(BPath& path) const;
@ -198,7 +199,7 @@ private:
void _UpdateHistoryMenu();
void _UpdateClipboardItems();
bool _ShowPage(BWebView* view);
bool _SelectView(BWebView* view);
void _ToggleFullscreen();
void _ResizeToScreen();
@ -244,7 +245,7 @@ private:
BStatusBar* fLoadingProgressBar;
BLayoutItem* fMenuGroup;
BLayoutItem* fTabGroup;
BOutlineListView* fWebViewList;
BLayoutItem* fNavigationGroup;
BLayoutItem* fFindGroup;
BLayoutItem* fStatusGroup;
@ -255,7 +256,6 @@ private:
BButton* fFindNextButton;
BButton* fFindCloseButton;
BCheckBox* fFindCaseSensitiveCheckBox;
TabManager* fTabManager;
bool fIsFullscreen;
bool fInterfaceVisible;

View File

@ -3,6 +3,7 @@ SubDir HAIKU_TOP src apps webpositive ;
SubDirC++Flags $(defines) -Wno-error=sequence-point -Wno-error=format-truncation ;
SubDirCcFlags $(defines) -Wno-error=sequence-point -Wno-error=format-truncation ;
DEBUG = 1 ;
# source directories
local sourceDirs =
autocompletion
@ -21,10 +22,8 @@ local sources =
BookmarkBar.cpp
FontSelectionView.cpp
# tabview
TabContainerView.cpp
TabManager.cpp
TabView.cpp
# ListView
WebViewListItem.cpp
AuthenticationPanel.cpp
BrowserApp.cpp

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2021 Pascal R. G. Abresch <nep@packageloss.eu>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "WebViewListItem.h"
#include <StringItem.h>
#include <OutlineListView.h>
WebViewListItem::WebViewListItem(BWebView* webView, const char* text, uint32 level, bool expanded)
:
BStringItem(text, level, expanded)
{
fWebView = webView;
}
WebViewListItem::~WebViewListItem()
{
}
void*
GetItemForView(BOutlineListView* list, BWebView* view) {
for (int i = 0; i < list->CountItems(); i++) {
WebViewListItem* item = static_cast<WebViewListItem*>(list->ItemAt(i));
if (item->fWebView == view)
return item;
}
return NULL;
}

View File

@ -0,0 +1,24 @@
/*
* Copyright (C) 2021 Pascal R. G. Abresch <nep@packageloss.eu>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef WEBVIEWLISTITEM_H
#define WEBVIEWLISTITEM_H
#include <StringItem.h>
#include "WebView.h"
class WebViewListItem : public BStringItem {
public:
WebViewListItem(BWebView* webView,
const char* text,
uint32 outlineLevel = 0,
bool expanded = true);
~WebViewListItem();
BWebView* fWebView;
};
#endif // WEBVIEWLISTITEM_H

View File

@ -1,525 +0,0 @@
/*
* Copyright (C) 2010 Rene Gollent <rene@gollent.com>
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "TabContainerView.h"
#include <stdio.h>
#include <Application.h>
#include <AbstractLayoutItem.h>
#include <Bitmap.h>
#include <Button.h>
#include <CardLayout.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <GroupView.h>
#include <SpaceLayoutItem.h>
#include <Window.h>
#include "TabView.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Tab Manager"
static const float kLeftTabInset = 4;
TabContainerView::TabContainerView(Controller* controller)
:
BGroupView(B_HORIZONTAL, 0.0),
fLastMouseEventTab(NULL),
fMouseDown(false),
fClickCount(0),
fSelectedTab(NULL),
fController(controller),
fFirstVisibleTabIndex(0)
{
SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
SetViewColor(B_TRANSPARENT_COLOR);
GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1);
GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f);
}
TabContainerView::~TabContainerView()
{
}
BSize
TabContainerView::MinSize()
{
// Eventually, we want to be scrolling if the tabs don't fit.
BSize size(BGroupView::MinSize());
size.width = 300;
return size;
}
void
TabContainerView::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BGroupView::MessageReceived(message);
}
}
void
TabContainerView::Draw(BRect updateRect)
{
// draw tab frame
BRect rect(Bounds());
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
uint32 borders = BControlLook::B_TOP_BORDER
| BControlLook::B_BOTTOM_BORDER;
be_control_look->DrawTabFrame(this, rect, updateRect, base, 0,
borders, B_NO_BORDER);
// draw tabs on top of frame
BGroupLayout* layout = GroupLayout();
int32 count = layout->CountItems() - 1;
for (int32 i = 0; i < count; i++) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(layout->ItemAt(i));
if (item == NULL || !item->IsVisible())
continue;
item->Parent()->Draw(item->Frame());
}
}
void
TabContainerView::MouseDown(BPoint where)
{
if (Window() == NULL)
return;
BMessage* currentMessage = Window()->CurrentMessage();
if (currentMessage == NULL)
return;
uint32 buttons;
if (currentMessage->FindInt32("buttons", (int32*)&buttons) != B_OK)
buttons = B_PRIMARY_MOUSE_BUTTON;
uint32 clicks;
if (currentMessage->FindInt32("clicks", (int32*)&clicks) != B_OK)
clicks = 1;
fMouseDown = true;
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
if (fLastMouseEventTab != NULL)
fLastMouseEventTab->MouseDown(where, buttons);
else {
if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0) {
// Middle click outside tabs should always open a new tab.
fController->DoubleClickOutsideTabs();
} else if (clicks > 1)
fClickCount++;
else
fClickCount = 1;
}
}
void
TabContainerView::MouseUp(BPoint where)
{
fMouseDown = false;
if (fLastMouseEventTab) {
fLastMouseEventTab->MouseUp(where);
fClickCount = 0;
} else if (fClickCount > 1) {
// NOTE: fClickCount is >= 1 only if the first click was outside
// any tab. So even if fLastMouseEventTab has been reset to NULL
// because this tab was removed during mouse down, we wouldn't
// run the "outside tabs" code below.
fController->DoubleClickOutsideTabs();
fClickCount = 0;
}
// Always check the tab under the mouse again, since we don't update
// it with fMouseDown == true.
_SendFakeMouseMoved();
}
void
TabContainerView::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
_MouseMoved(where, transit, dragMessage);
}
void
TabContainerView::DoLayout()
{
BGroupView::DoLayout();
_ValidateTabVisibility();
_SendFakeMouseMoved();
}
void
TabContainerView::AddTab(const char* label, int32 index)
{
TabView* tab;
if (fController != NULL)
tab = fController->CreateTabView();
else
tab = new TabView();
tab->SetLabel(label);
AddTab(tab, index);
}
void
TabContainerView::AddTab(TabView* tab, int32 index)
{
tab->SetContainerView(this);
if (index == -1)
index = GroupLayout()->CountItems() - 1;
tab->Update();
GroupLayout()->AddItem(index, tab->LayoutItem());
if (fSelectedTab == NULL)
SelectTab(tab);
bool isLast = index == GroupLayout()->CountItems() - 1;
if (isLast) {
TabLayoutItem* item
= dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index - 1));
if (item != NULL)
item->Parent()->Update();
}
SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex());
_ValidateTabVisibility();
}
TabView*
TabContainerView::RemoveTab(int32 index)
{
TabLayoutItem* item
= dynamic_cast<TabLayoutItem*>(GroupLayout()->RemoveItem(index));
if (item == NULL)
return NULL;
BRect dirty(Bounds());
dirty.left = item->Frame().left;
TabView* removedTab = item->Parent();
removedTab->SetContainerView(NULL);
if (removedTab == fLastMouseEventTab)
fLastMouseEventTab = NULL;
// Update tabs after or before the removed tab.
item = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index));
if (item != NULL) {
// This tab is behind the removed tab.
TabView* tab = item->Parent();
tab->Update();
if (removedTab == fSelectedTab) {
fSelectedTab = NULL;
SelectTab(tab);
} else if (fController != NULL && tab == fSelectedTab)
fController->UpdateSelection(index);
} else {
// The removed tab was the last tab.
item = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index - 1));
if (item != NULL) {
TabView* tab = item->Parent();
tab->Update();
if (removedTab == fSelectedTab) {
fSelectedTab = NULL;
SelectTab(tab);
}
}
}
Invalidate(dirty);
_ValidateTabVisibility();
return removedTab;
}
TabView*
TabContainerView::TabAt(int32 index) const
{
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
GroupLayout()->ItemAt(index));
if (item != NULL)
return item->Parent();
return NULL;
}
int32
TabContainerView::IndexOf(TabView* tab) const
{
if (tab == NULL || GroupLayout() == NULL)
return -1;
return GroupLayout()->IndexOfItem(tab->LayoutItem());
}
void
TabContainerView::SelectTab(int32 index)
{
TabView* tab = NULL;
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
GroupLayout()->ItemAt(index));
if (item != NULL)
tab = item->Parent();
SelectTab(tab);
}
void
TabContainerView::SelectTab(TabView* tab)
{
if (tab == fSelectedTab)
return;
// update old selected tab
if (fSelectedTab != NULL)
fSelectedTab->Update();
fSelectedTab = tab;
// update new selected tab
if (fSelectedTab != NULL)
fSelectedTab->Update();
int32 index = -1;
if (fSelectedTab != NULL)
index = GroupLayout()->IndexOfItem(tab->LayoutItem());
if (!tab->LayoutItem()->IsVisible())
SetFirstVisibleTabIndex(index);
if (fController != NULL)
fController->UpdateSelection(index);
}
void
TabContainerView::SetTabLabel(int32 index, const char* label)
{
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
GroupLayout()->ItemAt(index));
if (item == NULL)
return;
item->Parent()->SetLabel(label);
}
void
TabContainerView::SetFirstVisibleTabIndex(int32 index)
{
if (index < 0)
index = 0;
if (index > MaxFirstVisibleTabIndex())
index = MaxFirstVisibleTabIndex();
if (fFirstVisibleTabIndex == index)
return;
fFirstVisibleTabIndex = index;
_UpdateTabVisibility();
}
int32
TabContainerView::FirstVisibleTabIndex() const
{
return fFirstVisibleTabIndex;
}
int32
TabContainerView::MaxFirstVisibleTabIndex() const
{
float availableWidth = _AvailableWidthForTabs();
if (availableWidth < 0)
return 0;
float visibleTabsWidth = 0;
BGroupLayout* layout = GroupLayout();
int32 i = layout->CountItems() - 2;
for (; i >= 0; i--) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
layout->ItemAt(i));
if (item == NULL)
continue;
float itemWidth = item->MinSize().width;
if (availableWidth >= visibleTabsWidth + itemWidth)
visibleTabsWidth += itemWidth;
else {
// The tab before this tab is the last one that can be visible.
return i + 1;
}
}
return 0;
}
bool
TabContainerView::CanScrollLeft() const
{
return fFirstVisibleTabIndex < MaxFirstVisibleTabIndex();
}
bool
TabContainerView::CanScrollRight() const
{
BGroupLayout* layout = GroupLayout();
int32 count = layout->CountItems() - 1;
if (count > 0) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
layout->ItemAt(count - 1));
return !item->IsVisible();
}
return false;
}
// #pragma mark -
TabView*
TabContainerView::_TabAt(const BPoint& where) const
{
BGroupLayout* layout = GroupLayout();
int32 count = layout->CountItems() - 1;
for (int32 i = 0; i < count; i++) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(layout->ItemAt(i));
if (item == NULL || !item->IsVisible())
continue;
// Account for the fact that the tab frame does not contain the
// visible bottom border.
BRect frame = item->Frame();
frame.bottom++;
if (frame.Contains(where))
return item->Parent();
}
return NULL;
}
void
TabContainerView::_MouseMoved(BPoint where, uint32 _transit,
const BMessage* dragMessage)
{
TabView* tab = _TabAt(where);
if (fMouseDown) {
uint32 transit = tab == fLastMouseEventTab
? B_INSIDE_VIEW : B_OUTSIDE_VIEW;
if (fLastMouseEventTab)
fLastMouseEventTab->MouseMoved(where, transit, dragMessage);
return;
}
if (fLastMouseEventTab != NULL && fLastMouseEventTab == tab)
fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage);
else {
if (fLastMouseEventTab)
fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage);
fLastMouseEventTab = tab;
if (fLastMouseEventTab)
fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage);
else {
fController->SetToolTip(
B_TRANSLATE("Double-click or middle-click to open new tab."));
}
}
}
void
TabContainerView::_ValidateTabVisibility()
{
if (fFirstVisibleTabIndex > MaxFirstVisibleTabIndex())
SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex());
else
_UpdateTabVisibility();
}
void
TabContainerView::_UpdateTabVisibility()
{
float availableWidth = _AvailableWidthForTabs();
if (availableWidth < 0)
return;
float visibleTabsWidth = 0;
bool canScrollTabsLeft = fFirstVisibleTabIndex > 0;
bool canScrollTabsRight = false;
BGroupLayout* layout = GroupLayout();
int32 count = layout->CountItems() - 1;
for (int32 i = 0; i < count; i++) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
layout->ItemAt(i));
if (i < fFirstVisibleTabIndex)
item->SetVisible(false);
else {
float itemWidth = item->MinSize().width;
bool visible = availableWidth >= visibleTabsWidth + itemWidth;
item->SetVisible(visible && !canScrollTabsRight);
visibleTabsWidth += itemWidth;
if (!visible)
canScrollTabsRight = true;
}
}
fController->UpdateTabScrollability(canScrollTabsLeft, canScrollTabsRight);
}
float
TabContainerView::_AvailableWidthForTabs() const
{
float width = Bounds().Width() - 10;
// TODO: Don't really know why -10 is needed above.
float left;
float right;
GroupLayout()->GetInsets(&left, NULL, &right, NULL);
width -= left + right;
return width;
}
void
TabContainerView::_SendFakeMouseMoved()
{
BPoint where;
uint32 buttons;
GetMouse(&where, &buttons, false);
if (Bounds().Contains(where))
_MouseMoved(where, B_INSIDE_VIEW, NULL);
}

View File

@ -1,92 +0,0 @@
/*
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef TAB_CONTAINER_VIEW_H
#define TAB_CONTAINER_VIEW_H
#include <GroupView.h>
class TabView;
class TabContainerView : public BGroupView {
public:
class Controller {
public:
virtual void UpdateSelection(int32 index) = 0;
virtual bool HasFrames() = 0;
virtual TabView* CreateTabView() = 0;
virtual void DoubleClickOutsideTabs() = 0;
virtual void UpdateTabScrollability(bool canScrollLeft,
bool canScrollRight) = 0;
virtual void SetToolTip(const BString& text) = 0;
};
public:
TabContainerView(Controller* controller);
virtual ~TabContainerView();
virtual BSize MinSize();
virtual void MessageReceived(BMessage*);
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void DoLayout();
void AddTab(const char* label, int32 index = -1);
void AddTab(TabView* tab, int32 index = -1);
TabView* RemoveTab(int32 index);
TabView* TabAt(int32 index) const;
int32 IndexOf(TabView* tab) const;
int32 FirstTabIndex() { return 0; };
int32 LastTabIndex()
{ return GroupLayout() == NULL ? -1
: GroupLayout()->CountItems() - 1; };
int32 SelectedTabIndex()
{ return fSelectedTab == NULL ? -1
: IndexOf(fSelectedTab); };
TabView* SelectedTab() { return fSelectedTab; };
void SelectTab(int32 tabIndex);
void SelectTab(TabView* tab);
void SetTabLabel(int32 tabIndex, const char* label);
void SetFirstVisibleTabIndex(int32 index);
int32 FirstVisibleTabIndex() const;
int32 MaxFirstVisibleTabIndex() const;
bool CanScrollLeft() const;
bool CanScrollRight() const;
private:
TabView* _TabAt(const BPoint& where) const;
void _MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
void _ValidateTabVisibility();
void _UpdateTabVisibility();
float _AvailableWidthForTabs() const;
void _SendFakeMouseMoved();
private:
TabView* fLastMouseEventTab;
bool fMouseDown;
uint32 fClickCount;
TabView* fSelectedTab;
Controller* fController;
int32 fFirstVisibleTabIndex;
};
#endif // TAB_CONTAINER_VIEW_H

View File

@ -1,942 +0,0 @@
/*
* Copyright (C) 2010 Rene Gollent <rene@gollent.com>
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "TabManager.h"
#include <stdio.h>
#include <new>
#include <Application.h>
#include <AbstractLayoutItem.h>
#include <Bitmap.h>
#include <Button.h>
#include <CardLayout.h>
#include <ControlLook.h>
#include <Catalog.h>
#include <GroupView.h>
#include <MenuBar.h>
#include <MenuItem.h>
#include <PopUpMenu.h>
#include <Rect.h>
#include <SpaceLayoutItem.h>
#include <Window.h>
#include "TabContainerView.h"
#include "TabView.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Tab Manager"
const static BString kEmptyString;
// #pragma mark - Helper classes
class TabButton : public BButton {
public:
TabButton(BMessage* message)
: BButton("", message)
{
}
virtual BSize MinSize()
{
return BSize(12, 12);
}
virtual BSize MaxSize()
{
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
}
virtual BSize PreferredSize()
{
return MinSize();
}
virtual void Draw(BRect updateRect)
{
BRect bounds(Bounds());
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
uint32 flags = be_control_look->Flags(this);
uint32 borders = BControlLook::B_TOP_BORDER
| BControlLook::B_BOTTOM_BORDER;
be_control_look->DrawTabFrame(this, bounds, updateRect, base,
0, borders, B_NO_BORDER);
if (IsEnabled()) {
rgb_color button = tint_color(base, 1.07);
be_control_look->DrawButtonBackground(this, bounds, updateRect,
button, flags, 0);
}
BRect symbolRect(bounds);
symbolRect.left = (symbolRect.left + symbolRect.right) / 2 - 6;
symbolRect.top = (symbolRect.top + symbolRect.bottom) / 2 - 6;
symbolRect.right = symbolRect.left + 12;
symbolRect.bottom = symbolRect.top + 12;
DrawSymbol(symbolRect, updateRect, base);
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
}
};
class ScrollLeftTabButton : public TabButton {
public:
ScrollLeftTabButton(BMessage* message)
: TabButton(message)
{
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
float tint = IsEnabled() ? B_DARKEN_4_TINT : B_DARKEN_1_TINT;
be_control_look->DrawArrowShape(this, frame, updateRect,
base, BControlLook::B_LEFT_ARROW, 0, tint);
}
};
class ScrollRightTabButton : public TabButton {
public:
ScrollRightTabButton(BMessage* message)
: TabButton(message)
{
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
frame.OffsetBy(1, 0);
float tint = IsEnabled() ? B_DARKEN_4_TINT : B_DARKEN_1_TINT;
be_control_look->DrawArrowShape(this, frame, updateRect,
base, BControlLook::B_RIGHT_ARROW, 0, tint);
}
};
class NewTabButton : public TabButton {
public:
NewTabButton(BMessage* message)
: TabButton(message)
{
SetToolTip("New tab (Cmd-T)");
}
virtual BSize MinSize()
{
return BSize(18, 12);
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
SetHighColor(tint_color(base, B_DARKEN_4_TINT));
float inset = 3;
frame.InsetBy(2, 2);
frame.top++;
frame.left++;
FillRoundRect(BRect(frame.left, frame.top + inset,
frame.right, frame.bottom - inset), 1, 1);
FillRoundRect(BRect(frame.left + inset, frame.top,
frame.right - inset, frame.bottom), 1, 1);
}
};
class TabMenuTabButton : public TabButton {
public:
TabMenuTabButton(BMessage* message)
: TabButton(message)
, fCloseTime(0)
{
}
virtual BSize MinSize()
{
return BSize(18, 12);
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
be_control_look->DrawArrowShape(this, frame, updateRect,
base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT);
}
virtual void MouseDown(BPoint point)
{
// Don't reopen the menu if it's already open or freshly closed.
bigtime_t clickSpeed = 2000000;
get_click_speed(&clickSpeed);
bigtime_t clickTime = Window()->CurrentMessage()->FindInt64("when");
if (!IsEnabled() || (Value() == B_CONTROL_ON)
|| clickTime < fCloseTime + clickSpeed) {
return;
}
// Invoke must be called before setting B_CONTROL_ON
// for the button to stay "down"
Invoke();
SetValue(B_CONTROL_ON);
}
virtual void MouseUp(BPoint point)
{
// Do nothing
}
void MenuClosed()
{
fCloseTime = system_time();
SetValue(B_CONTROL_OFF);
}
private:
bigtime_t fCloseTime;
};
enum {
MSG_SCROLL_TABS_LEFT = 'stlt',
MSG_SCROLL_TABS_RIGHT = 'strt',
MSG_OPEN_TAB_MENU = 'otmn'
};
class TabContainerGroup : public BGroupView {
public:
TabContainerGroup(TabContainerView* tabContainerView)
:
BGroupView(B_HORIZONTAL, 0.0),
fTabContainerView(tabContainerView),
fScrollLeftTabButton(NULL),
fScrollRightTabButton(NULL),
fTabMenuButton(NULL)
{
}
virtual void AttachedToWindow()
{
if (fScrollLeftTabButton != NULL)
fScrollLeftTabButton->SetTarget(this);
if (fScrollRightTabButton != NULL)
fScrollRightTabButton->SetTarget(this);
if (fTabMenuButton != NULL)
fTabMenuButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
if (fTabContainerView == NULL)
return BGroupView::MessageReceived(message);
switch (message->what) {
case MSG_SCROLL_TABS_LEFT:
fTabContainerView->SetFirstVisibleTabIndex(
fTabContainerView->FirstVisibleTabIndex() - 1);
break;
case MSG_SCROLL_TABS_RIGHT:
fTabContainerView->SetFirstVisibleTabIndex(
fTabContainerView->FirstVisibleTabIndex() + 1);
break;
case MSG_OPEN_TAB_MENU:
{
BPopUpMenu* tabMenu = new BPopUpMenu("tab menu", true, false);
int tabCount = fTabContainerView->GetLayout()->CountItems();
for (int i = 0; i < tabCount; i++) {
TabView* tab = fTabContainerView->TabAt(i);
if (tab != NULL) {
BMenuItem* item = new(std::nothrow)
BMenuItem(tab->Label(), NULL);
if (item != NULL) {
tabMenu->AddItem(item);
if (i == fTabContainerView->SelectedTabIndex())
item->SetMarked(true);
}
}
}
// Force layout to get the final menu size. InvalidateLayout()
// did not seem to work here.
tabMenu->AttachedToWindow();
BRect buttonFrame = fTabMenuButton->Frame();
BRect menuFrame = tabMenu->Frame();
BPoint openPoint = ConvertToScreen(buttonFrame.LeftBottom());
// Open with the right side of the menu aligned with the right
// side of the button and a little below.
openPoint.x -= menuFrame.Width() - buttonFrame.Width();
openPoint.y += 2;
BMenuItem *selected = tabMenu->Go(openPoint, false, false,
ConvertToScreen(buttonFrame));
if (selected) {
selected->SetMarked(true);
int32 index = tabMenu->IndexOf(selected);
if (index != B_ERROR)
fTabContainerView->SelectTab(index);
}
fTabMenuButton->MenuClosed();
delete tabMenu;
break;
}
default:
BGroupView::MessageReceived(message);
break;
}
}
void AddScrollLeftButton(TabButton* button)
{
fScrollLeftTabButton = button;
GroupLayout()->AddView(button, 0.0f);
}
void AddScrollRightButton(TabButton* button)
{
fScrollRightTabButton = button;
GroupLayout()->AddView(button, 0.0f);
}
void AddTabMenuButton(TabMenuTabButton* button)
{
fTabMenuButton = button;
GroupLayout()->AddView(button, 0.0f);
}
void EnableScrollButtons(bool canScrollLeft, bool canScrollRight)
{
fScrollLeftTabButton->SetEnabled(canScrollLeft);
fScrollRightTabButton->SetEnabled(canScrollRight);
if (!canScrollLeft && !canScrollRight) {
// hide scroll buttons
} else {
// show scroll buttons
}
}
private:
TabContainerView* fTabContainerView;
TabButton* fScrollLeftTabButton;
TabButton* fScrollRightTabButton;
TabMenuTabButton* fTabMenuButton;
};
class TabButtonContainer : public BGroupView {
public:
TabButtonContainer()
:
BGroupView(B_HORIZONTAL, 0.0)
{
SetFlags(Flags() | B_WILL_DRAW);
SetViewColor(B_TRANSPARENT_COLOR);
SetLowUIColor(B_PANEL_BACKGROUND_COLOR);
GroupLayout()->SetInsets(0, 6, 0, 0);
}
virtual void Draw(BRect updateRect)
{
// draw nothing
}
};
class TabManagerController : public TabContainerView::Controller {
public:
TabManagerController(TabManager* manager);
virtual ~TabManagerController();
virtual void UpdateSelection(int32 index)
{
fManager->SelectTab(index);
}
virtual bool HasFrames()
{
return false;
}
virtual TabView* CreateTabView();
virtual void DoubleClickOutsideTabs();
virtual void UpdateTabScrollability(bool canScrollLeft,
bool canScrollRight)
{
fTabContainerGroup->EnableScrollButtons(canScrollLeft, canScrollRight);
}
virtual void SetToolTip(const BString& text)
{
if (fCurrentToolTip == text)
return;
fCurrentToolTip = text;
fManager->GetTabContainerView()->HideToolTip();
fManager->GetTabContainerView()->SetToolTip(
reinterpret_cast<BToolTip*>(NULL));
fManager->GetTabContainerView()->SetToolTip(fCurrentToolTip.String());
}
void CloseTab(int32 index);
void SetCloseButtonsAvailable(bool available)
{
fCloseButtonsAvailable = available;
}
bool CloseButtonsAvailable() const
{
return fCloseButtonsAvailable;
}
void SetDoubleClickOutsideTabsMessage(const BMessage& message,
const BMessenger& target);
void SetTabContainerGroup(TabContainerGroup* tabContainerGroup)
{
fTabContainerGroup = tabContainerGroup;
}
private:
TabManager* fManager;
TabContainerGroup* fTabContainerGroup;
bool fCloseButtonsAvailable;
BMessage* fDoubleClickOutsideTabsMessage;
BMessenger fTarget;
BString fCurrentToolTip;
};
// #pragma mark - WebTabView
class WebTabView : public TabView {
public:
WebTabView(TabManagerController* controller);
~WebTabView();
virtual BSize MaxSize();
virtual void DrawContents(BView* owner, BRect frame,
const BRect& updateRect);
virtual void MouseDown(BPoint where, uint32 buttons);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
void SetIcon(const BBitmap* icon);
private:
void _DrawCloseButton(BView* owner, BRect& frame, const BRect& updateRect);
BRect _CloseRectFrame(BRect frame) const;
private:
BBitmap* fIcon;
TabManagerController* fController;
bool fOverCloseRect;
bool fClicked;
};
WebTabView::WebTabView(TabManagerController* controller)
:
TabView(),
fIcon(NULL),
fController(controller),
fOverCloseRect(false),
fClicked(false)
{
}
WebTabView::~WebTabView()
{
delete fIcon;
}
static const int kIconSize = 18;
static const int kIconInset = 3;
BSize
WebTabView::MaxSize()
{
// Account for icon.
BSize size(TabView::MaxSize());
size.height = max_c(size.height, kIconSize + kIconInset * 2);
if (fIcon)
size.width += kIconSize + kIconInset * 2;
// Account for close button.
size.width += size.height;
return size;
}
void
WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect)
{
if (fController->CloseButtonsAvailable())
_DrawCloseButton(owner, frame, updateRect);
if (fIcon != NULL) {
BRect iconBounds(0, 0, kIconSize - 1, kIconSize - 1);
// clip to icon bounds, if they are smaller
if (iconBounds.Contains(fIcon->Bounds()))
iconBounds = fIcon->Bounds();
else {
// Try to scale down the icon by an even factor so the
// final size is between 14 and 18 pixel size. If this fails,
// the icon will simply be displayed at 18x18.
float scale = 2;
while ((fIcon->Bounds().Width() + 1) / scale > kIconSize)
scale *= 2;
if ((fIcon->Bounds().Width() + 1) / scale >= kIconSize - 4
&& (fIcon->Bounds().Height() + 1) / scale >= kIconSize - 4
&& (fIcon->Bounds().Height() + 1) / scale <= kIconSize) {
iconBounds.right = (fIcon->Bounds().Width() + 1) / scale - 1;
iconBounds.bottom = (fIcon->Bounds().Height() + 1) / scale - 1;
}
}
// account for borders
frame.top -= 2.0f;
BPoint iconPos(frame.left + kIconInset - 1,
frame.top + floorf((frame.Height() - iconBounds.Height()) / 2));
iconBounds.OffsetTo(iconPos);
owner->SetDrawingMode(B_OP_ALPHA);
owner->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds,
B_FILTER_BITMAP_BILINEAR);
owner->SetDrawingMode(B_OP_COPY);
frame.left = frame.left + kIconSize + kIconInset * 2;
}
TabView::DrawContents(owner, frame, updateRect);
}
void
WebTabView::MouseDown(BPoint where, uint32 buttons)
{
if (buttons & B_TERTIARY_MOUSE_BUTTON) {
// Immediately close tab
fController->CloseTab(ContainerView()->IndexOf(this));
return;
}
BRect closeRect = _CloseRectFrame(Frame());
if (!fController->CloseButtonsAvailable() || !closeRect.Contains(where)) {
TabView::MouseDown(where, buttons);
return;
}
fClicked = true;
ContainerView()->Invalidate(closeRect);
}
void
WebTabView::MouseUp(BPoint where)
{
if (!fClicked) {
TabView::MouseUp(where);
return;
}
fClicked = false;
if (_CloseRectFrame(Frame()).Contains(where))
fController->CloseTab(ContainerView()->IndexOf(this));
}
void
WebTabView::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
BRect closeRect = _CloseRectFrame(Frame());
bool overCloseRect = closeRect.Contains(where);
if (overCloseRect != fOverCloseRect
&& fController->CloseButtonsAvailable()) {
fOverCloseRect = overCloseRect;
ContainerView()->Invalidate(closeRect);
}
// Set the tool tip
fController->SetToolTip(overCloseRect ? "" : Label());
TabView::MouseMoved(where, transit, dragMessage);
}
void
WebTabView::SetIcon(const BBitmap* icon)
{
delete fIcon;
if (icon)
fIcon = new BBitmap(icon);
else
fIcon = NULL;
LayoutItem()->InvalidateLayout();
}
BRect
WebTabView::_CloseRectFrame(BRect frame) const
{
frame.left = frame.right - frame.Height();
return frame;
}
void
WebTabView::_DrawCloseButton(BView* owner, BRect& frame,
const BRect& updateRect)
{
BRect closeRect = _CloseRectFrame(frame);
frame.right = closeRect.left - be_control_look->DefaultLabelSpacing();
closeRect.left = (closeRect.left + closeRect.right) / 2 - 3;
closeRect.right = closeRect.left + 6;
closeRect.top = (closeRect.top + closeRect.bottom) / 2 - 3;
closeRect.bottom = closeRect.top + 6;
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
float tint = B_DARKEN_1_TINT;
float isFront = ContainerView()->SelectedTab()
== static_cast<TabView*>(this);
if (!isFront) {
base = tint_color(base, tint);
tint *= 1.02;
}
if (fOverCloseRect)
tint *= 1.4;
else
tint *= 1.2;
if (fClicked && fOverCloseRect) {
// Draw the button frame
BRect buttonRect(closeRect.InsetByCopy(-4, -4));
be_control_look->DrawButtonFrame(owner, buttonRect, updateRect,
base, base,
BControlLook::B_ACTIVATED | BControlLook::B_BLEND_FRAME);
be_control_look->DrawButtonBackground(owner, buttonRect, updateRect,
base, BControlLook::B_ACTIVATED);
closeRect.OffsetBy(1, 1);
tint *= 1.2;
}
// Draw the ×
base = tint_color(base, tint);
owner->SetHighColor(base);
owner->SetPenSize(2);
owner->StrokeLine(closeRect.LeftTop(), closeRect.RightBottom());
owner->StrokeLine(closeRect.LeftBottom(), closeRect.RightTop());
owner->SetPenSize(1);
}
// #pragma mark - TabManagerController
TabManagerController::TabManagerController(TabManager* manager)
:
fManager(manager),
fTabContainerGroup(NULL),
fCloseButtonsAvailable(false),
fDoubleClickOutsideTabsMessage(NULL)
{
}
TabManagerController::~TabManagerController()
{
delete fDoubleClickOutsideTabsMessage;
}
TabView*
TabManagerController::CreateTabView()
{
return new WebTabView(this);
}
void
TabManagerController::DoubleClickOutsideTabs()
{
fTarget.SendMessage(fDoubleClickOutsideTabsMessage);
}
void
TabManagerController::CloseTab(int32 index)
{
fManager->CloseTab(index);
}
void
TabManagerController::SetDoubleClickOutsideTabsMessage(const BMessage& message,
const BMessenger& target)
{
delete fDoubleClickOutsideTabsMessage;
fDoubleClickOutsideTabsMessage = new BMessage(message);
fTarget = target;
}
// #pragma mark - TabManager
TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage)
:
fController(new TabManagerController(this)),
fTarget(target)
{
fController->SetDoubleClickOutsideTabsMessage(*newTabMessage,
be_app_messenger);
fContainerView = new BView("web view container", 0);
fCardLayout = new BCardLayout();
fContainerView->SetLayout(fCardLayout);
fTabContainerView = new TabContainerView(fController);
fTabContainerGroup = new TabContainerGroup(fTabContainerView);
fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0);
fController->SetTabContainerGroup(fTabContainerGroup);
#if INTEGRATE_MENU_INTO_TAB_BAR
fMenu = new BMenu("Menu");
BMenuBar* menuBar = new BMenuBar("Menu bar");
menuBar->AddItem(fMenu);
TabButtonContainer* menuBarContainer = new TabButtonContainer();
menuBarContainer->GroupLayout()->AddView(menuBar);
fTabContainerGroup->GroupLayout()->AddView(menuBarContainer, 0.0f);
#endif
fTabContainerGroup->GroupLayout()->AddView(fTabContainerView);
fTabContainerGroup->AddScrollLeftButton(new ScrollLeftTabButton(
new BMessage(MSG_SCROLL_TABS_LEFT)));
fTabContainerGroup->AddScrollRightButton(new ScrollRightTabButton(
new BMessage(MSG_SCROLL_TABS_RIGHT)));
NewTabButton* newTabButton = new NewTabButton(newTabMessage);
newTabButton->SetTarget(be_app);
fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f);
fTabContainerGroup->AddTabMenuButton(new TabMenuTabButton(
new BMessage(MSG_OPEN_TAB_MENU)));
}
TabManager::~TabManager()
{
delete fController;
}
void
TabManager::SetTarget(const BMessenger& target)
{
fTarget = target;
}
const BMessenger&
TabManager::Target() const
{
return fTarget;
}
#if INTEGRATE_MENU_INTO_TAB_BAR
BMenu*
TabManager::Menu() const
{
return fMenu;
}
#endif
BView*
TabManager::TabGroup() const
{
return fTabContainerGroup;
}
BView*
TabManager::GetTabContainerView() const
{
return fTabContainerView;
}
BView*
TabManager::ContainerView() const
{
return fContainerView;
}
BView*
TabManager::ViewForTab(int32 tabIndex) const
{
BLayoutItem* item = fCardLayout->ItemAt(tabIndex);
if (item != NULL)
return item->View();
return NULL;
}
int32
TabManager::TabForView(const BView* containedView) const
{
int32 count = fCardLayout->CountItems();
for (int32 i = 0; i < count; i++) {
BLayoutItem* item = fCardLayout->ItemAt(i);
if (item->View() == containedView)
return i;
}
return -1;
}
bool
TabManager::HasView(const BView* containedView) const
{
return TabForView(containedView) >= 0;
}
void
TabManager::SelectTab(int32 tabIndex)
{
fCardLayout->SetVisibleItem(tabIndex);
fTabContainerView->SelectTab(tabIndex);
BMessage message(TAB_CHANGED);
message.AddInt32("tab index", tabIndex);
fTarget.SendMessage(&message);
}
void
TabManager::SelectTab(const BView* containedView)
{
int32 tabIndex = TabForView(containedView);
if (tabIndex >= 0)
SelectTab(tabIndex);
}
int32
TabManager::SelectedTabIndex() const
{
return fCardLayout->VisibleIndex();
}
void
TabManager::CloseTab(int32 tabIndex)
{
BMessage message(CLOSE_TAB);
message.AddInt32("tab index", tabIndex);
fTarget.SendMessage(&message);
}
void
TabManager::AddTab(BView* view, const char* label, int32 index)
{
fTabContainerView->AddTab(label, index);
fCardLayout->AddView(index, view);
}
BView*
TabManager::RemoveTab(int32 index)
{
// It's important to remove the view first, since
// removing the tab will preliminary mess with the selected tab
// and then item count of card layout and tab container will not
// match yet.
BLayoutItem* item = fCardLayout->RemoveItem(index);
if (item == NULL)
return NULL;
TabView* tab = fTabContainerView->RemoveTab(index);
delete tab;
BView* view = item->View();
delete item;
return view;
}
int32
TabManager::CountTabs() const
{
return fCardLayout->CountItems();
}
void
TabManager::SetTabLabel(int32 tabIndex, const char* label)
{
fTabContainerView->SetTabLabel(tabIndex, label);
}
const BString&
TabManager::TabLabel(int32 tabIndex)
{
TabView* tab = fTabContainerView->TabAt(tabIndex);
if (tab)
return tab->Label();
else
return kEmptyString;
}
void
TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon)
{
WebTabView* tab = dynamic_cast<WebTabView*>(fTabContainerView->TabAt(
TabForView(containedView)));
if (tab)
tab->SetIcon(icon);
}
void
TabManager::SetCloseButtonsAvailable(bool available)
{
if (available == fController->CloseButtonsAvailable())
return;
fController->SetCloseButtonsAvailable(available);
fTabContainerView->Invalidate();
}

View File

@ -1,76 +0,0 @@
/*
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef TAB_MANAGER_H
#define TAB_MANAGER_H
#include <Messenger.h>
#include <TabView.h>
enum {
TAB_CHANGED = 'tcha',
CLOSE_TAB = 'cltb'
};
class BBitmap;
class BCardLayout;
class BGroupView;
class BMenu;
class TabContainerGroup;
class TabContainerView;
class TabManagerController;
class TabManager {
public:
TabManager(const BMessenger& target,
BMessage* newTabMessage);
virtual ~TabManager();
void SetTarget(const BMessenger& target);
const BMessenger& Target() const;
#if INTEGRATE_MENU_INTO_TAB_BAR
BMenu* Menu() const;
#endif
BView* TabGroup() const;
BView* GetTabContainerView() const;
BView* ContainerView() const;
BView* ViewForTab(int32 tabIndex) const;
int32 TabForView(const BView* containedView) const;
bool HasView(const BView* containedView) const;
void SelectTab(int32 tabIndex);
void SelectTab(const BView* containedView);
int32 SelectedTabIndex() const;
void CloseTab(int32 tabIndex);
void AddTab(BView* view, const char* label,
int32 index = -1);
BView* RemoveTab(int32 index);
int32 CountTabs() const;
void SetTabLabel(int32 tabIndex, const char* label);
const BString& TabLabel(int32);
void SetTabIcon(const BView* containedView,
const BBitmap* icon);
void SetCloseButtonsAvailable(bool available);
private:
#if INTEGRATE_MENU_INTO_TAB_BAR
BMenu* fMenu;
#endif
TabContainerGroup* fTabContainerGroup;
TabContainerView* fTabContainerView;
BView* fContainerView;
BCardLayout* fCardLayout;
TabManagerController* fController;
BMessenger fTarget;
};
#endif // TAB_MANAGER_H

View File

@ -1,316 +0,0 @@
/*
* Copyright (C) 2010 Rene Gollent <rene@gollent.com>
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "TabView.h"
#include <stdio.h>
#include <Application.h>
#include <Bitmap.h>
#include <Button.h>
#include <CardLayout.h>
#include <ControlLook.h>
#include <GroupView.h>
#include <SpaceLayoutItem.h>
#include <TabView.h>
#include <Window.h>
#include "TabContainerView.h"
// #pragma mark - TabView
TabView::TabView()
:
fContainerView(NULL),
fLayoutItem(new TabLayoutItem(this)),
fLabel()
{
}
TabView::~TabView()
{
// The layout item is deleted for us by the layout which contains it.
if (fContainerView == NULL)
delete fLayoutItem;
}
BSize
TabView::MinSize()
{
BSize size(MaxSize());
size.width = 60.0f;
return size;
}
BSize
TabView::PreferredSize()
{
return MaxSize();
}
BSize
TabView::MaxSize()
{
float extra = be_control_look->DefaultLabelSpacing();
float labelWidth = 300.0f;
return BSize(labelWidth, _LabelHeight() + extra);
}
void
TabView::Draw(BRect updateRect)
{
BRect frame(fLayoutItem->Frame());
frame.right++;
frame.bottom++;
int32 index = fContainerView->IndexOf(this);
// make room for tail of last tab
bool isLast = index == fContainerView->LastTabIndex();
if (isLast)
frame.right -= 2;
DrawBackground(fContainerView, frame, updateRect);
bool isFront = index == fContainerView->SelectedTabIndex();
if (isFront)
frame.top += 3.0f;
else
frame.top += 6.0f;
float spacing = be_control_look->DefaultLabelSpacing();
frame.InsetBy(spacing, spacing / 2);
DrawContents(fContainerView, frame, updateRect);
}
void
TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect)
{
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
uint32 flags = 0;
uint32 borders = BControlLook::B_TOP_BORDER
| BControlLook::B_BOTTOM_BORDER;
int32 index = fContainerView->IndexOf(this);
int32 selected = fContainerView->SelectedTabIndex();
int32 first = fContainerView->FirstTabIndex();
int32 last = fContainerView->LastTabIndex();
if (index == selected) {
be_control_look->DrawActiveTab(owner, frame, updateRect, base, flags,
borders, BControlLook::B_TOP_BORDER, index, selected, first, last);
} else {
be_control_look->DrawInactiveTab(owner, frame, updateRect, base, flags,
borders, BControlLook::B_TOP_BORDER, index, selected, first, last);
}
}
void
TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect)
{
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect,
base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE));
}
void
TabView::MouseDown(BPoint where, uint32 buttons)
{
fContainerView->SelectTab(this);
}
void
TabView::MouseUp(BPoint where)
{
}
void
TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
}
void
TabView::Update()
{
fLayoutItem->InvalidateContainer();
}
void
TabView::SetContainerView(TabContainerView* containerView)
{
fContainerView = containerView;
}
TabContainerView*
TabView::ContainerView() const
{
return fContainerView;
}
BLayoutItem*
TabView::LayoutItem() const
{
return fLayoutItem;
}
void
TabView::SetLabel(const char* label)
{
if (fLabel == label)
return;
fLabel = label;
fLayoutItem->InvalidateLayout();
}
const BString&
TabView::Label() const
{
return fLabel;
}
BRect
TabView::Frame() const
{
return fLayoutItem->Frame();
}
float
TabView::_LabelHeight() const
{
font_height fontHeight;
fContainerView->GetFontHeight(&fontHeight);
return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
}
// #pragma mark - TabLayoutItem
TabLayoutItem::TabLayoutItem(TabView* parent)
:
fParent(parent),
fVisible(true)
{
}
bool
TabLayoutItem::IsVisible()
{
return fVisible;
}
void
TabLayoutItem::SetVisible(bool visible)
{
if (fVisible == visible)
return;
fVisible = visible;
InvalidateContainer();
fParent->ContainerView()->InvalidateLayout();
}
BRect
TabLayoutItem::Frame()
{
return fFrame;
}
void
TabLayoutItem::SetFrame(BRect frame)
{
BRect dirty = fFrame;
fFrame = frame;
dirty = dirty | fFrame;
InvalidateContainer(dirty);
}
BView*
TabLayoutItem::View()
{
return NULL;
}
BSize
TabLayoutItem::BaseMinSize()
{
return fParent->MinSize();
}
BSize
TabLayoutItem::BaseMaxSize()
{
return fParent->MaxSize();
}
BSize
TabLayoutItem::BasePreferredSize()
{
return fParent->PreferredSize();
}
BAlignment
TabLayoutItem::BaseAlignment()
{
return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
}
TabView*
TabLayoutItem::Parent() const
{
return fParent;
}
void
TabLayoutItem::InvalidateContainer()
{
InvalidateContainer(Frame());
}
void
TabLayoutItem::InvalidateContainer(BRect frame)
{
// Invalidate more than necessary, to help the TabContainerView
// redraw the parts outside any tabs... need 2px
frame.bottom += 2;
frame.right += 2;
fParent->ContainerView()->Invalidate(frame);
}

View File

@ -1,91 +0,0 @@
/*
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef TAB_VIEW_H
#define TAB_VIEW_H
#include <AbstractLayoutItem.h>
#include <Rect.h>
#include <String.h>
class BMessage;
class BView;
class TabContainerView;
class TabLayoutItem;
class TabView {
public:
TabView();
virtual ~TabView();
virtual BSize MinSize();
virtual BSize PreferredSize();
virtual BSize MaxSize();
void Draw(BRect updateRect);
virtual void DrawBackground(BView* owner, BRect frame,
const BRect& updateRect);
virtual void DrawContents(BView* owner, BRect frame,
const BRect& updateRect);
virtual void MouseDown(BPoint where, uint32 buttons);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void Update();
BLayoutItem* LayoutItem() const;
void SetContainerView(TabContainerView* view);
TabContainerView* ContainerView() const;
void SetLabel(const char* label);
const BString& Label() const;
BRect Frame() const;
private:
float _LabelHeight() const;
private:
TabContainerView* fContainerView;
TabLayoutItem* fLayoutItem;
BString fLabel;
};
class TabLayoutItem : public BAbstractLayoutItem {
public:
TabLayoutItem(TabView* parent);
virtual bool IsVisible();
virtual void SetVisible(bool visible);
virtual BRect Frame();
virtual void SetFrame(BRect frame);
virtual BView* View();
virtual BSize BaseMinSize();
virtual BSize BaseMaxSize();
virtual BSize BasePreferredSize();
virtual BAlignment BaseAlignment();
TabView* Parent() const;
void InvalidateContainer();
void InvalidateContainer(BRect frame);
private:
TabView* fParent;
BRect fFrame;
bool fVisible;
};
#endif // TAB_VIEW_H

View File

@ -134,11 +134,7 @@ format_signed_number(int32 value)
static string
read_pollfd(Context &context, void *data)
{
nfds_t numfds = 0;
if (context.GetContents(Context::INPUT_VALUES))
numfds = get_value<nfds_t>(context.GetValue(context.GetSibling(1)));
else if (context.GetContents(Context::OUTPUT_VALUES))
numfds = context.GetReturnValue();
nfds_t numfds = get_value<nfds_t>(context.GetValue(context.GetSibling(1)));
if ((int64)numfds <= 0)
return string();
@ -157,6 +153,10 @@ read_pollfd(Context &context, void *data)
r = "[";
for (nfds_t i = 0; i < numfds && added < 8; i++) {
if ((tmp[i].fd == -1 || tmp[i].revents == 0)
&& context.GetContents(Context::OUTPUT_VALUES)) {
continue;
}
if (added > 0)
r += ", ";
r += "{fd=" + format_signed_number(tmp[i].fd);
@ -176,7 +176,7 @@ read_pollfd(Context &context, void *data)
flags++;
}
}
if (tmp[i].fd != -1 && context.GetContents(Context::OUTPUT_VALUES)) {
if (context.GetContents(Context::OUTPUT_VALUES)) {
r += ", revents=";
int flags = 0;
if ((tmp[i].revents & POLLIN) != 0) {

View File

@ -124,7 +124,7 @@ Key 0x3d = 0xd18b 0xd0ab 0x13 0xcf82 0xe28891 0xd0ab 0xd18b 0xcf82
Key 0x3e = 0xd0b2 0xd092 0x04 0xe28882 0xe28886 0xd092 0xd0b2 0xe28882 0xe28886
Key 0x3f = 0xd0b0 0xd090 0x06 0xc2a3 '' 0xd090 0xd0b0 0xc2a3 ''
Key 0x40 = 0xd0bf 0xd09f 0x07 0xe282b4 ' ' 0xd09f 0xd0bf 0xe282b4 ' '
Key 0x41 = 0xd180 0xd0a0 0x08 0xd0a0 ' ' 0xe282bd 0xe282bd 0xd0a0 ' '
Key 0x41 = 0xd180 0xd0a0 0x08 0xe282bd ' ' 0xd0a0 0xe282bd 0xd0a0 ' '
Key 0x42 = 0xd0be 0xd09e 0x0a 0xe2809e ' ' 0xd09e 0xd0be 0xe2809e ' '
Key 0x43 = 0xd0bb 0xd09b 0x0b 0xe2809d ' ' 0xd09b 0xd0bb 0xe2809d ' '
Key 0x44 = 0xd0b4 0xd094 0x0c 0xe2809c 0xe28c80 0xd094 0xd0b4 0xe2809c 0xe28c80

View File

@ -157,8 +157,9 @@ ConditionVariableEntry::_RemoveFromVariable()
int32 tries = 0;
while (atomic_pointer_get(&fVariable) != NULL) {
tries++;
if ((tries % 100000) == 0)
if ((tries % 10000) == 0)
panic("variable pointer was not unset for a long time!");
cpu_pause();
}
return;
@ -396,6 +397,7 @@ ConditionVariable::_NotifyLocked(bool all, status_t result)
tries++;
if ((tries % 10000) == 0)
panic("entries count was not decremented for a long time!");
cpu_pause();
}
} else {
status_t waitStatus = atomic_get_and_set(&entry->fWaitStatus, result);