Compare commits
8 Commits
master
...
cf60bfdbc0
Author | SHA1 | Date |
---|---|---|
Pascal Abresch | cf60bfdbc0 | |
Pascal Abresch | aff45ca380 | |
Alexander von Gluck IV | 65ed50c713 | |
Lt-Henry | 6a9aea9dfd | |
Alex Hitech | 370623a923 | |
Augustin Cavalier | e0842c10af | |
Jérôme Duval | 101dc0ba83 | |
Jérôme Duval | 3285dcae22 |
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#define DRIVER_NAME "i2c_hid"
|
||||
#define DEVICE_PATH_SUFFIX "i2c"
|
||||
|
||||
#define DEVICE_NAME "I2C"
|
||||
|
||||
extern DeviceList *gDeviceList;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue