From f2de125b8c695e86bd3e896167553083b61e0908 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Tue, 11 Aug 2015 23:23:42 +0200 Subject: [PATCH 001/125] Removed code path for be_control_look == NULL. Adjusted TODO comment. --- src/kits/interface/MenuWindow.cpp | 39 +++++++++---------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/kits/interface/MenuWindow.cpp b/src/kits/interface/MenuWindow.cpp index 9523f67178..42889a9be6 100644 --- a/src/kits/interface/MenuWindow.cpp +++ b/src/kits/interface/MenuWindow.cpp @@ -203,23 +203,18 @@ void BMenuFrame::Draw(BRect updateRect) { if (fMenu != NULL && fMenu->CountItems() == 0) { - if (be_control_look != NULL) { - BRect rect(Bounds()); - be_control_look->DrawMenuBackground(this, rect, updateRect, - ui_color(B_MENU_BACKGROUND_COLOR)); - SetDrawingMode(B_OP_OVER); - } else { - // TODO: Review this as it's a bit hacky. - // Menu has a size of 0, 0, since there are no items in it. - // So the BMenuFrame class has to fake it and draw an empty item. - // Note that we can't add a real "empty" item because then we - // couldn't tell if the item was added by us or not. - // See also BMenu::UpdateWindowViewSize() - SetHighColor(ui_color(B_MENU_BACKGROUND_COLOR)); - SetLowColor(HighColor()); - FillRect(updateRect); - } + BRect rect(Bounds()); + be_control_look->DrawMenuBackground(this, rect, updateRect, + ui_color(B_MENU_BACKGROUND_COLOR)); + SetDrawingMode(B_OP_OVER); + // TODO: Review this as it's a bit hacky. + // Since there are no items in this menu, its size is 0x0. + // To show an empty BMenu, we use BMenuFrame to draw an empty item. + // It would be nice to simply add a real "empty" item, but in that case + // we couldn't tell if the item was added by us or not, and applications + // could break (because CountItems() would return 1 for an empty BMenu). + // See also BMenu::UpdateWindowViewSize() font_height height; GetFontHeight(&height); SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), @@ -229,18 +224,6 @@ BMenuFrame::Draw(BRect updateRect) ceilf(height.ascent + 1)); DrawString(kEmptyMenuLabel, where); } - - if (be_control_look != NULL) - return; - - SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), - B_DARKEN_2_TINT)); - BRect bounds(Bounds()); - - StrokeLine(BPoint(bounds.right, bounds.top), - BPoint(bounds.right, bounds.bottom - 1)); - StrokeLine(BPoint(bounds.left + 1, bounds.bottom), - BPoint(bounds.right, bounds.bottom)); } From a48ef9e817eccd46437c6748246623ea5cb44e84 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Wed, 12 Aug 2015 00:40:06 +0200 Subject: [PATCH 002/125] AppServer: check for NULL bitmap. Consistently check for NULL the ServerBitmap pointer. There seems to be cases where BView::DragMessage could pass an invalid Bitmap token to app_server. Maybe it's when a client only bitmap is passed, I don't know. Anyway, this is defensive programming, and at least we check for NULL consistently now. This fixes #11681. Note that SuperFreeCell still crashes, but at least app_server doesn't crash. --- src/servers/app/EventDispatcher.cpp | 3 ++- src/servers/app/ServerWindow.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/servers/app/EventDispatcher.cpp b/src/servers/app/EventDispatcher.cpp index b45f3c9298..9c8fb902f6 100644 --- a/src/servers/app/EventDispatcher.cpp +++ b/src/servers/app/EventDispatcher.cpp @@ -612,7 +612,8 @@ EventDispatcher::SetDragMessage(BMessage& message, if (fLastButtons == 0) { // mouse buttons has already been released or was never pressed - bitmap->ReleaseReference(); + if (bitmap != NULL) + bitmap->ReleaseReference(); return; } diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 242438faf2..fef86d05c6 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -2074,7 +2074,8 @@ fDesktop->UnlockSingleWindow(); fDesktop->EventDispatcher().SetDragMessage(dragMessage, bitmap, offset); fDesktop->LockSingleWindow(); - bitmap->ReleaseReference(); + if (bitmap != NULL) + bitmap->ReleaseReference(); } delete[] buffer; } From ff8c8dfc1754572d9185e04721c86b2ec701e068 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Wed, 12 Aug 2015 15:22:42 +0200 Subject: [PATCH 003/125] Improve patch in ticket #9377 Instead of locking the interface lock, set it busy and then unlock the interface list lock. --- .../kernel/network/stack/interfaces.cpp | 43 +++++++++++++------ src/add-ons/kernel/network/stack/interfaces.h | 4 ++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/add-ons/kernel/network/stack/interfaces.cpp b/src/add-ons/kernel/network/stack/interfaces.cpp index 20b4110ebd..0a6bebd8bb 100644 --- a/src/add-ons/kernel/network/stack/interfaces.cpp +++ b/src/add-ons/kernel/network/stack/interfaces.cpp @@ -445,6 +445,8 @@ InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain) Interface::Interface(const char* interfaceName, net_device_interface* deviceInterface) + : + fBusy(false) { TRACE("Interface %p: new \"%s\", device interface %p\n", this, interfaceName, deviceInterface); @@ -933,13 +935,13 @@ Interface::SetDown() if ((flags & IFF_UP) == 0) return; - // TODO: We acquire also the net_interfaces lock here - // to avoid a lock inversion in the ipv6 protocol implementation - // (see ticket #9377). - // A better solution would be to avoid locking the interface lock (fLock) - // when calling the lower layers. - RecursiveLocker interfacesLocker(sLock); - RecursiveLocker locker(fLock); + RecursiveLocker interfacesLock(sLock); + + if (IsBusy()) + return; + + SetBusy(true); + interfacesLock.Unlock(); DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); while (domain_datalink* datalink = iterator.Next()) { @@ -947,6 +949,8 @@ Interface::SetDown() } flags &= ~IFF_UP; + + SetBusy(false); } @@ -1076,10 +1080,11 @@ Interface::_SetUp() if (status != B_OK) return status; + RecursiveLocker interfacesLocker(sLock); + SetBusy(true); + interfacesLocker.Unlock(); + // Propagate flag to all datalink protocols - - RecursiveLocker locker(fLock); - DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); while (domain_datalink* datalink = iterator.Next()) { status = datalink->first_info->interface_up(datalink->first_protocol); @@ -1097,6 +1102,7 @@ Interface::_SetUp() } down_device_interface(fDeviceInterface); + SetBusy(false); return status; } } @@ -1109,6 +1115,8 @@ Interface::_SetUp() } flags |= IFF_UP; + SetBusy(false); + return B_OK; } @@ -1409,7 +1417,7 @@ get_interface(net_domain* domain, uint32 index) interface = sInterfaces.First(); else interface = find_interface(index); - if (interface == NULL) + if (interface == NULL || interface->IsBusy()) return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) @@ -1426,7 +1434,7 @@ get_interface(net_domain* domain, const char* name) RecursiveLocker locker(sLock); Interface* interface = find_interface(name); - if (interface == NULL) + if (interface == NULL || interface->IsBusy()) return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) @@ -1445,6 +1453,8 @@ get_interface_for_device(net_domain* domain, uint32 index) InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { if (interface->device->index == index) { + if (interface->IsBusy()) + return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; @@ -1470,6 +1480,8 @@ get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { + if (interface->IsBusy()) + continue; // Test if the hardware address matches, or if the given interface // matches, or if at least the index matches. if ((linkAddress.sdl_alen == interface->device->address.length @@ -1479,6 +1491,8 @@ get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 && linkAddress.sdl_index == interface->index)) { + if (interface->IsBusy()) + return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; @@ -1516,6 +1530,9 @@ get_interface_address_for_destination(net_domain* domain, InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { + if (interface->IsBusy()) + continue; + InterfaceAddress* address = interface->AddressForDestination(domain, destination); if (address != NULL) @@ -1543,6 +1560,8 @@ get_interface_address_for_link(net_domain* domain, const sockaddr* address, InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { + if (interface->IsBusy()) + continue; // Test if the hardware address matches, or if the given interface // matches, or if at least the index matches. if (linkAddress.sdl_alen == interface->device->address.length diff --git a/src/add-ons/kernel/network/stack/interfaces.h b/src/add-ons/kernel/network/stack/interfaces.h index f7bc63b21e..9c0cb63e27 100644 --- a/src/add-ons/kernel/network/stack/interfaces.h +++ b/src/add-ons/kernel/network/stack/interfaces.h @@ -152,6 +152,9 @@ public: domain_datalink* DomainDatalink(net_domain* domain) { return DomainDatalink(domain->family); } + inline void SetBusy(bool busy) { atomic_set(&fBusy, busy ? 1 : 0); }; + inline bool IsBusy() const { return atomic_get((int32*)&fBusy) == 1 ;}; + #if ENABLE_DEBUGGER_COMMANDS void Dump() const; #endif @@ -166,6 +169,7 @@ private: private: recursive_lock fLock; + int32 fBusy; net_device_interface* fDeviceInterface; AddressList fAddresses; DatalinkTable fDatalinkTable; From 0a02f8c287980b82a2ea49cdb28ea586d1667ccc Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Wed, 12 Aug 2015 18:08:32 +0200 Subject: [PATCH 004/125] LaunchDaemon: use setenv to set HOME env variable. * The API is saner: no need to build a string with var=value * It is safer: putenv requires the string passed to it to stay allocated, although most implementations (Haiku, Linux, BSD, OSX) do not follow POSIX on this, * Fix a problem reported in #12298 comments because the variable was set with extra quotes (putenv does not escape them), leading to Qupzilla not finding the home dir. --- src/servers/launch/LaunchDaemon.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index 93fbaac5dd..ef1f295c6b 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -1216,9 +1216,7 @@ LaunchDaemon::_StartSession(const char* login) exit(EXIT_FAILURE); if (passwd->pw_dir != NULL && passwd->pw_dir[0] != '\0') { - BString home="HOME=\""; - home << passwd->pw_dir << "\""; - putenv(home.String()); + setenv("HOME", passwd->pw_dir, true); if (chdir(passwd->pw_dir) != 0) { debug_printf("Could not switch to home dir %s: %s\n", From 9a900002db6813fdfdb31e491b0d51ec415083f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 13 Aug 2015 18:30:06 +0200 Subject: [PATCH 005/125] Updated cmake, curl and yasm packages. --- build/jam/repositories/HaikuPorts/x86 | 12 ++++++------ build/jam/repositories/HaikuPorts/x86_64 | 8 ++++---- build/jam/repositories/HaikuPorts/x86_gcc2 | 12 ++++++------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86 b/build/jam/repositories/HaikuPorts/x86 index cd30088f69..1a474803bb 100644 --- a/build/jam/repositories/HaikuPorts/x86 +++ b/build/jam/repositories/HaikuPorts/x86 @@ -37,12 +37,12 @@ RemotePackageRepository HaikuPorts clang-3.4-3 clang_analysis-3.4-3 clipdinger-0.4-1 - cmake-3.0.0_rc3-1 + cmake-3.3.0-1 coreutils-8.24-1 cpio-2.10-1 ctags-5.8-3 - curl-7.43.0-1 - curl_devel-7.43.0-1 + curl-7.44.0-1 + curl_devel-7.44.0-1 cvs-1.12.13.1-6 cvsps-2.2b1-1 diffutils-3.3-2 @@ -236,7 +236,7 @@ RemotePackageRepository HaikuPorts xml_parser-2.36-1 xz_utils-5.0.8-2 xz_utils_devel-5.0.8-2 - yasm-1.2.0-3 + yasm-1.3.0-1 zip-3.0-2 zlib-1.2.8-4 zlib_devel-1.2.8-4 @@ -245,8 +245,8 @@ RemotePackageRepository HaikuPorts binutils_x86_gcc2-2.17_2013_04_21-2 bzip2_x86_gcc2-1.0.6-5 bzip2_x86_gcc2_devel-1.0.6-5 - curl_x86_gcc2-7.43.0-1 - curl_x86_gcc2_devel-7.43.0-1 + curl_x86_gcc2-7.44.0-1 + curl_x86_gcc2_devel-7.44.0-1 expat_x86_gcc2-2.1.0-1 expat_x86_gcc2_devel-2.1.0-1 ffmpeg_x86_gcc2-0.10.2-4 diff --git a/build/jam/repositories/HaikuPorts/x86_64 b/build/jam/repositories/HaikuPorts/x86_64 index d299f495d3..6dd808a109 100644 --- a/build/jam/repositories/HaikuPorts/x86_64 +++ b/build/jam/repositories/HaikuPorts/x86_64 @@ -59,13 +59,13 @@ RemotePackageRepository HaikuPorts clang-3.5.1-1 clang_analysis-3.5.1-1 clipdinger-0.4-1 - cmake-3.2.3-1 + cmake-3.3.0-1 coreutils-8.24-1 cppunit-1.12.1-2 cppunit_devel-1.12.1-2 ctags-5.8-3 - curl-7.43.0-1 - curl_devel-7.43.0-1 + curl-7.44.0-1 + curl_devel-7.44.0-1 cvs-1.12.13.1-6 diffutils-3.3-2 dos2unix-7.2.2-1 @@ -318,7 +318,7 @@ RemotePackageRepository HaikuPorts x264_devel-20140308-1 xz_utils-5.0.8-2 xz_utils_devel-5.0.8-2 - yasm-1.2.0-3 + yasm-1.3.0-1 zip-3.0-2 zlib-1.2.8-4 zlib_devel-1.2.8-4 diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index bd7bd5789b..22b67d78c3 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -79,8 +79,8 @@ RemotePackageRepository HaikuPorts ctags-5.8-3 colors-2.3-1 coreutils-8.24-1 - curl-7.43.0-1 - curl_devel-7.43.0-1 + curl-7.44.0-1 + curl_devel-7.44.0-1 cvs-1.12.13.1-6 d52-3.4.1-1 desknotes-1.1-4 @@ -499,7 +499,7 @@ RemotePackageRepository HaikuPorts xrick-021212-2 yab-1.7.5-2 yab_ide-2.2.5-1 - yasm-1.2.0-3 + yasm-1.3.0-1 zip-3.0-2 zlib-1.2.8-4 zlib_devel-1.2.8-4 @@ -549,12 +549,12 @@ RemotePackageRepository HaikuPorts bzip2_x86_devel-1.0.6-5 capstone_x86-3.0.4-1 capstone_x86_devel-3.0.4-1 - cmake_x86-3.2.3-1 + cmake_x86-3.3.0-1 confuse_x86-2.7-2 confuse_x86_devel-2.7-2 copynametoclipboard-1.0.1-2 - curl_x86-7.43.0-1 - curl_x86_devel-7.43.0-1 + curl_x86-7.44.0-1 + curl_x86_devel-7.44.0-1 cvsps_x86-2.2b1-1 dbus_x86-1.8.6-1 dbus_x86_devel-1.8.6-1 From 827cdc0134902d5ce6f59d9aa0ecf5e7804a849a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 13 Aug 2015 18:58:35 +0200 Subject: [PATCH 006/125] ftp: declares header dependencies on libedit. --- src/bin/network/ftp/Jamfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/bin/network/ftp/Jamfile b/src/bin/network/ftp/Jamfile index 097fa70772..2c7c6396c6 100644 --- a/src/bin/network/ftp/Jamfile +++ b/src/bin/network/ftp/Jamfile @@ -13,7 +13,7 @@ SubDirCcFlags [ FDefines _BSD_SOURCE=1 ] ; UseBuildFeatureHeaders libedit ; -BinCommand ftp : +local ftp_src = cmds.c cmdtab.c complete.c @@ -24,6 +24,13 @@ BinCommand ftp : progressbar.c ruserpass.c util.c +; +Includes [ FGristFiles $(ftp_src) ] + : [ BuildFeatureAttribute libedit : headers ] ; + + +BinCommand ftp : + $(ftp_src) : [ BuildFeatureAttribute libedit : library ] [ BuildFeatureAttribute ncurses : library ] From 749241987723489674e347d8bed25730d43d29a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 13 Aug 2015 20:15:36 +0200 Subject: [PATCH 007/125] Updated tcpdump and libpcap packages. --- build/jam/repositories/HaikuPorts/x86 | 6 +++--- build/jam/repositories/HaikuPorts/x86_64 | 6 +++--- build/jam/repositories/HaikuPorts/x86_gcc2 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86 b/build/jam/repositories/HaikuPorts/x86 index 1a474803bb..73e98ef6f8 100644 --- a/build/jam/repositories/HaikuPorts/x86 +++ b/build/jam/repositories/HaikuPorts/x86 @@ -124,8 +124,8 @@ RemotePackageRepository HaikuPorts liblayout_devel-1.4.2-1 libogg-1.3.0-2 libogg_devel-1.3.0-2 - libpcap-1.7.3-1 - libpcap_devel-1.7.3-1 + libpcap-1.7.4-1 + libpcap_devel-1.7.4-1 libpcre-8.21-5 libpcre_devel-8.21-5 libpng-1.5.22-1 @@ -218,7 +218,7 @@ RemotePackageRepository HaikuPorts subversion-1.6.18-6 subversion_devel-1.6.18-6 tar-1.27.1-2 - tcpdump-4.7.4-1 + tcpdump-4.7.4-2 texinfo-4.13a-7 tiff-3.9.6-2 tiff_devel-3.9.6-2 diff --git a/build/jam/repositories/HaikuPorts/x86_64 b/build/jam/repositories/HaikuPorts/x86_64 index 6dd808a109..abe11d4d58 100644 --- a/build/jam/repositories/HaikuPorts/x86_64 +++ b/build/jam/repositories/HaikuPorts/x86_64 @@ -185,8 +185,8 @@ RemotePackageRepository HaikuPorts libmpeg2_devel-0.5.1-3 libogg-1.3.0-2 libogg_devel-1.3.0-2 - libpcap-1.7.3-1 - libpcap_devel-1.7.3-1 + libpcap-1.7.4-1 + libpcap_devel-1.7.4-1 libpcre-8.21-5 libpcre_devel-8.21-5 libpng-1.5.22-1 @@ -298,7 +298,7 @@ RemotePackageRepository HaikuPorts subversion-1.8.11-1 subversion_devel-1.8.11-1 tar-1.27.1-2 - tcpdump-4.7.4-1 + tcpdump-4.7.4-2 texinfo-4.13a-7 tiff-3.9.6-2 tiff_devel-3.9.6-2 diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 22b67d78c3..0db88ec5fa 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -260,8 +260,8 @@ RemotePackageRepository HaikuPorts libogg_devel-1.3.0-2 libpaper-1.1.24-1 libpaper_devel-1.1.24-1 - libpcap-1.7.3-1 - libpcap_devel-1.7.3-1 + libpcap-1.7.4-1 + libpcap_devel-1.7.4-1 libpcre-8.21-5 libpcre_devel-8.21-5 libpng-1.5.22-1 @@ -464,7 +464,7 @@ RemotePackageRepository HaikuPorts tar-1.26-6 tcl-8.5.18-1 tcl_devel-8.5.18-1 - tcpdump-4.7.4-1 + tcpdump-4.7.4-2 texinfo-4.13a-7 tiff-3.9.6-2 tiff_devel-3.9.6-2 From f474606ee92a7afddb5b3b6350a97ffd31e22c42 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 12 Aug 2015 20:53:59 +0200 Subject: [PATCH 008/125] libroot_debug: Merge guarded heap into libroot_debug. The individual debug heap implementations are now exposed via a structure of function pointers and a common frontend dispatches the malloc and malloc_debug APIs through them. The MALLOC_DEBUG environment variable can be used to select the guarded heap by adding 'g', otherwise the debug heap is used as the default. Consequently the separate libroot_guarded is not needed anymore and has been removed. To allow the use of environment variables this early, init_env_post_heap has been added and the heap dependent atfork() moved there. This allowed to fold the code of init_heap_post_env into init_heap so the former has been removed. --- build/jam/packages/HaikuDevel | 1 - headers/private/libroot/libroot_private.h | 2 +- src/bin/leak_analyser.sh | 2 +- src/system/libroot/Jamfile | 26 -- src/system/libroot/libroot_init.c | 4 +- .../libroot/posix/malloc/arch-specific.cpp | 7 - src/system/libroot/posix/malloc_debug/Jamfile | 5 +- .../posix/malloc_debug/guarded_heap.cpp | 191 ++++-------- .../libroot/posix/malloc_debug/heap.cpp | 211 +++++-------- .../posix/malloc_debug/malloc_debug_api.cpp | 283 ++++++++++++++++++ .../posix/malloc_debug/malloc_debug_api.h | 57 ++++ src/system/libroot/posix/stdlib/env.cpp | 5 + src/system/libroot/stubbed/libroot_stubs.c | 2 +- .../libroot/stubbed/libroot_stubs_legacy.c | 2 +- 14 files changed, 477 insertions(+), 321 deletions(-) create mode 100644 src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp create mode 100644 src/system/libroot/posix/malloc_debug/malloc_debug_api.h diff --git a/build/jam/packages/HaikuDevel b/build/jam/packages/HaikuDevel index b18f7d8b0a..de160cdb6f 100644 --- a/build/jam/packages/HaikuDevel +++ b/build/jam/packages/HaikuDevel @@ -21,7 +21,6 @@ AddFilesToPackage develop lib : kernel.so : _KERNEL_ ; # additional libraries local developmentLibs = libroot_debug.so - libroot_guarded.so ; AddFilesToPackage lib : $(developmentLibs) ; diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h index 1d5fad3045..d0676a63ed 100644 --- a/headers/private/libroot/libroot_private.h +++ b/headers/private/libroot/libroot_private.h @@ -33,8 +33,8 @@ status_t __flatten_process_args(const char* const* args, int32 argCount, char*** _flatArgs, size_t* _flatSize); void _call_atexit_hooks_for_range(addr_t start, addr_t size); void __init_env(const struct user_space_program_args *args); +void __init_env_post_heap(void); status_t __init_heap(void); -void __init_heap_post_env(void); void __heap_terminate_after(void); void __init_time(addr_t commPageTable); diff --git a/src/bin/leak_analyser.sh b/src/bin/leak_analyser.sh index 222388ee02..66c6880ae0 100755 --- a/src/bin/leak_analyser.sh +++ b/src/bin/leak_analyser.sh @@ -14,7 +14,7 @@ then To generate such a file run a program with the following environment variables prefixed and pipe the output to a file: - LD_PRELOAD=libroot_guarded.so MALLOC_DEBUG=es50 program > file + LD_PRELOAD=libroot_debug.so MALLOC_DEBUG=ges50 program > file The number after the "s" is the stack trace depth. Note that there is an implementation defined maximum. diff --git a/src/system/libroot/Jamfile b/src/system/libroot/Jamfile index 1b29fb53c7..b9d962207f 100644 --- a/src/system/libroot/Jamfile +++ b/src/system/libroot/Jamfile @@ -63,11 +63,6 @@ for architectureObject in [ MultiArchSubDirSetup ] { ; librootDebugObjects = $(librootDebugObjects:G=$(architecture)) ; - local librootGuardedObjects = - posix_malloc_guarded.o - ; - librootGuardedObjects = $(librootGuardedObjects:G=$(architecture)) ; - local librootNoDebugObjects = posix_malloc.o ; @@ -75,15 +70,12 @@ for architectureObject in [ MultiArchSubDirSetup ] { local libroot = [ MultiArchDefaultGristFiles libroot.so ] ; local librootDebug = $(libroot:B=libroot_debug) ; - local librootGuarded = $(libroot:B=libroot_guarded) ; DONT_LINK_AGAINST_LIBROOT on $(libroot) = true ; DONT_LINK_AGAINST_LIBROOT on $(librootDebug) = true ; - DONT_LINK_AGAINST_LIBROOT on $(librootGuarded) = true ; SetVersionScript $(libroot) : libroot_versions ; SetVersionScript $(librootDebug) : libroot_versions ; - SetVersionScript $(librootGuarded) : libroot_versions ; SharedLibrary $(libroot) : @@ -109,18 +101,6 @@ for architectureObject in [ MultiArchSubDirSetup ] { [ TargetLibgcc ] ; - HAIKU_SONAME on $(librootGuarded) = libroot.so ; - - SharedLibrary $(librootGuarded) - : - libroot_init.c - : - $(librootObjects) - $(librootGuardedObjects) - [ TargetStaticLibsupc++ ] - [ TargetLibgcc ] - ; - # Copy libroot.so and update the copy's revision section. We link # everything against the original, but the copy will end up on the disk # image (this way we avoid unnecessary dependencies). The copy will be @@ -132,18 +112,12 @@ for architectureObject in [ MultiArchSubDirSetup ] { libroot.so : revisioned ] ; local revisionedLibrootDebug = $(librootDebug:G=$(revisionedLibroot:G)) ; - local revisionedLibrootGuarded - = $(librootGuarded:G=$(revisionedLibroot:G)) ; MakeLocate $(revisionedLibroot) : $(targetDir) ; CopySetHaikuRevision $(revisionedLibroot) : $(libroot) ; MakeLocate $(revisionedLibrootDebug) : $(targetDir) ; CopySetHaikuRevision $(revisionedLibrootDebug) : $(librootDebug) ; - - MakeLocate $(revisionedLibrootGuarded) : $(targetDir) ; - CopySetHaikuRevision $(revisionedLibrootGuarded) - : $(librootGuarded) ; } } } diff --git a/src/system/libroot/libroot_init.c b/src/system/libroot/libroot_init.c index 03cb17f70d..893833eea7 100644 --- a/src/system/libroot/libroot_init.c +++ b/src/system/libroot/libroot_init.c @@ -77,9 +77,9 @@ initialize_before(image_id imageID) __gCPUCount = info.cpu_count; __init_time((addr_t)__gCommPageAddress); - __init_heap(); __init_env(__gRuntimeLoader->program_args); - __init_heap_post_env(); + __init_heap(); + __init_env_post_heap(); __init_pwd_backend(); __set_stack_protection(); } diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp index d2c25b8f5e..872867c38c 100644 --- a/src/system/libroot/posix/malloc/arch-specific.cpp +++ b/src/system/libroot/posix/malloc/arch-specific.cpp @@ -124,13 +124,6 @@ __init_heap(void) } -extern "C" void -__init_heap_post_env(void) -{ - // no heap options available -} - - extern "C" void __heap_terminate_after() { diff --git a/src/system/libroot/posix/malloc_debug/Jamfile b/src/system/libroot/posix/malloc_debug/Jamfile index 98d3b0bc58..0a2213d12f 100644 --- a/src/system/libroot/posix/malloc_debug/Jamfile +++ b/src/system/libroot/posix/malloc_debug/Jamfile @@ -15,10 +15,9 @@ for architectureObject in [ MultiArchSubDirSetup ] { MergeObject <$(architecture)>posix_malloc_debug.o : heap.cpp - ; - - MergeObject <$(architecture)>posix_malloc_guarded.o : guarded_heap.cpp + + malloc_debug_api.cpp ; } } diff --git a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp index bc5e17a429..f8d2c7c27a 100644 --- a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp +++ b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp @@ -3,6 +3,8 @@ * Distributed under the terms of the MIT License. */ +#include "malloc_debug_api.h" + #include #include @@ -985,68 +987,36 @@ dump_allocations_full() // #pragma mark - Heap Debug API -extern "C" status_t -heap_debug_start_wall_checking(int msInterval) -{ - return B_NOT_SUPPORTED; -} - - -extern "C" status_t -heap_debug_stop_wall_checking() -{ - return B_NOT_SUPPORTED; -} - - -extern "C" void -heap_debug_set_paranoid_validation(bool enabled) -{ -} - - -extern "C" void -heap_debug_set_memory_reuse(bool enabled) +static void +guarded_heap_set_memory_reuse(bool enabled) { sGuardedHeap.reuse_memory = enabled; } -extern "C" void -heap_debug_set_debugger_calls(bool enabled) +static void +guarded_heap_set_debugger_calls(bool enabled) { sDebuggerCalls = enabled; } -extern "C" void -heap_debug_set_default_alignment(size_t defaultAlignment) +static void +guarded_heap_set_default_alignment(size_t defaultAlignment) { sDefaultAlignment = defaultAlignment; } -extern "C" void -heap_debug_validate_heaps() -{ -} - - -extern "C" void -heap_debug_validate_walls() -{ -} - - -extern "C" void -heap_debug_dump_allocations(bool statsOnly, thread_id thread) +static void +guarded_heap_dump_allocations(bool statsOnly, thread_id thread) { dump_allocations(sGuardedHeap, statsOnly, thread); } -extern "C" void -heap_debug_dump_heaps(bool dumpAreas, bool dumpBins) +static void +guarded_heap_dump_heaps(bool dumpAreas, bool dumpBins) { WriteLocker heapLocker(sGuardedHeap.lock); dump_guarded_heap(sGuardedHeap); @@ -1070,31 +1040,16 @@ heap_debug_dump_heaps(bool dumpAreas, bool dumpBins) } -extern "C" void * -heap_debug_malloc_with_guard_page(size_t size) -{ - return malloc(size); -} - - -extern "C" status_t -heap_debug_get_allocation_info(void *address, size_t *size, - thread_id *thread) -{ - return B_NOT_SUPPORTED; -} - - -extern "C" status_t -heap_debug_dump_allocations_on_exit(bool enabled) +static status_t +guarded_heap_set_dump_allocations_on_exit(bool enabled) { sDumpAllocationsOnExit = enabled; return B_OK; } -extern "C" status_t -heap_debug_set_stack_trace_depth(size_t stackTraceDepth) +static status_t +guarded_heap_set_stack_trace_depth(size_t stackTraceDepth) { if (stackTraceDepth == 0) { sStackTraceDepth = 0; @@ -1139,8 +1094,8 @@ init_after_fork() } -extern "C" status_t -__init_heap(void) +static status_t +guarded_heap_init(void) { if (!guarded_heap_area_create(sGuardedHeap, GUARDED_HEAP_INITIAL_SIZE)) return B_ERROR; @@ -1164,35 +1119,8 @@ __init_heap(void) } -extern "C" void -__init_heap_post_env(void) -{ - const char *mode = getenv("MALLOC_DEBUG"); - if (mode != NULL) { - if (strchr(mode, 'r')) - heap_debug_set_memory_reuse(false); - if (strchr(mode, 'e')) - heap_debug_dump_allocations_on_exit(true); - - size_t defaultAlignment = 0; - const char *argument = strchr(mode, 'a'); - if (argument != NULL - && sscanf(argument, "a%" B_SCNuSIZE, &defaultAlignment) == 1) { - heap_debug_set_default_alignment(defaultAlignment); - } - - size_t stackTraceDepth = 0; - argument = strchr(mode, 's'); - if (argument != NULL - && sscanf(argument, "s%" B_SCNuSIZE, &stackTraceDepth) == 1) { - heap_debug_set_stack_trace_depth(stackTraceDepth); - } - } -} - - -extern "C" void -__heap_terminate_after() +static void +guarded_heap_terminate_after() { if (sDumpAllocationsOnExit) dump_allocations_full(); @@ -1202,17 +1130,8 @@ __heap_terminate_after() // #pragma mark - Public API -extern "C" void* -sbrk_hook(long) -{ - debug_printf("sbrk not supported on malloc debug\n"); - panic("sbrk not supported on malloc debug\n"); - return NULL; -} - - -extern "C" void* -memalign(size_t alignment, size_t size) +static void* +heap_memalign(size_t alignment, size_t size) { if (size == 0) size = 1; @@ -1221,23 +1140,23 @@ memalign(size_t alignment, size_t size) } -extern "C" void* -malloc(size_t size) +static void* +heap_malloc(size_t size) { - return memalign(sDefaultAlignment, size); + return heap_memalign(sDefaultAlignment, size); } -extern "C" void -free(void* address) +static void +heap_free(void* address) { if (!guarded_heap_free(address)) panic("free failed for address %p", address); } -extern "C" void* -realloc(void* address, size_t newSize) +static void* +heap_realloc(void* address, size_t newSize) { if (newSize == 0) { free(address); @@ -1245,40 +1164,42 @@ realloc(void* address, size_t newSize) } if (address == NULL) - return memalign(sDefaultAlignment, newSize); + return heap_memalign(sDefaultAlignment, newSize); return guarded_heap_realloc(address, newSize); } -extern "C" void* -calloc(size_t numElements, size_t size) -{ - void* address = malloc(numElements * size); - if (address != NULL) - memset(address, 0, numElements * size); +heap_implementation __mallocGuardedHeap = { + guarded_heap_init, + guarded_heap_terminate_after, - return address; -} + heap_memalign, + heap_malloc, + heap_free, + heap_realloc, + NULL, // calloc + NULL, // valloc + NULL, // posix_memalign -extern "C" void* -valloc(size_t size) -{ - return memalign(B_PAGE_SIZE, size); -} + NULL, // start_wall_checking + NULL, // stop_wall_checking + NULL, // set_paranoid_validation + guarded_heap_set_memory_reuse, + guarded_heap_set_debugger_calls, + guarded_heap_set_default_alignment, -extern "C" int -posix_memalign(void **pointer, size_t alignment, size_t size) -{ - // this cryptic line accepts zero and all powers of two - if (((~alignment + 1) | ((alignment << 1) - 1)) != ~0UL) - return EINVAL; + NULL, // validate_heaps + NULL, // validate_walls - *pointer = memalign(alignment, size); - if (*pointer == NULL) - return ENOMEM; + guarded_heap_dump_allocations, + guarded_heap_dump_heaps, + heap_malloc, - return 0; -} + NULL, // get_allocation_info + + guarded_heap_set_dump_allocations_on_exit, + guarded_heap_set_stack_trace_depth +}; diff --git a/src/system/libroot/posix/malloc_debug/heap.cpp b/src/system/libroot/posix/malloc_debug/heap.cpp index 10745f39d0..096fd699b2 100644 --- a/src/system/libroot/posix/malloc_debug/heap.cpp +++ b/src/system/libroot/posix/malloc_debug/heap.cpp @@ -10,8 +10,9 @@ */ +#include "malloc_debug_api.h" + #include -#include #include #include #include @@ -38,6 +39,9 @@ #define ASSERT(x) if (!(x)) panic("assert failed: %s", #x); +static void *debug_heap_memalign(size_t alignment, size_t size); + + static bool sDebuggerCalls = true; static bool sReuseMemory = true; static bool sParanoidValidation = false; @@ -773,7 +777,7 @@ heap_remove_area(heap_allocator *heap, heap_area *area) } -heap_allocator * +static heap_allocator * heap_create_allocator(const char *name, addr_t base, size_t size, const heap_class *heapClass) { @@ -1103,15 +1107,7 @@ heap_allocate_from_bin(heap_allocator *heap, uint32 binIndex, size_t size) } -static bool -is_valid_alignment(size_t number) -{ - // this cryptic line accepts zero and all powers of two - return ((~number + 1) | ((number << 1) - 1)) == ~0UL; -} - - -void * +static void * heap_memalign(heap_allocator *heap, size_t alignment, size_t size) { INFO(("memalign(alignment = %lu, size = %lu)\n", alignment, size)); @@ -1172,7 +1168,7 @@ heap_memalign(heap_allocator *heap, size_t alignment, size_t size) } -status_t +static status_t heap_free(heap_allocator *heap, void *address) { if (address == NULL) @@ -1473,7 +1469,7 @@ heap_realloc(heap_allocator *heap, void *address, void **newAddress, newSize -= sizeof(addr_t) + sizeof(heap_leak_check_info); // if not, allocate a new chunk of memory - *newAddress = memalign(sDefaultAlignment, newSize); + *newAddress = debug_heap_memalign(sDefaultAlignment, newSize); if (*newAddress == NULL) { // we tried but it didn't work out, but still the operation is done return B_OK; @@ -1643,8 +1639,8 @@ heap_wall_checker(void *data) // #pragma mark - Heap Debug API -extern "C" status_t -heap_debug_start_wall_checking(int msInterval) +static status_t +debug_heap_start_wall_checking(int msInterval) { if (sWallCheckThread < 0) { sWallCheckThread = spawn_thread(heap_wall_checker, "heap wall checker", @@ -1659,8 +1655,8 @@ heap_debug_start_wall_checking(int msInterval) } -extern "C" status_t -heap_debug_stop_wall_checking() +static status_t +debug_heap_stop_wall_checking() { int32 result; sStopWallChecking = true; @@ -1668,66 +1664,52 @@ heap_debug_stop_wall_checking() } -extern "C" void -heap_debug_set_paranoid_validation(bool enabled) +static void +debug_heap_set_paranoid_validation(bool enabled) { sParanoidValidation = enabled; } -extern "C" void -heap_debug_set_memory_reuse(bool enabled) +static void +debug_heap_set_memory_reuse(bool enabled) { sReuseMemory = enabled; } -extern "C" void -heap_debug_set_debugger_calls(bool enabled) +static void +debug_heap_set_debugger_calls(bool enabled) { sDebuggerCalls = enabled; } -extern "C" void -heap_debug_set_default_alignment(size_t defaultAlignment) +static void +debug_heap_set_default_alignment(size_t defaultAlignment) { sDefaultAlignment = defaultAlignment; } -extern "C" void -heap_debug_validate_heaps() +static void +debug_heap_validate_heaps() { for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++) heap_validate_heap(sHeaps[i]); } -extern "C" void -heap_debug_validate_walls() -{ - heap_validate_walls(); -} - - -extern "C" void -heap_debug_dump_allocations(bool statsOnly, thread_id thread) -{ - dump_allocations(statsOnly, thread); -} - - -extern "C" void -heap_debug_dump_heaps(bool dumpAreas, bool dumpBins) +static void +debug_heap_dump_heaps(bool dumpAreas, bool dumpBins) { for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++) dump_allocator(sHeaps[i], dumpAreas, dumpBins); } -extern "C" void * -heap_debug_malloc_with_guard_page(size_t size) +static void * +debug_heap_malloc_with_guard_page(size_t size) { size_t areaSize = ROUNDUP(size + sizeof(area_allocation_info) + B_PAGE_SIZE, B_PAGE_SIZE); @@ -1775,8 +1757,8 @@ heap_debug_malloc_with_guard_page(size_t size) } -extern "C" status_t -heap_debug_get_allocation_info(void *address, size_t *size, +static status_t +debug_heap_get_allocation_info(void *address, size_t *size, thread_id *thread) { for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++) { @@ -1807,25 +1789,11 @@ heap_debug_get_allocation_info(void *address, size_t *size, } -extern "C" status_t -heap_debug_dump_allocations_on_exit(bool enabled) -{ - return B_NOT_SUPPORTED; -} - - -extern "C" status_t -heap_debug_set_stack_trace_depth(size_t stackTraceDepth) -{ - return B_NOT_SUPPORTED; -} - - // #pragma mark - Init -extern "C" status_t -__init_heap(void) +static status_t +debug_heap_init(void) { // This will locate the heap base at 384 MB and reserve the next 1152 MB // for it. They may get reclaimed by other areas, though, but the maximum @@ -1853,53 +1821,11 @@ __init_heap(void) } -extern "C" void -__init_heap_post_env(void) -{ - const char *mode = getenv("MALLOC_DEBUG"); - if (mode != NULL) { - if (strchr(mode, 'p')) - heap_debug_set_paranoid_validation(true); - if (strchr(mode, 'w')) - heap_debug_start_wall_checking(500); - else if (strchr(mode, 'W')) - heap_debug_start_wall_checking(100); - if (strchr(mode, 'g')) - sUseGuardPage = true; - if (strchr(mode, 'r')) - heap_debug_set_memory_reuse(false); - - size_t defaultAlignment = 0; - const char *argument = strchr(mode, 'a'); - if (argument != NULL - && sscanf(argument, "a%" B_SCNuSIZE, &defaultAlignment) == 1) { - heap_debug_set_default_alignment(defaultAlignment); - } - } -} - - -extern "C" void -__heap_terminate_after() -{ - // nothing to do -} - - // #pragma mark - Public API -extern "C" void * -sbrk_hook(long) -{ - debug_printf("sbrk not supported on malloc debug\n"); - panic("sbrk not supported on malloc debug\n"); - return NULL; -} - - -void * -memalign(size_t alignment, size_t size) +static void * +debug_heap_memalign(size_t alignment, size_t size) { size_t alignedSize = size + sizeof(addr_t) + sizeof(heap_leak_check_info); if (alignment != 0 && alignment < B_PAGE_SIZE) @@ -1974,18 +1900,18 @@ memalign(size_t alignment, size_t size) } -void * -malloc(size_t size) +static void * +debug_heap_malloc(size_t size) { if (sUseGuardPage) - return heap_debug_malloc_with_guard_page(size); + return debug_heap_malloc_with_guard_page(size); - return memalign(sDefaultAlignment, size); + return debug_heap_memalign(sDefaultAlignment, size); } -void -free(void *address) +static void +debug_heap_free(void *address) { for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++) { heap_allocator *heap = sHeaps[i]; @@ -2017,11 +1943,11 @@ free(void *address) } -void * -realloc(void *address, size_t newSize) +static void * +debug_heap_realloc(void *address, size_t newSize) { if (address == NULL) - return memalign(sDefaultAlignment, newSize); + return debug_heap_memalign(sDefaultAlignment, newSize); if (newSize == 0) { free(address); @@ -2079,7 +2005,7 @@ realloc(void *address, size_t newSize) } // have to allocate/copy/free - TODO maybe resize the area instead? - newAddress = malloc(newSize); + newAddress = debug_heap_memalign(sDefaultAlignment, newSize); if (newAddress == NULL) { panic("realloc(): failed to allocate new block of %ld" " bytes\n", newSize); @@ -2100,33 +2026,32 @@ realloc(void *address, size_t newSize) } -void * -calloc(size_t numElements, size_t size) -{ - void *address = malloc(numElements * size); - if (address != NULL) - memset(address, 0, numElements * size); +heap_implementation __mallocDebugHeap = { + debug_heap_init, + NULL, // terminate_after - return address; -} + debug_heap_memalign, + debug_heap_malloc, + debug_heap_free, + debug_heap_realloc, + NULL, // calloc + NULL, // valloc + NULL, // posix_memalign -extern "C" void * -valloc(size_t size) -{ - return memalign(B_PAGE_SIZE, size); -} + debug_heap_start_wall_checking, + debug_heap_stop_wall_checking, + debug_heap_set_paranoid_validation, + debug_heap_set_memory_reuse, + debug_heap_set_debugger_calls, + debug_heap_set_default_alignment, + debug_heap_validate_heaps, + heap_validate_walls, + dump_allocations, + debug_heap_dump_heaps, + debug_heap_malloc_with_guard_page, + debug_heap_get_allocation_info, - -extern "C" int -posix_memalign(void **pointer, size_t alignment, size_t size) -{ - if (!is_valid_alignment(alignment)) - return EINVAL; - - *pointer = memalign(alignment, size); - if (*pointer == NULL) - return ENOMEM; - - return 0; -} + NULL, // set_dump_allocations_on_exit + NULL // set_stack_trace_depth +}; diff --git a/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp b/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp new file mode 100644 index 0000000000..45d3c1c6c3 --- /dev/null +++ b/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp @@ -0,0 +1,283 @@ +/* + * Copyright 2015, Michael Lotz . + * Distributed under the terms of the MIT License. + */ + + +#include "malloc_debug_api.h" + +#include +#include + +#include +#include + + +static heap_implementation* sCurrentHeap = NULL; + + +// #pragma mark - Heap Debug API + + +extern "C" status_t +heap_debug_start_wall_checking(int msInterval) +{ + if (sCurrentHeap->start_wall_checking != NULL) + return sCurrentHeap->start_wall_checking(msInterval); + + return B_NOT_SUPPORTED; +} + + +extern "C" status_t +heap_debug_stop_wall_checking() +{ + if (sCurrentHeap->stop_wall_checking != NULL) + return sCurrentHeap->stop_wall_checking(); + + return B_NOT_SUPPORTED; +} + + +extern "C" void +heap_debug_set_paranoid_validation(bool enabled) +{ + if (sCurrentHeap->set_paranoid_validation != NULL) + sCurrentHeap->set_paranoid_validation(enabled); +} + + +extern "C" void +heap_debug_set_memory_reuse(bool enabled) +{ + if (sCurrentHeap->set_memory_reuse != NULL) + sCurrentHeap->set_memory_reuse(enabled); +} + + +extern "C" void +heap_debug_set_debugger_calls(bool enabled) +{ + if (sCurrentHeap->set_debugger_calls != NULL) + sCurrentHeap->set_debugger_calls(enabled); +} + + +extern "C" void +heap_debug_set_default_alignment(size_t defaultAlignment) +{ + if (sCurrentHeap->set_default_alignment != NULL) + sCurrentHeap->set_default_alignment(defaultAlignment); +} + + +extern "C" void +heap_debug_validate_heaps() +{ + if (sCurrentHeap->validate_heaps != NULL) + sCurrentHeap->validate_heaps(); +} + + +extern "C" void +heap_debug_validate_walls() +{ + if (sCurrentHeap->validate_walls != NULL) + sCurrentHeap->validate_walls(); +} + + +extern "C" void +heap_debug_dump_allocations(bool statsOnly, thread_id thread) +{ + if (sCurrentHeap->dump_allocations != NULL) + sCurrentHeap->dump_allocations(statsOnly, thread); +} + + +extern "C" void +heap_debug_dump_heaps(bool dumpAreas, bool dumpBins) +{ + if (sCurrentHeap->dump_heaps != NULL) + sCurrentHeap->dump_heaps(dumpAreas, dumpBins); +} + + +extern "C" void * +heap_debug_malloc_with_guard_page(size_t size) +{ + if (sCurrentHeap->malloc_with_guard_page != NULL) + return sCurrentHeap->malloc_with_guard_page(size); + + return NULL; +} + + +extern "C" status_t +heap_debug_get_allocation_info(void *address, size_t *size, + thread_id *thread) +{ + if (sCurrentHeap->get_allocation_info != NULL) + return sCurrentHeap->get_allocation_info(address, size, thread); + + return B_NOT_SUPPORTED; +} + + +extern "C" status_t +heap_debug_set_dump_allocations_on_exit(bool enabled) +{ + if (sCurrentHeap->set_dump_allocations_on_exit != NULL) + return sCurrentHeap->set_dump_allocations_on_exit(enabled); + + return B_NOT_SUPPORTED; +} + + +extern "C" status_t +heap_debug_set_stack_trace_depth(size_t stackTraceDepth) +{ + if (sCurrentHeap->set_stack_trace_depth != NULL) + return sCurrentHeap->set_stack_trace_depth(stackTraceDepth); + + return B_NOT_SUPPORTED; +} + + +// #pragma mark - Init + + +extern "C" status_t +__init_heap(void) +{ + const char *mode = getenv("MALLOC_DEBUG"); + if (mode == NULL || strchr(mode, 'g') == NULL) + sCurrentHeap = &__mallocDebugHeap; + else + sCurrentHeap = &__mallocGuardedHeap; + + status_t result = sCurrentHeap->init(); + if (result != B_OK) + return result; + + if (mode != NULL) { + if (strchr(mode, 'p') != NULL) + heap_debug_set_paranoid_validation(true); + if (strchr(mode, 'r') != NULL) + heap_debug_set_memory_reuse(false); + if (strchr(mode, 'e') != NULL) + heap_debug_set_dump_allocations_on_exit(true); + + size_t defaultAlignment = 0; + const char *argument = strchr(mode, 'a'); + if (argument != NULL + && sscanf(argument, "a%" B_SCNuSIZE, &defaultAlignment) == 1) { + heap_debug_set_default_alignment(defaultAlignment); + } + + size_t stackTraceDepth = 0; + argument = strchr(mode, 's'); + if (argument != NULL + && sscanf(argument, "s%" B_SCNuSIZE, &stackTraceDepth) == 1) { + heap_debug_set_stack_trace_depth(stackTraceDepth); + } + + int wallCheckInterval = 0; + argument = strchr(mode, 'w'); + if (argument != NULL + && sscanf(argument, "w%d", &wallCheckInterval) == 1) { + heap_debug_start_wall_checking(wallCheckInterval); + } + } + + return B_OK; +} + + +extern "C" void +__heap_terminate_after() +{ + if (sCurrentHeap->terminate_after != NULL) + sCurrentHeap->terminate_after(); +} + + +// #pragma mark - Public API + + +extern "C" void* +sbrk_hook(long) +{ + debug_printf("sbrk not supported on malloc debug\n"); + debugger("sbrk not supported on malloc debug"); + return NULL; +} + + +extern "C" void* +memalign(size_t alignment, size_t size) +{ + return sCurrentHeap->memalign(alignment, size); +} + + +extern "C" void* +malloc(size_t size) +{ + return sCurrentHeap->malloc(size); +} + + +extern "C" void +free(void* address) +{ + sCurrentHeap->free(address); +} + + +extern "C" void* +realloc(void* address, size_t newSize) +{ + return sCurrentHeap->realloc(address, newSize); +} + + +extern "C" void* +calloc(size_t numElements, size_t size) +{ + if (sCurrentHeap->calloc != NULL) + return sCurrentHeap->calloc(numElements, size); + + void* address = malloc(numElements * size); + if (address != NULL) + memset(address, 0, numElements * size); + + return address; +} + + +extern "C" void* +valloc(size_t size) +{ + if (sCurrentHeap->valloc != NULL) + return sCurrentHeap->valloc(size); + + return memalign(B_PAGE_SIZE, size); +} + + +extern "C" int +posix_memalign(void **pointer, size_t alignment, size_t size) +{ + if (sCurrentHeap->posix_memalign != NULL) + return sCurrentHeap->posix_memalign(pointer, alignment, size); + + if (!is_valid_alignment(alignment)) + return EINVAL; + + *pointer = memalign(alignment, size); + if (*pointer == NULL) + return ENOMEM; + + return 0; +} diff --git a/src/system/libroot/posix/malloc_debug/malloc_debug_api.h b/src/system/libroot/posix/malloc_debug/malloc_debug_api.h new file mode 100644 index 0000000000..dc949a9dd9 --- /dev/null +++ b/src/system/libroot/posix/malloc_debug/malloc_debug_api.h @@ -0,0 +1,57 @@ +/* + * Copyright 2015, Michael Lotz . + * Distributed under the terms of the MIT License. + */ +#ifndef MALLOC_DEBUG_API_H +#define MALLOC_DEBUG_API_H + +#include + + +struct heap_implementation { + status_t (*init)(); + void (*terminate_after)(); + + // Mandatory hooks + void* (*memalign)(size_t alignment, size_t size); + void* (*malloc)(size_t size); + void (*free)(void* address); + void* (*realloc)(void* address, size_t newSize); + + // Hooks with default implementations + void* (*calloc)(size_t numElements, size_t size); + void* (*valloc)(size_t size); + int (*posix_memalign)(void** pointer, size_t alignment, + size_t size); + + // Heap Debug API + status_t (*start_wall_checking)(int msInterval); + status_t (*stop_wall_checking)(); + void (*set_paranoid_validation)(bool enabled); + void (*set_memory_reuse)(bool enabled); + void (*set_debugger_calls)(bool enabled); + void (*set_default_alignment)(size_t defaultAlignment); + void (*validate_heaps)(); + void (*validate_walls)(); + void (*dump_allocations)(bool statsOnly, thread_id thread); + void (*dump_heaps)(bool dumpAreas, bool dumpBins); + void* (*malloc_with_guard_page)(size_t size); + status_t (*get_allocation_info)(void* address, size_t *size, + thread_id *thread); + status_t (*set_dump_allocations_on_exit)(bool enabled); + status_t (*set_stack_trace_depth)(size_t stackTraceDepth); +}; + + +extern heap_implementation __mallocDebugHeap; +extern heap_implementation __mallocGuardedHeap; + + +static inline bool +is_valid_alignment(size_t number) +{ + // this cryptic line accepts zero and all powers of two + return ((~number + 1) | ((number << 1) - 1)) == ~0UL; +} + +#endif // MALLOC_DEBUG_API_H diff --git a/src/system/libroot/posix/stdlib/env.cpp b/src/system/libroot/posix/stdlib/env.cpp index 578a25506b..e811eeb6f5 100644 --- a/src/system/libroot/posix/stdlib/env.cpp +++ b/src/system/libroot/posix/stdlib/env.cpp @@ -205,7 +205,12 @@ __init_env(const struct user_space_program_args *args) // protect our implementation environ = args->env; sManagedEnviron = NULL; +} + +void +__init_env_post_heap() +{ atfork(environ_fork_hook); } diff --git a/src/system/libroot/stubbed/libroot_stubs.c b/src/system/libroot/stubbed/libroot_stubs.c index 961185532f..cd8ff77e4c 100644 --- a/src/system/libroot/stubbed/libroot_stubs.c +++ b/src/system/libroot/stubbed/libroot_stubs.c @@ -892,8 +892,8 @@ void __ilogb() {} void __ilogbf() {} void __ilogbl() {} void __init_env() {} +void __init_env_post_heap() {} void __init_heap() {} -void __init_heap_post_env() {} void __init_once() {} void __init_pthread() {} void __init_pwd_backend() {} diff --git a/src/system/libroot/stubbed/libroot_stubs_legacy.c b/src/system/libroot/stubbed/libroot_stubs_legacy.c index 2d72b862d0..855c3bbad2 100644 --- a/src/system/libroot/stubbed/libroot_stubs_legacy.c +++ b/src/system/libroot/stubbed/libroot_stubs_legacy.c @@ -726,8 +726,8 @@ void __ilogb() {} void __ilogbf() {} void __ilogbl() {} void __init_env() {} +void __init_env_post_heap() {} void __init_heap() {} -void __init_heap_post_env() {} void __init_once() {} void __init_pthread() {} void __init_pwd_backend() {} From 8fa441bf5c9a995d3a66da8eb55d244f4b6c7bbd Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Thu, 13 Aug 2015 21:02:09 +0200 Subject: [PATCH 009/125] libroot_debug: Revert to a legacy default alignment of 8. This reverts the legacy default alignment (in absence of max_align_t) to 8, as it was before. --- src/system/libroot/posix/malloc_debug/guarded_heap.cpp | 2 +- src/system/libroot/posix/malloc_debug/heap.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp index f8d2c7c27a..728ae2373a 100644 --- a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp +++ b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp @@ -38,7 +38,7 @@ static int32 sStackEndTLSIndex = -1; using namespace std; static size_t sDefaultAlignment = alignof(max_align_t); #else -static size_t sDefaultAlignment = 0; +static size_t sDefaultAlignment = 8; #endif diff --git a/src/system/libroot/posix/malloc_debug/heap.cpp b/src/system/libroot/posix/malloc_debug/heap.cpp index 096fd699b2..3c9ed49218 100644 --- a/src/system/libroot/posix/malloc_debug/heap.cpp +++ b/src/system/libroot/posix/malloc_debug/heap.cpp @@ -54,7 +54,7 @@ static bool sUseGuardPage = false; using namespace std; static size_t sDefaultAlignment = alignof(max_align_t); #else -static size_t sDefaultAlignment = 0; +static size_t sDefaultAlignment = 8; #endif From 1748116d1c5dbfd50da5c8d8e4c53b92b1021029 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Thu, 13 Aug 2015 22:33:55 +0200 Subject: [PATCH 010/125] libroot_debug.so: Fix missing alignment in guarded realloc. --- src/system/libroot/posix/malloc_debug/guarded_heap.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp index 728ae2373a..f527ff527d 100644 --- a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp +++ b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp @@ -747,7 +747,8 @@ guarded_heap_realloc(void* address, size_t newSize) if (oldSize == newSize) return address; - void* newBlock = guarded_heap_allocate(sGuardedHeap, newSize, 0); + void* newBlock = guarded_heap_allocate(sGuardedHeap, newSize, + sDefaultAlignment); if (newBlock == NULL) return NULL; From dfcf52c9f13cfe96b517549c57327380c82e6d4a Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Thu, 13 Aug 2015 22:34:51 +0200 Subject: [PATCH 011/125] leak_analyser: Update excludes with more generic regex for ICU. Also add initialize_before of libroot to the default excludes. --- src/bin/leak_analyser.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/leak_analyser.sh b/src/bin/leak_analyser.sh index 66c6880ae0..2532e2af52 100755 --- a/src/bin/leak_analyser.sh +++ b/src/bin/leak_analyser.sh @@ -94,6 +94,7 @@ EXCLUDE_PATTERN="" if [ -z "$NO_DEFAULTS" ] then declare -a DEFAULT_EXCLUDE_LIST=( \ + " initialize_before " \ " __cxa_atexit " \ " BPrivate::Libroot::LocaleBackend::LoadBackend" \ " initialize_before " \ @@ -108,8 +109,7 @@ then " _init " \ " BTranslatorRoster::Default" \ "Translator> " \ - " icu::" \ - " icu::" \ + " icu(_[0-9]+)?::" \ ) for EXCLUDE in "${DEFAULT_EXCLUDE_LIST[@]}" From 74c001d51d1317ad4e6ba5cb77ef33f21f8188ae Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 13 Aug 2015 22:47:42 +0200 Subject: [PATCH 012/125] Add xmlroff package, with dependencies. --- build/jam/repositories/HaikuPorts/x86_gcc2 | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 0db88ec5fa..1dfd5affee 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -308,8 +308,8 @@ RemotePackageRepository HaikuPorts libxml2-2.8.0-9 libxml2_devel-2.8.0-9 libxml2_python-2.8.0-9 - libxslt-1.1.28-4 - libxslt_devel-1.1.28-4 + libxslt-1.1.28-5 + libxslt_devel-1.1.28-5 libzip-0.11.2-1 libzip_devel-0.11.2-1 lighttpd-1.4.35-2 @@ -547,6 +547,8 @@ RemotePackageRepository HaikuPorts burnitnow_x86-0.1.0-1 bzip2_x86-1.0.6-5 bzip2_x86_devel-1.0.6-5 + cairo_x86-1.12.18-1 + cairo_x86_devel-1.12.18-1 capstone_x86-3.0.4-1 capstone_x86_devel-3.0.4-1 cmake_x86-3.3.0-1 @@ -584,8 +586,8 @@ RemotePackageRepository HaikuPorts flare_x86-0.19-3 fluidsynth_x86-1.1.6-2 fluidsynth_x86_devel-1.1.6-2 - fontconfig_x86-2.11.1-2 - fontconfig_x86_devel-2.11.1-2 + fontconfig_x86-2.11.1-3 + fontconfig_x86_devel-2.11.1-3 freedroidrpg_x86-0.15.1-1 freetype_x86-2.6-1 freetype_x86_devel-2.6-1 @@ -595,6 +597,8 @@ RemotePackageRepository HaikuPorts gcc_x86_syslibs-4.8.5_2015_07_11-2 gcc_x86_syslibs_devel-4.8.5_2015_07_11-2 gcc6809_x86-4.6.1-2 + gdk_pixbuf_x86-2.31.5-1 + gdk_pixbuf_x86_devel-2.31.5-1 gettext_x86-0.18.1.1-6 gettext_x86_libintl-0.18.1.1-6 giflib_x86-5.1.0-1 @@ -733,8 +737,8 @@ RemotePackageRepository HaikuPorts libwebp_x86_devel-0.4.1-1 libxml2_x86-2.9.2-1 libxml2_x86_devel-2.9.2-1 - libxslt_x86-1.1.28-2 - libxslt_x86_devel-1.1.28-2 + libxslt_x86-1.1.28-5 + libxslt_x86_devel-1.1.28-5 libzip_x86-0.11.2-1 libzip_x86_devel-0.11.2-1 llvm_x86-3.5.2-1 @@ -780,6 +784,8 @@ RemotePackageRepository HaikuPorts openssl_x86-1.0.0s-1 openssl_x86_devel-1.0.0s-1 openttd_x86-1.3.3-1 + pango_x86-1.37.0-1 + pango_x86_devel-1.37.0-1 pciutils_x86-3.2.1-1 pciutils_x86_devel-3.2.1-1 physfs_x86-2.0.3-1 @@ -854,6 +860,8 @@ RemotePackageRepository HaikuPorts vacuum_x86-1.2.5-1 vcmi_x86-0.94-1 wizznic_x86-0.9.9-2 + xmlroff_x86-0.6.2-1 + xmlroff_x86_devel-0.6.2-1 xz_utils_x86-5.0.8-2 xz_utils_x86_devel-5.0.8-2 zlib_x86-1.2.8-4 @@ -908,6 +916,7 @@ RemotePackageRepository HaikuPorts burnitnow_x86 bzip2 bzr + cairo_x86 canna capitalbe capstone_x86 @@ -988,6 +997,7 @@ RemotePackageRepository HaikuPorts gettext gettext_x86 gdb + gdk_pixbuf_x86 giflib git glew @@ -1189,6 +1199,7 @@ RemotePackageRepository HaikuPorts openttd_x86 p7zip paladin + pango_x86 paragui patch pciutils @@ -1305,6 +1316,7 @@ RemotePackageRepository HaikuPorts yasm youtube_dl xcb_proto + xmlroff_x86 xmlto xml_parser xproto From 1e57dd30a8f5e2ba40497dfdf1278da67c1015e9 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 14 Aug 2015 18:44:36 +0200 Subject: [PATCH 013/125] Fix xmlroff package. --- build/jam/repositories/HaikuPorts/x86_gcc2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 1dfd5affee..82b246f2f8 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -860,8 +860,8 @@ RemotePackageRepository HaikuPorts vacuum_x86-1.2.5-1 vcmi_x86-0.94-1 wizznic_x86-0.9.9-2 - xmlroff_x86-0.6.2-1 - xmlroff_x86_devel-0.6.2-1 + xmlroff_x86-0.6.2-2 + xmlroff_x86_devel-0.6.2-2 xz_utils_x86-5.0.8-2 xz_utils_x86_devel-5.0.8-2 zlib_x86-1.2.8-4 From ab341b9d63801d389875e644a555dccb3e166914 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 14 Aug 2015 12:50:05 -0500 Subject: [PATCH 014/125] kernel/arm: Correct platform id on ARM --- src/system/kernel/arch/arm/arch_system_info.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/system/kernel/arch/arm/arch_system_info.cpp b/src/system/kernel/arch/arm/arch_system_info.cpp index 49a3c7318b..ae8784b405 100644 --- a/src/system/kernel/arch/arm/arch_system_info.cpp +++ b/src/system/kernel/arch/arm/arch_system_info.cpp @@ -29,7 +29,8 @@ arch_fill_topology_node(cpu_topology_node_info* node, int32 cpu) { switch (node->type) { case B_TOPOLOGY_ROOT: - node->data.root.platform = B_CPU_PPC_64; + // TODO: ARM_64? + node->data.root.platform = B_CPU_ARM; break; case B_TOPOLOGY_PACKAGE: From 17ddd6c09d38d06eb4cf50696b15da39dde26fd1 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 14 Aug 2015 13:46:05 -0500 Subject: [PATCH 015/125] libroot/arm: Add in some missing math functions * Using native assembly functions would be a lot faster, but would require quite a bit of changes to glibc. * This gets arm linking for now... I'd personally like to see musl in here in the future for gcc4 images. (pre-R2) --- src/system/libroot/posix/glibc/arch/arm/Jamfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/system/libroot/posix/glibc/arch/arm/Jamfile b/src/system/libroot/posix/glibc/arch/arm/Jamfile index 394d8eda0b..13db611f18 100644 --- a/src/system/libroot/posix/glibc/arch/arm/Jamfile +++ b/src/system/libroot/posix/glibc/arch/arm/Jamfile @@ -34,6 +34,9 @@ local genericSources = s_isnan.c s_isnanf.c s_signbit.c s_signbitf.c s_signbitl.c + s_clog.c s_clogf.c + s_log1p.c s_log1pf.c s_log1pl.c + s_csqrt.c s_csqrtf.c s_floor.c s_floorf.c s_ceil.c s_ceilf.c s_modf.c From b73c4b60f361e65c797a412cb92cd3baab6b30b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Fri, 14 Aug 2015 22:39:54 +0200 Subject: [PATCH 016/125] Update icu packages for x86_64. --- build/jam/repositories/HaikuPorts/x86_64 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86_64 b/build/jam/repositories/HaikuPorts/x86_64 index abe11d4d58..f948ca9c62 100644 --- a/build/jam/repositories/HaikuPorts/x86_64 +++ b/build/jam/repositories/HaikuPorts/x86_64 @@ -135,10 +135,10 @@ RemotePackageRepository HaikuPorts harfbuzz_devel-0.9.40-1 help2man-1.46.6-1 htmldoc-1.8.27-3 - icu-55.1-3 - icu_devel-55.1-3 - icu54-54.1-1 - icu54_devel-54.1-1 + icu-55.1-5 + icu_devel-55.1-5 + icu54-54.1-2 + icu54_devel-54.1-2 intltool-0.40.6-4 jam-2.5_2012_10_12-2 jasper-1.900.1-4 From 667361d71f400c2b6c2fe2571b7e53f9c776e6b6 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 14 Aug 2015 20:39:00 -0400 Subject: [PATCH 017/125] Debugger: Add worker helper function. Worker: - Add helper to check if the background worker thread has any unfinished jobs in its queue. --- src/apps/debugger/util/Worker.cpp | 8 ++++++++ src/apps/debugger/util/Worker.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/apps/debugger/util/Worker.cpp b/src/apps/debugger/util/Worker.cpp index 0a3133cbe5..f1f58ab380 100644 --- a/src/apps/debugger/util/Worker.cpp +++ b/src/apps/debugger/util/Worker.cpp @@ -342,6 +342,14 @@ Worker::ResumeJob(Job* job) } +bool +Worker::HasPendingJobs() +{ + AutoLocker locker(this); + return !fJobs.IsEmpty(); +} + + status_t Worker::AddListener(const JobKey& key, JobListener* listener) { diff --git a/src/apps/debugger/util/Worker.h b/src/apps/debugger/util/Worker.h index f0b6b176c8..c993f4dee0 100644 --- a/src/apps/debugger/util/Worker.h +++ b/src/apps/debugger/util/Worker.h @@ -149,6 +149,8 @@ public: // only valid for jobs that are // suspended pending user input + bool HasPendingJobs(); + status_t AddListener(const JobKey& key, JobListener* listener); void RemoveListener(const JobKey& key, From 0324fc408c217619b188747ab635be946d0d1247 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 14 Aug 2015 20:40:55 -0400 Subject: [PATCH 018/125] Debugger: Add status bar to main team window. TeamWindow: - Add a status bar in the form of a string view to the bottom of the window, along with a helper function to request updating it. --- .../gui/team_window/TeamWindow.cpp | 26 +++++++++++++++++-- .../gui/team_window/TeamWindow.h | 3 +++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 4b7f15ed8b..8b6ce8757a 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -74,7 +74,8 @@ enum { MSG_LOCATE_SOURCE_IF_NEEDED = 'lsin', MSG_SOURCE_ENTRY_QUERY_COMPLETE = 'seqc', MSG_CLEAR_STACK_TRACE = 'clst', - MSG_HANDLE_LOAD_SETTINGS = 'hlst' + MSG_HANDLE_LOAD_SETTINGS = 'hlst', + MSG_UPDATE_STATUS_BAR = 'upsb' }; @@ -133,6 +134,7 @@ TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* listener) fStepOutButton(NULL), fMenuBar(NULL), fSourcePathView(NULL), + fStatusBarView(NULL), fConsoleOutputView(NULL), fFunctionSplitView(NULL), fSourceSplitView(NULL), @@ -525,6 +527,13 @@ TeamWindow::MessageReceived(BMessage* message) _LoadSettings(settings); break; } + case MSG_UPDATE_STATUS_BAR: + { + const char* messageText; + if (message->FindString("message", &messageText) == B_OK) + fStatusBarView->SetText(messageText); + break; + } case MSG_TEAM_RENAMED: { _UpdateTitle(); @@ -725,6 +734,15 @@ TeamWindow::SaveSettings(GuiTeamUiSettings* settings) } +void +TeamWindow::DisplayBackgroundStatus(const char* message) +{ + BMessage updateMessage(MSG_UPDATE_STATUS_BAR); + updateMessage.AddString("message", message); + PostMessage(&updateMessage); +} + + void TeamWindow::ThreadSelectionChanged(::Thread* thread) { @@ -995,7 +1013,11 @@ TeamWindow::_Init() .SetInsets(0.0) .Add(fConsoleOutputView = ConsoleOutputView::Create()) .End() - .End(); + .End() + .Add(fStatusBarView = new BStringView("status", "Ready.")); + + fStatusBarView->SetExplicitMinSize(BSize(50.0, B_SIZE_UNSET)); + fStatusBarView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); // add source view sourceScrollView->SetTarget(fSourceView = SourceView::Create(fTeam, this)); diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h index f9be9461df..825ecf0d03 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h @@ -71,6 +71,8 @@ public: status_t SaveSettings( GuiTeamUiSettings* settings); + void DisplayBackgroundStatus(const char* message); + private: enum ActiveSourceObject { @@ -228,6 +230,7 @@ private: BButton* fStepOutButton; BMenuBar* fMenuBar; BStringView* fSourcePathView; + BStringView* fStatusBarView; ConsoleOutputView* fConsoleOutputView; BSplitView* fFunctionSplitView; BSplitView* fSourceSplitView; From 7f77789d5b4e4eb34bad204d7a1ebc00b3006db6 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 14 Aug 2015 20:42:11 -0400 Subject: [PATCH 019/125] Debugger: Add work notification hook to UserInterface. UserInterface: - Add new hook function used to notify the UI that some form of background work is taking place for informational purposes, i.e. no interaction required. Implement accordingly in GraphicalUserInterface. --- src/apps/debugger/user_interface/UserInterface.h | 9 +++++++++ .../user_interface/cli/CommandLineUserInterface.cpp | 6 ++++++ .../user_interface/cli/CommandLineUserInterface.h | 2 ++ .../user_interface/gui/GraphicalUserInterface.cpp | 7 +++++++ .../debugger/user_interface/gui/GraphicalUserInterface.h | 4 +++- 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index b87fedf44f..8783cdfc18 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -66,6 +66,15 @@ public: virtual void NotifyUser(const char* title, const char* message, user_notification_type type) = 0; + virtual void NotifyBackgroundWorkStatus(const char* message) + = 0; + // this is used to inform the user about + // background processing work, but doesn't + // otherwise require any form of + // user interaction, i.e. for a status bar + // to indicate that debug information is + // being parsed. + virtual int32 SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3) diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index dfbe7c598d..93d1d45b5e 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp @@ -203,6 +203,12 @@ CommandLineUserInterface::NotifyUser(const char* title, const char* message, } +void +CommandLineUserInterface::NotifyBackgroundWorkStatus(const char* message) +{ +} + + int32 CommandLineUserInterface::SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h index 8eec3a3c87..bb59ce3750 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h @@ -42,6 +42,8 @@ public: virtual void NotifyUser(const char* title, const char* message, user_notification_type type); + virtual void NotifyBackgroundWorkStatus( + const char* message); virtual int32 SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3); diff --git a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp index 8daac7f774..68a9e16134 100644 --- a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp +++ b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp @@ -248,6 +248,13 @@ GraphicalUserInterface::NotifyUser(const char* title, const char* message, } +void +GraphicalUserInterface::NotifyBackgroundWorkStatus(const char* message) +{ + fTeamWindow->DisplayBackgroundStatus(message); +} + + int32 GraphicalUserInterface::SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, diff --git a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h index 59ec0292a3..c86436f63c 100644 --- a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h +++ b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2014, Rene Gollent, rene@gollent.com. + * Copyright 2014-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef GRAPHICAL_USER_INTERFACE_H @@ -38,6 +38,8 @@ public: virtual void NotifyUser(const char* title, const char* message, user_notification_type type); + virtual void NotifyBackgroundWorkStatus( + const char* message); virtual int32 SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3); From 674e0424f74b40f22171a6030b1fadccf02e3655 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 14 Aug 2015 20:44:48 -0400 Subject: [PATCH 020/125] Debugger: Extend ImageDebugInfoJobListener. ImageDebugInfoJobListener: - Add hook for notification that the loading job is in progress. Call as appropriate when the job actually starts. --- src/apps/debugger/jobs/Jobs.h | 1 + src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index 1f6b2444ca..6e33346ace 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -97,6 +97,7 @@ public: virtual ~ImageDebugInfoJobListener(); virtual void ImageDebugInfoJobNeedsUserInput(Job* job, ImageDebugInfoLoadingState* state); + virtual void ImageDebugInfoJobInProgress(Image* image); }; diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp index 600055c0f6..06a88b70a8 100644 --- a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -29,6 +29,12 @@ ImageDebugInfoJobListener::ImageDebugInfoJobNeedsUserInput(Job* job, } +void +ImageDebugInfoJobListener::ImageDebugInfoJobInProgress(Image* image) +{ +} + + // #pragma mark - LoadImageDebugInfoJob @@ -65,6 +71,9 @@ LoadImageDebugInfoJob::Do() ImageInfo imageInfo(fImage->Info()); locker.Unlock(); + if (fListener != NULL) + fListener->ImageDebugInfoJobInProgress(fImage); + // create the debug info ImageDebugInfo* debugInfo; status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo( From 36a43c9d5168ea26fe3c2c1f8f7ed8d52a2be34c Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 14 Aug 2015 20:46:37 -0400 Subject: [PATCH 021/125] Debugger: Implement notifications for debug info loading. TeamDebugger: - When notified that an image debug info job has started loading, notify the user interface accordingly. Also reset status to a ready state whenever all in-flight jobs are complete. This allows the user to know when then debug subsystem is still in the process of parsing debug information, as this can be time consuming for larger programs/libraries. --- .../debugger/controllers/TeamDebugger.cpp | 23 ++++++++++++++++++- src/apps/debugger/controllers/TeamDebugger.h | 6 +++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 352b7d11f0..72abdef437 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -1373,6 +1373,7 @@ void TeamDebugger::JobDone(Job* job) { TRACE_JOBS("TeamDebugger::JobDone(%p)\n", job); + _ResetUserBackgroundStatusIfNeeded(); } @@ -1381,6 +1382,7 @@ TeamDebugger::JobFailed(Job* job) { TRACE_JOBS("TeamDebugger::JobFailed(%p)\n", job); // TODO: notify user + _ResetUserBackgroundStatusIfNeeded(); } @@ -1390,6 +1392,7 @@ TeamDebugger::JobAborted(Job* job) TRACE_JOBS("TeamDebugger::JobAborted(%p)\n", job); // TODO: For a stack frame source loader thread we should reset the // loading state! Asynchronously due to locking order. + _ResetUserBackgroundStatusIfNeeded(); } @@ -1407,6 +1410,16 @@ TeamDebugger::ImageDebugInfoJobNeedsUserInput(Job* job, } +void +TeamDebugger::ImageDebugInfoJobInProgress(Image* image) +{ + BString message; + message.SetToFormat("Loading debug information for %s...", + image->Name().String()); + fUserInterface->NotifyBackgroundWorkStatus(message.String()); +} + + void TeamDebugger::ThreadStateChanged(const ::Team::ThreadEvent& event) { @@ -1908,7 +1921,6 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID) bool handlePostExecSetup = fExecPending && image->Type() == B_APP_IMAGE && state != IMAGE_DEBUG_INFO_LOADING; - // this needs to be done first so that breakpoints are loaded. // otherwise, UpdateImageBreakpoints() won't find the appropriate // UserBreakpoints to create/install instances for. @@ -1922,6 +1934,7 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID) if (state == IMAGE_DEBUG_INFO_LOADED || state == IMAGE_DEBUG_INFO_UNAVAILABLE) { + // update breakpoints in the image fBreakpointManager->UpdateImageBreakpoints(image); @@ -2486,6 +2499,14 @@ TeamDebugger::_NotifyUser(const char* title, const char* text,...) } +void +TeamDebugger::_ResetUserBackgroundStatusIfNeeded() +{ + if (!fWorker->HasPendingJobs()) + fUserInterface->NotifyBackgroundWorkStatus("Ready."); +} + + // #pragma mark - Listener diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index d69e0f53f0..d588cf368d 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -140,6 +140,7 @@ private: virtual void ImageDebugInfoJobNeedsUserInput(Job* job, ImageDebugInfoLoadingState* state); + virtual void ImageDebugInfoJobInProgress(Image* image); // Team::Listener virtual void ThreadStateChanged( @@ -235,6 +236,11 @@ private: void _NotifyUser(const char* title, const char* text,...); + void _ResetUserBackgroundStatusIfNeeded(); + // updates user interface to + // ready/completed message + // for background work status + private: Listener* fListener; SettingsManager* fSettingsManager; From 76cc2d8f45677bb322fae487a415efd5edb3d18b Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 14 Aug 2015 21:06:29 -0500 Subject: [PATCH 022/125] glibc/arm: Filling in more ARM gaps --- src/system/libroot/posix/glibc/arch/arm/Jamfile | 11 +++++++---- .../libroot/posix/glibc/arch/generic/s_log1pl.c | 13 +++++++++++++ .../posix/glibc/include/arch/arm/bits/huge_val.h | 6 ++++++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_log1pl.c diff --git a/src/system/libroot/posix/glibc/arch/arm/Jamfile b/src/system/libroot/posix/glibc/arch/arm/Jamfile index 13db611f18..9bfb08399a 100644 --- a/src/system/libroot/posix/glibc/arch/arm/Jamfile +++ b/src/system/libroot/posix/glibc/arch/arm/Jamfile @@ -34,9 +34,12 @@ local genericSources = s_isnan.c s_isnanf.c s_signbit.c s_signbitf.c s_signbitl.c - s_clog.c s_clogf.c + s_nan.c s_nanf.c s_nanl.c + w_hypot.c w_hypotf.c w_hypotl.c + s_fpclassify.c s_fpclassifyf.c + s_clog.c s_clogf.c s_clogl.c s_log1p.c s_log1pf.c s_log1pl.c - s_csqrt.c s_csqrtf.c + s_csqrt.c s_csqrtf.c s_csqrtl.c s_floor.c s_floorf.c s_ceil.c s_ceilf.c s_modf.c @@ -56,7 +59,7 @@ local genericSources = e_asin.c w_asin.c e_log10.c w_log10.c e_acos.c w_acos.c - e_atan2.c w_atan2.c mpatan2.c mpatan.c mptan.c mpsqrt.c w_sqrt.c w_sqrtf.c + e_atan2.c w_atan2.c w_atan2l.c mpatan2.c mpatan.c mptan.c mpsqrt.c w_sqrt.c w_sqrtf.c e_fmod.c w_fmod.c e_log.c w_log.c e_cosh.c w_cosh.c @@ -65,7 +68,7 @@ local genericSources = s_sinf.c k_sinf.c s_ldexp.c s_ldexpf.c s_scalbnf.c s_scalbn.c - s_copysign.c + s_copysign.c s_copysignf.c s_copysignl.c s_tanh.c s_tanf.c k_tanf.c s_lround.c s_lroundf.c s_round.c s_roundf.c s_rint.c s_rintf.c s_lrintf.c diff --git a/src/system/libroot/posix/glibc/arch/generic/s_log1pl.c b/src/system/libroot/posix/glibc/arch/generic/s_log1pl.c new file mode 100644 index 0000000000..a216fb3cef --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_log1pl.c @@ -0,0 +1,13 @@ +#include +#include +#include + +long double +__log1pl (long double x) +{ + fputs ("__log1pl not implemented\n", stderr); + __set_errno (ENOSYS); + return 0.0; +} + +stub_warning (log1pl) diff --git a/src/system/libroot/posix/glibc/include/arch/arm/bits/huge_val.h b/src/system/libroot/posix/glibc/include/arch/arm/bits/huge_val.h index b4f56217f4..ac432e39ed 100644 --- a/src/system/libroot/posix/glibc/include/arch/arm/bits/huge_val.h +++ b/src/system/libroot/posix/glibc/include/arch/arm/bits/huge_val.h @@ -55,4 +55,10 @@ static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; #endif /* GCC. */ +#if __GNUC_PREREQ(3,3) +# define HUGE_VALL (__builtin_huge_vall()) +#else +# define HUGE_VALL ((long double) HUGE_VAL) +#endif + #define HUGE_VALF HUGE_VAL From 73d0cc722797278a09368c3be29023b3af5a5391 Mon Sep 17 00:00:00 2001 From: autonielx Date: Sat, 15 Aug 2015 06:29:29 +0200 Subject: [PATCH 023/125] Update translations from Pootle --- data/catalogs/apps/haikudepot/pt_BR.catkeys | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/catalogs/apps/haikudepot/pt_BR.catkeys b/data/catalogs/apps/haikudepot/pt_BR.catkeys index adfaa949f3..a5a4049ef6 100644 --- a/data/catalogs/apps/haikudepot/pt_BR.catkeys +++ b/data/catalogs/apps/haikudepot/pt_BR.catkeys @@ -1,4 +1,4 @@ -1 portuguese (brazil) x-vnd.Haiku-HaikuDepot 3134988464 +1 portuguese (brazil) x-vnd.Haiku-HaikuDepot 4123398005 Name PackageListView Nome Available packages MainWindow Pacotes disponíveis Open %DeskbarLink% PackageManager Abrir %DeskbarLink% @@ -133,6 +133,7 @@ If you do not provide an email address, you will not be able to reset your passw Authentication failed. Connection to the service failed. UserLoginWindow Autenticação falhou. Conexão ao serviço falhou. Cancel RatePackageWindow Cancelar Package action failed PackageInfoView Ação do pacote falhou +OK UserLoginWindow OK Send RatePackageWindow Enviar Failed to create account UserLoginWindow Falhou ao criar conta There are problems with the data you entered:\n\n UserLoginWindow Existem problemas com os dados que você inseriu:\n\n From 5d91a421b99fee96e1eda7bd383d7e685d803eeb Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 14 Aug 2015 23:37:49 -0500 Subject: [PATCH 024/125] glibc/arm: More generic math functions --- .../libroot/posix/glibc/arch/arm/Jamfile | 11 +- .../libroot/posix/glibc/arch/generic/e_logf.c | 38 ++----- .../libroot/posix/glibc/arch/generic/e_logl.c | 14 +++ .../posix/glibc/arch/generic/e_sqrtl.c | 104 ++++++++++++++++++ .../posix/glibc/arch/generic/s_atanl.c | 14 +++ 5 files changed, 152 insertions(+), 29 deletions(-) create mode 100644 src/system/libroot/posix/glibc/arch/generic/e_logl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/e_sqrtl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_atanl.c diff --git a/src/system/libroot/posix/glibc/arch/arm/Jamfile b/src/system/libroot/posix/glibc/arch/arm/Jamfile index 9bfb08399a..18924a7e2f 100644 --- a/src/system/libroot/posix/glibc/arch/arm/Jamfile +++ b/src/system/libroot/posix/glibc/arch/arm/Jamfile @@ -35,6 +35,7 @@ local genericSources = s_signbit.c s_signbitf.c s_signbitl.c s_nan.c s_nanf.c s_nanl.c + e_hypot.c e_hypotf.c e_hypotl.c w_hypot.c w_hypotf.c w_hypotl.c s_fpclassify.c s_fpclassifyf.c s_clog.c s_clogf.c s_clogl.c @@ -54,12 +55,16 @@ local genericSources = halfulp.c mpa.c mplog.c mpexp.c s_sin.c - s_atan.c s_atanf.c + s_atan.c s_atanf.c s_atanl.c s_tan.c - e_asin.c w_asin.c + e_asin.c e_asinl.c + w_asin.c w_asinl.c e_log10.c w_log10.c + e_logf.c e_logl.c e_acos.c w_acos.c - e_atan2.c w_atan2.c w_atan2l.c mpatan2.c mpatan.c mptan.c mpsqrt.c w_sqrt.c w_sqrtf.c + e_atan2.c e_atan2l.c + w_atan2.c w_atan2l.c mpatan2.c mpatan.c mptan.c mpsqrt.c w_sqrt.c w_sqrtf.c + e_sqrtl.c e_fmod.c w_fmod.c e_log.c w_log.c e_cosh.c w_cosh.c diff --git a/src/system/libroot/posix/glibc/arch/generic/e_logf.c b/src/system/libroot/posix/glibc/arch/generic/e_logf.c index de8f869df4..cf75e11781 100644 --- a/src/system/libroot/posix/glibc/arch/generic/e_logf.c +++ b/src/system/libroot/posix/glibc/arch/generic/e_logf.c @@ -13,18 +13,10 @@ * ==================================================== */ -#if defined(LIBM_SCCS) && !defined(lint) -static char rcsid[] = "$NetBSD: e_logf.c,v 1.4 1995/05/10 20:45:54 jtc Exp $"; -#endif +#include +#include -#include "math.h" -#include "math_private.h" - -#ifdef __STDC__ static const float -#else -static float -#endif ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ two25 = 3.355443200e+07, /* 0x4c000000 */ @@ -36,18 +28,10 @@ Lg5 = 1.8183572590e-01, /* 3E3A3325 */ Lg6 = 1.5313838422e-01, /* 3E1CD04F */ Lg7 = 1.4798198640e-01; /* 3E178897 */ -#ifdef __STDC__ static const float zero = 0.0; -#else -static float zero = 0.0; -#endif -#ifdef __STDC__ - float __ieee754_logf(float x) -#else - float __ieee754_logf(x) - float x; -#endif +float +__ieee754_logf(float x) { float hfsq,f,s,z,R,w,t1,t2,dk; int32_t k,ix,i,j; @@ -56,13 +40,14 @@ static float zero = 0.0; k=0; if (ix < 0x00800000) { /* x < 2**-126 */ - if ((ix&0x7fffffff)==0) - return -two25/(x-x); /* log(+-0)=-inf */ - if (ix<0) return (x-x)/(x-x); /* log(-#) = NaN */ + if (__builtin_expect((ix&0x7fffffff)==0, 0)) + return -two25/zero; /* log(+-0)=-inf */ + if (__builtin_expect(ix<0, 0)) + return (x-x)/(x-x); /* log(-#) = NaN */ k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(ix,x); } - if (ix >= 0x7f800000) return x+x; + if (__builtin_expect(ix >= 0x7f800000, 0)) return x+x; k += (ix>>23)-127; ix &= 0x007fffff; i = (ix+(0x95f64<<3))&0x800000; @@ -76,9 +61,9 @@ static float zero = 0.0; } R = f*f*((float)0.5-(float)0.33333333333333333*f); if(k==0) return f-R; else {dk=(float)k; - return dk*ln2_hi-((R-dk*ln2_lo)-f);} + return dk*ln2_hi-((R-dk*ln2_lo)-f);} } - s = f/((float)2.0+f); + s = f/((float)2.0+f); dk = (float)k; z = s*s; i = ix-(0x6147a<<3); @@ -97,3 +82,4 @@ static float zero = 0.0; return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); } } +strong_alias (__ieee754_logf, __logf_finite) diff --git a/src/system/libroot/posix/glibc/arch/generic/e_logl.c b/src/system/libroot/posix/glibc/arch/generic/e_logl.c new file mode 100644 index 0000000000..7a4ea1b07f --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_logl.c @@ -0,0 +1,14 @@ +#include +#include +#include + +long double +__ieee754_logl (long double x) +{ + fputs ("__ieee754_logl not implemented\n", stderr); + __set_errno (ENOSYS); + return 0.0; +} +strong_alias (__ieee754_logl, __logl_finite) + +stub_warning (logl) diff --git a/src/system/libroot/posix/glibc/arch/generic/e_sqrtl.c b/src/system/libroot/posix/glibc/arch/generic/e_sqrtl.c new file mode 100644 index 0000000000..ac1b22175e --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_sqrtl.c @@ -0,0 +1,104 @@ +/* + * IBM Accurate Mathematical Library + * written by International Business Machines Corp. + * Copyright (C) 2001-2015 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see . + */ +/*********************************************************************/ +/* MODULE_NAME: uroot.c */ +/* */ +/* FUNCTION: usqrt */ +/* */ +/* FILES NEEDED: dla.h endian.h mydefs.h uroot.h */ +/* uroot.tbl */ +/* */ +/* An ultimate sqrt routine. Given an IEEE double machine number x */ +/* it computes the correctly rounded (to nearest) value of square */ +/* root of x. */ +/* Assumption: Machine arithmetic operations are performed in */ +/* round to nearest mode of IEEE 754 standard. */ +/* */ +/*********************************************************************/ + +#include + +typedef union {int64_t i[2]; long double x; double d[2]; } mynumber; + +static const double + t512 = 0x1p512, + tm256 = 0x1p-256, + two54 = 0x1p54, /* 0x4350000000000000 */ + twom54 = 0x1p-54; /* 0x3C90000000000000 */ + +/*********************************************************************/ +/* An ultimate sqrt routine. Given an IEEE double machine number x */ +/* it computes the correctly rounded (to nearest) value of square */ +/* root of x. */ +/*********************************************************************/ +long double __ieee754_sqrtl(long double x) +{ + static const long double big = 134217728.0, big1 = 134217729.0; + long double t,s,i; + mynumber a,c; + uint64_t k, l; + int64_t m, n; + double d; + + a.x=x; + k=a.i[0] & INT64_C(0x7fffffffffffffff); + /*----------------- 2^-1022 <= | x |< 2^1024 -----------------*/ + if (k>INT64_C(0x000fffff00000000) && k> 53; + m = (a.i[1] >> 52) & 0x7ff; + if (m == 0) { + a.d[1] *= two54; + m = ((a.i[1] >> 52) & 0x7ff) - 54; + } + m += n; + if (m > 0) + a.i[1] = (a.i[1] & INT64_C(0x800fffffffffffff)) | (m << 52); + else if (m <= -54) { + a.i[1] &= INT64_C(0x8000000000000000); + } else { + m += 54; + a.i[1] = (a.i[1] & INT64_C(0x800fffffffffffff)) | (m << 52); + a.d[1] *= twom54; + } + } + a.i[0] = l; + s = a.x; + d = __ieee754_sqrt (a.d[0]); + c.i[0] = INT64_C(0x2000000000000000)+((k&INT64_C(0x7fe0000000000000))>>1); + c.i[1] = 0; + i = d; + t = 0.5L * (i + s / i); + i = 0.5L * (t + s / t); + return c.x * i; + } + else { + if (k>=INT64_C(0x7ff0000000000000)) { + if (a.i[0] == INT64_C(0xfff0000000000000)) + return (big1-big1)/(big-big); /* sqrt (-Inf) = NaN. */ + return x; /* sqrt (NaN) = NaN, sqrt (+Inf) = +Inf. */ + } + if (x == 0) return x; + if (x < 0) return (big1-big1)/(big-big); + return tm256*__ieee754_sqrtl(x*t512); + } +} +strong_alias (__ieee754_sqrtl, __sqrtl_finite) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_atanl.c b/src/system/libroot/posix/glibc/arch/generic/s_atanl.c new file mode 100644 index 0000000000..2957d702d5 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_atanl.c @@ -0,0 +1,14 @@ +#include +#include +#include + +long double +__atanl (long double x) +{ + fputs ("__atanl not implemented\n", stderr); + __set_errno (ENOSYS); + return 0.0; +} +weak_alias (__atanl, atanl) + +stub_warning (atanl) From ea2e2f5e11076e114678bb7606df1ad69c2c4716 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 15 Aug 2015 10:39:24 +0200 Subject: [PATCH 025/125] Update LnLauncher package to include launch daemon script. --- build/jam/repositories/HaikuPorts/x86_gcc2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 82b246f2f8..ded04fb4c0 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -316,7 +316,7 @@ RemotePackageRepository HaikuPorts lighttpd_devel-1.4.35-2 links-2.8-1 lmarbles-1.0.8-2 - lnlauncher-1.1.2-1 + lnlauncher-1.1.2-2 ltris-1.0.19-1 lua-5.2.1-6 lua_devel-5.2.1-6 From 4c7fff8044e28c8e2198ba629fe242893bf970e4 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 15 Aug 2015 11:39:05 +0200 Subject: [PATCH 026/125] Add package for jabber4haiku. --- build/jam/repositories/HaikuPorts/x86_gcc2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index ded04fb4c0..77a2030519 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -182,6 +182,7 @@ RemotePackageRepository HaikuPorts imagemagick_devel-6.8.9_8-1 intltool-0.40.6-4 itstool-2.0.2-1 + jabber4haiku-1.2.1-1 jam-2.5_2012_10_12-2 jasper-1.900.1-4 jasper_devel-1.900.1-4 @@ -1031,6 +1032,7 @@ RemotePackageRepository HaikuPorts imagemagick intltool itstool + jabber4haiku jam jasper jbig2dec From 9d9c74ecdb2da0b47f4722697467e4c1b4235966 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 15 Aug 2015 16:41:24 -0400 Subject: [PATCH 027/125] Debugger: Cleanups and improvements for status notification. Worker/Job: - Add job listener hooks for when work actually begins for a job, and when a job is suspended to wait for user input. - Add hook for setting a job description string, and implement in several subclasses. LoadImageDebugInfoJob: - Get rid of ImageDebugInfoJobListener since its functionality can be handled via the more general job wait for user input hook. Refactor accordingly. TeamDebugger: - Adjust to use new job hooks. When a worker job is initiated, we now check if the job has a description, and if so pass it on to the UI to display a notification. DwarfLoadingStateHandler: - Notify the UI when a package download is in progress. With these changes, the status bar now notifies the user if any of the following actions are in flight: 1) Loading/parsing debug information 2) Stack trace retrieval 3) Source code retrieval 4) Downloading a debug info package --- .../debugger/controllers/TeamDebugger.cpp | 51 ++++++++++--------- src/apps/debugger/controllers/TeamDebugger.h | 9 ++-- .../debugger/controllers/ThreadHandler.cpp | 17 ++++--- src/apps/debugger/controllers/ThreadHandler.h | 5 +- .../DwarfLoadingStateHandler.cpp | 5 ++ src/apps/debugger/jobs/GetStackTraceJob.cpp | 10 ++-- src/apps/debugger/jobs/Jobs.h | 27 +++------- .../debugger/jobs/LoadImageDebugInfoJob.cpp | 51 ++++--------------- src/apps/debugger/jobs/LoadSourceCodeJob.cpp | 3 ++ src/apps/debugger/util/Worker.cpp | 30 +++++++++++ src/apps/debugger/util/Worker.h | 8 +++ 11 files changed, 110 insertions(+), 106 deletions(-) diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 72abdef437..e86bfb90f2 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -1369,6 +1370,17 @@ TeamDebugger::UserInterfaceQuitRequested(QuitOption quitOption) } +void +TeamDebugger::JobStarted(Job* job) +{ + BString description(job->GetDescription()); + if (!description.IsEmpty()) { + description.Append(B_UTF8_ELLIPSIS); + fUserInterface->NotifyBackgroundWorkStatus(description.String()); + } +} + + void TeamDebugger::JobDone(Job* job) { @@ -1377,6 +1389,21 @@ TeamDebugger::JobDone(Job* job) } +void +TeamDebugger::JobWaitingForInput(Job* job) +{ + LoadImageDebugInfoJob* infoJob = dynamic_cast(job); + + if (infoJob == NULL) + return; + + BMessage message(MSG_DEBUG_INFO_NEEDS_USER_INPUT); + message.AddPointer("job", infoJob); + message.AddPointer("state", infoJob->GetLoadingState()); + PostMessage(&message); +} + + void TeamDebugger::JobFailed(Job* job) { @@ -1396,30 +1423,6 @@ TeamDebugger::JobAborted(Job* job) } -void -TeamDebugger::ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state) -{ - TRACE_JOBS("TeamDebugger::DebugInfoJobNeedsUserInput(%p, %p)\n", - job, state); - - BMessage message(MSG_DEBUG_INFO_NEEDS_USER_INPUT); - message.AddPointer("job", job); - message.AddPointer("state", state); - PostMessage(&message); -} - - -void -TeamDebugger::ImageDebugInfoJobInProgress(Image* image) -{ - BString message; - message.SetToFormat("Loading debug information for %s...", - image->Name().String()); - fUserInterface->NotifyBackgroundWorkStatus(message.String()); -} - - void TeamDebugger::ThreadStateChanged(const ::Team::ThreadEvent& event) { diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index d588cf368d..7e645860bf 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -32,8 +32,7 @@ class WatchpointManager; class TeamDebugger : public BLooper, private UserInterfaceListener, - private JobListener, private ImageDebugInfoJobListener, - private Team::Listener { + private JobListener, private Team::Listener { public: class Listener; @@ -134,14 +133,12 @@ private: QuitOption quitOption); // JobListener + virtual void JobStarted(Job* job); virtual void JobDone(Job* job); + virtual void JobWaitingForInput(Job* job); virtual void JobFailed(Job* job); virtual void JobAborted(Job* job); - virtual void ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state); - virtual void ImageDebugInfoJobInProgress(Image* image); - // Team::Listener virtual void ThreadStateChanged( const ::Team::ThreadEvent& event); diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp index 999a6b0d12..fd5d228de5 100644 --- a/src/apps/debugger/controllers/ThreadHandler.cpp +++ b/src/apps/debugger/controllers/ThreadHandler.cpp @@ -76,14 +76,13 @@ private: ThreadHandler::ThreadHandler(Thread* thread, Worker* worker, - DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + DebuggerInterface* debuggerInterface, JobListener* jobListener, BreakpointManager* breakpointManager) : fThread(thread), fWorker(worker), fDebuggerInterface(debuggerInterface), - fDebugInfoJobListener(listener), + fJobListener(jobListener), fBreakpointManager(breakpointManager), fStepMode(STEP_NONE), fStepStatement(NULL), @@ -113,7 +112,7 @@ void ThreadHandler::Init() { fWorker->ScheduleJob(new(std::nothrow) GetThreadStateJob(fDebuggerInterface, - fThread)); + fThread), fJobListener); fConditionWaitSem = create_sem(0, "breakpoint condition waiter"); } @@ -458,7 +457,8 @@ ThreadHandler::HandleThreadStateChanged() if (fThread->State() == THREAD_STATE_STOPPED && fThread->GetCpuState() == NULL) { fWorker->ScheduleJob( - new(std::nothrow) GetCpuStateJob(fDebuggerInterface, fThread)); + new(std::nothrow) GetCpuStateJob(fDebuggerInterface, fThread), + fJobListener); } } @@ -475,8 +475,8 @@ ThreadHandler::HandleCpuStateChanged() if (fThread->GetCpuState() != NULL && fThread->GetStackTrace() == NULL) { fWorker->ScheduleJob( new(std::nothrow) GetStackTraceJob(fDebuggerInterface, - fDebugInfoJobListener, fDebuggerInterface->GetArchitecture(), - fThread)); + fJobListener, fDebuggerInterface->GetArchitecture(), + fThread), fJobListener); } } @@ -954,7 +954,8 @@ ThreadHandler::_HandleBreakpointConditionIfNeeded(CpuState* cpuState) status_t error = fWorker->ScheduleJob( new(std::nothrow) ExpressionEvaluationJob(fThread->GetTeam(), - fDebuggerInterface, language, expressionInfo, frame, fThread)); + fDebuggerInterface, language, expressionInfo, frame, fThread), + fJobListener); BPrivate::ObjectDeleter deleter( listener); diff --git a/src/apps/debugger/controllers/ThreadHandler.h b/src/apps/debugger/controllers/ThreadHandler.h index 432eac1e9f..85ac8be6be 100644 --- a/src/apps/debugger/controllers/ThreadHandler.h +++ b/src/apps/debugger/controllers/ThreadHandler.h @@ -20,6 +20,7 @@ class BreakpointManager; class DebuggerInterface; class ExpressionResult; class ImageDebugInfoJobListener; +class JobListener; class StackFrame; class Statement; class Worker; @@ -30,7 +31,7 @@ class ThreadHandler : public BReferenceable, private ImageDebugInfoProvider, public: ThreadHandler(Thread* thread, Worker* worker, DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + JobListener* listener, BreakpointManager* breakpointManager); ~ThreadHandler(); @@ -117,7 +118,7 @@ private: Thread* fThread; Worker* fWorker; DebuggerInterface* fDebuggerInterface; - ImageDebugInfoJobListener* fDebugInfoJobListener; + JobListener* fJobListener; BreakpointManager* fBreakpointManager; uint32 fStepMode; Statement* fStepStatement; diff --git a/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp index f174bfd11f..9cc89e0cc6 100644 --- a/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp +++ b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -108,6 +109,10 @@ DwarfLoadingStateHandler::HandleState( BString command; command.SetToFormat("/bin/pkgman install -y %s", requiredPackage.String()); + BString notification; + notification.SetToFormat("Installing package %s" B_UTF8_ELLIPSIS, + requiredPackage.String()); + interface->NotifyBackgroundWorkStatus(notification); int error = system(command.String()); if (interface->IsInteractive()) { if (WIFEXITED(error)) { diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp index d0b28ce167..a44bbdbe36 100644 --- a/src/apps/debugger/jobs/GetStackTraceJob.cpp +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -18,12 +18,11 @@ GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, Architecture* architecture, - Thread* thread) + JobListener* listener, Architecture* architecture, Thread* thread) : fKey(thread, JOB_TYPE_GET_STACK_TRACE), fDebuggerInterface(debuggerInterface), - fDebugInfoJobListener(listener), + fJobListener(listener), fArchitecture(architecture), fThread(thread) { @@ -32,6 +31,9 @@ GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, fCpuState = fThread->GetCpuState(); if (fCpuState != NULL) fCpuState->AcquireReference(); + + + SetDescription("Retrieving stack trace for thread %" B_PRId32, fThread->ID()); } @@ -84,7 +86,7 @@ GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) // schedule a job, if not loaded ImageDebugInfo* info; status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(), - image, fDebugInfoJobListener, &info); + image, fJobListener, &info); if (error != B_OK) return error; diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index 6e33346ace..e4b3e5bcab 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -92,20 +92,11 @@ private: }; -class ImageDebugInfoJobListener { -public: - virtual ~ImageDebugInfoJobListener(); - virtual void ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state); - virtual void ImageDebugInfoJobInProgress(Image* image); -}; - - class GetStackTraceJob : public Job, private ImageDebugInfoProvider { public: GetStackTraceJob( DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + JobListener* jobListener, Architecture* architecture, Thread* thread); virtual ~GetStackTraceJob(); @@ -120,7 +111,7 @@ private: private: SimpleJobKey fKey; DebuggerInterface* fDebuggerInterface; - ImageDebugInfoJobListener* fDebugInfoJobListener; + JobListener* fJobListener; Architecture* fArchitecture; Thread* fThread; CpuState* fCpuState; @@ -129,8 +120,7 @@ private: class LoadImageDebugInfoJob : public Job { public: - LoadImageDebugInfoJob(Image* image, - ImageDebugInfoJobListener* listener); + LoadImageDebugInfoJob(Image* image); virtual ~LoadImageDebugInfoJob(); virtual const JobKey& Key() const; @@ -138,7 +128,7 @@ public: static status_t ScheduleIfNecessary(Worker* worker, Image* image, - ImageDebugInfoJobListener* listener, + JobListener* jobListener, ImageDebugInfo** _imageDebugInfo = NULL); // If already loaded returns a // reference, if desired. If not loaded @@ -147,19 +137,16 @@ public: // if scheduling the job failed, or the // debug info already failed to load // earlier. -private: - void NotifyUserInputListener(); - -private: - typedef BObjectList ListenerList; + ImageDebugInfoLoadingState* + GetLoadingState() + { return &fState; } private: SimpleJobKey fKey; Image* fImage; ImageDebugInfoLoadingState fState; - ImageDebugInfoJobListener* fListener; }; diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp index 06a88b70a8..d576f08fb2 100644 --- a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -14,39 +14,19 @@ #include "Team.h" -// #pragma mark - ImageDebugInfoJobListener - - -ImageDebugInfoJobListener::~ImageDebugInfoJobListener() -{ -} - - -void -ImageDebugInfoJobListener::ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state) -{ -} - - -void -ImageDebugInfoJobListener::ImageDebugInfoJobInProgress(Image* image) -{ -} - - // #pragma mark - LoadImageDebugInfoJob -LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image, - ImageDebugInfoJobListener* listener) +LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image) : fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO), fImage(image), - fState(), - fListener(listener) + fState() { fImage->AcquireReference(); + + SetDescription("Loading debugging information for %s", + fImage->Name().String()); } @@ -71,9 +51,6 @@ LoadImageDebugInfoJob::Do() ImageInfo imageInfo(fImage->Info()); locker.Unlock(); - if (fListener != NULL) - fListener->ImageDebugInfoJobInProgress(fImage); - // create the debug info ImageDebugInfo* debugInfo; status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo( @@ -83,7 +60,6 @@ LoadImageDebugInfoJob::Do() locker.Lock(); if (fState.UserInputRequired()) { - NotifyUserInputListener(); return WaitForUserInput(); } else if (error == B_OK) { error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED); @@ -97,7 +73,7 @@ LoadImageDebugInfoJob::Do() /*static*/ status_t LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, - ImageDebugInfoJobListener* listener, ImageDebugInfo** _imageDebugInfo) + JobListener* listener, ImageDebugInfo** _imageDebugInfo) { AutoLocker teamLocker(image->GetTeam()); @@ -122,12 +98,12 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, return B_ERROR; // schedule a job - LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image, - listener); + LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob( + image); if (job == NULL) return B_NO_MEMORY; - status_t error = worker->ScheduleJob(job); + status_t error = worker->ScheduleJob(job, listener); if (error != B_OK) { image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); return error; @@ -139,12 +115,3 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, *_imageDebugInfo = NULL; return B_OK; } - - -void -LoadImageDebugInfoJob::NotifyUserInputListener() -{ - if (fListener != NULL) - fListener->ImageDebugInfoJobNeedsUserInput(this, &fState); -} - diff --git a/src/apps/debugger/jobs/LoadSourceCodeJob.cpp b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp index 402a9ab711..6265a03ff3 100644 --- a/src/apps/debugger/jobs/LoadSourceCodeJob.cpp +++ b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp @@ -30,6 +30,9 @@ LoadSourceCodeJob::LoadSourceCodeJob( fLoadForFunction(loadForFunction) { fFunctionInstance->AcquireReference(); + + SetDescription("Loading source code for function %s", + fFunctionInstance->PrettyName().String()); } diff --git a/src/apps/debugger/util/Worker.cpp b/src/apps/debugger/util/Worker.cpp index f1f58ab380..0a184bdfbc 100644 --- a/src/apps/debugger/util/Worker.cpp +++ b/src/apps/debugger/util/Worker.cpp @@ -70,12 +70,24 @@ JobListener::~JobListener() } +void +JobListener::JobStarted(Job* job) +{ +} + + void JobListener::JobDone(Job* job) { } +void +JobListener::JobWaitingForInput(Job* job) +{ +} + + void JobListener::JobFailed(Job* job) { @@ -121,6 +133,15 @@ Job::WaitForUserInput() } +void +Job::SetDescription(const char* format, ...) +{ + va_list args; + va_start(args, format); + fDescription.SetToFormatVarArgs(format, args); +} + + void Job::SetWorker(Worker* worker) { @@ -179,6 +200,13 @@ Job::NotifyListeners() for (int32 i = count - 1; i >= 0; i--) { JobListener* listener = fListeners.ItemAt(i); switch (fState) { + case JOB_STATE_ACTIVE: + listener->JobStarted(this); + break; + case JOB_STATE_WAITING: + if (fWaitStatus == JOB_USER_INPUT_WAITING) + listener->JobWaitingForInput(this); + break; case JOB_STATE_SUCCEEDED: listener->JobDone(this); break; @@ -403,6 +431,7 @@ Worker::WaitForUserInput(Job* waitingJob) return B_INTERRUPTED; waitingJob->SetWaitStatus(JOB_USER_INPUT_WAITING); + waitingJob->NotifyListeners(); fSuspendedJobs.Add(waitingJob); return B_OK; @@ -459,6 +488,7 @@ Worker::_ProcessJobs() // process the next job if (Job* job = fUnscheduledJobs.RemoveHead()) { job->SetState(JOB_STATE_ACTIVE); + job->NotifyListeners(); locker.Unlock(); status_t error = job->Do(); diff --git a/src/apps/debugger/util/Worker.h b/src/apps/debugger/util/Worker.h index c993f4dee0..d27abe7a07 100644 --- a/src/apps/debugger/util/Worker.h +++ b/src/apps/debugger/util/Worker.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -69,7 +70,9 @@ class JobListener { public: virtual ~JobListener(); + virtual void JobStarted(Job* job); virtual void JobDone(Job* job); + virtual void JobWaitingForInput(Job* job); virtual void JobFailed(Job* job); virtual void JobAborted(Job* job); }; @@ -89,9 +92,13 @@ public: Worker* GetWorker() const { return fWorker; } job_state State() const { return fState; } + const BString& GetDescription() const + { return fDescription; } + protected: job_wait_status WaitFor(const JobKey& key); status_t WaitForUserInput(); + void SetDescription(const char* format, ...); private: friend class Worker; @@ -122,6 +129,7 @@ private: JobList fDependentJobs; job_wait_status fWaitStatus; ListenerList fListeners; + BString fDescription; public: Job* fNext; From b3fe4614950eebad8d93e299b52d940eb9e7d286 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sun, 16 Aug 2015 08:50:22 +0200 Subject: [PATCH 028/125] Updated bepodder, added new qbittorrent and dependancy built by Diver --- build/jam/repositories/HaikuPorts/x86_gcc2 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 77a2030519..9edeb9942a 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -52,7 +52,7 @@ RemotePackageRepository HaikuPorts belife-1.0.0-2 bemines-1.0b2-1 bepdf-1.2.0-1 - bepodder-1.3.0-1 + bepodder-1.3.0-2 bescreencapture-1.9.4-1 bezilla-2.0.0.22-1 binutils-2.17_2013_04_21-2 @@ -726,6 +726,8 @@ RemotePackageRepository HaikuPorts libtheora_x86_devel-1.1.1-2 libtool_x86-2.4.2-1 libtool_x86_libltdl-2.4.2-1 + libtorrent_rasterbar_x86-1.0.6-1 + libtorrent_rasterbar_x86_devel-1.0.6-1 libusb_x86-1.0.18-1 libusb_x86_devel-1.0.18-1 libuuid_x86-1.0.3-2 @@ -799,6 +801,7 @@ RemotePackageRepository HaikuPorts protrekkr_x86-2.5.4-2 popt_x86-1.16-1 popt_x86_devel-1.16-1 + qbittorrent_x86-3.2.3-1 qemu_x86-2.1.2-1 qca2_x86-2.0.3-1 qca2_x86_devel-2.0.3-1 @@ -1118,6 +1121,7 @@ RemotePackageRepository HaikuPorts libtheora libtool libtool_x86 + libtorrent_rasterbar_x86 libunistring libusb libusb_x86 @@ -1230,6 +1234,7 @@ RemotePackageRepository HaikuPorts python_setuptools python_twisted python_zope.interface + qbittorrent_x86 qemacs qemu_x86 qca2_x86 From ebc6718fb20cea97b782dd3e3fab4ebecff94fd9 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 16 Aug 2015 13:03:26 +0200 Subject: [PATCH 029/125] Add package for GrafX2. --- build/jam/repositories/HaikuPorts/x86_gcc2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 9edeb9942a..5554e8157f 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -162,6 +162,7 @@ RemotePackageRepository HaikuPorts gperf-3.0.4-1 gpgme-1.5.2-2 gpgme_devel-1.5.2-2 + grafx2-2.5-1 grep-2.20-1 groff-1.20.1-3 gtk_doc-1.20-1 @@ -1016,6 +1017,7 @@ RemotePackageRepository HaikuPorts gperf gpgme gpgme_x86 + grafx2 graphite2_x86 grep groff From 28b7dd63d3653969aabe4fa9d45d3f8b6767683f Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sun, 16 Aug 2015 13:41:28 +0200 Subject: [PATCH 030/125] Updated qbittorrent and quicklaunch. --- build/jam/repositories/HaikuPorts/x86_gcc2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 5554e8157f..dc9844b37b 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -802,7 +802,7 @@ RemotePackageRepository HaikuPorts protrekkr_x86-2.5.4-2 popt_x86-1.16-1 popt_x86_devel-1.16-1 - qbittorrent_x86-3.2.3-1 + qbittorrent_x86-3.2.3-2 qemu_x86-2.1.2-1 qca2_x86-2.0.3-1 qca2_x86_devel-2.0.3-1 @@ -810,7 +810,7 @@ RemotePackageRepository HaikuPorts qjson_x86_devel-0.8.1-1 qmplay2_x86-15.05.30-2 quassel_x86-0.10.0-2 - quicklaunch-0.9.10-1 + quicklaunch-0.9.11-1 qupzilla_x86-1.8.6-1 radare2_x86-0.9.9-1 radare2_x86_devel-0.9.9-1 From 897d8754a63c4d87ee66ce4ee79167ed089d2311 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 16 Aug 2015 14:48:07 +0200 Subject: [PATCH 031/125] GrafX2: update to a version that actually works. --- build/jam/repositories/HaikuPorts/x86_gcc2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index dc9844b37b..f496cf0737 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -162,7 +162,7 @@ RemotePackageRepository HaikuPorts gperf-3.0.4-1 gpgme-1.5.2-2 gpgme_devel-1.5.2-2 - grafx2-2.5-1 + grafx2-2.5-2 grep-2.20-1 groff-1.20.1-3 gtk_doc-1.20-1 From 103adddb37d379a722b6cc9bca82879abaafc5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 17 Aug 2015 19:44:45 +0200 Subject: [PATCH 032/125] BTextView: do not restrict max size in GetHeightForWidth(). --- src/kits/interface/TextView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kits/interface/TextView.cpp b/src/kits/interface/TextView.cpp index f5625d90a5..d9091683e7 100644 --- a/src/kits/interface/TextView.cpp +++ b/src/kits/interface/TextView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2014 Haiku, Inc. All rights reserved. + * Copyright 2001-2015 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -2601,7 +2601,7 @@ BTextView::GetHeightForWidth(float width, float* min, float* max, if (min != NULL) *min = fTextRect.Height(); if (max != NULL) - *max = fTextRect.Height(); + *max = B_SIZE_UNLIMITED; if (preferred != NULL) *preferred = fTextRect.Height(); } From 0104e6facbceb84f3a6241abbb3261de091d85cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 17 Aug 2015 20:28:17 +0200 Subject: [PATCH 033/125] Tracker: Use BEntry::Name(), minor cleanup. * Use BEntry::Name() over GetName() where appropriate. * Fixed some weird indentation. * Simplified some constructs. --- src/kits/tracker/FSUtils.cpp | 131 ++++++++++++++++------------------- 1 file changed, 59 insertions(+), 72 deletions(-) diff --git a/src/kits/tracker/FSUtils.cpp b/src/kits/tracker/FSUtils.cpp index a17a074be6..b6ad7cd241 100644 --- a/src/kits/tracker/FSUtils.cpp +++ b/src/kits/tracker/FSUtils.cpp @@ -1024,7 +1024,7 @@ MoveTask(BObjectList* srcList, BEntry* destEntry, BList* pointList, // resolve name collisions and hierarchy problems if (CheckName(moveMode, &sourceEntry, &destDir, - collisionCount > 1, conflictCheckResult) != B_OK) { + collisionCount > 1, conflictCheckResult) != B_OK) { // we will skip the current item, because we got a conflict // and were asked to or because there was some conflict @@ -1152,7 +1152,7 @@ CopyFile(BEntry* srcFile, StatStruct* srcStat, BDirectory* destDir, BEntry conflictingEntry; if (destDir->FindEntry(destName, &conflictingEntry) == B_OK) { switch (loopControl->OverwriteOnConflict(srcFile, destName, destDir, - false, false)) { + false, false)) { case TrackerCopyLoopControl::kSkip: // we are about to ignore this entire directory return; @@ -1573,36 +1573,35 @@ status_t RecursiveMove(BEntry* entry, BDirectory* destDir, CopyLoopControl* loopControl) { - char name[B_FILE_NAME_LENGTH]; - if (entry->GetName(name) == B_OK) { - if (destDir->Contains(name)) { - BPath path (destDir, name); - BDirectory subDir (path.Path()); - entry_ref ref; - entry->GetRef(&ref); - BDirectory source(&ref); - if (source.InitCheck() == B_OK) { - source.Rewind(); - BEntry current; - while (source.GetNextEntry(¤t) == B_OK) { - if (current.IsDirectory()) { - RecursiveMove(¤t, &subDir, loopControl); - current.Remove(); - } else { - current.GetName(name); - if (loopControl->OverwriteOnConflict(¤t, name, + const char* name = entry->Name(); + + if (destDir->Contains(name)) { + BPath path (destDir, name); + BDirectory subDir (path.Path()); + entry_ref ref; + entry->GetRef(&ref); + BDirectory source(&ref); + if (source.InitCheck() == B_OK) { + source.Rewind(); + BEntry current; + while (source.GetNextEntry(¤t) == B_OK) { + if (current.IsDirectory()) { + RecursiveMove(¤t, &subDir, loopControl); + current.Remove(); + } else { + name = current.Name(); + if (loopControl->OverwriteOnConflict(¤t, name, &subDir, true, false) != TrackerCopyLoopControl::kSkip) { - MoveError::FailOnError(current.MoveTo(&subDir, - NULL, true)); - } + MoveError::FailOnError(current.MoveTo(&subDir, + NULL, true)); } } } - entry->Remove(); - } else - MoveError::FailOnError(entry->MoveTo(destDir)); - } + } + entry->Remove(); + } else + MoveError::FailOnError(entry->MoveTo(destDir)); return B_OK; } @@ -1998,7 +1997,6 @@ ConflictCheckResult PreFlightNameCheck(BObjectList* srcList, const BDirectory* destDir, int32* collisionCount, uint32 moveMode) { - // count the number of name collisions in dest folder *collisionCount = 0; @@ -2009,10 +2007,8 @@ PreFlightNameCheck(BObjectList* srcList, const BDirectory* destDir, BDirectory parent; entry.GetParent(&parent); - if (parent != *destDir) { - if (destDir->Contains(srcRef->name)) - (*collisionCount)++; - } + if (parent != *destDir && destDir->Contains(srcRef->name)) + (*collisionCount)++; } // prompt user only if there is more than one collision, otherwise the @@ -2064,16 +2060,15 @@ FileStatToString(StatStruct* stat, char* buffer, int32 length) status_t CheckName(uint32 moveMode, const BEntry* sourceEntry, const BDirectory* destDir, bool multipleCollisions, - ConflictCheckResult &replaceAll) + ConflictCheckResult& conflictMode) { - if (moveMode == kDuplicateSelection) + if (moveMode == kDuplicateSelection) { // when duplicating, we will never have a conflict return B_OK; + } // see if item already exists in destination dir - status_t err = B_OK; - char name[B_FILE_NAME_LENGTH]; - sourceEntry->GetName(name); + const char* name = sourceEntry->Name(); bool sourceIsDirectory = sourceEntry->IsDirectory(); BDirectory srcDirectory; @@ -2082,8 +2077,7 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, BEntry destEntry; destDir->GetEntry(&destEntry); - if (moveMode != kCreateLink - && moveMode != kCreateRelativeLink + if (moveMode != kCreateLink && moveMode != kCreateRelativeLink && (srcDirectory == *destDir || srcDirectory.Contains(&destEntry))) { BAlert* alert = new BAlert("", @@ -2108,9 +2102,10 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, } BEntry entry; - if (destDir->FindEntry(name, &entry) != B_OK) + if (destDir->FindEntry(name, &entry) != B_OK) { // no conflict, return return B_OK; + } if (moveMode == kCreateLink || moveMode == kCreateRelativeLink) { // if we are creating link in the same directory, the conflict will @@ -2124,8 +2119,8 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, bool destIsDir = entry.IsDirectory(); // be sure not to replace the parent directory of the item being moved if (destIsDir) { - BDirectory test_dir(&entry); - if (test_dir.Contains(sourceEntry)) { + BDirectory targetDir(&entry); + if (targetDir.Contains(sourceEntry)) { BAlert* alert = new BAlert("", B_TRANSLATE("You can't replace a folder " "with one of its sub-folders."), @@ -2141,18 +2136,18 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, if (moveMode != kCreateLink && moveMode != kCreateRelativeLink && destIsDir != sourceIsDirectory) { - BAlert* alert = new BAlert("", sourceIsDirectory - ? B_TRANSLATE("You cannot replace a file with a folder or a " + BAlert* alert = new BAlert("", sourceIsDirectory + ? B_TRANSLATE("You cannot replace a file with a folder or a " "symbolic link.") - : B_TRANSLATE("You cannot replace a folder or a symbolic link " + : B_TRANSLATE("You cannot replace a folder or a symbolic link " "with a file."), B_TRANSLATE("OK"), 0, 0, B_WIDTH_AS_USUAL, - B_WARNING_ALERT); - alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); - alert->Go(); - return B_ERROR; - } + B_WARNING_ALERT); + alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); + alert->Go(); + return B_ERROR; + } - if (replaceAll != kReplaceAll) { + if (conflictMode != kReplaceAll) { // prompt user to determine whether to replace or not BString replaceMsg; @@ -2170,8 +2165,8 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, char sourceBuffer[96], destBuffer[96]; StatStruct statBuffer; - if (!sourceEntry->IsDirectory() && sourceEntry->GetStat( - &statBuffer) == B_OK) { + if (!sourceEntry->IsDirectory() + && sourceEntry->GetStat(&statBuffer) == B_OK) { FileStatToString(&statBuffer, sourceBuffer, 96); } else sourceBuffer[0] = '\0'; @@ -2185,10 +2180,8 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, replaceMsg.ReplaceAll("%name", name); replaceMsg.ReplaceFirst("%dest", destBuffer); replaceMsg.ReplaceFirst("%src", sourceBuffer); - replaceMsg.ReplaceFirst("%movemode", - moveMode == kMoveSelectionTo - ? B_TRANSLATE("moving") - : B_TRANSLATE("copying")); + replaceMsg.ReplaceFirst("%movemode", moveMode == kMoveSelectionTo + ? B_TRANSLATE("moving") : B_TRANSLATE("copying")); } // special case single collision (don't need Replace All shortcut) @@ -2216,22 +2209,21 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, } // delete destination item - if (!destIsDir) - err = entry.Remove(); - else + if (destIsDir) return B_OK; - if (err != B_OK) { + status_t status = entry.Remove(); + if (status != B_OK) { BString error(B_TRANSLATE("There was a problem trying to replace " "\"%name\". The item might be open or busy.")); - error.ReplaceFirst("%name", name);; + error.ReplaceFirst("%name", name); BAlert* alert = new BAlert("", error.String(), B_TRANSLATE("Cancel"), 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); } - return err; + return status; } @@ -2962,14 +2954,10 @@ FSRecursiveCreateFolder(BPath path) entry.SetTo(path.Path()); if (entry.Exists()) return B_FILE_EXISTS; - else { - char name[B_FILE_NAME_LENGTH]; - BDirectory parent; - entry.GetParent(&parent); - entry.GetName(name); - parent.CreateDirectory(name, NULL); - } + BDirectory parent; + entry.GetParent(&parent); + parent.CreateDirectory(entry.Name(), NULL); return B_OK; } @@ -3017,8 +3005,7 @@ _RestoreTask(BObjectList* list) if (!originalEntry.Exists()) { BDirectory dir(parentPath.Path()); if (dir.InitCheck() == B_OK) { - char leafName[B_FILE_NAME_LENGTH]; - originalEntry.GetName(leafName); + const char* leafName = originalEntry.Name(); if (entry.MoveTo(&dir, leafName) == B_OK) { BNode node(&entry); if (node.InitCheck() == B_OK) From f8300bd9794b3cbb021bc4152500b73352f0b4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 17 Aug 2015 20:39:33 +0200 Subject: [PATCH 034/125] Tracker: Added a "Skip all" functionality. * Also, the copy prompt gets a missing "Replace" button (instead of only offering "Replace all"). --- src/kits/tracker/FSUtils.cpp | 65 +++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/src/kits/tracker/FSUtils.cpp b/src/kits/tracker/FSUtils.cpp index b6ad7cd241..aaca5fc1ff 100644 --- a/src/kits/tracker/FSUtils.cpp +++ b/src/kits/tracker/FSUtils.cpp @@ -101,6 +101,7 @@ enum { enum ConflictCheckResult { kCanceled = kUserCanceled, kPrompt, + kSkipAll, kReplace, kReplaceAll, kNoConflicts @@ -2019,9 +2020,12 @@ PreFlightNameCheck(BObjectList* srcList, const BDirectory* destDir, BString replaceMsg(B_TRANSLATE_NOCOLLECT(kReplaceManyStr)); replaceMsg.ReplaceAll("%verb", verb); - BAlert* alert = new BAlert("", replaceMsg.String(), - B_TRANSLATE("Cancel"), B_TRANSLATE("Prompt"), - B_TRANSLATE("Replace all")); + BAlert* alert = new BAlert(); + alert->SetText(replaceMsg.String()); + alert->AddButton(B_TRANSLATE("Cancel")); + alert->AddButton(B_TRANSLATE("Prompt")); + alert->AddButton(B_TRANSLATE("Skip all")); + alert->AddButton(B_TRANSLATE("Replace all")); alert->SetShortcut(0, B_ESCAPE); switch (alert->Go()) { case 0: @@ -2032,7 +2036,11 @@ PreFlightNameCheck(BObjectList* srcList, const BDirectory* destDir, return kPrompt; case 2: - // user selected "Replace All" + // user selected "Skip all" + return kSkipAll; + + case 3: + // user selected "Replace all" return kReplaceAll; } } @@ -2060,7 +2068,7 @@ FileStatToString(StatStruct* stat, char* buffer, int32 length) status_t CheckName(uint32 moveMode, const BEntry* sourceEntry, const BDirectory* destDir, bool multipleCollisions, - ConflictCheckResult& conflictMode) + ConflictCheckResult& conflictResolution) { if (moveMode == kDuplicateSelection) { // when duplicating, we will never have a conflict @@ -2147,7 +2155,10 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, return B_ERROR; } - if (conflictMode != kReplaceAll) { + if (conflictResolution == kSkipAll) + return B_ERROR; + + if (conflictResolution != kReplaceAll) { // prompt user to determine whether to replace or not BString replaceMsg; @@ -2187,24 +2198,38 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, // special case single collision (don't need Replace All shortcut) BAlert* alert; if (multipleCollisions || sourceIsDirectory) { - alert = new BAlert("", replaceMsg.String(), - B_TRANSLATE("Skip"), B_TRANSLATE("Replace all")); + alert = new BAlert(); + alert->SetText(replaceMsg.String()); + alert->AddButton(B_TRANSLATE("Skip")); + alert->AddButton(B_TRANSLATE("Skip all")); + alert->AddButton(B_TRANSLATE("Replace")); + alert->AddButton(B_TRANSLATE("Replace all")); + switch (alert->Go()) { + case 0: + conflictResolution = kCanceled; + return B_ERROR; + case 1: + conflictResolution = kSkipAll; + return B_ERROR; + case 2: + conflictResolution = kReplace; + break; + case 3: + conflictResolution = kReplaceAll; + break; + } } else { alert = new BAlert("", replaceMsg.String(), B_TRANSLATE("Cancel"), B_TRANSLATE("Replace")); alert->SetShortcut(0, B_ESCAPE); - } - switch (alert->Go()) { - case 0: // user selected "Cancel" or "Skip" - replaceAll = kCanceled; - return B_ERROR; - - case 1: // user selected "Replace" or "Replace All" - replaceAll = kReplaceAll; - // doesn't matter which since a single - // collision "Replace" is equivalent to a - // "Replace All" - break; + switch (alert->Go()) { + case 0: + conflictResolution = kCanceled; + return B_ERROR; + case 1: + conflictResolution = kReplace; + break; + } } } From b20d210d5a7514d0bd799931c103dec954794c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 17 Aug 2015 20:47:08 +0200 Subject: [PATCH 035/125] Mail: minor cleanup. --- src/apps/mail/ComboBox.cpp | 7 + src/apps/mail/ComboBox.h | 1 + src/apps/mail/MailWindow.cpp | 443 ++++++++++++++++------------------- src/apps/mail/MailWindow.h | 219 ++++++++--------- 4 files changed, 319 insertions(+), 351 deletions(-) diff --git a/src/apps/mail/ComboBox.cpp b/src/apps/mail/ComboBox.cpp index 68abfcd741..0424ac066c 100644 --- a/src/apps/mail/ComboBox.cpp +++ b/src/apps/mail/ComboBox.cpp @@ -1253,6 +1253,13 @@ BComboBox::Text() const } +int32 +BComboBox::TextLength() const +{ + return fText->TextLength(); +} + + BTextView * BComboBox::TextView() { diff --git a/src/apps/mail/ComboBox.h b/src/apps/mail/ComboBox.h index 35f6321c7f..1ab8886c3c 100644 --- a/src/apps/mail/ComboBox.h +++ b/src/apps/mail/ComboBox.h @@ -150,6 +150,7 @@ public: virtual void SetLabel(const char *text); virtual void SetText(const char *text); const char *Text() const; + int32 TextLength() const; BTextView *TextView(); virtual void SetDivider(float dividing_line); float Divider() const; diff --git a/src/apps/mail/MailWindow.cpp b/src/apps/mail/MailWindow.cpp index 7649ccf4a1..5453023210 100644 --- a/src/apps/mail/MailWindow.cpp +++ b/src/apps/mail/MailWindow.cpp @@ -93,7 +93,7 @@ of their respective holders. All rights reserved. using namespace BPrivate; -const char *kUndoStrings[] = { +const char* kUndoStrings[] = { "Undo", "Undo typing", "Undo cut", @@ -102,7 +102,7 @@ const char *kUndoStrings[] = { "Undo drop" }; -const char *kRedoStrings[] = { +const char* kRedoStrings[] = { "Redo", "Redo typing", "Redo cut", @@ -113,7 +113,7 @@ const char *kRedoStrings[] = { // Text for both the main menu and the pop-up menu. -static const char *kSpamMenuItemTextArray[] = { +static const char* kSpamMenuItemTextArray[] = { "Mark as spam and move to trash", // M_TRAIN_SPAM_AND_DELETE "Mark as spam", // M_TRAIN_SPAM "Unmark this message", // M_UNTRAIN @@ -122,12 +122,12 @@ static const char *kSpamMenuItemTextArray[] = { static const uint32 kMsgQuitAndKeepAllStatus = 'Casm'; -static const char *kQueriesDirectory = "mail/queries"; -static const char *kAttrQueryInitialMode = "_trk/qryinitmode"; +static const char* kQueriesDirectory = "mail/queries"; +static const char* kAttrQueryInitialMode = "_trk/qryinitmode"; // taken from src/kits/tracker/Attributes.h -static const char *kAttrQueryInitialString = "_trk/qryinitstr"; -static const char *kAttrQueryInitialNumAttrs = "_trk/qryinitnumattrs"; -static const char *kAttrQueryInitialAttrs = "_trk/qryinitattrs"; +static const char* kAttrQueryInitialString = "_trk/qryinitstr"; +static const char* kAttrQueryInitialNumAttrs = "_trk/qryinitnumattrs"; +static const char* kAttrQueryInitialAttrs = "_trk/qryinitattrs"; static const uint32 kAttributeItemMain = 'Fatr'; // taken from src/kits/tracker/FindPanel.h static const uint32 kByNameItem = 'Fbyn'; @@ -138,11 +138,30 @@ static const uint32 kByForumlaItem = 'Fbyq'; // taken from src/kits/tracker/FindPanel.h +// static bitmap cache +BObjectList TMailWindow::sBitmapCache; +BLocker TMailWindow::sBitmapCacheLock; + // static list for tracking of Windows BList TMailWindow::sWindowList; BLocker TMailWindow::sWindowListLock; +class HorizontalLine : public BView { +public: + HorizontalLine(BRect rect) + : + BView (rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW) + { + } + + virtual void Draw(BRect rect) + { + FillRect(rect, B_SOLID_HIGH); + } +}; + + // #pragma mark - @@ -216,8 +235,7 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, // few seconds. if (!fIncoming) { - QueryMenu *queryMenu; - queryMenu = new QueryMenu(B_TRANSLATE("Open draft"), false); + QueryMenu* queryMenu = new QueryMenu(B_TRANSLATE("Open draft"), false); queryMenu->SetTargetForItems(be_app); queryMenu->SetPredicate("MAIL:draft==1"); @@ -377,7 +395,7 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, menu = new BMenu(B_TRANSLATE("Message")); if (!resending && fIncoming) { - BMenuItem *menuItem; + BMenuItem* menuItem; menu->AddItem(new BMenuItem(B_TRANSLATE("Reply"), new BMessage(M_REPLY),'R')); menu->AddItem(new BMenuItem(B_TRANSLATE("Reply to sender"), @@ -492,7 +510,7 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, r = Frame(); r.OffsetTo(0, 0); r.top = fHeaderView->Frame().bottom - 1; - fContentView = new TContentView(r, fIncoming, const_cast(font), + fContentView = new TContentView(r, fIncoming, const_cast(font), false, fApp->ColoredQuotes()); // TContentView needs to be properly const, for now cast away constness @@ -554,20 +572,17 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, } -BObjectList TMailWindow::fBitmapCache; -BLocker TMailWindow::fBitmapCacheLock; - BBitmap* TMailWindow::_RetrieveVectorIcon(int32 id) { // Lock access to the list - BAutolock lock(fBitmapCacheLock); + BAutolock lock(sBitmapCacheLock); if (!lock.IsLocked()) return NULL; // Check for the bitmap in the cache first BitmapItem* item; - for (int32 i = 0; (item = fBitmapCache.ItemAt(i)) != NULL; i++) { + for (int32 i = 0; (item = sBitmapCache.ItemAt(i)) != NULL; i++) { if (item->id == id) return item->bm; } @@ -588,7 +603,7 @@ TMailWindow::_RetrieveVectorIcon(int32 id) item = (BitmapItem*)malloc(sizeof(BitmapItem)); item->bm = bitmap; item->id = id; - fBitmapCache.AddItem(item); + sBitmapCache.AddItem(item); return bitmap; } @@ -599,7 +614,7 @@ TMailWindow::_RetrieveVectorIcon(int32 id) void TMailWindow::BuildToolBar() { - fToolBar = new BToolBar(BRect(0, 0, 100, 50)); + fToolBar = new BToolBar(); fToolBar->AddAction(M_NEW, this, _RetrieveVectorIcon(11), NULL, B_TRANSLATE("New")); fToolBar->AddSeparator(); @@ -720,7 +735,7 @@ TMailWindow::~TMailWindow() status_t -TMailWindow::GetMailNodeRef(node_ref &nodeRef) const +TMailWindow::GetMailNodeRef(node_ref& nodeRef) const { if (fRef == NULL) return B_ERROR; @@ -731,7 +746,7 @@ TMailWindow::GetMailNodeRef(node_ref &nodeRef) const bool -TMailWindow::GetTrackerWindowFile(entry_ref *ref, bool next) const +TMailWindow::GetTrackerWindowFile(entry_ref* ref, bool next) const { // Position was already saved if (next && fNextTrackerPositionSaved) { @@ -789,7 +804,7 @@ TMailWindow::GetTrackerWindowFile(entry_ref *ref, bool next) const void -TMailWindow::SaveTrackerPosition(entry_ref *ref) +TMailWindow::SaveTrackerPosition(entry_ref* ref) { // if only one of them is saved, we're not going to do it again if (fNextTrackerPositionSaved || fPrevTrackerPositionSaved) @@ -803,7 +818,7 @@ TMailWindow::SaveTrackerPosition(entry_ref *ref) void -TMailWindow::SetOriginatingWindow(BWindow *window) +TMailWindow::SetOriginatingWindow(BWindow* window) { delete fOriginatingWindow; fOriginatingWindow = new BMessenger(window); @@ -824,7 +839,7 @@ TMailWindow::SetTrackerSelectionToCurrent() void TMailWindow::PreserveReadingPos(bool save) { - BScrollBar *scroll = fContentView->fTextView->ScrollBar(B_VERTICAL); + BScrollBar* scroll = fContentView->fTextView->ScrollBar(B_VERTICAL); if (scroll == NULL || fRef == NULL) return; @@ -881,7 +896,7 @@ TMailWindow::MenusBeginning() bool enable; int32 finish = 0; int32 start = 0; - BTextView *textView; + BTextView* textView; if (!fIncoming) { bool gotToField = fHeaderView->fTo->Text()[0] != 0; @@ -937,9 +952,9 @@ TMailWindow::MenusBeginning() fPrint->SetEnabled(fContentView->fTextView->TextLength()); - textView = dynamic_cast(CurrentFocus()); + textView = dynamic_cast(CurrentFocus()); if (textView != NULL - && dynamic_cast(textView->Parent()) != NULL) { + && dynamic_cast(textView->Parent()) != NULL) { // one of To:, Subject:, Account:, Cc:, Bcc: textView->GetSelection(&start, &finish); } else if (fContentView->fTextView->IsFocus()) { @@ -958,7 +973,7 @@ TMailWindow::MenusBeginning() bool isRedo = false; undo_state undoState = B_UNDO_UNAVAILABLE; - BTextView *focusTextView = dynamic_cast(CurrentFocus()); + BTextView* focusTextView = dynamic_cast(CurrentFocus()); if (focusTextView != NULL) undoState = focusTextView->UndoState(&isRedo); @@ -985,7 +1000,7 @@ TMailWindow::MenusBeginning() void -TMailWindow::MessageReceived(BMessage *msg) +TMailWindow::MessageReceived(BMessage* msg) { bool wasReadMsg = false; switch (msg->what) { @@ -1012,15 +1027,15 @@ TMailWindow::MessageReceived(BMessage *msg) { int32 prevState = fFieldState; int32 fieldMask = msg->FindInt32("bitmask"); - void *source; + void* source; if (msg->FindPointer("source", &source) == B_OK) { int32 length; if (fieldMask == FIELD_BODY) - length = ((TTextView *)source)->TextLength(); + length = ((TTextView*)source)->TextLength(); else - length = ((BComboBox *)source)->TextView()->TextLength(); + length = ((BComboBox*)source)->TextView()->TextLength(); if (length) fFieldState |= fieldMask; @@ -1039,7 +1054,7 @@ TMailWindow::MessageReceived(BMessage *msg) fChanged = true; // Update title bar if "subject" has changed - if (!fIncoming && fieldMask & FIELD_SUBJECT) { + if (!fIncoming && (fieldMask & FIELD_SUBJECT) != 0) { // If no subject, set to "Mail" if (!fHeaderView->fSubject->TextView()->TextLength()) SetTitle(B_TRANSLATE_SYSTEM_NAME("Mail")); @@ -1077,7 +1092,7 @@ TMailWindow::MessageReceived(BMessage *msg) TODO: Replace this code with a split toolbar button */ uint32 buttons; - if (msg->FindInt32("buttons", (int32 *)&buttons) == B_OK + if (msg->FindInt32("buttons", (int32*)&buttons) == B_OK && buttons == B_SECONDARY_MOUSE_BUTTON) { BPopUpMenu menu("Spam Actions", false, false); for (int i = 0; i < 4; i++) @@ -1086,7 +1101,7 @@ TMailWindow::MessageReceived(BMessage *msg) BPoint where; msg->FindPoint("where", &where); - BMenuItem *item; + BMenuItem* item; if ((item = menu.Go(where, false, false)) != NULL) PostMessage(item->Message()); break; @@ -1116,7 +1131,7 @@ TMailWindow::MessageReceived(BMessage *msg) // TODO: This needs removed in favor of a split toolbar button. // See comments for Spam button uint32 buttons; - if (msg->FindInt32("buttons", (int32 *)&buttons) == B_OK + if (msg->FindInt32("buttons", (int32*)&buttons) == B_OK && buttons == B_SECONDARY_MOUSE_BUTTON) { BPopUpMenu menu("Reply To", false, false); menu.AddItem(new BMenuItem(B_TRANSLATE("Reply"), @@ -1129,7 +1144,7 @@ TMailWindow::MessageReceived(BMessage *msg) BPoint where; msg->FindPoint("where", &where); - BMenuItem *item; + BMenuItem* item; if ((item = menu.Go(where, false, false)) != NULL) { item->SetTarget(this); PostMessage(item->Message()); @@ -1143,7 +1158,7 @@ TMailWindow::MessageReceived(BMessage *msg) // TODO: This needs removed in favor of a split toolbar button. // See comments for Spam button uint32 buttons; - if (msg->FindInt32("buttons", (int32 *)&buttons) == B_OK + if (msg->FindInt32("buttons", (int32*)&buttons) == B_OK && buttons == B_SECONDARY_MOUSE_BUTTON) { BPopUpMenu menu("Forward", false, false); menu.AddItem(new BMenuItem(B_TRANSLATE("Forward"), @@ -1155,7 +1170,7 @@ TMailWindow::MessageReceived(BMessage *msg) BPoint where; msg->FindPoint("where", &where); - BMenuItem *item; + BMenuItem* item; if ((item = menu.Go(where, false, false)) != NULL) { item->SetTarget(this); PostMessage(item->Message()); @@ -1182,7 +1197,7 @@ TMailWindow::MessageReceived(BMessage *msg) case M_DELETE_PREV: case M_DELETE_NEXT: { - if (msg->what == M_DELETE_NEXT && (modifiers() & B_SHIFT_KEY)) + if (msg->what == M_DELETE_NEXT && (modifiers() & B_SHIFT_KEY) != 0) msg->what = M_DELETE_PREV; bool foundRef = false; @@ -1233,8 +1248,8 @@ TMailWindow::MessageReceived(BMessage *msg) // If the next file was found, open it. If it was not, // we have no choice but to close this window. if (foundRef) { - TMailWindow *window - = static_cast(be_app)->FindWindow(nextRef); + TMailWindow* window + = static_cast(be_app)->FindWindow(nextRef); if (window == NULL) OpenMessage(&nextRef, fHeaderView->fCharacterSetUserSees); else @@ -1272,10 +1287,8 @@ TMailWindow::MessageReceived(BMessage *msg) break; case M_CLOSE_CUSTOM: if (msg->HasString("status")) { - const char *str; - msg->FindString("status", (const char**) &str); BMessage message(B_CLOSE_REQUESTED); - message.AddString("status", str); + message.AddString("status", msg->GetString("status")); PostMessage(&message); } else { BRect r = Frame(); @@ -1331,7 +1344,7 @@ TMailWindow::MessageReceived(BMessage *msg) case M_SAVE: { const char* address; - if (msg->FindString("address", (const char**)&address) != B_NO_ERROR) + if (msg->FindString("address", (const char**)&address) != B_OK) break; BVolumeRoster volumeRoster; @@ -1448,10 +1461,10 @@ TMailWindow::MessageReceived(BMessage *msg) } if (sigList.CountItems() > 0) { srand(time(0)); - PostMessage((BMessage *)sigList.ItemAt(rand() + PostMessage((BMessage*)sigList.ItemAt(rand() % sigList.CountItems())); - for (int32 i = 0; (message = (BMessage *)sigList.ItemAt(i)) + for (int32 i = 0; (message = (BMessage*)sigList.ItemAt(i)) != NULL; i++) delete message; } @@ -1466,8 +1479,8 @@ TMailWindow::MessageReceived(BMessage *msg) } case M_SIG_MENU: { - TMenu *menu; - BMenuItem *item; + TMenu* menu; + BMenuItem* item; menu = new TMenu("Add Signature", INDEX_SIGNATURE, M_SIGNATURE, true); @@ -1481,7 +1494,7 @@ TMailWindow::MessageReceived(BMessage *msg) if ((item = menu->Go(where, false, true)) != NULL) { item->SetTarget(this); - (dynamic_cast(item))->Invoke(); + (dynamic_cast(item))->Invoke(); } delete menu; break; @@ -1544,7 +1557,7 @@ TMailWindow::MessageReceived(BMessage *msg) entry_ref orgRef = *fRef; entry_ref nextRef = *fRef; if (GetTrackerWindowFile(&nextRef, (msg->what == M_NEXTMSG))) { - TMailWindow *window = static_cast(be_app) + TMailWindow* window = static_cast(be_app) ->FindWindow(nextRef); if (window == NULL) { BNode node(fRef); @@ -1672,7 +1685,7 @@ TMailWindow::MessageReceived(BMessage *msg) void -TMailWindow::AddEnclosure(BMessage *msg) +TMailWindow::AddEnclosure(BMessage* msg) { if (fEnclosuresView == NULL && !fIncoming) { BRect r; @@ -1720,7 +1733,7 @@ TMailWindow::QuitRequested() || (fEnclosuresView != NULL && fEnclosuresView->fList->CountItems()))) { if (fResending) { - BAlert *alert = new BAlert("", B_TRANSLATE( + BAlert* alert = new BAlert("", B_TRANSLATE( "Send this message before closing?"), B_TRANSLATE("Cancel"), B_TRANSLATE("Don't send"), @@ -1741,7 +1754,7 @@ TMailWindow::QuitRequested() break; } } else { - BAlert *alert = new BAlert("", + BAlert* alert = new BAlert("", B_TRANSLATE("Save this message as a draft before closing?"), B_TRANSLATE("Cancel"), B_TRANSLATE("Don't save"), @@ -1771,7 +1784,7 @@ TMailWindow::QuitRequested() if (CurrentMessage() && CurrentMessage()->HasString("status")) { // User explicitly requests a status to set this message to. if (!CurrentMessage()->HasString("same")) { - const char *status = CurrentMessage()->FindString("status"); + const char* status = CurrentMessage()->FindString("status"); if (status != NULL) { BNode node(fRef); if (node.InitCheck() == B_NO_ERROR) { @@ -1807,7 +1820,7 @@ TMailWindow::Show() if (!fResending && (fIncoming || fReplying)) { fContentView->fTextView->MakeFocus(true); } else { - BTextView *textView = fHeaderView->fTo->TextView(); + BTextView* textView = fHeaderView->fTo->TextView(); fHeaderView->fTo->MakeFocus(true); textView->Select(0, textView->TextLength()); } @@ -1822,61 +1835,57 @@ TMailWindow::Zoom(BPoint /*pos*/, float /*x*/, float /*y*/) { float height; float width; - BScreen screen(this); - BRect r; - BRect s_frame = screen.Frame(); - r = Frame(); + BRect rect = Frame(); width = 80 * fApp->ContentFont().StringWidth("M") - + (r.Width() - fContentView->fTextView->Bounds().Width() + 6); - if (width > (s_frame.Width() - 8)) - width = s_frame.Width() - 8; + + (rect.Width() - fContentView->fTextView->Bounds().Width() + 6); + + BScreen screen(this); + BRect screenFrame = screen.Frame(); + if (width > (screenFrame.Width() - 8)) + width = screenFrame.Width() - 8; height = max_c(fContentView->fTextView->CountLines(), 20) * fContentView->fTextView->LineHeight(0) - + (r.Height() - fContentView->fTextView->Bounds().Height()); - if (height > (s_frame.Height() - 29)) - height = s_frame.Height() - 29; + + (rect.Height() - fContentView->fTextView->Bounds().Height()); + if (height > (screenFrame.Height() - 29)) + height = screenFrame.Height() - 29; - r.right = r.left + width; - r.bottom = r.top + height; + rect.right = rect.left + width; + rect.bottom = rect.top + height; - if (abs((int)(Frame().Width() - r.Width())) < 5 - && abs((int)(Frame().Height() - r.Height())) < 5) { - r = fZoom; + if (abs((int)(Frame().Width() - rect.Width())) < 5 + && abs((int)(Frame().Height() - rect.Height())) < 5) { + rect = fZoom; } else { fZoom = Frame(); - s_frame.InsetBy(6, 6); + screenFrame.InsetBy(6, 6); - if (r.Width() > s_frame.Width()) - r.right = r.left + s_frame.Width(); - if (r.Height() > s_frame.Height()) - r.bottom = r.top + s_frame.Height(); + if (rect.Width() > screenFrame.Width()) + rect.right = rect.left + screenFrame.Width(); + if (rect.Height() > screenFrame.Height()) + rect.bottom = rect.top + screenFrame.Height(); - if (r.right > s_frame.right) - { - r.left -= r.right - s_frame.right; - r.right = s_frame.right; + if (rect.right > screenFrame.right) { + rect.left -= rect.right - screenFrame.right; + rect.right = screenFrame.right; } - if (r.bottom > s_frame.bottom) - { - r.top -= r.bottom - s_frame.bottom; - r.bottom = s_frame.bottom; + if (rect.bottom > screenFrame.bottom) { + rect.top -= rect.bottom - screenFrame.bottom; + rect.bottom = screenFrame.bottom; } - if (r.left < s_frame.left) - { - r.right += s_frame.left - r.left; - r.left = s_frame.left; + if (rect.left < screenFrame.left) { + rect.right += screenFrame.left - rect.left; + rect.left = screenFrame.left; } - if (r.top < s_frame.top) - { - r.bottom += s_frame.top - r.top; - r.top = s_frame.top; + if (rect.top < screenFrame.top) { + rect.bottom += screenFrame.top - rect.top; + rect.top = screenFrame.top; } } - ResizeTo(r.Width(), r.Height()); - MoveTo(r.LeftTop()); + ResizeTo(rect.Width(), rect.Height()); + MoveTo(rect.LeftTop()); } @@ -1892,10 +1901,10 @@ TMailWindow::WindowActivated(bool status) void -TMailWindow::Forward(entry_ref *ref, TMailWindow *window, +TMailWindow::Forward(entry_ref* ref, TMailWindow* window, bool includeAttachments) { - BEmailMessage *mail = window->Mail(); + BEmailMessage* mail = window->Mail(); if (mail == NULL) return; @@ -1915,10 +1924,10 @@ TMailWindow::Forward(entry_ref *ref, TMailWindow *window, if (useAccountFrom == ACCOUNT_FROM_MAIL) { fHeaderView->fAccountID = fMail->Account(); - BMenu *menu = fHeaderView->fAccountMenu; + BMenu* menu = fHeaderView->fAccountMenu; for (int32 i = menu->CountItems(); i-- > 0;) { - BMenuItem *item = menu->ItemAt(i); - BMessage *msg; + BMenuItem* item = menu->ItemAt(i); + BMessage* msg; if (item && (msg = item->Message()) != NULL && msg->FindInt32("id") == fHeaderView->fAccountID) item->SetMarked(true); @@ -1939,19 +1948,6 @@ TMailWindow::Forward(entry_ref *ref, TMailWindow *window, } -class HorizontalLine : public BView { - public: - HorizontalLine(BRect rect) - : - BView (rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW) {} - - virtual void Draw(BRect rect) - { - FillRect(rect, B_SOLID_HIGH); - } -}; - - void TMailWindow::Print() { @@ -1989,8 +1985,7 @@ TMailWindow::Print() add_header_field(fSubject); add_header_field(fTo); - if ((fHeaderView->fCc != NULL) - && (strcmp(fHeaderView->fCc->Text(),"") != 0)) + if (fHeaderView->fCc != NULL && fHeaderView->fCc->TextLength() != 0) add_header_field(fCc); if (fHeaderView->fDate != NULL) @@ -2025,21 +2020,18 @@ TMailWindow::Print() BPoint(0.0, curPageRect.bottom - ((curPage == 1) ? header_height : 0))); - float curPageHeight = fContentView->fTextView-> - TextHeight(fromLine, lastLine) + ((curPage == 1) - ? header_height : 0); + float curPageHeight = fContentView->fTextView->TextHeight( + fromLine, lastLine) + (curPage == 1 ? header_height : 0); if (curPageHeight > pageRect.Height()) { curPageHeight = fContentView->fTextView->TextHeight( - fromLine, --lastLine) + ((curPage == 1) - ? header_height : 0); + fromLine, --lastLine) + (curPage == 1 ? header_height : 0); } curPageRect.bottom = curPageRect.top + curPageHeight - 1.0; - if ((curPage >= print.FirstPage()) - && (curPage <= print.LastPage())) { + if (curPage >= print.FirstPage() && curPage <= print.LastPage()) { print.DrawView(fContentView->fTextView, curPageRect, - BPoint(0.0, (curPage == 1) ? header_height : 0.0)); + BPoint(0.0, curPage == 1 ? header_height : 0.0)); print.SpoolPage(); } @@ -2072,8 +2064,8 @@ TMailWindow::PrintSetup() void -TMailWindow::SetTo(const char *mailTo, const char *subject, const char *ccTo, - const char *bccTo, const BString *body, BMessage *enclosures) +TMailWindow::SetTo(const char* mailTo, const char* subject, const char* ccTo, + const char* bccTo, const BString* body, BMessage* enclosures) { Lock(); @@ -2099,7 +2091,7 @@ TMailWindow::SetTo(const char *mailTo, const char *subject, const char *ccTo, void -TMailWindow::CopyMessage(entry_ref *ref, TMailWindow *src) +TMailWindow::CopyMessage(entry_ref* ref, TMailWindow* src) { BNode file(ref); if (file.InitCheck() == B_OK) { @@ -2117,8 +2109,8 @@ TMailWindow::CopyMessage(entry_ref *ref, TMailWindow *src) fHeaderView->fCc->SetText(string.String()); } - TTextView *text = src->fContentView->fTextView; - text_run_array *style = text->RunArray(0, text->TextLength()); + TTextView* text = src->fContentView->fTextView; + text_run_array* style = text->RunArray(0, text->TextLength()); fContentView->fTextView->SetText(text->Text(), text->TextLength(), style); @@ -2127,12 +2119,12 @@ TMailWindow::CopyMessage(entry_ref *ref, TMailWindow *src) void -TMailWindow::Reply(entry_ref *ref, TMailWindow *window, uint32 type) +TMailWindow::Reply(entry_ref* ref, TMailWindow* window, uint32 type) { fRepliedMail = *ref; SetOriginatingWindow(window); - BEmailMessage *mail = window->Mail(); + BEmailMessage* mail = window->Mail(); if (mail == NULL) return; @@ -2167,10 +2159,10 @@ TMailWindow::Reply(entry_ref *ref, TMailWindow *window, uint32 type) else fHeaderView->fAccountID = accountID; - BMenu *menu = fHeaderView->fAccountMenu; + BMenu* menu = fHeaderView->fAccountMenu; for (int32 i = menu->CountItems(); i-- > 0;) { - BMenuItem *item = menu->ItemAt(i); - BMessage *msg; + BMenuItem* item = menu->ItemAt(i); + BMessage* msg; if (item && (msg = item->Message()) != NULL && msg->FindInt32("id") == fHeaderView->fAccountID) item->SetMarked(true); @@ -2204,7 +2196,7 @@ TMailWindow::Reply(entry_ref *ref, TMailWindow *window, uint32 type) int32 finish, start; window->fContentView->fTextView->GetSelection(&start, &finish); if (start != finish) { - char *text = (char *)malloc(finish - start + 1); + char* text = (char*)malloc(finish - start + 1); if (text == NULL) return; @@ -2219,11 +2211,11 @@ TMailWindow::Reply(entry_ref *ref, TMailWindow *window, uint32 type) finish = fContentView->fTextView->CountLines(); for (int32 loop = 0; loop < finish; loop++) { fContentView->fTextView->GoToLine(loop); - fContentView->fTextView->Insert((const char *)QUOTE); + fContentView->fTextView->Insert((const char*)QUOTE); } if (fApp->ColoredQuotes()) { - const BFont *font = fContentView->fTextView->Font(); + const BFont* font = fContentView->fTextView->Font(); int32 length = fContentView->fTextView->TextLength(); TextRunArray style(length / 8 + 8); @@ -2433,9 +2425,9 @@ TMailWindow::Send(bool now) characterSetToUse, encodingForBody); if (fEnclosuresView != NULL) { - TListItem *item; + TListItem* item; int32 index = 0; - while ((item = (TListItem *)fEnclosuresView->fList->ItemAt(index++)) + while ((item = (TListItem*)fEnclosuresView->fList->ItemAt(index++)) != NULL) { if (item->Component()) continue; @@ -2489,7 +2481,7 @@ TMailWindow::Send(bool now) BAlert* alert = new BAlert("no daemon", B_TRANSLATE("The mail_daemon is not running. The message is " - "queued and will be sent when the mail_daemon is started."), + "queued and will be sent when the mail_daemon is started."), B_TRANSLATE("Start now"), B_TRANSLATE("OK")); alert->SetShortcut(1, B_ESCAPE); int32 start = alert->Go(); @@ -2529,7 +2521,8 @@ TMailWindow::Send(bool now) if (result != B_NO_ERROR && result != B_MAIL_NO_DAEMON) { beep(); - BAlert* alert = new BAlert("", errorMessage.String(), B_TRANSLATE("OK")); + BAlert* alert = new BAlert("", errorMessage.String(), + B_TRANSLATE("OK")); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); } @@ -2547,20 +2540,20 @@ TMailWindow::Send(bool now) status_t TMailWindow::SaveAsDraft() { - status_t status; - BPath draftPath; - BDirectory dir; - BFile draft; - uint32 flags = 0; + BPath draftPath; + BDirectory dir; + BFile draft; + uint32 flags = 0; if (fDraft) { - if ((status = draft.SetTo(fRef, - B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE)) != B_OK) { + status_t status = draft.SetTo(fRef, + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + if (status != B_OK) return status; - } } else { // Get the user home directory - if ((status = find_directory(B_USER_DIRECTORY, &draftPath)) != B_OK) + status_t status = find_directory(B_USER_DIRECTORY, &draftPath); + if (status != B_OK) return status; // Append the relative path of the draft directory @@ -2588,12 +2581,18 @@ TMailWindow::SaveAsDraft() uint32 originalLength = strlen(fileName); // convert /, \ and : to - - for (char *bad = fileName; (bad = strchr(bad, '/')) != NULL; - ++bad) *bad = '-'; - for (char *bad = fileName; (bad = strchr(bad, '\\')) != NULL; - ++bad) *bad = '-'; - for (char *bad = fileName; (bad = strchr(bad, ':')) != NULL; - ++bad) *bad = '-'; + for (char* bad = fileName; (bad = strchr(bad, '/')) != NULL; + ++bad) { + *bad = '-'; + } + for (char* bad = fileName; (bad = strchr(bad, '\\')) != NULL; + ++bad) { + *bad = '-'; + } + for (char* bad = fileName; (bad = strchr(bad, ':')) != NULL; + ++bad) { + *bad = '-'; + } // Create the file; if the name exists, find a unique name flags = B_WRITE_ONLY | B_CREATE_FILE | B_FAIL_IF_EXISTS; @@ -2627,9 +2626,7 @@ TMailWindow::SaveAsDraft() draft.Write(fContentView->fTextView->Text(), fContentView->fTextView->TextLength()); - // // Add the header stuff as attributes - // WriteAttrString(&draft, B_MAIL_ATTR_NAME, fHeaderView->fTo->Text()); WriteAttrString(&draft, B_MAIL_ATTR_TO, fHeaderView->fTo->Text()); WriteAttrString(&draft, B_MAIL_ATTR_SUBJECT, fHeaderView->fSubject->Text()); @@ -2654,12 +2651,11 @@ TMailWindow::SaveAsDraft() // Add Attachment paths in attribute if (fEnclosuresView != NULL) { - TListItem *item; - BPath path; + TListItem* item; BString pathStr; - for (int32 i = 0; (item = (TListItem *) - fEnclosuresView->fList->ItemAt(i)) != NULL; i++) { + for (int32 i = 0; (item = (TListItem*)fEnclosuresView->fList->ItemAt(i)) + != NULL; i++) { if (i > 0) pathStr.Append(":"); @@ -2667,6 +2663,7 @@ TMailWindow::SaveAsDraft() if (!entry.Exists()) continue; + BPath path; entry.GetPath(&path); pathStr.Append(path.Path()); } @@ -2688,10 +2685,9 @@ TMailWindow::SaveAsDraft() status_t -TMailWindow::TrainMessageAs(const char *CommandWord) +TMailWindow::TrainMessageAs(const char* commandWord) { status_t errorCode = -1; - char errorString[1500]; BEntry fileEntry; BPath filePath; BMessage replyMessage; @@ -2700,7 +2696,7 @@ TMailWindow::TrainMessageAs(const char *CommandWord) if (fRef == NULL) goto ErrorExit; // Need to have a real file and name. - errorCode = fileEntry.SetTo(fRef, true /* traverse */); + errorCode = fileEntry.SetTo(fRef, true); if (errorCode != B_OK) goto ErrorExit; errorCode = fileEntry.GetPath(&filePath); @@ -2717,15 +2713,17 @@ TMailWindow::TrainMessageAs(const char *CommandWord) if (errorCode != B_OK) { BPath path; entry_ref ref; - directory_which places[] - = {B_SYSTEM_NONPACKAGED_BIN_DIRECTORY, B_SYSTEM_BIN_DIRECTORY}; + directory_which places[] = {B_SYSTEM_NONPACKAGED_BIN_DIRECTORY, + B_SYSTEM_BIN_DIRECTORY}; for (int32 i = 0; i < 2; i++) { find_directory(places[i],&path); path.Append("spamdbm"); if (!BEntry(path.Path()).Exists()) continue; get_ref_for_path(path.Path(),&ref); - if ((errorCode = be_roster->Launch (&ref)) == B_OK) + + errorCode = be_roster->Launch(&ref); + if (errorCode == B_OK) break; } if (errorCode != B_OK) @@ -2751,9 +2749,9 @@ TMailWindow::TrainMessageAs(const char *CommandWord) scriptingMessage.MakeEmpty(); scriptingMessage.what = B_SET_PROPERTY; - scriptingMessage.AddSpecifier(CommandWord); + scriptingMessage.AddSpecifier(commandWord); errorCode = scriptingMessage.AddData("data", B_STRING_TYPE, - filePath.Path(), strlen(filePath.Path()) + 1, false /* fixed size */); + filePath.Path(), strlen(filePath.Path()) + 1, false); if (errorCode != B_OK) goto ErrorExit; replyMessage.MakeEmpty(); @@ -2770,9 +2768,10 @@ TMailWindow::TrainMessageAs(const char *CommandWord) ErrorExit: beep(); - sprintf(errorString, "Unable to train the message file \"%s\" as %s. " - "Possibly useful error code: %s (%" B_PRId32 ").", - filePath.Path(), CommandWord, strerror(errorCode), errorCode); + char errorString[1500]; + snprintf(errorString, sizeof(errorString), "Unable to train the message " + "file \"%s\" as %s. Possibly useful error code: %s (%" B_PRId32 ").", + filePath.Path(), commandWord, strerror(errorCode), errorCode); BAlert* alert = new BAlert("", errorString, B_TRANSLATE("OK")); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); @@ -2784,9 +2783,7 @@ ErrorExit: void TMailWindow::SetTitleForMessage() { - // - // Figure out the title of this message and set the title bar - // + // Figure out the title of this message and set the title bar BString title = B_TRANSLATE_SYSTEM_NAME("Mail"); if (fIncoming) { @@ -2800,19 +2797,19 @@ TMailWindow::SetTitleForMessage() if (fApp->ShowSpamGUI() && fRef != NULL) { BString classification; - BNode node (fRef); - char numberString [30]; - BString oldTitle (title); - float spamRatio; - if (node.InitCheck() != B_OK || node.ReadAttrString - ("MAIL:classification", &classification) != B_OK) + BNode node(fRef); + char numberString[30]; + BString oldTitle(title); + float spamRatio; + if (node.InitCheck() != B_OK || node.ReadAttrString( + "MAIL:classification", &classification) != B_OK) classification = "Unrated"; if (classification != "Spam" && classification != "Genuine") { // Uncertain, Unrated and other unknown classes, show the ratio. - if (node.InitCheck() == B_OK && sizeof (spamRatio) == - node.ReadAttr("MAIL:ratio_spam", B_FLOAT_TYPE, 0, - &spamRatio, sizeof (spamRatio))) { - sprintf (numberString, "%.4f", spamRatio); + if (node.InitCheck() == B_OK && node.ReadAttr("MAIL:ratio_spam", + B_FLOAT_TYPE, 0, &spamRatio, sizeof(spamRatio)) + == sizeof(spamRatio)) { + sprintf(numberString, "%.4f", spamRatio); classification << " " << numberString; } } @@ -2824,20 +2821,17 @@ TMailWindow::SetTitleForMessage() } -// -// Open *another* message in the existing mail window. Some code here is -// duplicated from various constructors. -// The duplicated code should be in a private initializer method -- axeld. -// - +/*! Open *another* message in the existing mail window. Some code here is + duplicated from various constructors. + TODO: The duplicated code should be moved to a private initializer method +*/ status_t -TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) +TMailWindow::OpenMessage(const entry_ref* ref, uint32 characterSetForDecoding) { if (ref == NULL) return B_ERROR; - // - // Set some references to the email file - // + + // Set some references to the email file delete fRef; fRef = new entry_ref(*ref); @@ -2907,8 +2901,8 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) BMessage msg(REFS_RECEIVED); entry_ref enc_ref; - char *s = strtok((char *)string.String(), ":"); - while (s) { + char* s = strtok((char*)string.String(), ":"); + while (s != NULL) { BEntry entry(s, true); if (entry.Exists()) { entry.GetRef(&enc_ref); @@ -2942,10 +2936,8 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) SetTitleForMessage(); if (fIncoming) { - // // Put the addresses in the 'Save Address' Menu - // - BMenuItem *item; + BMenuItem* item; while ((item = fSaveAddrMenu->RemoveItem((int32)0)) != NULL) delete item; @@ -2957,10 +2949,10 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) get_address_list(addressList, fMail->From(), extract_address); get_address_list(addressList, fMail->ReplyTo(), extract_address); - BMessage *msg; + BMessage* msg; for (int32 i = addressList.CountItems(); i-- > 0;) { - char *address = (char *)addressList.RemoveItem((int32)0); + char* address = (char*)addressList.RemoveItem((int32)0); // insert the new address in alphabetical order int32 index = 0; @@ -2984,9 +2976,7 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) free(address); } - // // Clear out existing contents of text view. - // fContentView->fTextView->SetText("", (int32)0); fContentView->fTextView->LoadMessage(fMail, false, NULL); @@ -2999,50 +2989,17 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) } -TMailWindow * +TMailWindow* TMailWindow::FrontmostWindow() { BAutolock locker(sWindowListLock); if (sWindowList.CountItems() > 0) - return (TMailWindow *)sWindowList.ItemAt(0); + return (TMailWindow*)sWindowList.ItemAt(0); return NULL; } -/* -// Copied from src/kits/tracker/FindPanel.cpp. -uint32 -TMailWindow::InitialMode(const BNode *node) -{ - if (!node || node->InitCheck() != B_OK) - return kByNameItem; - - uint32 result; - if (node->ReadAttr(kAttrQueryInitialMode, B_INT32_TYPE, 0, - (int32 *)&result, sizeof(int32)) <= 0) - return kByNameItem; - - return result; -} - - -// Copied from src/kits/tracker/FindPanel.cpp. -int32 -TMailWindow::InitialAttrCount(const BNode *node) -{ - if (!node || node->InitCheck() != B_OK) - return 1; - - int32 result; - if (node->ReadAttr(kAttrQueryInitialNumAttrs, B_INT32_TYPE, 0, - &result, sizeof(int32)) <= 0) - return 1; - - return result; -}*/ - - // #pragma mark - @@ -3168,7 +3125,7 @@ TMailWindow::_BuildQueryString(BEntry* entry) const { int32 count = 1; if (node.ReadAttr(kAttrQueryInitialNumAttrs, B_INT32_TYPE, 0, - (int32 *)&count, sizeof(int32)) <= 0) { + (int32*)&count, sizeof(int32)) <= 0) { count = 1; } @@ -3179,14 +3136,14 @@ TMailWindow::_BuildQueryString(BEntry* entry) const if (count > 1) queryString << "("; - char *buffer = new char[info.size]; + char* buffer = new char[info.size]; if (node.ReadAttr(kAttrQueryInitialAttrs, B_MESSAGE_TYPE, 0, buffer, (size_t)info.size) == info.size) { BMessage message; if (message.Unflatten(buffer) == B_OK) { for (int32 index = 0; /*index < count*/; index++) { - const char *field; - const char *value; + const char* field; + const char* value; if (message.FindString("menuSelection", index, &field) != B_OK || message.FindString("attrViewText", index, &value) diff --git a/src/apps/mail/MailWindow.h b/src/apps/mail/MailWindow.h index 8b2294b3fb..6713f6eb85 100644 --- a/src/apps/mail/MailWindow.h +++ b/src/apps/mail/MailWindow.h @@ -65,153 +65,156 @@ class BMenuBar; class BMenuItem; class Words; + class TMailWindow : public BWindow { - public: +public: TMailWindow(BRect frame, const char* title, TMailApp* app, const entry_ref* ref, const char* to, const BFont *font, bool resending, BMessenger* trackerMessenger); - virtual ~TMailWindow(); + virtual ~TMailWindow(); - virtual void FrameResized(float width, float height); - virtual void MenusBeginning(); - virtual void MessageReceived(BMessage*); - virtual bool QuitRequested(); - virtual void Show(); - virtual void Zoom(BPoint, float, float); - virtual void WindowActivated(bool state); + virtual void FrameResized(float width, float height); + virtual void MenusBeginning(); + virtual void MessageReceived(BMessage*); + virtual bool QuitRequested(); + virtual void Show(); + virtual void Zoom(BPoint, float, float); + virtual void WindowActivated(bool state); - void SetTo(const char* mailTo, const char* subject, + void SetTo(const char* mailTo, const char* subject, const char* ccTo = NULL, const char* bccTo = NULL, const BString* body = NULL, BMessage* enclosures = NULL); - void AddSignature(BMailMessage*); - void Forward(entry_ref*, TMailWindow*, + void AddSignature(BMailMessage*); + void Forward(entry_ref*, TMailWindow*, bool includeAttachments); - void Print(); - void PrintSetup(); - void Reply(entry_ref*, TMailWindow*, uint32); - void CopyMessage(entry_ref* ref, TMailWindow* src); - status_t Send(bool); - status_t SaveAsDraft(); - status_t OpenMessage(const entry_ref* ref, + void Print(); + void PrintSetup(); + void Reply(entry_ref*, TMailWindow*, uint32); + void CopyMessage(entry_ref* ref, TMailWindow* src); + status_t Send(bool now); + status_t SaveAsDraft(); + status_t OpenMessage(const entry_ref* ref, uint32 characterSetForDecoding = B_MAIL_NULL_CONVERSION); - status_t GetMailNodeRef(node_ref &nodeRef) const; - BEmailMessage* Mail() const { return fMail; } + status_t GetMailNodeRef(node_ref &nodeRef) const; + BEmailMessage* Mail() const { return fMail; } - bool GetTrackerWindowFile(entry_ref*, + bool GetTrackerWindowFile(entry_ref*, bool dir) const; - void SaveTrackerPosition(entry_ref*); - void SetOriginatingWindow(BWindow* window); + void SaveTrackerPosition(entry_ref*); + void SetOriginatingWindow(BWindow* window); - void PreserveReadingPos(bool save); - void MarkMessageRead(entry_ref* message, + void PreserveReadingPos(bool save); + void MarkMessageRead(entry_ref* message, read_flags flag); - void SetTrackerSelectionToCurrent(); - TMailWindow* FrontmostWindow(); - void UpdateViews(); - void UpdatePreferences(); + void SetTrackerSelectionToCurrent(); + TMailWindow* FrontmostWindow(); + void UpdateViews(); + void UpdatePreferences(); - protected: - void SetTitleForMessage(); - void AddEnclosure(BMessage* msg); - void BuildToolBar(); - status_t TrainMessageAs(const char* commandWord); +protected: + void SetTitleForMessage(); + void AddEnclosure(BMessage* msg); + void BuildToolBar(); + status_t TrainMessageAs(const char* commandWord); - private: - void _UpdateSizeLimits(); +private: + void _UpdateSizeLimits(); - status_t _GetQueryPath(BPath* path) const; - void _RebuildQueryMenu(bool firstTime = false); - char* _BuildQueryString(BEntry* entry) const; + status_t _GetQueryPath(BPath* path) const; + void _RebuildQueryMenu(bool firstTime = false); + char* _BuildQueryString(BEntry* entry) const; - void _AddReadButton(); - void _UpdateReadButton(); + void _AddReadButton(); + void _UpdateReadButton(); - void _SetDownloading(bool downloading); + void _SetDownloading(bool downloading); - TMailApp* fApp; + static BBitmap* _RetrieveVectorIcon(int32 id); - BEmailMessage* fMail; - entry_ref* fRef; - // Reference to currently displayed file - int32 fFieldState; - BFilePanel* fPanel; - BMenuBar* fMenuBar; - BMenuItem* fAdd; - BMenuItem* fCut; - BMenuItem* fCopy; - BMenuItem* fHeader; - BMenuItem* fPaste; - BMenuItem* fPrint; - BMenuItem* fPrintSetup; - BMenuItem* fQuote; - BMenuItem* fRaw; - BMenuItem* fRemove; - BMenuItem* fRemoveQuote; - BMenuItem* fSendNow; - BMenuItem* fSendLater; - BMenuItem* fUndo; - BMenuItem* fRedo; - BMenuItem* fNextMsg; - BMenuItem* fPrevMsg; - BMenuItem* fDeleteNext; - BMenuItem* fSpelling; - BMenu* fSaveAddrMenu; +private: + TMailApp* fApp; - BMenu* fQueryMenu; - BMenu* fLeaveStatusMenu; + BEmailMessage* fMail; + entry_ref* fRef; + // Reference to currently displayed file + int32 fFieldState; + BFilePanel* fPanel; + BMenuBar* fMenuBar; + BMenuItem* fAdd; + BMenuItem* fCut; + BMenuItem* fCopy; + BMenuItem* fHeader; + BMenuItem* fPaste; + BMenuItem* fPrint; + BMenuItem* fPrintSetup; + BMenuItem* fQuote; + BMenuItem* fRaw; + BMenuItem* fRemove; + BMenuItem* fRemoveQuote; + BMenuItem* fSendNow; + BMenuItem* fSendLater; + BMenuItem* fUndo; + BMenuItem* fRedo; + BMenuItem* fNextMsg; + BMenuItem* fPrevMsg; + BMenuItem* fDeleteNext; + BMenuItem* fSpelling; + BMenu* fSaveAddrMenu; - static BBitmap* _RetrieveVectorIcon(int32 id); - struct BitmapItem { - BBitmap* bm; - int32 id; - }; - static BObjectList fBitmapCache; - static BLocker fBitmapCacheLock; + BMenu* fQueryMenu; + BMenu* fLeaveStatusMenu; - BToolBar* fToolBar; + struct BitmapItem { + BBitmap* bm; + int32 id; + }; + static BObjectList sBitmapCache; + static BLocker sBitmapCacheLock; - BRect fZoom; - TContentView* fContentView; - THeaderView* fHeaderView; - TEnclosuresView* fEnclosuresView; - TMenu* fSignature; + BToolBar* fToolBar; - BMessenger fTrackerMessenger; - // Talks to tracker window that this was launched from. - BMessenger fMessengerToSpamServer; + BRect fZoom; + TContentView* fContentView; + THeaderView* fHeaderView; + TEnclosuresView* fEnclosuresView; + TMenu* fSignature; - entry_ref fPrevRef; - entry_ref fNextRef; - bool fPrevTrackerPositionSaved : 1; - bool fNextTrackerPositionSaved : 1; + BMessenger fTrackerMessenger; + // Talks to tracker window that this was launched from. + BMessenger fMessengerToSpamServer; - entry_ref fOpenFolder; + entry_ref fPrevRef; + entry_ref fNextRef; + bool fPrevTrackerPositionSaved : 1; + bool fNextTrackerPositionSaved : 1; - bool fSigAdded : 1; - bool fIncoming : 1; - bool fReplying : 1; - bool fResending : 1; - bool fSent : 1; - bool fDraft : 1; - bool fChanged : 1; + entry_ref fOpenFolder; - static BList sWindowList; - static BLocker sWindowListLock; + bool fSigAdded : 1; + bool fIncoming : 1; + bool fReplying : 1; + bool fResending : 1; + bool fSent : 1; + bool fDraft : 1; + bool fChanged : 1; - entry_ref fRepliedMail; - BMessenger* fOriginatingWindow; + static BList sWindowList; + static BLocker sWindowListLock; - bool fAutoMarkRead : 1; - bool fKeepStatusOnQuit; + entry_ref fRepliedMail; + BMessenger* fOriginatingWindow; - bool fDownloading; + bool fAutoMarkRead : 1; + bool fKeepStatusOnQuit; + + bool fDownloading; }; -#endif // _MAIL_WINDOW_H +#endif // _MAIL_WINDOW_H From 92a3fa86dbc1f99f2c063a967fc650da499bad34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 17 Aug 2015 21:13:47 +0200 Subject: [PATCH 036/125] Add ncurses6 packages, update cmake, mpg123, unrar packages. --- build/jam/repositories/HaikuPorts/x86 | 13 +++++++++---- build/jam/repositories/HaikuPorts/x86_64 | 11 +++++++---- build/jam/repositories/HaikuPorts/x86_gcc2 | 17 +++++++++++------ 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86 b/build/jam/repositories/HaikuPorts/x86 index 73e98ef6f8..4deb6e4c6e 100644 --- a/build/jam/repositories/HaikuPorts/x86 +++ b/build/jam/repositories/HaikuPorts/x86 @@ -37,7 +37,7 @@ RemotePackageRepository HaikuPorts clang-3.4-3 clang_analysis-3.4-3 clipdinger-0.4-1 - cmake-3.3.0-1 + cmake-3.3.1-1 coreutils-8.24-1 cpio-2.10-1 ctags-5.8-3 @@ -175,12 +175,14 @@ RemotePackageRepository HaikuPorts mpc_devel-1.0.3-1 mpfr-3.1.3-1 mpfr_devel-3.1.3-1 - mpg123-1.22.3-1 - mpg123_devel-1.22.3-1 + mpg123-1.22.4-1 + mpg123_devel-1.22.4-1 nano-2.4.2-1 nasm-2.11.08-1 ncurses-5.9-10 ncurses_devel-5.9-10 + ncurses6-6.0-1 + ncurses6_devel-6.0-1 neon-0.29.6-7 neon_devel-0.29.6-7 netcat-1.10-1 @@ -226,7 +228,7 @@ RemotePackageRepository HaikuPorts tinyxml-2.6.2-1 tinyxml_devel-2.6.2-1 transmission-2.84-3 - unrar-5.1.5-1 + unrar-5.3.2-1 unzip-6.0-2 vision-0.9.7.r949-3 vim-7.4-1 @@ -303,6 +305,8 @@ RemotePackageRepository HaikuPorts mesa_x86_gcc2_swrast-7.9.2-5 ncurses_x86_gcc2-5.9-10 ncurses_x86_gcc2_devel-5.9-10 + ncurses6_x86_gcc2-6.0-1 + ncurses6_x86_gcc2_devel-6.0-1 openssl_x86_gcc2-1.0.0s-1 openssl_x86_gcc2_devel-1.0.0s-1 pkgconfig_x86_gcc2-0.27.1-2 @@ -419,6 +423,7 @@ RemotePackageRepository HaikuPorts nano nasm ncurses + ncurses6 neon netcat openssh diff --git a/build/jam/repositories/HaikuPorts/x86_64 b/build/jam/repositories/HaikuPorts/x86_64 index f948ca9c62..9556628848 100644 --- a/build/jam/repositories/HaikuPorts/x86_64 +++ b/build/jam/repositories/HaikuPorts/x86_64 @@ -59,7 +59,7 @@ RemotePackageRepository HaikuPorts clang-3.5.1-1 clang_analysis-3.5.1-1 clipdinger-0.4-1 - cmake-3.3.0-1 + cmake-3.3.1-1 coreutils-8.24-1 cppunit-1.12.1-2 cppunit_devel-1.12.1-2 @@ -248,12 +248,14 @@ RemotePackageRepository HaikuPorts mpc_devel-1.0.3-1 mpfr-3.1.3-1 mpfr_devel-3.1.3-1 - mpg123-1.22.3-1 - mpg123_devel-1.22.3-1 + mpg123-1.22.4-1 + mpg123_devel-1.22.4-1 nano-2.4.2-1 nasm-2.11.08-1 ncurses-5.9-10 ncurses_devel-5.9-10 + ncurses6-6.0-1 + ncurses6_devel-6.0-1 neon-0.29.6-7 neon_devel-0.29.6-7 netcat-1.10-1 @@ -306,7 +308,7 @@ RemotePackageRepository HaikuPorts tinyxml-2.6.2-1 tinyxml_devel-2.6.2-1 transmission-2.84-3 - unrar-5.1.5-1 + unrar-5.3.2-1 unzip-6.0-2 vim-7.4-2 vision-0.9.7.r949-3 @@ -444,6 +446,7 @@ RemotePackageRepository HaikuPorts nano nasm ncurses + ncurses6 neon netcat ninja diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index f496cf0737..88fe445cd3 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -345,8 +345,8 @@ RemotePackageRepository HaikuPorts moe-1.1.2-1 mog-0.63.1548-1 most-pre5.1_15-1 - mpg123-1.22.3-1 - mpg123_devel-1.22.3-1 + mpg123-1.22.4-1 + mpg123_devel-1.22.4-1 mtr-0.73-1 multitalk-1.4-1 mupdf-1.7-1 @@ -358,6 +358,8 @@ RemotePackageRepository HaikuPorts nasm-2.11.08-1 ncurses-5.9-9 ncurses_devel-5.9-9 + ncurses6-6.0-1 + ncurses6_devel-6.0-1 neon-0.29.6-6 neon_devel-0.29.6-6 netcat-1.10-1 @@ -476,7 +478,7 @@ RemotePackageRepository HaikuPorts twolame-0.3.13-1 twolame_devel-0.3.13-1 ubertuber-0.9.11-1 - unrar-5.2.6-1 + unrar-5.3.2-1 unzip-6.0-2 util_macros-1.19.0-2 vasm-1.7c-1 @@ -553,7 +555,7 @@ RemotePackageRepository HaikuPorts cairo_x86_devel-1.12.18-1 capstone_x86-3.0.4-1 capstone_x86_devel-3.0.4-1 - cmake_x86-3.3.0-1 + cmake_x86-3.3.1-1 confuse_x86-2.7-2 confuse_x86_devel-2.7-2 copynametoclipboard-1.0.1-2 @@ -767,8 +769,8 @@ RemotePackageRepository HaikuPorts mpd_x86-0.18.12_git-1 mpfr_x86-3.1.3-1 mpfr_x86_devel-3.1.3-1 - mpg123_x86-1.22.3-1 - mpg123_x86_devel-1.22.3-1 + mpg123_x86-1.22.4-1 + mpg123_x86_devel-1.22.4-1 mplayer_x86-1.1.1-3 mupdf_x86-1.7-1 mupdf_x86_devel-1.7-1 @@ -776,6 +778,8 @@ RemotePackageRepository HaikuPorts musicpc_x86-0.26-1 ncurses_x86-5.9-9 ncurses_x86_devel-5.9-9 + ncurses6_x86-6.0-1 + ncurses6_x86_devel-6.0-1 ninja_x86-1.5.1-2 ocp_x86-0.1.21_git-1 openal_x86-1.13.0-2 @@ -1190,6 +1194,7 @@ RemotePackageRepository HaikuPorts nano nasm ncurses + ncurses6 neon netcat netpulse From 1ecd2c816383d6ad83fd8beeaf738ce19f39b9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 18 Aug 2015 21:10:04 +0200 Subject: [PATCH 037/125] Add libasr, freeciv and its dependencies for x86_64. * Update freetype for x86_64. --- build/jam/repositories/HaikuPorts/x86_64 | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86_64 b/build/jam/repositories/HaikuPorts/x86_64 index 9556628848..2dd5299d27 100644 --- a/build/jam/repositories/HaikuPorts/x86_64 +++ b/build/jam/repositories/HaikuPorts/x86_64 @@ -88,8 +88,9 @@ RemotePackageRepository HaikuPorts fontconfig-2.11.1-3 fontconfig_devel-2.11.1-3 fossil-1.33-1 - freetype-2.6-1 - freetype_devel-2.6-1 + freeciv-2.5.1-1 + freetype-2.6-2 + freetype_devel-2.6-2 fribidi-0.19.6-2 fribidi_devel-0.19.6-2 gawk-4.1.0-2 @@ -153,6 +154,8 @@ RemotePackageRepository HaikuPorts lcms-2.7-1 lcms_devel-2.7-1 less-451-4 + libasr-1.0.2-1 + libasr_devel-1.0.2-1 libass-0.12.2-1 libass_devel-0.12.2-1 libassuan-2.2.0-1 @@ -177,6 +180,10 @@ RemotePackageRepository HaikuPorts libicns_devel-0.8.1-1 libiconv-1.13.1-6 libiconv_devel-1.13.1-6 + libmad-0.15.1b-2 + libmad_devel-0.15.1b-2 + libmikmod-3.3.7-1 + libmikmod_devel-3.3.7-1 libmkv-0.6.5.1-3 libmkv_devel-0.6.5.1-3 libmp4v2-2.0.0-2 @@ -287,6 +294,10 @@ RemotePackageRepository HaikuPorts sdl_gfx_devel-2.0.25-2 sdl_image-1.2.12-5 sdl_image_devel-1.2.12-5 + sdl_mixer-1.2.12-6 + sdl_mixer_devel-1.2.12-6 + sdl_ttf-2.0.11-2 + sdl_ttf_devel-2.0.11-2 sed-4.2.1-6 serf-1.3.7-1 serf_devel-1.3.7-1 @@ -360,6 +371,7 @@ RemotePackageRepository HaikuPorts flex fontconfig fossil + freeciv freetype fribidi gawk @@ -394,6 +406,7 @@ RemotePackageRepository HaikuPorts lame lcms less + libasr libass libassuan libbluray @@ -406,6 +419,8 @@ RemotePackageRepository HaikuPorts libgpg_error libicns libiconv + libmad + libmikmod libmkv libmp4v2 libmpeg2 @@ -469,6 +484,8 @@ RemotePackageRepository HaikuPorts scons sdl_gfx sdl_image + sdl_mixer + sdl_ttf sed serf sharutils From 36c3cc97320f57550a298c181f3a75bc4327a212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 19 Aug 2015 21:31:46 +0200 Subject: [PATCH 038/125] Update bash packages. --- build/jam/repositories/HaikuPorts/x86 | 2 +- build/jam/repositories/HaikuPorts/x86_64 | 2 +- build/jam/repositories/HaikuPorts/x86_gcc2 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86 b/build/jam/repositories/HaikuPorts/x86 index 4deb6e4c6e..cf0a2fee84 100644 --- a/build/jam/repositories/HaikuPorts/x86 +++ b/build/jam/repositories/HaikuPorts/x86 @@ -22,7 +22,7 @@ RemotePackageRepository HaikuPorts apr_util_devel-1.4.1-4 autoconf-2.69-6 automake-1.13.1-4 - bash-4.3.39-1 + bash-4.3.42-1 beam-1.2-1 bepdf-1.2.0-1 bescreencapture-1.9.4-1 diff --git a/build/jam/repositories/HaikuPorts/x86_64 b/build/jam/repositories/HaikuPorts/x86_64 index 2dd5299d27..5f30837cac 100644 --- a/build/jam/repositories/HaikuPorts/x86_64 +++ b/build/jam/repositories/HaikuPorts/x86_64 @@ -23,7 +23,7 @@ RemotePackageRepository HaikuPorts apr_util_devel-1.5.4-1 autoconf-2.69-6 automake-1.13.1-4 - bash-4.3.39-1 + bash-4.3.42-1 # bepdf-1.1.1~beta5_2013_04_28-1 binutils-2.25_12015_07_31-1 bison-2.6.5-1 diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 88fe445cd3..bdcb2c9234 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -43,7 +43,7 @@ RemotePackageRepository HaikuPorts autoconf-2.69-5 automake-1.13.1-4 avra-1.3.0-1 - bash-4.3.39-1 + bash-4.3.42-1 beae-1.2-3 beam-1.2-1 becjk-1.0.1-1 From 36ab52c74eb0e51bc6540dfc3f1dd5a26bd779f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Thu, 20 Aug 2015 16:25:07 +0200 Subject: [PATCH 039/125] HaikuDepot: Adapt package contents when package status changes Based on a patch in ticket #11886 by TwoFx, but with checks for packageRef.Get() != NULL and better member name for the package status. --- src/apps/haikudepot/ui/PackageContentsView.cpp | 12 ++++++++++-- src/apps/haikudepot/ui/PackageContentsView.h | 1 + src/apps/haikudepot/ui/PackageInfoView.cpp | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/apps/haikudepot/ui/PackageContentsView.cpp b/src/apps/haikudepot/ui/PackageContentsView.cpp index 6e6b08cc52..17f0384325 100644 --- a/src/apps/haikudepot/ui/PackageContentsView.cpp +++ b/src/apps/haikudepot/ui/PackageContentsView.cpp @@ -239,7 +239,8 @@ private: PackageContentsView::PackageContentsView(const char* name) : BView("package_contents_view", B_WILL_DRAW), - fPackageLock("package contents populator lock") + fPackageLock("package contents populator lock"), + fLastPackageState(NONE) { fContentListView = new BOutlineListView("content list view", B_SINGLE_SELECTION_LIST); @@ -283,8 +284,14 @@ PackageContentsView::AllAttached() void PackageContentsView::SetPackage(const PackageInfoRef& package) { - if (fPackage == package) + // When getting a ref to the same package, don't return when the + // package state has changed, since in that case, we may now be able + // to read contents where we previously could not. (For example, the + // package has been installed.) + if (fPackage == package + && (package.Get() == NULL || package->State() == fLastPackageState)) { return; + } // printf("PackageContentsView::SetPackage(%s)\n", // package.Get() != NULL ? package->Name().String() : "NULL"); @@ -294,6 +301,7 @@ PackageContentsView::SetPackage(const PackageInfoRef& package) { BAutolock lock(&fPackageLock); fPackage = package; + fLastPackageState = package.Get() != NULL ? package->State() : NONE; } release_sem_etc(fContentPopulatorSem, 1, 0); } diff --git a/src/apps/haikudepot/ui/PackageContentsView.h b/src/apps/haikudepot/ui/PackageContentsView.h index 2cd58a2f09..136a53c459 100644 --- a/src/apps/haikudepot/ui/PackageContentsView.h +++ b/src/apps/haikudepot/ui/PackageContentsView.h @@ -39,6 +39,7 @@ private: sem_id fContentPopulatorSem; BLocker fPackageLock; PackageInfoRef fPackage; + PackageState fLastPackageState; }; #endif // PACKAGE_CONTENTS_VIEW_H diff --git a/src/apps/haikudepot/ui/PackageInfoView.cpp b/src/apps/haikudepot/ui/PackageInfoView.cpp index 5d95ce4387..03178c5e94 100644 --- a/src/apps/haikudepot/ui/PackageInfoView.cpp +++ b/src/apps/haikudepot/ui/PackageInfoView.cpp @@ -1426,6 +1426,7 @@ PackageInfoView::MessageReceived(BMessage* message) } if ((changes & PKG_CHANGED_STATE) != 0) { + fPagesView->SetPackage(package, false); fPackageActionView->SetPackage(*package.Get()); } From 883b3e1d5cd632bb1a86def5d39a3eebf32ace13 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 17 Aug 2015 21:51:30 +0200 Subject: [PATCH 040/125] DebugAnalyzer: Fix 64 bit build. --- src/apps/debuganalyzer/DebugAnalyzer.cpp | 8 ++-- .../chart/BigtimeChartAxisLegendSource.cpp | 2 +- .../gui/chart/LegendChartAxis.cpp | 2 +- .../chart/NanotimeChartAxisLegendSource.cpp | 2 +- .../gui/main_window/GeneralPage.cpp | 4 +- .../gui/main_window/SchedulingPage.cpp | 17 ++++---- .../gui/main_window/ThreadsPage.cpp | 4 +- .../gui/thread_window/GeneralPage.cpp | 10 ++--- .../gui/thread_window/ThreadWindow.cpp | 4 +- src/apps/debuganalyzer/model/Model.cpp | 6 +-- .../model_loader/ModelLoader.cpp | 39 ++++++++++--------- .../model_loader/ThreadModelLoader.cpp | 4 +- 12 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/apps/debuganalyzer/DebugAnalyzer.cpp b/src/apps/debuganalyzer/DebugAnalyzer.cpp index d800cfba7a..d319604165 100644 --- a/src/apps/debuganalyzer/DebugAnalyzer.cpp +++ b/src/apps/debuganalyzer/DebugAnalyzer.cpp @@ -38,11 +38,11 @@ printf("ReadyToRun()\n"); PostMessage(B_QUIT_REQUESTED); } - virtual void ArgvReceived(int32 argc, char** argv) + virtual void ArgvReceived(int32 argc, char** argv) { -printf("ArgvReceived()\n"); -for (int32 i = 0; i < argc; i++) -printf(" arg %ld: \"%s\"\n", i, argv[i]); + printf("ArgvReceived()\n"); + for (int32 i = 0; i < argc; i++) + printf(" arg %" B_PRId32 ": \"%s\"\n", i, argv[i]); for (int32 i = 1; i < argc; i++) { PathDataSource* dataSource = new(std::nothrow) PathDataSource; diff --git a/src/apps/debuganalyzer/gui/chart/BigtimeChartAxisLegendSource.cpp b/src/apps/debuganalyzer/gui/chart/BigtimeChartAxisLegendSource.cpp index 2a58e071b8..364c50e68d 100644 --- a/src/apps/debuganalyzer/gui/chart/BigtimeChartAxisLegendSource.cpp +++ b/src/apps/debuganalyzer/gui/chart/BigtimeChartAxisLegendSource.cpp @@ -59,7 +59,7 @@ BigtimeChartAxisLegendSource::GetAxisLegends(const ChartDataRange& range, decomposed_bigtime decomposed; decompose_time(time, decomposed); char buffer[128]; - snprintf(buffer, sizeof(buffer), "%02lld:%02d:%02d.%06d", + snprintf(buffer, sizeof(buffer), "%02" B_PRIu64 ":%02d:%02d.%06d", decomposed.hours, decomposed.minutes, decomposed.seconds, decomposed.micros); // TODO: Drop superfluous micro seconds digits, or even microseconds and seconds diff --git a/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp b/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp index 035f3d1326..c8bbc34cff 100644 --- a/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp +++ b/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp @@ -89,7 +89,7 @@ LegendChartAxis::_FilterLegends(int32 totalSize, int32 spacing, // Filter out all higher level legends colliding with lower level or // preceeding same-level legends. We iterate backwards from the lower to // the higher levels - for (int32 level = std::max(minLevel, 0L); level <= maxLevel;) { + for (int32 level = std::max(minLevel, (int32)0); level <= maxLevel;) { legendCount = fLegends.CountItems(); // get the first legend position/end diff --git a/src/apps/debuganalyzer/gui/chart/NanotimeChartAxisLegendSource.cpp b/src/apps/debuganalyzer/gui/chart/NanotimeChartAxisLegendSource.cpp index 49ebd4aba9..1e234b059a 100644 --- a/src/apps/debuganalyzer/gui/chart/NanotimeChartAxisLegendSource.cpp +++ b/src/apps/debuganalyzer/gui/chart/NanotimeChartAxisLegendSource.cpp @@ -60,7 +60,7 @@ NanotimeChartAxisLegendSource::GetAxisLegends(const ChartDataRange& range, decomposed_nanotime decomposed; decompose_time(time, decomposed); char buffer[128]; - snprintf(buffer, sizeof(buffer), "%02lld:%02d:%02d.%09d", + snprintf(buffer, sizeof(buffer), "%02" B_PRId64 ":%02d:%02d.%09d", decomposed.hours, decomposed.minutes, decomposed.seconds, decomposed.nanos); // TODO: Drop superfluous nanoseconds digits, or even nanoseconds and seconds diff --git a/src/apps/debuganalyzer/gui/main_window/GeneralPage.cpp b/src/apps/debuganalyzer/gui/main_window/GeneralPage.cpp index b1df7de5d9..6511319acd 100644 --- a/src/apps/debuganalyzer/gui/main_window/GeneralPage.cpp +++ b/src/apps/debuganalyzer/gui/main_window/GeneralPage.cpp @@ -68,11 +68,11 @@ MainWindow::GeneralPage::SetModel(Model* model) fIdleTimeView->SetText(buffer); // team count - snprintf(buffer, sizeof(buffer), "%ld", fModel->CountTeams()); + snprintf(buffer, sizeof(buffer), "%" B_PRId32, fModel->CountTeams()); fTeamCountView->SetText(buffer); // threads - snprintf(buffer, sizeof(buffer), "%ld", fModel->CountThreads()); + snprintf(buffer, sizeof(buffer), "%" B_PRId32, fModel->CountThreads()); fThreadCountView->SetText(buffer); } else { fDataSourceView->SetText(""); diff --git a/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp b/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp index 49a798b078..5def8141fa 100644 --- a/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp +++ b/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp @@ -318,7 +318,7 @@ protected: int32 lineHeight = (int32)fFontInfo.lineHeight; minLine = (int32)rect.top / lineHeight; maxLine = ((int32)ceilf(rect.bottom) + lineHeight - 1) / lineHeight; - minLine = std::max(minLine, 0L); + minLine = std::max(minLine, (int32)0); maxLine = std::min(maxLine, CountLines() - 1); } @@ -1449,7 +1449,8 @@ printf("failed to read event!\n"); Model::ThreadSchedulingState* thread = fState.LookupThread( event->thread); if (thread == NULL) { - printf("Schedule event for unknown thread: %ld\n", event->thread); + printf("Schedule event for unknown thread: %" B_PRId32 "\n", + event->thread); return; } @@ -1464,8 +1465,8 @@ printf("failed to read event!\n"); thread = fState.LookupThread(event->previous_thread); if (thread == NULL) { - printf("Schedule event for unknown previous thread: %ld\n", - event->previous_thread); + printf("Schedule event for unknown previous thread: %" B_PRId32 + "\n", event->previous_thread); return; } @@ -1529,8 +1530,8 @@ printf("failed to read event!\n"); Model::ThreadSchedulingState* thread = fState.LookupThread( event->thread); if (thread == NULL) { - printf("Enqueued in run queue event for unknown thread: %ld\n", - event->thread); + printf("Enqueued in run queue event for unknown thread: %" B_PRId32 + "\n", event->thread); return; } @@ -1559,8 +1560,8 @@ printf("failed to read event!\n"); Model::ThreadSchedulingState* thread = fState.LookupThread( event->thread); if (thread == NULL) { - printf("Removed from run queue event for unknown thread: %ld\n", - event->thread); + printf("Removed from run queue event for unknown thread: %" B_PRId32 + "\n", event->thread); return; } diff --git a/src/apps/debuganalyzer/gui/main_window/ThreadsPage.cpp b/src/apps/debuganalyzer/gui/main_window/ThreadsPage.cpp index 88e9965fb5..80e9180799 100644 --- a/src/apps/debuganalyzer/gui/main_window/ThreadsPage.cpp +++ b/src/apps/debuganalyzer/gui/main_window/ThreadsPage.cpp @@ -51,8 +51,8 @@ public: { char buffer[128]; Model::Team* team = thread->GetTeam(); - snprintf(buffer, sizeof(buffer), "%s (%ld)", team->Name(), - team->ID()); + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId32 ")", + team->Name(), team->ID()); value.SetTo(buffer); return true; } diff --git a/src/apps/debuganalyzer/gui/thread_window/GeneralPage.cpp b/src/apps/debuganalyzer/gui/thread_window/GeneralPage.cpp index a0d17eb5bf..017afe7c5e 100644 --- a/src/apps/debuganalyzer/gui/thread_window/GeneralPage.cpp +++ b/src/apps/debuganalyzer/gui/thread_window/GeneralPage.cpp @@ -55,7 +55,7 @@ ThreadWindow::GeneralPage::SetModel(Model* model, Model::Thread* thread) // ID char buffer[128]; - snprintf(buffer, sizeof(buffer), "%ld", fThread->ID()); + snprintf(buffer, sizeof(buffer), "%" B_PRId32, fThread->ID()); fThreadIDView->SetText(buffer); // team @@ -65,28 +65,28 @@ ThreadWindow::GeneralPage::SetModel(Model* model, Model::Thread* thread) char timeBuffer[64]; format_nanotime(fThread->TotalRunTime(), timeBuffer, sizeof(timeBuffer)); - snprintf(buffer, sizeof(buffer), "%s (%lld)", timeBuffer, + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId64 ")", timeBuffer, fThread->Runs()); fRunTimeView->SetText(buffer); // wait time format_nanotime(fThread->TotalWaitTime(), timeBuffer, sizeof(timeBuffer)); - snprintf(buffer, sizeof(buffer), "%s (%lld)", timeBuffer, + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId64 ")", timeBuffer, fThread->Waits()); fWaitTimeView->SetText(buffer); // latencies format_nanotime(fThread->TotalLatency(), timeBuffer, sizeof(timeBuffer)); - snprintf(buffer, sizeof(buffer), "%s (%lld)", timeBuffer, + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId64 ")", timeBuffer, fThread->Latencies()); fLatencyView->SetText(buffer); // preemptions format_nanotime(fThread->TotalRerunTime(), timeBuffer, sizeof(timeBuffer)); - snprintf(buffer, sizeof(buffer), "%s (%lld)", timeBuffer, + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId64 ")", timeBuffer, fThread->Preemptions()); fPreemptionView->SetText(buffer); diff --git a/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp b/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp index a3bba76c8c..491b5b853e 100644 --- a/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp +++ b/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp @@ -27,8 +27,8 @@ static BString get_window_name(Model::Thread* thread) { char buffer[1024]; - snprintf(buffer, sizeof(buffer), "Thread: %s (%ld)", thread->Name(), - thread->ID()); + snprintf(buffer, sizeof(buffer), "Thread: %s (%" B_PRId32 ")", + thread->Name(), thread->ID()); return BString(buffer); } diff --git a/src/apps/debuganalyzer/model/Model.cpp b/src/apps/debuganalyzer/model/Model.cpp index f1e1f64b43..fe1119ab7d 100644 --- a/src/apps/debuganalyzer/model/Model.cpp +++ b/src/apps/debuganalyzer/model/Model.cpp @@ -785,7 +785,7 @@ Model::AddTeam(const system_profiler_team_added* event, nanotime_t time) { Team* team = TeamByID(event->team); if (team != NULL) { - fprintf(stderr, "Duplicate team: %ld\n", event->team); + fprintf(stderr, "Duplicate team: %" B_PRId32 "\n", event->team); // TODO: User feedback! return team; } @@ -830,7 +830,7 @@ Model::AddThread(const system_profiler_thread_added* event, nanotime_t time) // check whether we do already know the thread Thread* thread = ThreadByID(event->thread); if (thread != NULL) { - fprintf(stderr, "Duplicate thread: %ld\n", event->thread); + fprintf(stderr, "Duplicate thread: %" B_PRId32 "\n", event->thread); // TODO: User feedback! return thread; } @@ -838,7 +838,7 @@ Model::AddThread(const system_profiler_thread_added* event, nanotime_t time) // get its team Team* team = TeamByID(event->team); if (team == NULL) { - fprintf(stderr, "No team for thread: %ld\n", event->thread); + fprintf(stderr, "No team for thread: %" B_PRId32 "\n", event->thread); return NULL; } diff --git a/src/apps/debuganalyzer/model_loader/ModelLoader.cpp b/src/apps/debuganalyzer/model_loader/ModelLoader.cpp index e8acbbfcfc..7b75f2cfd0 100644 --- a/src/apps/debuganalyzer/model_loader/ModelLoader.cpp +++ b/src/apps/debuganalyzer/model_loader/ModelLoader.cpp @@ -721,9 +721,9 @@ ModelLoader::_ProcessEvent(uint32 event, uint32 cpu, const void* buffer, break; default: -printf("unsupported event type %lu, size: %lu\n", event, size); -return B_BAD_DATA; - break; + printf("unsupported event type %" B_PRIu32 ", size: %" B_PRIuSIZE + "\n", event, size); + return B_BAD_DATA; } return B_OK; @@ -889,8 +889,10 @@ ModelLoader::_HandleTeamRemoved(system_profiler_team_removed* event) { if (Model::Team* team = fModel->TeamByID(event->team)) team->SetDeletionTime(fState->LastEventTime()); - else - printf("Warning: Removed event for unknown team: %ld\n", event->team); + else { + printf("Warning: Removed event for unknown team: %" B_PRId32 "\n", + event->team); + } } @@ -913,7 +915,7 @@ ModelLoader::_HandleThreadRemoved(system_profiler_thread_removed* event) { ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { - printf("Warning: Removed event for unknown thread: %ld\n", + printf("Warning: Removed event for unknown thread: %" B_PRId32 "\n", event->thread); thread = _AddUnknownThread(event->thread); } @@ -931,7 +933,7 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu, ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { - printf("Warning: Schedule event for unknown thread: %ld\n", + printf("Warning: Schedule event for unknown thread: %" B_PRId32 "\n", event->thread); thread = _AddUnknownThread(event->thread); return; @@ -966,8 +968,8 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu, thread = fState->LookupThread(event->previous_thread); if (thread == NULL) { - printf("Warning: Schedule event for unknown previous thread: %ld\n", - event->previous_thread); + printf("Warning: Schedule event for unknown previous thread: %" B_PRId32 + "\n", event->previous_thread); thread = _AddUnknownThread(event->previous_thread); } @@ -1035,8 +1037,8 @@ ModelLoader::_HandleThreadEnqueuedInRunQueue( ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { - printf("Warning: Enqueued in run queue event for unknown thread: %ld\n", - event->thread); + printf("Warning: Enqueued in run queue event for unknown thread: %" + B_PRId32 "\n", event->thread); thread = _AddUnknownThread(event->thread); } @@ -1073,7 +1075,7 @@ ModelLoader::_HandleThreadRemovedFromRunQueue(uint32 cpu, ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { printf("Warning: Removed from run queue event for unknown thread: " - "%ld\n", event->thread); + "%" B_PRId32 "\n", event->thread); thread = _AddUnknownThread(event->thread); } @@ -1112,8 +1114,8 @@ ModelLoader::_HandleIOSchedulerAdded(system_profiler_io_scheduler_added* event) { Model::IOScheduler* scheduler = fModel->IOSchedulerByID(event->scheduler); if (scheduler != NULL) { - printf("Warning: Duplicate added event for I/O scheduler %ld\n", - event->scheduler); + printf("Warning: Duplicate added event for I/O scheduler %" B_PRId32 + "\n", event->scheduler); return; } @@ -1134,12 +1136,13 @@ ModelLoader::_HandleIORequestScheduled(io_request_scheduled* event) ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { - printf("Warning: I/O request for unknown thread %ld\n", event->thread); + printf("Warning: I/O request for unknown thread %" B_PRId32 "\n", + event->thread); thread = _AddUnknownThread(event->thread); } if (fModel->IOSchedulerByID(event->scheduler) == NULL) { - printf("Warning: I/O requests for unknown scheduler %ld\n", + printf("Warning: I/O requests for unknown scheduler %" B_PRId32 "\n", event->scheduler); // TODO: Add state for unknown scheduler, as we do for threads. return; @@ -1307,8 +1310,8 @@ ModelLoader::_AddThreadWaitObject(ExtendedThreadSchedulingState* thread, = fModel->WaitObjectGroupFor(type, object); if (waitObjectGroup == NULL) { // The algorithm should prevent this case. -printf("ModelLoader::_AddThreadWaitObject(): Unknown wait object: type: %lu, " -"object: %#lx\n", type, object); + printf("ModelLoader::_AddThreadWaitObject(): Unknown wait object: type:" + " %" B_PRIu32 ", " "object: %#" B_PRIxADDR "\n", type, object); return; } diff --git a/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp index 192abfdb8e..3ff9a47fa0 100644 --- a/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp +++ b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp @@ -114,9 +114,9 @@ ThreadModelLoader::_Load() // create the groups int32 waitObjectCount = waitObjects.CountItems(); -printf("%ld wait objects\n", waitObjectCount); + printf("%" B_PRId32 " wait objects\n", waitObjectCount); for (int32 i = 0; i < waitObjectCount;) { -printf("new wait object group at %ld\n", i); + printf("new wait object group at %" B_PRId32 "\n", i); // collect the objects for this group Model::ThreadWaitObject* firstObject = waitObjects.ItemAt(i); int32 k = i + 1; From efb0a3a853557e69ecf2bc88adc9a69ed08d1514 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 17 Aug 2015 22:13:59 +0200 Subject: [PATCH 041/125] EntryCache: Add entry_cache_add_missing() for negative caching. It provides a way for filesystems to cache a lookup failure and therefore prevents repeated lookups of missing entries. This is a common scenario for example in command lookup and compiling, where each directory in PATH or each include directory is searched for the given entry. --- headers/os/drivers/fs_cache.h | 2 ++ headers/private/fs_shell/fssh_api_wrapper.h | 1 + headers/private/fs_shell/fssh_fs_cache.h | 2 ++ .../userlandfs/server/haiku/entry_cache.cpp | 7 ++++++ src/system/kernel/fs/EntryCache.cpp | 10 ++++++-- src/system/kernel/fs/EntryCache.h | 5 ++-- src/system/kernel/fs/vfs.cpp | 24 ++++++++++++++++--- src/tools/fs_shell/vfs.cpp | 9 +++++++ 8 files changed, 53 insertions(+), 7 deletions(-) diff --git a/headers/os/drivers/fs_cache.h b/headers/os/drivers/fs_cache.h index 64667699a5..9a71a5b5e1 100644 --- a/headers/os/drivers/fs_cache.h +++ b/headers/os/drivers/fs_cache.h @@ -104,6 +104,8 @@ extern status_t file_map_translate(void *map, off_t offset, size_t size, /* entry cache */ extern status_t entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID); +extern status_t entry_cache_add_missing(dev_t mountID, ino_t dirID, + const char* name); extern status_t entry_cache_remove(dev_t mountID, ino_t dirID, const char* name); diff --git a/headers/private/fs_shell/fssh_api_wrapper.h b/headers/private/fs_shell/fssh_api_wrapper.h index 337648f2e2..1651b2a041 100644 --- a/headers/private/fs_shell/fssh_api_wrapper.h +++ b/headers/private/fs_shell/fssh_api_wrapper.h @@ -871,6 +871,7 @@ /* entry cache */ #define entry_cache_add fssh_entry_cache_add +#define entry_cache_add_missing fssh_entry_cache_add_missing #define entry_cache_remove fssh_entry_cache_remove //////////////////////////////////////////////////////////////////////////////// diff --git a/headers/private/fs_shell/fssh_fs_cache.h b/headers/private/fs_shell/fssh_fs_cache.h index 87eef13f39..88cc9a392e 100644 --- a/headers/private/fs_shell/fssh_fs_cache.h +++ b/headers/private/fs_shell/fssh_fs_cache.h @@ -126,6 +126,8 @@ extern fssh_status_t fssh_file_map_translate(void *_map, fssh_off_t offset, extern fssh_status_t fssh_entry_cache_add(fssh_dev_t mountID, fssh_ino_t dirID, const char* name, fssh_ino_t nodeID); +extern fssh_status_t fssh_entry_cache_add_missing(fssh_dev_t mountID, + fssh_ino_t dirID, const char* name); extern fssh_status_t fssh_entry_cache_remove(fssh_dev_t mountID, fssh_ino_t dirID, const char* name); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/entry_cache.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/entry_cache.cpp index 8ea12b8158..7aa60ac982 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/entry_cache.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/entry_cache.cpp @@ -17,6 +17,13 @@ entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID) } +status_t +entry_cache_add_missing(dev_t mountID, ino_t dirID, const char* name) +{ + return B_OK; +} + + status_t entry_cache_remove(dev_t mountID, ino_t dirID, const char* name) { diff --git a/src/system/kernel/fs/EntryCache.cpp b/src/system/kernel/fs/EntryCache.cpp index e9a6a14db9..63743b8f4c 100644 --- a/src/system/kernel/fs/EntryCache.cpp +++ b/src/system/kernel/fs/EntryCache.cpp @@ -90,7 +90,7 @@ EntryCache::Init() status_t -EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID) +EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID, bool missing) { EntryCacheKey key(dirID, name); @@ -99,6 +99,7 @@ EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID) EntryCacheEntry* entry = fEntries.Lookup(key); if (entry != NULL) { entry->node_id = nodeID; + entry->missing = missing; if (entry->generation != fCurrentGeneration) { if (entry->index >= 0) { fGenerations[entry->generation].entries[entry->index] = NULL; @@ -114,6 +115,7 @@ EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID) entry->node_id = nodeID; entry->dir_id = dirID; + entry->missing = missing; entry->generation = fCurrentGeneration; entry->index = kEntryNotInArray; strcpy(entry->name, name); @@ -155,7 +157,8 @@ EntryCache::Remove(ino_t dirID, const char* name) bool -EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID) +EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID, + bool& _missing) { EntryCacheKey key(dirID, name); @@ -171,6 +174,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID) // The entry is already in the current generation or is being moved to // it by another thread. _nodeID = entry->node_id; + _missing = entry->missing; return true; } @@ -184,6 +188,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID) fGenerations[fCurrentGeneration].entries[index] = entry; entry->index = index; _nodeID = entry->node_id; + _missing = entry->missing; return true; } @@ -201,6 +206,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID) _AddEntryToCurrentGeneration(entry); _nodeID = entry->node_id; + _missing = entry->missing; return true; } diff --git a/src/system/kernel/fs/EntryCache.h b/src/system/kernel/fs/EntryCache.h index 79a8df0f06..4cbf865915 100644 --- a/src/system/kernel/fs/EntryCache.h +++ b/src/system/kernel/fs/EntryCache.h @@ -36,6 +36,7 @@ struct EntryCacheEntry { ino_t dir_id; int32 generation; int32 index; + bool missing; char name[1]; }; @@ -87,12 +88,12 @@ public: status_t Init(); status_t Add(ino_t dirID, const char* name, - ino_t nodeID); + ino_t nodeID, bool missing); status_t Remove(ino_t dirID, const char* name); bool Lookup(ino_t dirID, const char* name, - ino_t& nodeID); + ino_t& nodeID, bool& missing); const char* DebugReverseLookup(ino_t nodeID, ino_t& _dirID); diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 6e98ac4f5e..68f58c63ec 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -2089,9 +2089,12 @@ static status_t lookup_dir_entry(struct vnode* dir, const char* name, struct vnode** _vnode) { ino_t id; + bool missing; - if (dir->mount->entry_cache.Lookup(dir->id, name, id)) - return get_vnode(dir->device, id, _vnode, true, false); + if (dir->mount->entry_cache.Lookup(dir->id, name, id, missing)) { + return missing ? B_ENTRY_NOT_FOUND + : get_vnode(dir->device, id, _vnode, true, false); + } status_t status = FS_CALL(dir, lookup, name, &id); if (status != B_OK) @@ -4011,7 +4014,22 @@ entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID) return B_BAD_VALUE; locker.Unlock(); - return mount->entry_cache.Add(dirID, name, nodeID); + return mount->entry_cache.Add(dirID, name, nodeID, false); +} + + +extern "C" status_t +entry_cache_add_missing(dev_t mountID, ino_t dirID, const char* name) +{ + // lookup mount -- the caller is required to make sure that the mount + // won't go away + MutexLocker locker(sMountMutex); + struct fs_mount* mount = find_mount(mountID); + if (mount == NULL) + return B_BAD_VALUE; + locker.Unlock(); + + return mount->entry_cache.Add(dirID, name, -1, true); } diff --git a/src/tools/fs_shell/vfs.cpp b/src/tools/fs_shell/vfs.cpp index 9308a351da..5137ddd364 100644 --- a/src/tools/fs_shell/vfs.cpp +++ b/src/tools/fs_shell/vfs.cpp @@ -2277,6 +2277,15 @@ fssh_entry_cache_add(fssh_dev_t mountID, fssh_ino_t dirID, const char* name, } +extern "C" fssh_status_t +fssh_entry_cache_add_missing(fssh_dev_t mountID, fssh_ino_t dirID, + const char* name) +{ + // We don't implement an entry cache in the FS shell. + return FSSH_B_OK; +} + + extern "C" fssh_status_t fssh_entry_cache_remove(fssh_dev_t mountID, fssh_ino_t dirID, const char* name) { From 44b69ccbdb65be0ee0f6ececa9279397f8908d84 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 17 Aug 2015 22:25:44 +0200 Subject: [PATCH 042/125] bfs: Use negative caching on directory lookup failures. --- src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index c6c0f03b95..fe2478aa6a 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -587,6 +587,9 @@ bfs_lookup(fs_volume* _volume, fs_vnode* _directory, const char* file, status = tree->Find((uint8*)file, (uint16)strlen(file), _vnodeID); if (status != B_OK) { //PRINT(("bfs_walk() could not find %Ld:\"%s\": %s\n", directory->BlockNumber(), file, strerror(status))); + if (status == B_ENTRY_NOT_FOUND) + entry_cache_add_missing(volume->ID(), directory->ID(), file); + return status; } From 5d4501aa0187e1a8790784dc2ab3382a16660e93 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Thu, 20 Aug 2015 21:54:41 +0200 Subject: [PATCH 043/125] Assorted whitespace cleanup and typo fixes. --- headers/private/kernel/thread.h | 2 +- headers/private/kernel/thread_types.h | 2 +- headers/private/shared/OpenHashTable.h | 6 +++--- src/system/kernel/fs/Vnode.h | 2 +- src/system/kernel/fs/vfs.cpp | 10 +++++----- src/tests/add-ons/kernel/kernelland_emu/lock.cpp | 8 ++++---- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/headers/private/kernel/thread.h b/headers/private/kernel/thread.h index b4899ed945..a352f2eae0 100644 --- a/headers/private/kernel/thread.h +++ b/headers/private/kernel/thread.h @@ -302,7 +302,7 @@ thread_is_blocked(Thread* thread) especially with a client lock that uses the thread blocking API. After a blocked thread has been interrupted or the the time out occurred it cannot acquire the client lock (or any other lock using the thread blocking API) - without first making sure that the thread doesn't still appears to be + without first making sure that the thread doesn't still appear to be waiting to other client code. Otherwise another thread could try to unblock it which could erroneously unblock the thread while already waiting on the client lock. So usually when interruptions or timeouts are possible a diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 1bbab89333..cf9e8fa872 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -453,7 +453,7 @@ struct Thread : TeamThreadIteratorEntry, KernelReferenceable { // modified by the thread itself and // thus freely readable by it - void (*cancel_function)(int); + void (*cancel_function)(int); struct { uint8 parameters[SYSCALL_RESTART_PARAMETER_SIZE]; diff --git a/headers/private/shared/OpenHashTable.h b/headers/private/shared/OpenHashTable.h index 8659b32c14..eb000595c6 100644 --- a/headers/private/shared/OpenHashTable.h +++ b/headers/private/shared/OpenHashTable.h @@ -233,21 +233,21 @@ template int32 OpenHashTable::ArraySize() const { - return fArraySize; + return fArraySize; } template int32 OpenHashTable::VectorSize() const { - return fElementVector->Size(); + return fElementVector->Size(); } template int32 OpenHashTable::CountElements() const { - return fElementCount; + return fElementCount; } diff --git a/src/system/kernel/fs/Vnode.h b/src/system/kernel/fs/Vnode.h index d4ef8fd3ff..6efe921a5c 100644 --- a/src/system/kernel/fs/Vnode.h +++ b/src/system/kernel/fs/Vnode.h @@ -80,7 +80,7 @@ private: static const uint32 kFlagsCovering = 0x00000100; static const uint32 kFlagsType = 0xfffff000; - static const uint32 kBucketCount = 32; + static const uint32 kBucketCount = 32; struct LockWaiter : DoublyLinkedListLinkImpl { LockWaiter* next; diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 68f58c63ec..b279556bd9 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -1145,8 +1145,8 @@ restart: rw_lock_read_unlock(&sVnodeLock); if (!canWait || --tries < 0) { // vnode doesn't seem to become unbusy - dprintf("vnode %" B_PRIdDEV ":%" B_PRIdINO " is not becoming unbusy!\n", - mountID, vnodeID); + dprintf("vnode %" B_PRIdDEV ":%" B_PRIdINO + " is not becoming unbusy!\n", mountID, vnodeID); return B_BUSY; } snooze(5000); // 5 ms @@ -1300,7 +1300,7 @@ free_unused_vnodes(int32 level) AutoLocker nodeLocker(vnode); // Check whether the node is still unused -- since we only append to the - // the tail of the unused queue, the vnode should still be at its head. + // tail of the unused queue, the vnode should still be at its head. // Alternatively we could check its ref count for 0 and its busy flag, // but if the node is no longer at the head of the queue, it means it // has been touched in the meantime, i.e. it is no longer the least @@ -2100,7 +2100,7 @@ lookup_dir_entry(struct vnode* dir, const char* name, struct vnode** _vnode) if (status != B_OK) return status; - // The lookup() hook call get_vnode() or publish_vnode(), so we do already + // The lookup() hook calls get_vnode() or publish_vnode(), so we do already // have a reference and just need to look the node up. rw_lock_read_lock(&sVnodeLock); *_vnode = lookup_vnode(dir->device, id); @@ -8890,7 +8890,7 @@ _user_open_entry_ref(dev_t device, ino_t inode, const char* userName, if ((openMode & O_CREAT) != 0) { return file_create_entry_ref(device, inode, name, openMode, perms, - false); + false); } return file_open_entry_ref(device, inode, name, openMode, false); diff --git a/src/tests/add-ons/kernel/kernelland_emu/lock.cpp b/src/tests/add-ons/kernel/kernelland_emu/lock.cpp index 7d5ad1fbce..eb75880c79 100644 --- a/src/tests/add-ons/kernel/kernelland_emu/lock.cpp +++ b/src/tests/add-ons/kernel/kernelland_emu/lock.cpp @@ -479,11 +479,11 @@ _rw_lock_read_unlock_threads_locked(rw_lock* lock) if (--lock->active_readers > 0) return; - if (lock->active_readers < 0) { - panic("rw_lock_read_unlock(): lock %p not read-locked", lock); + if (lock->active_readers < 0) { + panic("rw_lock_read_unlock(): lock %p not read-locked", lock); lock->active_readers = 0; - return; - } + return; + } rw_lock_unblock(lock); } From c4a9344a117d3c918506c5d91300a6ce3554c7a2 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Thu, 20 Aug 2015 21:59:41 +0200 Subject: [PATCH 044/125] libroot_debug: Support alignments > B_PAGE_SIZE in guarded heap. These are always allocated using an area. The allocation size is increased as to guarantee the availability of a suitable address. The pages between the allocation info and the actual, aligned start address and the pages past the allocation end are then protected. This commit also fixes corruption of the allocation info for large allocations that used areas. The alignment wasn't taken into account when calculating the amount of space needed. The alignment could then lead to rounding down the allocation start such that it would overlap with the allocation info. --- .../posix/malloc_debug/guarded_heap.cpp | 100 +++++++++++------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp index f527ff527d..63c8ee0b53 100644 --- a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp +++ b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp @@ -496,52 +496,78 @@ guarded_heap_add_area(guarded_heap& heap, uint32 counter) } +static void* +guarded_heap_allocate_with_area(size_t size, size_t alignment) +{ + size_t infoSpace = alignment >= B_PAGE_SIZE ? B_PAGE_SIZE + : (sizeof(guarded_heap_page) + alignment - 1) & ~(alignment - 1); + + size_t pagesNeeded = (size + infoSpace + B_PAGE_SIZE - 1) / B_PAGE_SIZE; + + if (alignment > B_PAGE_SIZE) + pagesNeeded += alignment / B_PAGE_SIZE - 1; + + void* address = NULL; + area_id area = create_area("guarded_heap_huge_allocation", &address, + B_ANY_ADDRESS, (pagesNeeded + 1) * B_PAGE_SIZE, B_NO_LOCK, + B_READ_AREA | B_WRITE_AREA); + if (area < 0) { + panic("failed to create area for allocation of %" B_PRIuSIZE " pages", + pagesNeeded); + return NULL; + } + + // We just use a page object + guarded_heap_page* page = (guarded_heap_page*)address; + page->flags = GUARDED_HEAP_PAGE_FLAG_USED | GUARDED_HEAP_PAGE_FLAG_FIRST + | GUARDED_HEAP_PAGE_FLAG_AREA; + page->allocation_size = size; + page->allocation_base = (void*)(((addr_t)address + + pagesNeeded * B_PAGE_SIZE - size) & ~(alignment - 1)); + page->alignment = alignment; + page->thread = find_thread(NULL); + page->alloc_stack_trace_depth = guarded_heap_fill_stack_trace( + page->stack_trace, sStackTraceDepth, 2); + page->free_stack_trace_depth = 0; + + if (alignment <= B_PAGE_SIZE) { + // Protect just the guard page. + mprotect((void*)((addr_t)address + pagesNeeded * B_PAGE_SIZE), + B_PAGE_SIZE, 0); + } else { + // Protect empty pages before the allocation start... + addr_t protectedStart = (addr_t)address + B_PAGE_SIZE; + size_t protectedSize = (addr_t)page->allocation_base - protectedStart; + if (protectedSize > 0) + mprotect((void*)protectedStart, protectedSize, 0); + + // ... and after allocation end. + size_t allocatedPages = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE; + protectedStart = (addr_t)page->allocation_base + + allocatedPages * B_PAGE_SIZE; + protectedSize = (addr_t)address + (pagesNeeded + 1) * B_PAGE_SIZE + - protectedStart; + + // There is at least the guard page. + mprotect((void*)protectedStart, protectedSize, 0); + } + + return page->allocation_base; +} + + static void* guarded_heap_allocate(guarded_heap& heap, size_t size, size_t alignment) { if (alignment == 0) alignment = 1; - if (alignment > B_PAGE_SIZE) { - panic("alignment of %" B_PRIuSIZE " not supported", alignment); - return NULL; - } - size_t pagesNeeded = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE + 1; - if (pagesNeeded * B_PAGE_SIZE >= GUARDED_HEAP_AREA_USE_THRESHOLD) { + if (alignment > B_PAGE_SIZE + || pagesNeeded * B_PAGE_SIZE >= GUARDED_HEAP_AREA_USE_THRESHOLD) { // Don't bother, use an area directly. Since it will also fault once // it is deleted, that fits our model quite nicely. - - pagesNeeded = (size + sizeof(guarded_heap_page) + B_PAGE_SIZE - 1) - / B_PAGE_SIZE; - - void* address = NULL; - area_id area = create_area("guarded_heap_huge_allocation", &address, - B_ANY_ADDRESS, (pagesNeeded + 1) * B_PAGE_SIZE, B_NO_LOCK, - B_READ_AREA | B_WRITE_AREA); - if (area < 0) { - panic("failed to create area for allocation of %" B_PRIuSIZE - " pages", pagesNeeded); - return NULL; - } - - // We just use a page object - guarded_heap_page* page = (guarded_heap_page*)address; - page->flags = GUARDED_HEAP_PAGE_FLAG_USED - | GUARDED_HEAP_PAGE_FLAG_FIRST | GUARDED_HEAP_PAGE_FLAG_AREA; - page->allocation_size = size; - page->allocation_base = (void*)(((addr_t)address - + pagesNeeded * B_PAGE_SIZE - size) & ~(alignment - 1)); - page->alignment = alignment; - page->thread = find_thread(NULL); - page->alloc_stack_trace_depth = guarded_heap_fill_stack_trace( - page->stack_trace, sStackTraceDepth, 2); - page->free_stack_trace_depth = 0; - - mprotect((void*)((addr_t)address + pagesNeeded * B_PAGE_SIZE), - B_PAGE_SIZE, 0); - - return page->allocation_base; + return guarded_heap_allocate_with_area(size, alignment); } void* result = NULL; From 5ca445dfc6fb352f2a74e238e29f4708273974ec Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 21 Aug 2015 21:02:55 +0200 Subject: [PATCH 045/125] FS module docs: Add documentation for entry_cache_add_missing(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was missed when introducing the feature in hrev49558. Thanks Jérôme for the pointer! Also add a note explaining that update operations on cached entries and the removal of uncached entries are safe. --- docs/user/drivers/fs_modules.dox | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/user/drivers/fs_modules.dox b/docs/user/drivers/fs_modules.dox index e386f195a9..80e2c0e9e9 100644 --- a/docs/user/drivers/fs_modules.dox +++ b/docs/user/drivers/fs_modules.dox @@ -316,6 +316,16 @@ entry_cache_add() function when it encounters an entry that might not yet be known to the entry cache and entry_cache_remove() when a directory entry has been removed. + The entry cache can also be used for negative caching. If the file system + determines that the requested entry is not present during a lookup, it can + cache this lookup failure by calling entry_cache_add_missing(). Further + calls to fs_vnode_ops::lookup() for the missing entry will then be + avoided. + Note that it is safe to call entry_cache_add() and + entry_cache_add_missing() with the same directory/name pair previously + given to either function to update a cache entry, without needing to call + entry_cache_remove() first. It is also safe to call entry_cache_remove() + for pairs that have never been added to the cache. */ // TODO: From 811f0164a0edc6c7be1fa43f4e16234cfaa2f70a Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 21 Aug 2015 23:03:37 +0200 Subject: [PATCH 046/125] BRoster: Make sure we aren't the registrar when initializing. This fixes a regression introduced in 9bfc833, where the old way of getting the roster port was replaced with its launch_daemon counterpart. The previous method of finding the roster did always fail when running from the registrar, as at the time of initialization (initialize_before of libbe) the registrar looper doesn't exist yet. This commit restores the previous behaviour by checking if the returned registrar team is the current team and avoiding initialization in that case. The regression caused a 5 second boot delay when later BApplication initialization of the registrar tried to communicate with itself with a reply timeout of that length. Fixes #12258 at least partially and might affect #12237. --- src/kits/app/Roster.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index dc6a914107..1a8c76900b 100644 --- a/src/kits/app/Roster.cpp +++ b/src/kits/app/Roster.cpp @@ -2607,9 +2607,13 @@ BRoster::_InitMessenger() BMessage data; if (BLaunchRoster().GetData("application/x-vnd.Haiku-registrar", data) == B_OK) { + port_id port = data.GetInt32("port", -1); team_id team = data.GetInt32("team", -1); - if (port >= 0) { + + if (port >= 0 && team != current_team()) { + // Make sure we aren't the registrar ourselves. + DBG(OUT(" found roster port\n")); BMessenger::Private(fMessenger).SetTo(team, port, From 3667f6efdbeac23c708a9a610391cc4780b9fd54 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 21 Aug 2015 23:23:26 +0200 Subject: [PATCH 047/125] BApplication: Avoid create_app_meta_mime() for the registrar. BApplication::_InitData() already avoided the use of BRoster from the registrar (and launch_daemon) where it isn't available. Since create_app_meta_mime() indirectly just sends a message to the registrar using BRoster, it too cannot work when the registrar isn't available. --- src/kits/app/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kits/app/Application.cpp b/src/kits/app/Application.cpp index cf83e1df88..cda2c6d891 100644 --- a/src/kits/app/Application.cpp +++ b/src/kits/app/Application.cpp @@ -509,7 +509,7 @@ BApplication::_InitData(const char* signature, bool initGUI, status_t* _error) // create meta MIME BPath path; - if (path.SetTo(&ref) == B_OK) + if (registerApp && path.SetTo(&ref) == B_OK) create_app_meta_mime(path.Path(), false, true, false); #ifndef RUN_WITHOUT_APP_SERVER From 2d9d01e2e849737a184f83779311a04346a5be98 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 21 Aug 2015 23:45:28 -0400 Subject: [PATCH 048/125] Debugger: Refactor non-interactive report handling. - Add dedicated ReportDebugger application class for the case where we're asked to do nothing more than save a report. Also add a corresponding UserInterface subclass whose sole purpose is to take those necessary actions and then exit. - When the debugger is invoked via the --save-report option, we now start via the aforementioned report/interface rather than piggybacking on the CLI. - Clean up CommandLineUserInterface/CliContext to remove handling for the report saving option. Should hopefully resolve #12155. --- src/apps/debugger/Debugger.cpp | 108 +++++++- src/apps/debugger/Jamfile | 4 + .../user_interface/cli/CliContext.cpp | 18 +- .../debugger/user_interface/cli/CliContext.h | 6 +- .../cli/CommandLineUserInterface.cpp | 76 +----- .../cli/CommandLineUserInterface.h | 19 +- .../report/ReportUserInterface.cpp | 233 ++++++++++++++++++ .../report/ReportUserInterface.h | 66 +++++ 8 files changed, 416 insertions(+), 114 deletions(-) create mode 100644 src/apps/debugger/user_interface/report/ReportUserInterface.cpp create mode 100644 src/apps/debugger/user_interface/report/ReportUserInterface.h diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp index 5b72949475..603a2124b9 100644 --- a/src/apps/debugger/Debugger.cpp +++ b/src/apps/debugger/Debugger.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2011-2014, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -26,6 +26,7 @@ #include "GraphicalUserInterface.h" #include "ImageDebugLoadingStateHandlerRoster.h" #include "MessageCodes.h" +#include "ReportUserInterface.h" #include "SettingsManager.h" #include "SignalSet.h" #include "StartTeamWindow.h" @@ -143,7 +144,6 @@ parse_arguments(int argc, const char* const* argv, bool noOutput, case 's': { - options.useCLI = true; options.saveReport = true; options.reportPath = optarg; break; @@ -393,6 +393,21 @@ private: }; +class ReportDebugger : private TeamDebugger::Listener { +public: + ReportDebugger(); + ~ReportDebugger(); + bool Run(const Options& options); + +private: + // TeamDebugger::Listener + virtual void TeamDebuggerStarted(TeamDebugger* debugger); + virtual void TeamDebuggerRestartRequested( + TeamDebugger* debugger); + virtual void TeamDebuggerQuit(TeamDebugger* debugger); +}; + + // #pragma mark - Debugger application class @@ -723,8 +738,7 @@ CliDebugger::Run(const Options& options) // create the command line UI CommandLineUserInterface* userInterface - = new(std::nothrow) CommandLineUserInterface(options.saveReport, - options.reportPath, options.thread); + = new(std::nothrow) CommandLineUserInterface(); if (userInterface == NULL) { fprintf(stderr, "Error: Out of memory!\n"); return false; @@ -774,6 +788,89 @@ CliDebugger::TeamDebuggerQuit(TeamDebugger* debugger) } +// #pragma mark - ReportDebugger + + +ReportDebugger::ReportDebugger() +{ +} + + +ReportDebugger::~ReportDebugger() +{ +} + + +bool +ReportDebugger::Run(const Options& options) +{ + // initialize global objects and settings manager + status_t error = global_init(); + if (error != B_OK) { + fprintf(stderr, "Error: Global initialization failed: %s\n", + strerror(error)); + return false; + } + + SettingsManager settingsManager; + error = settingsManager.Init(); + if (error != B_OK) { + fprintf(stderr, "Error: Settings manager initialization failed: " + "%s\n", strerror(error)); + return false; + } + + // create the report UI + ReportUserInterface* userInterface + = new(std::nothrow) ReportUserInterface(options.thread, options.reportPath); + if (userInterface == NULL) { + fprintf(stderr, "Error: Out of memory!\n"); + return false; + } + BReference userInterfaceReference(userInterface, true); + + // get/run the program to be debugged and start the team debugger + DebuggedProgramInfo programInfo; + if (!get_debugged_program(options, programInfo)) + return false; + + TeamDebugger* teamDebugger = start_team_debugger(programInfo.team, + &settingsManager, this, programInfo.thread, + programInfo.commandLineArgc, programInfo.commandLineArgv, + programInfo.stopInMain, userInterface); + if (teamDebugger == NULL) + return false; + + thread_id teamDebuggerThread = teamDebugger->Thread(); + + // run the input loop + userInterface->Run(); + + // wait for the team debugger thread to terminate + wait_for_thread(teamDebuggerThread, NULL); + + return true; +} + + +void +ReportDebugger::TeamDebuggerStarted(TeamDebugger* debugger) +{ +} + + +void +ReportDebugger::TeamDebuggerRestartRequested(TeamDebugger* debugger) +{ +} + + +void +ReportDebugger::TeamDebuggerQuit(TeamDebugger* debugger) +{ +} + + // #pragma mark - @@ -792,6 +889,9 @@ main(int argc, const char* const* argv) if (options.useCLI) { CliDebugger debugger; return debugger.Run(options) ? 0 : 1; + } else if (options.saveReport) { + ReportDebugger debugger; + return debugger.Run(options) ? 0 : 1; } Debugger app; diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 0985601c1f..773da5f236 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -46,6 +46,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui teams_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui utility_windows ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui value ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface report ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) value ] ; @@ -321,6 +322,9 @@ local sources = TableCellValueRenderer.cpp TableCellValueRendererUtils.cpp + # user_interface/report + ReportUserInterface.cpp + # user_interface/util UiUtils.cpp diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index 7c97d2d674..9a66b1a309 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.cpp +++ b/src/apps/debugger/user_interface/cli/CliContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014, Rene Gollent, rene@gollent.com. + * Copyright 2012-2015, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -98,7 +98,6 @@ CliContext::CliContext() fInputLoopWaitingForEvents(0), fEventsOccurred(0), fInputLoopWaiting(false), - fInteractive(true), fTerminating(false), fCurrentThread(NULL), fCurrentStackTrace(NULL), @@ -219,13 +218,6 @@ CliContext::Terminating() } -void -CliContext::SetInteractive(bool interactive) -{ - fInteractive = interactive; -} - - thread_id CliContext::CurrentThreadID() const { @@ -415,6 +407,7 @@ CliContext::ProcessPendingEvents() switch (event->Type()) { case EVENT_QUIT: + case EVENT_DEBUG_REPORT_CHANGED: case EVENT_USER_INTERRUPT: break; case EVENT_THREAD_ADDED: @@ -453,13 +446,6 @@ CliContext::ProcessPendingEvents() if (fExpressionValue != NULL) fExpressionValue->AcquireReference(); break; - case EVENT_DEBUG_REPORT_CHANGED: - if (!IsInteractive()) { - Terminating(); - QuitSession(true); - } - break; - } } } diff --git a/src/apps/debugger/user_interface/cli/CliContext.h b/src/apps/debugger/user_interface/cli/CliContext.h index 8232c783c0..66f35e22d8 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -1,6 +1,6 @@ /* * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2014, Rene Gollent, rene@gollent.com. + * Copyright 2014-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef CLI_CONTEXT_H @@ -57,9 +57,6 @@ public: bool IsTerminating() const { return fTerminating; } - bool IsInteractive() const { return fInteractive; } - void SetInteractive(bool interactive); - // service methods for the input loop thread follow Team* GetTeam() const { return fTeam; } @@ -150,7 +147,6 @@ private: uint32 fInputLoopWaitingForEvents; uint32 fEventsOccurred; bool fInputLoopWaiting; - bool fInteractive; volatile bool fTerminating; Thread* fCurrentThread; diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index 93d1d45b5e..faecbe7601 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -93,13 +93,9 @@ private: // #pragma mark - CommandLineUserInterface -CommandLineUserInterface::CommandLineUserInterface(bool saveReport, - const char* reportPath, thread_id reportTargetThread) +CommandLineUserInterface::CommandLineUserInterface() : fCommands(20, true), - fReportPath(reportPath), - fSaveReport(saveReport), - fReportTargetThread(reportTargetThread), fShowSemaphore(-1), fShown(false), fTerminating(false) @@ -128,8 +124,6 @@ CommandLineUserInterface::Init(Team* team, UserInterfaceListener* listener) if (error != B_OK) return error; - fContext.SetInteractive(!fSaveReport); - error = _RegisterCommands(); if (error != B_OK) return error; @@ -138,8 +132,6 @@ CommandLineUserInterface::Init(Team* team, UserInterfaceListener* listener) if (fShowSemaphore < 0) return fShowSemaphore; - team->AddListener(this); - return B_OK; } @@ -176,9 +168,7 @@ CommandLineUserInterface::Terminate() bool CommandLineUserInterface::IsInteractive() const { - // if we were invoked solely for the purpose of saving a crash report, - // then we're not taking user input into account. - return !fSaveReport; + return true; } @@ -237,43 +227,12 @@ CommandLineUserInterface::Run() if (error != B_OK) return; - if (fSaveReport) { - ArgumentVector args; - char buffer[256]; - const char* parseErrorLocation; - if (_ReportTargetThreadStopNeeded()) { - snprintf(buffer, sizeof(buffer), "stop %" B_PRId32, - fReportTargetThread); - args.Parse(buffer, &parseErrorLocation); - _ExecuteCommand(args.ArgumentCount(), args.Arguments()); - } else - _SubmitSaveReport(); - } - _InputLoop(); // Release the Show() semaphore to signal Terminate(). release_sem(fShowSemaphore); } -void -CommandLineUserInterface::ThreadStateChanged(const Team::ThreadEvent& event) -{ - if (fSaveReport) { - Thread* thread = event.GetThread(); - // If we were asked to attach/report on a specific thread - // rather than a team, and said thread was still - // running, when we attached, we need to wait for its corresponding - // stop state before generating a report, else we might not get its - // stack trace. - if (thread->ID() == fReportTargetThread - && thread->State() == THREAD_STATE_STOPPED) { - _SubmitSaveReport(); - } - } -} - - /*static*/ status_t CommandLineUserInterface::_InputLoopEntry(void* data) { @@ -473,32 +432,3 @@ CommandLineUserInterface::_CompareCommandEntries(const CommandEntry* command1, { return ::Compare(command1->Name(), command2->Name()); } - - -bool -CommandLineUserInterface::_ReportTargetThreadStopNeeded() const -{ - if (fReportTargetThread < 0) - return false; - - Team* team = fContext.GetTeam(); - AutoLocker teamLocker(team); - Thread* thread = team->ThreadByID(fReportTargetThread); - if (thread == NULL) - return false; - - return thread->State() != THREAD_STATE_STOPPED; -} - - -void -CommandLineUserInterface::_SubmitSaveReport() -{ - ArgumentVector args; - char buffer[256]; - const char* parseErrorLocation; - snprintf(buffer, sizeof(buffer), "save-report %s", - fReportPath != NULL ? fReportPath : ""); - args.Parse(buffer, &parseErrorLocation); - _ExecuteCommand(args.ArgumentCount(), args.Arguments()); -} diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h index bb59ce3750..e908e2dcd1 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -17,12 +17,9 @@ class CliCommand; -class CommandLineUserInterface : public UserInterface, - public ::Team::Listener { +class CommandLineUserInterface : public UserInterface { public: - CommandLineUserInterface(bool saveReport, - const char* reportPath, - thread_id reportTargetThread); + CommandLineUserInterface(); virtual ~CommandLineUserInterface(); virtual const char* ID() const; @@ -54,10 +51,6 @@ public: // everything has been set up. Enters the // input loop. - // Team::Listener - virtual void ThreadStateChanged( - const Team::ThreadEvent& event); - private: struct CommandEntry; typedef BObjectList CommandList; @@ -82,15 +75,9 @@ private: const CommandEntry* command1, const CommandEntry* command2); - bool _ReportTargetThreadStopNeeded() const; - void _SubmitSaveReport(); - private: CliContext fContext; CommandList fCommands; - const char* fReportPath; - bool fSaveReport; - thread_id fReportTargetThread; sem_id fShowSemaphore; bool fShown; volatile bool fTerminating; diff --git a/src/apps/debugger/user_interface/report/ReportUserInterface.cpp b/src/apps/debugger/user_interface/report/ReportUserInterface.cpp new file mode 100644 index 0000000000..57fcdf7534 --- /dev/null +++ b/src/apps/debugger/user_interface/report/ReportUserInterface.cpp @@ -0,0 +1,233 @@ +/* + * Copyright 2015, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "ReportUserInterface.h" + +#include + +#include +#include +#include + +#include + +#include "MessageCodes.h" +#include "UiUtils.h" + + +ReportUserInterface::ReportUserInterface(thread_id targetThread, + const char* reportPath) + : + fTeam(NULL), + fListener(NULL), + fTargetThread(targetThread), + fReportPath(reportPath), + fShowSemaphore(-1), + fReportSemaphore(-1), + fShown(false), + fTerminating(false) +{ +} + + +ReportUserInterface::~ReportUserInterface() +{ + if (fShowSemaphore >= 0) + delete_sem(fShowSemaphore); + + fTeam->RemoveListener(this); +} + + +const char* +ReportUserInterface::ID() const +{ + return "ReportUserInterface"; +} + + +status_t +ReportUserInterface::Init(Team* team, UserInterfaceListener* listener) +{ + fShowSemaphore = create_sem(0, "show report"); + if (fShowSemaphore < 0) + return fShowSemaphore; + + fReportSemaphore = create_sem(0, "report generator wait"); + if (fReportSemaphore < 0) + return fReportSemaphore; + + fTeam = team; + fListener = listener; + + fTeam->AddListener(this); + + return B_OK; +} + + +void +ReportUserInterface::Show() +{ + fShown = true; + release_sem(fShowSemaphore); +} + + +void +ReportUserInterface::Terminate() +{ + fTerminating = true; +} + + +bool +ReportUserInterface::IsInteractive() const +{ + return false; +} + + +status_t +ReportUserInterface::LoadSettings(const TeamUiSettings* settings) +{ + return B_OK; +} + + +status_t +ReportUserInterface::SaveSettings(TeamUiSettings*& settings) const +{ + return B_OK; +} + + +void +ReportUserInterface::NotifyUser(const char* title, const char* message, + user_notification_type type) +{ +} + + +void +ReportUserInterface::NotifyBackgroundWorkStatus(const char* message) +{ +} + + +int32 +ReportUserInterface::SynchronouslyAskUser(const char* title, + const char* message, const char* choice1, const char* choice2, + const char* choice3) +{ + return -1; +} + + +status_t +ReportUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref) +{ + return B_UNSUPPORTED; +} + + +void +ReportUserInterface::Run() +{ + // Wait for the Show() semaphore to be released. + status_t error; + do { + error = acquire_sem(fShowSemaphore); + } while (error == B_INTERRUPTED); + + if (error != B_OK) + return; + + bool waitNeeded = false; + if (fTargetThread > 0) { + AutoLocker< ::Team> teamLocker(fTeam); + ::Thread* thread = fTeam->ThreadByID(fTargetThread); + if (thread == NULL) + waitNeeded = true; + else if (thread->State() != THREAD_STATE_STOPPED) { + waitNeeded = true; + fListener->ThreadActionRequested(fTargetThread, MSG_THREAD_STOP); + } + } + + if (waitNeeded) { + do { + error = acquire_sem(fShowSemaphore); + } while (error == B_INTERRUPTED); + + if (error != B_OK) + return; + } + + entry_ref ref; + if (fReportPath != NULL && fReportPath[0] == '/') { + error = get_ref_for_path(fReportPath, &ref); + } else { + char filename[B_FILE_NAME_LENGTH]; + if (fReportPath != NULL) + strlcpy(filename, fReportPath, sizeof(filename)); + else + UiUtils::ReportNameForTeam(fTeam, filename, sizeof(filename)); + + BPath path; + error = find_directory(B_DESKTOP_DIRECTORY, &path); + if (error == B_OK) + error = path.Append(filename); + if (error == B_OK) + error = get_ref_for_path(path.Path(), &ref); + } + + if (error != B_OK) + printf("Unable to get ref for report path %s\n", strerror(error)); + else { + fListener->DebugReportRequested(&ref); + + do { + error = acquire_sem(fReportSemaphore); + } while (error == B_INTERRUPTED); + } + + fListener->UserInterfaceQuitRequested( + UserInterfaceListener::QUIT_OPTION_ASK_KILL_TEAM); +} + + +void +ReportUserInterface::ThreadAdded(const Team::ThreadEvent& event) +{ + ::Thread* thread = event.GetThread(); + if (thread->ID() != fTargetThread) + return; + + if (thread->State() != THREAD_STATE_STOPPED) + fListener->ThreadActionRequested(thread->ID(), MSG_THREAD_STOP); + else + release_sem(fShowSemaphore); +} + + +void +ReportUserInterface::ThreadStateChanged(const Team::ThreadEvent& event) +{ + ::Thread* thread = event.GetThread(); + if (thread->ID() != fTargetThread) + return; + else if (thread->State() == THREAD_STATE_STOPPED) + release_sem(fShowSemaphore); +} + + +void +ReportUserInterface::DebugReportChanged(const Team::DebugReportEvent& event) +{ + printf("Debug report saved to %s\n", event.GetReportPath()); + release_sem(fReportSemaphore); +} diff --git a/src/apps/debugger/user_interface/report/ReportUserInterface.h b/src/apps/debugger/user_interface/report/ReportUserInterface.h new file mode 100644 index 0000000000..8b06d30e3a --- /dev/null +++ b/src/apps/debugger/user_interface/report/ReportUserInterface.h @@ -0,0 +1,66 @@ +/* + * Copyright 2015, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef REPORT_USER_INTERFACE_H +#define REPORT_USER_INTERFACE_H + + +#include +#include + +#include "UserInterface.h" +#include "Team.h" + + +class ReportUserInterface : public UserInterface, + private Team::Listener { +public: + ReportUserInterface(thread_id targetThread, + const char* reportPath); + virtual ~ReportUserInterface(); + + virtual const char* ID() const; + + virtual status_t Init(Team* team, + UserInterfaceListener* listener); + virtual void Show(); + virtual void Terminate(); + + virtual bool IsInteractive() const; + + virtual status_t LoadSettings(const TeamUiSettings* settings); + virtual status_t SaveSettings(TeamUiSettings*& settings) const; + + virtual void NotifyUser(const char* title, + const char* message, + user_notification_type type); + virtual void NotifyBackgroundWorkStatus( + const char* message); + virtual int32 SynchronouslyAskUser(const char* title, + const char* message, const char* choice1, + const char* choice2, const char* choice3); + virtual status_t SynchronouslyAskUserForFile(entry_ref* _ref); + + void Run(); + + // Team::Listener + virtual void ThreadAdded(const Team::ThreadEvent& event); + virtual void ThreadStateChanged( + const Team::ThreadEvent& event); + virtual void DebugReportChanged( + const Team::DebugReportEvent& event); + +private: + ::Team* fTeam; + UserInterfaceListener* fListener; + thread_id fTargetThread; + const char* fReportPath; + sem_id fShowSemaphore; + sem_id fReportSemaphore; + bool fShown; + volatile bool fTerminating; +}; + + +#endif // REPORT_USER_INTERFACE_H From 6b6288a6de70a4b80d9c53db5b3fc4743a2b5ee7 Mon Sep 17 00:00:00 2001 From: autonielx Date: Sat, 22 Aug 2015 06:41:34 +0200 Subject: [PATCH 049/125] Update translations from Pootle --- data/catalogs/add-ons/disk_systems/bfs/fr.catkeys | 2 +- .../add-ons/media/media-add-ons/mixer/fr.catkeys | 6 +++--- .../add-ons/network_settings/dnsclient/hu.catkeys | 10 +++++++++- data/catalogs/add-ons/network_settings/ipv4/hu.catkeys | 2 ++ data/catalogs/add-ons/network_settings/ipv6/hu.catkeys | 2 ++ data/catalogs/apps/aboutsystem/ru.catkeys | 4 +++- data/catalogs/apps/drivesetup/ru.catkeys | 3 ++- data/catalogs/apps/haikudepot/ru.catkeys | 5 ++++- data/catalogs/apps/mail/hu.catkeys | 3 ++- data/catalogs/apps/mail/pl.catkeys | 3 ++- data/catalogs/apps/mail/ru.catkeys | 3 ++- data/catalogs/apps/mediaconverter/ru.catkeys | 4 +++- data/catalogs/apps/terminal/ru.catkeys | 4 +++- 13 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 data/catalogs/add-ons/network_settings/ipv4/hu.catkeys create mode 100644 data/catalogs/add-ons/network_settings/ipv6/hu.catkeys diff --git a/data/catalogs/add-ons/disk_systems/bfs/fr.catkeys b/data/catalogs/add-ons/disk_systems/bfs/fr.catkeys index 7167a3ef89..d558f47501 100644 --- a/data/catalogs/add-ons/disk_systems/bfs/fr.catkeys +++ b/data/catalogs/add-ons/disk_systems/bfs/fr.catkeys @@ -2,7 +2,7 @@ Enable query support BFS_Initialize_Parameter Activer le support des requêtes 2048 (Recommended) BFS_Initialize_Parameter 2048 (Recommandé) 8192 (Mostly large files) BFS_Initialize_Parameter 8192 (Surtout des gros fichiers) -Disabling query support may speed up certain file system operations, but should only be used if one is absolutely certain that one will not need queries.\nAny volume that is intended for booting Haiku must have query support enabled. BFS_Initialize_Parameter Désactiver le support des requête peut accélérer certaines opérations du système de fichiers, mais vous devez être certains de ne jamais avoir besoin des requêtes.\nTout volume destiné à amorcer Haiku doit avoir le support des requête activé. +Disabling query support may speed up certain file system operations, but should only be used if one is absolutely certain that one will not need queries.\nAny volume that is intended for booting Haiku must have query support enabled. BFS_Initialize_Parameter Désactiver le support des requêtes peut accélérer certaines opérations du système de fichiers, mais vous devez être certain de ne jamais avoir besoin des requêtes.\nTout volume destiné à amorcer Haiku doit avoir le support des requêtes activé. 1024 (Mostly small files) BFS_Initialize_Parameter 1024 (Surtout des petits fichiers) Blocksize: BFS_Initialize_Parameter Taille de bloc : Name: BFS_Initialize_Parameter Nom : diff --git a/data/catalogs/add-ons/media/media-add-ons/mixer/fr.catkeys b/data/catalogs/add-ons/media/media-add-ons/mixer/fr.catkeys index a5b0fc7f71..5c74f1cd7f 100644 --- a/data/catalogs/add-ons/media/media-add-ons/mixer/fr.catkeys +++ b/data/catalogs/add-ons/media/media-add-ons/mixer/fr.catkeys @@ -7,7 +7,7 @@ Output mapping AudioMixer Correspondances de sorties Allow input channel remapping AudioMixer Autoriser la réassignation des canaux d’entrées Resampling algorithm AudioMixer Algorithme de ré-échantillonnage Attenuate mixer output by 3dB (like BeOS R5) AudioMixer Atténuer la sortie du mélangeur de 3 dB (comme BeOS R5) -Display balance control for stereo connections AudioMixer Afficher le contrôle de balance pour des connexions stéréo +Display balance control for stereo connections AudioMixer Afficher le contrôle de balance pour les connexions stéréo To output AudioMixer Vers la sortie not connected AudioMixer débranché Refuse input format changes AudioMixer Refuser les changements de formats d’entrées @@ -17,11 +17,11 @@ dB AudioMixer dB Gain controls AudioMixer Contrôles de gain Input mapping AudioMixer Correspondances d’entrées Mute AudioMixer Sourdine -Input channel destinations AudioMixer Destination des canaux d’entrées +Input channel destinations AudioMixer Destinations des canaux d’entrées To master AudioMixer Vers la sortie principale Master output AudioMixer Sortie principale Setup AudioMixer Réglages -Use non linear gain sliders (like BeOS R5) AudioMixer Utiliser les curseurs de gain non-linéaire (comme BeOS R5) +Use non linear gain sliders (like BeOS R5) AudioMixer Utiliser les curseurs de gain non-linéaires (comme BeOS R5) Gain AudioMixer Gain Allow output channel remapping AudioMixer Autoriser la réassignation des canaux de sorties Physical input channels AudioMixer Canaux d’entrées physiques diff --git a/data/catalogs/add-ons/network_settings/dnsclient/hu.catkeys b/data/catalogs/add-ons/network_settings/dnsclient/hu.catkeys index 1246c1d202..1bbc078e25 100644 --- a/data/catalogs/add-ons/network_settings/dnsclient/hu.catkeys +++ b/data/catalogs/add-ons/network_settings/dnsclient/hu.catkeys @@ -1,2 +1,10 @@ -1 hungarian x-vnd.Haiku-DNSClientService 3886749326 +1 hungarian x-vnd.Haiku-DNSClientService 2825577357 +DNS settings DNSClientServiceAddOn DNS-beállítások +Move down DNSSettingsView Mozgatás lefelé +DNS settings DNSSettingsView DNS-beállítások +Remove DNSSettingsView Eltávolítás Domain: DNSSettingsView Tartomány: +Add DNSSettingsView Hozzáad +Server: DNSSettingsView Kiszolgáló: +Move up DNSSettingsView Mozgatás felfelé +Apply DNSSettingsView Alkalmaz diff --git a/data/catalogs/add-ons/network_settings/ipv4/hu.catkeys b/data/catalogs/add-ons/network_settings/ipv4/hu.catkeys new file mode 100644 index 0000000000..bf0288fa1c --- /dev/null +++ b/data/catalogs/add-ons/network_settings/ipv4/hu.catkeys @@ -0,0 +1,2 @@ +1 hungarian x-vnd.Haiku-IPv4Interface 2854844856 +IPv4 IPv4InterfaceAddOn IPv4 diff --git a/data/catalogs/add-ons/network_settings/ipv6/hu.catkeys b/data/catalogs/add-ons/network_settings/ipv6/hu.catkeys new file mode 100644 index 0000000000..33e3e9a972 --- /dev/null +++ b/data/catalogs/add-ons/network_settings/ipv6/hu.catkeys @@ -0,0 +1,2 @@ +1 hungarian x-vnd.Haiku-IPv6Interface 1391114020 +IPv6 IPv6InterfaceAddOn IPv6 diff --git a/data/catalogs/apps/aboutsystem/ru.catkeys b/data/catalogs/apps/aboutsystem/ru.catkeys index 417aa0e07b..ed6e539ff3 100644 --- a/data/catalogs/apps/aboutsystem/ru.catkeys +++ b/data/catalogs/apps/aboutsystem/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Haiku-About 14540716 +1 russian x-vnd.Haiku-About 3251436090 Copyright © 1999-2010 by the authors of Gutenprint. All rights reserved. AboutView Все права защищены © 1999-2010 авторы Gutenprint. Copyright © 1996-2002, 2006 David Turner, Robert Wilhelm and Werner Lemberg. AboutView Все права защищены © 1996-2002, 2006 David Turner, Robert Wilhelm и Werner Lemberg. Past website & marketing:\n AboutView Старый вебсайт и маркетинг:\n @@ -8,6 +8,7 @@ Copyright © 1996-2005 Julian R Seward. All rights reserved. AboutView Все %d MiB total AboutView Всего %d МБ Michael Phipps (project founder)\n\n AboutView Michael Phipps (основателю проекта)\n\n %d MiB used (%d%%) AboutView %d МБ использовано (%d%%) +Contains software from the GNU Project, released under the GPL and LGPL licenses:\nGNU C Library, GNU coretools, diffutils, findutils, sharutils, gawk, bison, m4, make, wget, ncurses, termcap, Bourne Again Shell.\nCopyright © The Free Software Foundation. AboutView Содержит программное обеспечение из проекта GNU, выпущен под лицензиями GPL и LGPL:\nGNU библиотека, GNU coretools, diffutils, findutils, sharutils, gawk, bison, m4, make, wget, ncurses, termcap, Bourne Again Shell.\n\nВсе права защищены © Фонд свободного программного обеспечения. AboutSystem System name О системе Copyright © 2003 Peter Hanappe and others. AboutView Все права защищены © 2003 Peter Hanappe и другие. Copyright © 1994-1997 Mark Kilgard. All rights reserved. AboutView Все права защищены © 1994-1997 Mark Kilgard. @@ -40,6 +41,7 @@ Copyright © 1996-1997 Jeff Prosise. All rights reserved. AboutView Все пр Copyright © 2006-2012 Kentaro Fukuchi AboutView Все права защищены © 2006-2012 Kentaro Fukuchi Copyright © 1994-2009, Thomas G. Lane, Guido Vollbeding. This software is based in part on the work of the Independent JPEG Group. AboutView Все права защищены © 1994-2009, Thomas G. Lane, Guido Vollbeding. Это программное обеспечение частично основано на работе Independent JPEG Group. Past maintainers:\n AboutView Предыдущие разработчики:\n +Contains software from the FreeBSD Project, released under the BSD license:\nftpd, ping, telnet, telnetd, traceroute\nCopyright © 1994-2008 The FreeBSD Project. All rights reserved. AboutView Содержит программное обеспечение из проекта FreeBSD, выпущен под лицензией BSD:\ncal, ftpd, ping, telnet, telnetd, tracerout\nВсе права защищены © 1994-2008 Проект FreeBSD. GNU GPL v3 AboutWindow GNU GPL v3 \n\nSpecial thanks to:\n AboutView \n\nОсобая благодарность:\n \n…and probably some more we forgot to mention (sorry!)\n\n AboutView \n…а также те, кого мы забыли упомянуть (простите!)\n\n diff --git a/data/catalogs/apps/drivesetup/ru.catkeys b/data/catalogs/apps/drivesetup/ru.catkeys index 62377017e2..b953cdc3f1 100644 --- a/data/catalogs/apps/drivesetup/ru.catkeys +++ b/data/catalogs/apps/drivesetup/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Haiku-DriveSetup 1450212098 +1 russian x-vnd.Haiku-DriveSetup 2321187933 DriveSetup System name Разметка диска Could not acquire partitioning information. MainWindow Невозможно получить информацию о разделах. Cancel AbstractParametersPanel Отмена @@ -44,6 +44,7 @@ Change ChangeParametersPanel Изменить Are you sure you want to write the changes back to disk now?\n\nAll data on the disk %s will be irretrievably lost if you do so! MainWindow Вы уверены, что хотите записать изменения на диск прямо сейчас?\n\nВсе данные на диске %s будут безвозвратно потеряны, если вы продолжите! Are you sure you want to delete the selected partition?\n\nAll data on the partition will be irretrievably lost if you do so! MainWindow Вы уверены, что хотите удалить выбранный раздел?\n\nВсе данные на этом разделе будут безвозвратно потеряны, если вы продолжите! Create… MainWindow Создать… +Are you sure you want to format a raw disk? (Most people initialize the disk with a partitioning system first) You will be asked again before changes are written to the disk. MainWindow Вы уверены, что хотите отформатировать весь диск? (Обычно на диске сначала создаются разделы) Повторный запрос будет выдан непосредственно перед записью изменений на диск. The disk has been successfully initialized.\n MainWindow Диск был успешно инициализирован.\n Could not unmount partition %s. MainWindow Невозможно отключить раздел %s. Failed to change the parameters of the partition. No changes have been written to disk. MainWindow Не удалось изменить параметры раздела. Изменения не были записаны на диск. diff --git a/data/catalogs/apps/haikudepot/ru.catkeys b/data/catalogs/apps/haikudepot/ru.catkeys index c68a262688..f5c0ff39a2 100644 --- a/data/catalogs/apps/haikudepot/ru.catkeys +++ b/data/catalogs/apps/haikudepot/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Haiku-HaikuDepot 3588353727 +1 russian x-vnd.Haiku-HaikuDepot 4273323974 Name PackageListView Имя Available packages MainWindow Доступные пакеты Open %DeskbarLink% PackageManager Открыть %DeskbarLink% @@ -53,6 +53,7 @@ The user name needs to be at least 3 letters long. UserLoginWindow Имя по Log in UserLoginWindow Войти… Repeat pass phrase: UserLoginWindow Повторить пароль: Ratings PackageInfoView Оценки +But none could be listed here, sorry. UserLoginWindow Но не удалось определить с какими именно, извините. System & Utilities Model Система и утилиты Inactive PackageListView Неактивный Refresh depots MainWindow Обновить склады @@ -89,6 +90,7 @@ Failed to create or update rating: %s\n RatePackageWindow Не удалось You need to be logged into an account before you can rate packages. MainWindow Вы должны войти в свою учётную запись перед тем как оценить пакет. It responded with: RatePackageWindow Он ответил так: User name: UserLoginWindow Имя пользователя: +User Menu MainWindow Меню пользователя Unstable but usable RatePackageWindow Нестабилен, но пригодный для использования The email address appears to be malformed. UserLoginWindow Некорректный адрес электронной почты. Games Model Игры @@ -131,6 +133,7 @@ If you do not provide an email address, you will not be able to reset your passw It responded with: UserLoginWindow Он ответил так: Authentication failed. Connection to the service failed. UserLoginWindow Неверный логин/пароль. Соединение с сервисом прервано. Cancel RatePackageWindow Отмена +Package action failed PackageInfoView Действие с пакетом не удалось. OK UserLoginWindow OK Send RatePackageWindow Отправить - no package size - diff --git a/data/catalogs/apps/mail/hu.catkeys b/data/catalogs/apps/mail/hu.catkeys index ee41f920be..9e0341ec3d 100644 --- a/data/catalogs/apps/mail/hu.catkeys +++ b/data/catalogs/apps/mail/hu.catkeys @@ -1,4 +1,4 @@ -1 hungarian x-vnd.Be-MAIL 233997769 +1 hungarian x-vnd.Be-MAIL 1310033600 View Mail Nézet %d - Date Mail %d - dátum Attach attributes: Mail Jellemzők csatolása: @@ -146,6 +146,7 @@ Open attachment Mail Megnyitás sent B_USER_DIRECTORY/mail/sent Elküldött (Date unavailable) Mail (A dátum nem elérhető) Put your favorite e-mail queries and query templates in this folder. Mail Helyezze a kedvenc lekérdezéseket és a lekérdezési sablonokat ebbe a mappába. +Spam Mail Levélszemét Reply Mail Válasz From: Mail Feladó: Couldn't open this signature. Sorry. Mail Sajnálom, de nem nyitható meg ez az aláírás. diff --git a/data/catalogs/apps/mail/pl.catkeys b/data/catalogs/apps/mail/pl.catkeys index 44f6e1bea3..c64581502f 100644 --- a/data/catalogs/apps/mail/pl.catkeys +++ b/data/catalogs/apps/mail/pl.catkeys @@ -1,4 +1,4 @@ -1 polish x-vnd.Be-MAIL 233997769 +1 polish x-vnd.Be-MAIL 1310033600 View Mail Widok %d - Date Mail %d - Data Attach attributes: Mail Dołączaj atrybuty: @@ -146,6 +146,7 @@ Open attachment Mail Otwórz załącznik sent B_USER_DIRECTORY/mail/sent sent (Date unavailable) Mail (Data niedostępna) Put your favorite e-mail queries and query templates in this folder. Mail Umieść swoje ulubione zapytania wiadomości i szablony zapytań w tym katalogu. +Spam Mail Spam Reply Mail Odpowiedz From: Mail Od: Couldn't open this signature. Sorry. Mail Nie można otworzyć tej sygnaturki. Przepraszamy. diff --git a/data/catalogs/apps/mail/ru.catkeys b/data/catalogs/apps/mail/ru.catkeys index b2a4934f2f..5ed0a23f3c 100644 --- a/data/catalogs/apps/mail/ru.catkeys +++ b/data/catalogs/apps/mail/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Be-MAIL 233997769 +1 russian x-vnd.Be-MAIL 1310033600 View Mail Вид %d - Date Mail %d - Дата Attach attributes: Mail Прикрепление атрибутов: @@ -146,6 +146,7 @@ Open attachment Mail Открыть вложение sent B_USER_DIRECTORY/mail/sent Отправленные (Date unavailable) Mail (Дата недоступна) Put your favorite e-mail queries and query templates in this folder. Mail Перенесите в эту папку ваши почтовые запросы. +Spam Mail Спам Reply Mail Ответить From: Mail От: Couldn't open this signature. Sorry. Mail Невозможно открыть эту подпись. Извините. diff --git a/data/catalogs/apps/mediaconverter/ru.catkeys b/data/catalogs/apps/mediaconverter/ru.catkeys index c9942293b0..b09d72e45e 100644 --- a/data/catalogs/apps/mediaconverter/ru.catkeys +++ b/data/catalogs/apps/mediaconverter/ru.catkeys @@ -1,6 +1,8 @@ -1 russian x-vnd.Haiku-MediaConverter 3111641182 +1 russian x-vnd.Haiku-MediaConverter 341686525 Video using parameters form settings MediaConverter Видео использует параметры из настроек +{0, plural, one{The file was not recognized as a supported media file:} other{# files were not recognized as supported media files:}} MediaConverter {0, plural, one{Файл не был распознан как поддерживаемый медиафайл:} few{# файла не были распознаны как поддерживаемые медиафайлы:} other{# файлов не было распознано как поддерживаемые медиафайлы:}} Video encoding: MediaConverter Кодирование видео: +%u x %u, %.2ffps MediaFileInfo Width x Height, fps %u x %u, %.2fкадр/с Error read audio frame %lld MediaConverter Ошибка чтения аудио кадра %lld No audio Audio codecs list Без аудио Error MediaConverter Ошибка diff --git a/data/catalogs/apps/terminal/ru.catkeys b/data/catalogs/apps/terminal/ru.catkeys index 723b0a2640..39019cf44c 100644 --- a/data/catalogs/apps/terminal/ru.catkeys +++ b/data/catalogs/apps/terminal/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Haiku-Terminal 235954604 +1 russian x-vnd.Haiku-Terminal 2918699501 Not found. Terminal TermWindow Текст не найден Switch Terminals Terminal TermWindow Переключить терминалы Change directory Terminal TermView Сменить каталог @@ -34,6 +34,7 @@ Settings Terminal TermWindow Настройки Window size Terminal TermWindow Размер окна Selected text Terminal AppearancePrefView Выделенного текста Find Terminal FindWindow Найти +The pattern specifying the window titles. The following placeholders\ncan be used: Terminal AppearancePrefView Этот шаблон описывает заголовки окна.\nВозможно использовать следующие переменные:\n Appearance Terminal PrefWindow Внешний вид Tab title: Terminal AppearancePrefView Заголовок вкладки: OK Terminal SetTitleWindow ОК @@ -76,6 +77,7 @@ Midnight Terminal colors scheme Полночь Decrease Terminal TermWindow Уменьшить Default Terminal colors scheme По умолчанию Create link here Terminal TermView Создать ссылку здесь +The pattern specifying the tab titles. The following placeholders\ncan be used: Terminal AppearancePrefView Этот шаблон описывает заголовки вкладок.\nВозможно использовать следующие переменные: Close Terminal TermWindow Закрыть Text Terminal AppearancePrefView Текста Clear all Terminal TermWindow Очистить всё From 4b26da642b959ca65d926b52c64b369b9a61b021 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 22 Aug 2015 15:08:24 +0200 Subject: [PATCH 050/125] PowerStatus: show when the battery is charging. --- src/apps/powerstatus/PowerStatusView.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/apps/powerstatus/PowerStatusView.cpp b/src/apps/powerstatus/PowerStatusView.cpp index 3b9d26c64c..ca46b4672c 100644 --- a/src/apps/powerstatus/PowerStatusView.cpp +++ b/src/apps/powerstatus/PowerStatusView.cpp @@ -11,6 +11,7 @@ #include "PowerStatusView.h" +#include #include #include #include @@ -222,6 +223,26 @@ PowerStatusView::_DrawBattery(BRect rect) } } + if (fOnline) { + // When charging, draw a lightning symbol over the battery. + SetHighColor(255, 255, 0, 180); + SetDrawingMode(B_OP_ALPHA); + SetScale(std::min(Bounds().Width(), Bounds().Height()) / 16); + + static const BPoint points[] = { + BPoint(2,13), + BPoint(9,5), + BPoint(9,7), + BPoint(16,2), + BPoint(8,11), + BPoint(8,9) + }; + FillPolygon(points,6); + + SetScale(1); + SetDrawingMode(B_OP_OVER); + } + SetHighColor(0, 0, 0); } From 44884f88fa858077aba2b50613bca7bfb87a1a36 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 22 Aug 2015 16:13:53 +0200 Subject: [PATCH 051/125] Add packages for gws and haikuporter. --- build/jam/repositories/HaikuPorts/x86_gcc2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index bdcb2c9234..7e90023a97 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -14,6 +14,8 @@ RemotePackageRepository HaikuPorts droid-113-1 flare_x86_data-0.19-3 freedroidrpg_x86_data-0.15.1-1 + gws-0.1.8-1 + haikuporter-1.0.0-1 hub-1.12.4-1 openttd_gfx-0.4.7-1 openttd_msx-0.3.1-1 @@ -1030,6 +1032,7 @@ RemotePackageRepository HaikuPorts gutenprint gyp gzip + haikuporter haikuwebkit_x86 harfbuzz_x86 help2man From f6b2da0a717c495da57e6978d7ab7e0ada5640dd Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 22 Aug 2015 17:17:16 +0200 Subject: [PATCH 052/125] launch_daemon: Add env vars from sourced files to correct list. The environment variables were always added to the static environment list instead of the one supplied as argument. This worked for targets, as there the scripts are evaluated before the static environment is used. For services and jobs this isn't the case, causing sourced environment variables to be missing. --- src/servers/launch/BaseJob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servers/launch/BaseJob.cpp b/src/servers/launch/BaseJob.cpp index 555375e3a9..3dc5d93b25 100644 --- a/src/servers/launch/BaseJob.cpp +++ b/src/servers/launch/BaseJob.cpp @@ -172,7 +172,7 @@ BaseJob::GetSourceFilesEnvironment(BStringList& environment) { int32 count = fSourceFiles.CountStrings(); for (int32 index = 0; index < count; index++) { - _GetSourceFileEnvironment(fSourceFiles.StringAt(index), fEnvironment); + _GetSourceFileEnvironment(fSourceFiles.StringAt(index), environment); } } From adba4ce988febe32e061aac861f9c489af2798c4 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 10 Mar 2014 20:27:18 -0400 Subject: [PATCH 053/125] Add BSpinner class based on GCI2013 work --- headers/private/interface/Spinner.h | 180 +++ src/kits/interface/Jamfile | 1 + src/kits/interface/Spinner.cpp | 1875 +++++++++++++++++++++++++++ 3 files changed, 2056 insertions(+) create mode 100644 headers/private/interface/Spinner.h create mode 100644 src/kits/interface/Spinner.cpp diff --git a/headers/private/interface/Spinner.h b/headers/private/interface/Spinner.h new file mode 100644 index 0000000000..18801e74c7 --- /dev/null +++ b/headers/private/interface/Spinner.h @@ -0,0 +1,180 @@ +/* + * Copyright 2004 DarkWyrm + * Copyright 2013 FeemanLou + * Copyright 2014 Haiku, Inc. All rights reserved. + * + * Distributed under the terms of the MIT license. + * + * Originally written by DarkWyrm + * Updated by FreemanLou as part of Google GCI 2013 + * + * Authors: + * DarkWyrm, darkwyrm@earthlink.net + * FeemanLou + * John Scipione, jscipione@gmail.com + */ +#ifndef SPINNER_H +#define SPINNER_H + + +#include +#include + + +class BTextView; +class SpinnerArrow; +class SpinnerTextView; + + +/*! BSpinner provides a numeric input whose value can be nudged up or down + by way of two small buttons on the right. +*/ +class BSpinner : public BView, public BInvoker { +public: + BSpinner(BRect frame, const char* name, + const char* label, BMessage* message, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BSpinner(const char* name, const char* label, + BMessage* message, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BSpinner(BMessage* data); + virtual ~BSpinner(); + + static BArchivable* Instantiate(BMessage* data); + virtual status_t Archive(BMessage* data, bool deep = true) const; + + virtual status_t GetSupportedSuites(BMessage* message); + virtual BHandler* ResolveSpecifier(BMessage* message, int32 index, + BMessage* specifier, int32 form, + const char* property); + + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); + virtual void FrameResized(float width, float height); + virtual void MakeFocus(bool focus = true); + virtual void ResizeToPreferred(); + virtual void SetFlags(uint32 flags); + virtual void ValueChanged(); + virtual void WindowActivated(bool active); + + alignment Alignment() const { return fAlignment; }; + virtual void SetAlignment(alignment align); + + float Divider() const { return fDivider; }; + virtual void SetDivider(float position); + + bool IsEnabled() const { return fIsEnabled; }; + virtual void SetEnabled(bool enable); + + const char* Label() const { return fLabel; }; + virtual void SetLabel(const char* text); + + uint32 Precision() const { return fPrecision; }; + virtual void SetPrecision(uint32 precision) { fPrecision = precision; }; + + double MaxValue() const { return fMaxValue; } + virtual void SetMaxValue(double max); + + double MinValue() const { return fMinValue; } + virtual void SetMinValue(double min); + + void Range(double* min, double* max); + virtual void SetRange(double min, double max); + + double Step() const { return fStep; } + virtual void SetStep(double step) { fStep = step; }; + + double Value() const { return fValue; }; + virtual void SetValue(double value); + + bool IsDecrementEnabled() const; + virtual void SetDecrementEnabled(bool enable); + + bool IsIncrementEnabled() const; + virtual void SetIncrementEnabled(bool enable); + + virtual BSize MinSize(); + virtual BSize MaxSize(); + virtual BSize PreferredSize(); + virtual BAlignment LayoutAlignment(); + + BLayoutItem* CreateLabelLayoutItem(); + BLayoutItem* CreateTextViewLayoutItem(); + + BTextView* TextView() const; + +private: + // FBC padding + virtual void _ReservedSpinner20(); + virtual void _ReservedSpinner19(); + virtual void _ReservedSpinner18(); + virtual void _ReservedSpinner17(); + virtual void _ReservedSpinner16(); + virtual void _ReservedSpinner15(); + virtual void _ReservedSpinner14(); + virtual void _ReservedSpinner13(); + virtual void _ReservedSpinner12(); + virtual void _ReservedSpinner11(); + virtual void _ReservedSpinner10(); + virtual void _ReservedSpinner9(); + virtual void _ReservedSpinner8(); + virtual void _ReservedSpinner7(); + virtual void _ReservedSpinner6(); + virtual void _ReservedSpinner5(); + virtual void _ReservedSpinner4(); + virtual void _ReservedSpinner3(); + virtual void _ReservedSpinner2(); + virtual void _ReservedSpinner1(); + +protected: + virtual status_t AllArchived(BMessage* into) const; + virtual status_t AllUnarchived(const BMessage* from); + + virtual void LayoutInvalidated(bool descendants); + virtual void DoLayout(); + +private: + class LabelLayoutItem; + class TextViewLayoutItem; + struct LayoutData; + + friend class SpinnerArrow; + friend class SpinnerTextView; + + friend class LabelLayoutItem; + friend class TextViewLayoutItem; + friend struct LayoutData; + + void _DrawLabel(BRect updateRect); + void _DrawTextView(BRect updateRect); + void _InitObject(); + void _LayoutTextView(); + void _UpdateFrame(); + void _UpdateTextViewColors(bool enable); + void _ValidateLayoutData(); + + BSpinner& operator=(const BSpinner& other); + + alignment fAlignment; + float fDivider; + bool fIsEnabled; + const char* fLabel; + double fMinValue; + double fMaxValue; + double fStep; + double fValue; + uint32 fPrecision; + + LayoutData* fLayoutData; + + SpinnerTextView* fTextView; + SpinnerArrow* fIncrement; + SpinnerArrow* fDecrement; + + // FBC padding + uint32 _reserved[20]; +}; + + +#endif // SPINNER_H diff --git a/src/kits/interface/Jamfile b/src/kits/interface/Jamfile index af100e0bfc..79a00d0d00 100644 --- a/src/kits/interface/Jamfile +++ b/src/kits/interface/Jamfile @@ -116,6 +116,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { Size.cpp Slider.cpp SpaceLayoutItem.cpp + Spinner.cpp SplitLayout.cpp SplitLayoutBuilder.cpp SplitView.cpp diff --git a/src/kits/interface/Spinner.cpp b/src/kits/interface/Spinner.cpp new file mode 100644 index 0000000000..1176c4ad35 --- /dev/null +++ b/src/kits/interface/Spinner.cpp @@ -0,0 +1,1875 @@ +/* + * Copyright 2004 DarkWyrm + * Copyright 2013 FeemanLou + * Copyright 2014 Haiku, Inc. All rights reserved. + * + * Distributed under the terms of the MIT license. + * + * Originally written by DarkWyrm + * Updated by FreemanLou as part of Google GCI 2013 + * + * Authors: + * DarkWyrm, darkwyrm@earthlink.net + * FeemanLou + * John Scipione, jscipione@gmail.com + */ + + +#include "Spinner.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Thread.h" + + +static const float kFrameMargin = 2.0f; + +const char* const kFrameField = "BSpinner:layoutItem:frame"; +const char* const kLabelItemField = "BSpinner:labelItem"; +const char* const kTextViewItemField = "BSpinner:textViewItem"; + + +static double +roundTo(double value, uint32 n) +{ + return floor(value * pow(10.0, n) + 0.5) / pow(10.0, n); +} + + +static property_info sProperties[] = { + { + "Align", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the alignment of the spinner label.", + 0, + { B_INT32_TYPE } + }, + { + "Align", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the alignment of the spinner label.", + 0, + { B_INT32_TYPE } + }, + + { + "Divider", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the divider position of the spinner.", + 0, + { B_FLOAT_TYPE } + }, + { + "Divider", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the divider position of the spinner.", + 0, + { B_FLOAT_TYPE } + }, + + { + "Enabled", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns whether or not the spinner is enabled.", + 0, + { B_BOOL_TYPE } + }, + { + "Enabled", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets whether or not the spinner is enabled.", + 0, + { B_BOOL_TYPE } + }, + + { + "Label", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the spinner label.", + 0, + { B_STRING_TYPE } + }, + { + "Label", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the spinner label.", + 0, + { B_STRING_TYPE } + }, + + { + "Message", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the spinner invocation message.", + 0, + { B_MESSAGE_TYPE } + }, + { + "Message", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the spinner invocation message.", + 0, + { B_MESSAGE_TYPE } + }, + + { + "MaxValue", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the maximum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "MaxValue", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the maximum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "MinValue", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the minimum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "MinValue", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the minimum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "Precision", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the number of decimal places of precision of the spinner.", + 0, + { B_UINT32_TYPE } + }, + { + "Precision", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the number of decimal places of precision of the spinner.", + 0, + { B_UINT32_TYPE } + }, + + { + "Step", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the step size of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "Step", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the step size of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "Value", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "Value", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { 0 } +}; + + +typedef enum { + ARROW_UP, + ARROW_DOWN +} arrow_direction; + + +class SpinnerArrow : public BView { +public: + SpinnerArrow(BRect frame, const char* name, + arrow_direction direction); + virtual ~SpinnerArrow(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void Draw(BRect updateRect); + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* message); + + bool IsEnabled() const { return fIsEnabled; } + virtual void SetEnabled(bool enable) { fIsEnabled = enable; }; + +private: + void _DoneTracking(BPoint where); + void _Track(BPoint where, uint32); + + arrow_direction fArrowDirection; + BSpinner* fParent; + bool fIsEnabled; + bool fIsMouseDown; + bool fIsMouseOver; + bigtime_t fRepeatDelay; +}; + + +class SpinnerTextView : public BTextView { +public: + SpinnerTextView(BRect rect, BRect textRect); + virtual ~SpinnerTextView(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void KeyDown(const char* bytes, int32 numBytes); + virtual void MakeFocus(bool focus); + +private: + void _SetValueToText(); + + BSpinner* fParent; +}; + + +class BSpinner::LabelLayoutItem : public BAbstractLayoutItem { +public: + LabelLayoutItem(BSpinner* parent); + LabelLayoutItem(BMessage* archive); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + void SetParent(BSpinner* parent); + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + BRect FrameInParent() const; + + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* from); + +private: + BSpinner* fParent; + BRect fFrame; +}; + + +class BSpinner::TextViewLayoutItem : public BAbstractLayoutItem { +public: + TextViewLayoutItem(BSpinner* parent); + TextViewLayoutItem(BMessage* archive); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + void SetParent(BSpinner* parent); + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + BRect FrameInParent() const; + + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* from); + +private: + BSpinner* fParent; + BRect fFrame; +}; + + +struct BSpinner::LayoutData { + LayoutData(float width, float height) + : + label_layout_item(NULL), + text_view_layout_item(NULL), + label_width(0), + label_height(0), + text_view_width(0), + text_view_height(0), + previous_width(width), + previous_height(height), + valid(false) + { + } + + LabelLayoutItem* label_layout_item; + TextViewLayoutItem* text_view_layout_item; + + font_height font_info; + + float label_width; + float label_height; + float text_view_width; + float text_view_height; + + float previous_width; + float previous_height; + + BSize min; + BAlignment alignment; + + bool valid; +}; + + +// #pragma mark - SpinnerArrow + + +SpinnerArrow::SpinnerArrow(BRect frame, const char* name, + arrow_direction direction) + : + BView(frame, name, B_FOLLOW_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW), + fArrowDirection(direction), + fParent(NULL), + fIsEnabled(true), + fIsMouseDown(false), + fIsMouseOver(false), + fRepeatDelay(100000) +{ + rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(backgroundColor); + SetLowColor(backgroundColor); +} + + +SpinnerArrow::~SpinnerArrow() +{ +} + + +void +SpinnerArrow::AttachedToWindow() +{ + fParent = static_cast(Parent()); + + BView::AttachedToWindow(); +} + + +void +SpinnerArrow::DetachedFromWindow() +{ + fParent = NULL; + + BView::DetachedFromWindow(); +} + + +void +SpinnerArrow::Draw(BRect updateRect) +{ + BRect rect(Bounds()); + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + BView::Draw(updateRect); + + float tint; + if (!fIsEnabled) + tint = B_DARKEN_1_TINT; + else if (fIsMouseDown) + tint = B_DARKEN_MAX_TINT; + else if (fIsMouseOver) + tint = B_DARKEN_3_TINT; + else + tint = B_DARKEN_2_TINT; + + rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetHighColor(tint_color(backgroundColor, tint)); + + // draw a gradient background + BGradientLinear gradient; + gradient.AddColor(tint_color(backgroundColor, B_LIGHTEN_2_TINT), 0); + gradient.AddColor(backgroundColor, 255); + gradient.SetStart(rect.LeftTop()); + gradient.SetEnd(rect.LeftBottom()); + FillRect(rect, gradient); + + // draw the border + StrokeRect(rect); + + // draw the arrow + BPoint point1; + BPoint point2; + BPoint point3; + if (fArrowDirection == ARROW_UP) { + point1.x = ceilf(rect.Width() / 2); + point1.y = rect.top + 1.0f; + + point2.x = point1.x - 3.0f; + point2.y = rect.bottom - 2.0f; + + point3.x = point1.x + 3.0f; + point3.y = rect.bottom - 2.0f; + } else { + point1.x = ceilf(rect.Width() / 2); + point1.y = rect.bottom - 1.0f; + + point2.x = point1.x - 3.0f; + point2.y = rect.top + 2.0f; + + point3.x = point1.x + 3.0f; + point3.y = rect.top + 2.0f; + } + FillTriangle(point1, point2, point3); +} + + +void +SpinnerArrow::MouseDown(BPoint where) +{ + if (fIsEnabled) { + fIsMouseDown = true; + Invalidate(); + fRepeatDelay = 100000; + MouseDownThread::TrackMouse(this, + &SpinnerArrow::_DoneTracking, &SpinnerArrow::_Track); + } + + BView::MouseDown(where); +} + + +void +SpinnerArrow::MouseMoved(BPoint where, uint32 transit, + const BMessage* message) +{ + switch (transit) { + case B_ENTERED_VIEW: + case B_INSIDE_VIEW: + { + BPoint where; + uint32 buttons; + GetMouse(&where, &buttons); + fIsMouseOver = Bounds().Contains(where) && buttons == 0; + if (!fIsMouseDown) + Invalidate(); + + break; + } + + case B_EXITED_VIEW: + case B_OUTSIDE_VIEW: + fIsMouseOver = false; + MouseUp(Bounds().LeftTop()); + break; + } + + BView::MouseMoved(where, transit, message); +} + + +void +SpinnerArrow::MouseUp(BPoint where) +{ + fIsMouseDown = false; + Invalidate(); + + BView::MouseUp(where); +} + + +// #pragma mark - SpinnerArrow private methods + + +void +SpinnerArrow::_DoneTracking(BPoint where) +{ + if (fIsMouseDown || !Bounds().Contains(where)) + fIsMouseDown = false; +} + + +void +SpinnerArrow::_Track(BPoint where, uint32) +{ + if (fParent == NULL || !Bounds().Contains(where)) { + fIsMouseDown = false; + return; + } + fIsMouseDown = true; + + double step = fArrowDirection == ARROW_UP + ? fParent->Step() + : -fParent->Step(); + double newValue = fParent->Value() + step; + if (newValue < fParent->MinValue()) { + // new value is below lower bound, clip to lower bound + fParent->SetValue(fParent->MinValue()); + } else if (newValue>fParent->MaxValue()) { + // new value is above upper bound, clip to upper bound + fParent->SetValue(fParent->MaxValue()); + } else { + // new value is in range + fParent->SetValue(newValue); + } + fParent->Invoke(); + fParent->Invalidate(); + + snooze(fRepeatDelay); + fRepeatDelay = 10000; +} + + +// #pragma mark - SpinnerTextView + + +SpinnerTextView::SpinnerTextView(BRect rect, BRect textRect) + : + BTextView(rect, "textview", textRect, B_FOLLOW_ALL, + B_WILL_DRAW | B_NAVIGABLE), + fParent(NULL) +{ + rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(backgroundColor); + SetLowColor(backgroundColor); + + SetAlignment(B_ALIGN_RIGHT); + for (uint32 c = 0; c <= 42; c++) + DisallowChar(c); + + DisallowChar('/'); + for (uint32 c = 58; c <= 127; c++) + DisallowChar(c); +} + + +SpinnerTextView::~SpinnerTextView() +{ +} + + +void +SpinnerTextView::AttachedToWindow() +{ + fParent = static_cast(Parent()); + + BTextView::AttachedToWindow(); +} + + +void +SpinnerTextView::DetachedFromWindow() +{ + fParent = NULL; + + BTextView::DetachedFromWindow(); +} + + +void +SpinnerTextView::KeyDown(const char* bytes, int32 numBytes) +{ + if (fParent == NULL) { + BTextView::KeyDown(bytes, numBytes); + return; + } + + switch (bytes[0]) { + case B_ENTER: + case B_SPACE: + _SetValueToText(); + break; + + case B_TAB: + fParent->KeyDown(bytes, numBytes); + break; + + case B_UP_ARROW: + case B_PAGE_UP: + case B_DOWN_ARROW: + case B_PAGE_DOWN: + { + double step = fParent->Step(); + if (*bytes == B_DOWN_ARROW || *bytes == B_PAGE_DOWN) + step *= -1; + + fParent->SetValue(fParent->Value() + step); + fParent->Invoke(); + fParent->Invalidate(); + break; + } + + default: + BTextView::KeyDown(bytes, numBytes); + } +} + + +void +SpinnerTextView::MakeFocus(bool focus) +{ + BTextView::MakeFocus(focus); + + if (focus) + SelectAll(); + else + _SetValueToText(); + + if (fParent != NULL) + fParent->_DrawTextView(fParent->Bounds()); +} + + +// #pragma mark - SpinnerTextView private methods + + +void +SpinnerTextView::_SetValueToText() +{ + if (fParent == NULL) + return; + + fParent->SetValue(roundTo(atof(Text()), fParent->Precision())); + fParent->Invoke(); + fParent->Invalidate(); +} + + +// #pragma mark - BSpinner::LabelLayoutItem + + +BSpinner::LabelLayoutItem::LabelLayoutItem(BSpinner* parent) + : + fParent(parent), + fFrame() +{ +} + + +BSpinner::LabelLayoutItem::LabelLayoutItem(BMessage* from) + : + BAbstractLayoutItem(from), + fParent(NULL), + fFrame() +{ + from->FindRect(kFrameField, &fFrame); +} + + +bool +BSpinner::LabelLayoutItem::IsVisible() +{ + return !fParent->IsHidden(fParent); +} + + +void +BSpinner::LabelLayoutItem::SetVisible(bool visible) +{ +} + + +BRect +BSpinner::LabelLayoutItem::Frame() +{ + return fFrame; +} + + +void +BSpinner::LabelLayoutItem::SetFrame(BRect frame) +{ + fFrame = frame; + fParent->_UpdateFrame(); +} + + +void +BSpinner::LabelLayoutItem::SetParent(BSpinner* parent) +{ + fParent = parent; +} + + +BView* +BSpinner::LabelLayoutItem::View() +{ + return fParent; +} + + +BSize +BSpinner::LabelLayoutItem::BaseMinSize() +{ + fParent->_ValidateLayoutData(); + + if (fParent->Label() == NULL) + return BSize(-1.0f, -1.0f); + + return BSize(fParent->fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(), + fParent->fLayoutData->label_height); +} + + +BSize +BSpinner::LabelLayoutItem::BaseMaxSize() +{ + return BaseMinSize(); +} + + +BSize +BSpinner::LabelLayoutItem::BasePreferredSize() +{ + return BaseMinSize(); +} + + +BAlignment +BSpinner::LabelLayoutItem::BaseAlignment() +{ + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); +} + + +BRect +BSpinner::LabelLayoutItem::FrameInParent() const +{ + return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); +} + + +status_t +BSpinner::LabelLayoutItem::Archive(BMessage* into, bool deep) const +{ + BArchiver archiver(into); + status_t result = BAbstractLayoutItem::Archive(into, deep); + + if (result == B_OK) + result = into->AddRect(kFrameField, fFrame); + + return archiver.Finish(result); +} + + +BArchivable* +BSpinner::LabelLayoutItem::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "BSpinner::LabelLayoutItem")) + return new LabelLayoutItem(from); + + return NULL; +} + + +// #pragma mark - BSpinner::TextViewLayoutItem + + +BSpinner::TextViewLayoutItem::TextViewLayoutItem(BSpinner* parent) + : + fParent(parent), + fFrame() +{ + SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); +} + + +BSpinner::TextViewLayoutItem::TextViewLayoutItem(BMessage* from) + : + BAbstractLayoutItem(from), + fParent(NULL), + fFrame() +{ + from->FindRect(kFrameField, &fFrame); +} + + +bool +BSpinner::TextViewLayoutItem::IsVisible() +{ + return !fParent->IsHidden(fParent); +} + + +void +BSpinner::TextViewLayoutItem::SetVisible(bool visible) +{ + // not allowed +} + + +BRect +BSpinner::TextViewLayoutItem::Frame() +{ + return fFrame; +} + + +void +BSpinner::TextViewLayoutItem::SetFrame(BRect frame) +{ + fFrame = frame; + fParent->_UpdateFrame(); +} + + +void +BSpinner::TextViewLayoutItem::SetParent(BSpinner* parent) +{ + fParent = parent; +} + + +BView* +BSpinner::TextViewLayoutItem::View() +{ + return fParent; +} + + +BSize +BSpinner::TextViewLayoutItem::BaseMinSize() +{ + fParent->_ValidateLayoutData(); + + BSize size(fParent->fLayoutData->text_view_width, + fParent->fLayoutData->text_view_height); + return size; +} + + +BSize +BSpinner::TextViewLayoutItem::BaseMaxSize() +{ + return BaseMinSize(); +} + + +BSize +BSpinner::TextViewLayoutItem::BasePreferredSize() +{ + return BaseMinSize(); +} + + +BAlignment +BSpinner::TextViewLayoutItem::BaseAlignment() +{ + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); +} + + +BRect +BSpinner::TextViewLayoutItem::FrameInParent() const +{ + return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); +} + + +status_t +BSpinner::TextViewLayoutItem::Archive(BMessage* into, bool deep) const +{ + BArchiver archiver(into); + status_t result = BAbstractLayoutItem::Archive(into, deep); + + if (result == B_OK) + result = into->AddRect(kFrameField, fFrame); + + return archiver.Finish(result); +} + + +BArchivable* +BSpinner::TextViewLayoutItem::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "BSpinner::TextViewLayoutItem")) + return new LabelLayoutItem(from); + + return NULL; +} + + +// #pragma mark - BSpinner + + +BSpinner::BSpinner(BRect frame, const char* name, const char* label, + BMessage* message, uint32 resizingMode, uint32 flags) + : + BView(frame, name, resizingMode, flags | B_WILL_DRAW | B_FRAME_EVENTS), + fLabel(label) +{ + SetMessage(message); + _InitObject(); +} + + +BSpinner::BSpinner(const char* name, const char* label, BMessage* message, + uint32 flags) + : + BView(name, flags | B_WILL_DRAW | B_FRAME_EVENTS), + fLabel(label) +{ + SetMessage(message); + _InitObject(); +} + + +BSpinner::BSpinner(BMessage* data) + : + BView(data) +{ + _InitObject(); + + if (data->FindInt32("_align") != B_OK) + fAlignment = B_ALIGN_LEFT; + + if (data->FindInt32("_divider") != B_OK) + fDivider = 0.0f; + + if (data->FindBool("_enabled") != B_OK) + fIsEnabled = true; + + if (data->FindString("_label", &fLabel) != B_OK) + fLabel = NULL; + + BMessage* message = NULL; + if (data->FindMessage("_message", message) == B_OK) + SetMessage(message); + + if (data->FindDouble("_max", &fMaxValue) != B_OK) + fMinValue = 100.0; + + if (data->FindDouble("_min", &fMinValue) != B_OK) + fMinValue = 0.0; + + if (data->FindUInt32("_precision", &fPrecision) != B_OK) + fPrecision = 2; + + if (data->FindDouble("_step", &fStep) != B_OK) + fStep = 1.0; + + if (data->FindDouble("_value", &fValue) != B_OK) + fValue = 0.0; +} + + +BSpinner::~BSpinner() +{ + delete fLayoutData; + fLayoutData = NULL; +} + + +BArchivable* +BSpinner::Instantiate(BMessage* data) +{ + if (validate_instantiation(data, "Spinner")) + return new BSpinner(data); + + return NULL; +} + + +status_t +BSpinner::Archive(BMessage* data, bool deep) const +{ + status_t status = BView::Archive(data, deep); + data->AddString("class", "Spinner"); + + if (status == B_OK) + status = data->AddInt32("_align", fAlignment); + + if (status == B_OK) + status = data->AddFloat("_divider", fDivider); + + if (status == B_OK) + status = data->AddBool("_enabled", fIsEnabled); + + if (status == B_OK && fLabel != NULL) + status = data->AddString("_label", fLabel); + + if (status == B_OK && Message() != NULL) + status = data->AddMessage("_message", Message()); + + if (status == B_OK) + status = data->AddDouble("_max", fMaxValue); + + if (status == B_OK) + status = data->AddDouble("_min", fMinValue); + + if (status == B_OK) + status = data->AddUInt32("_precision", fPrecision); + + if (status == B_OK) + status = data->AddDouble("_step", fStep); + + if (status == B_OK) + status = data->AddDouble("_value", fValue); + + return status; +} + + +status_t +BSpinner::GetSupportedSuites(BMessage* message) +{ + message->AddString("suites", "suite/vnd.Haiku-spinner"); + + BPropertyInfo prop_info(sProperties); + message->AddFlat("messages", &prop_info); + + return BView::GetSupportedSuites(message); +} + + +BHandler* +BSpinner::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier, + int32 form, const char* property) +{ + return BView::ResolveSpecifier(message, index, specifier, form, + property); +} + + +void +BSpinner::AttachedToWindow() +{ + if (!Messenger().IsValid()) + SetTarget(Window()); + + SetValue(fValue); + // sets the text and enables or disables the arrows + _UpdateTextViewColors(IsEnabled()); + fTextView->MakeEditable(IsEnabled()); + + BView::AttachedToWindow(); +} + + +void +BSpinner::Draw(BRect updateRect) +{ + _DrawLabel(updateRect); + _DrawTextView(updateRect); + fIncrement->Invalidate(); + fDecrement->Invalidate(); +} + + +void +BSpinner::FrameResized(float width, float height) +{ + BView::FrameResized(width, height); + + // TODO: this causes flickering still... + + // changes in width + + BRect bounds = Bounds(); + + if (bounds.Width() > fLayoutData->previous_width) { + // invalidate the region between the old and the new right border + BRect rect = bounds; + rect.left += fLayoutData->previous_width - kFrameMargin; + rect.right--; + Invalidate(rect); + } else if (bounds.Width() < fLayoutData->previous_width) { + // invalidate the region of the new right border + BRect rect = bounds; + rect.left = rect.right - kFrameMargin; + Invalidate(rect); + } + + // changes in height + + if (bounds.Height() > fLayoutData->previous_height) { + // invalidate the region between the old and the new bottom border + BRect rect = bounds; + rect.top += fLayoutData->previous_height - kFrameMargin; + rect.bottom--; + Invalidate(rect); + // invalidate label area + rect = bounds; + rect.right = fDivider; + Invalidate(rect); + } else if (bounds.Height() < fLayoutData->previous_height) { + // invalidate the region of the new bottom border + BRect rect = bounds; + rect.top = rect.bottom - kFrameMargin; + Invalidate(rect); + // invalidate label area + rect = bounds; + rect.right = fDivider; + Invalidate(rect); + } + + fLayoutData->previous_width = bounds.Width(); + fLayoutData->previous_height = bounds.Height(); +} + + +void +BSpinner::MakeFocus(bool focus) +{ + fTextView->MakeFocus(focus); +} + + +void +BSpinner::ResizeToPreferred() +{ + BView::ResizeToPreferred(); + + const char* label = Label(); + if (label != NULL) { + fDivider = ceilf(StringWidth(label)) + + be_control_look->DefaultLabelSpacing(); + } else + fDivider = 0.0f; + + _LayoutTextView(); +} + + +void +BSpinner::SetFlags(uint32 flags) +{ + // If the textview is navigable, set it to not navigable if needed, + // else if it is not navigable, set it to navigable if needed + if (fTextView->Flags() & B_NAVIGABLE) { + if (!(flags & B_NAVIGABLE)) + fTextView->SetFlags(fTextView->Flags() & ~B_NAVIGABLE); + } else { + if (flags & B_NAVIGABLE) + fTextView->SetFlags(fTextView->Flags() | B_NAVIGABLE); + } + + // Don't make this one navigable + flags &= ~B_NAVIGABLE; + + BView::SetFlags(flags); +} + + +void +BSpinner::ValueChanged() +{ + // hook method - does nothing +} + + +void +BSpinner::WindowActivated(bool active) +{ + _DrawTextView(fTextView->Frame()); +} + + +void +BSpinner::SetAlignment(alignment align) +{ + fAlignment = align; +} + + +void +BSpinner::SetDivider(float position) +{ + position = roundf(position); + + float delta = fDivider - position; + if (delta == 0.0f) + return; + + fDivider = position; + + if ((Flags() & B_SUPPORTS_LAYOUT) != 0) { + // We should never get here, since layout support means, we also + // layout the divider, and don't use this method at all. + Relayout(); + } else { + _LayoutTextView(); + Invalidate(); + } +} + + +void +BSpinner::SetEnabled(bool enable) +{ + if (IsEnabled() == enable) + return; + + fIsEnabled = enable; + fTextView->MakeEditable(enable); + if (enable) + fTextView->SetFlags(fTextView->Flags() | B_NAVIGABLE); + else + fTextView->SetFlags(fTextView->Flags() & ~B_NAVIGABLE); + + _UpdateTextViewColors(enable); + fTextView->Invalidate(); + SetIncrementEnabled(enable && fValue < fMaxValue); + SetDecrementEnabled(enable && fValue > fMinValue); + + _LayoutTextView(); + Invalidate(); + if (Window() != NULL) + Window()->UpdateIfNeeded(); +} + + +void +BSpinner::SetLabel(const char* label) +{ + fLabel = label; + if (Window() != NULL) { + Invalidate(); + Window()->UpdateIfNeeded(); + } + + InvalidateLayout(); +} + + +void +BSpinner::SetMaxValue(double max) +{ + fMaxValue = max; + if (fValue > fMaxValue) + SetValue(fMaxValue); +} + + +void +BSpinner::SetMinValue(double min) +{ + fMinValue = min; + if (fValue < fMinValue) + SetValue(fMinValue); +} + + +void +BSpinner::Range(double* min, double* max) +{ + *min = fMinValue; + *max = fMaxValue; +} + + +void +BSpinner::SetRange(double min, double max) +{ + SetMinValue(min); + SetMaxValue(max); +} + + +void +BSpinner::SetValue(double value) +{ + // clip to range + if (value < fMinValue) + value = fMinValue; + else if (value > fMaxValue) + value = fMaxValue; + + // update the text view + char* format; + asprintf(&format, "%%.%" B_PRId32 "f", fPrecision); + char* valueString; + asprintf(&valueString, format, value); + fTextView->SetText(valueString); + free(format); + free(valueString); + + // update the up and down arrows + SetIncrementEnabled(IsEnabled() && value < fMaxValue); + SetDecrementEnabled(IsEnabled() && value > fMinValue); + + if (value == fValue) + return; + + fValue = value; + ValueChanged(); +} + + +bool +BSpinner::IsDecrementEnabled() const +{ + return fDecrement->IsEnabled(); +} + + +void +BSpinner::SetDecrementEnabled(bool enable) +{ + if (IsDecrementEnabled() == enable) + return; + + fDecrement->SetEnabled(enable); + fDecrement->Invalidate(); +} + + +bool +BSpinner::IsIncrementEnabled() const +{ + return fIncrement->IsEnabled(); +} + + +void +BSpinner::SetIncrementEnabled(bool enable) +{ + if (IsIncrementEnabled() == enable) + return; + + fIncrement->SetEnabled(enable); + fIncrement->Invalidate(); +} + + +BSize +BSpinner::MinSize() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeSize(ExplicitMinSize(), fLayoutData->min); +} + + +BSize +BSpinner::MaxSize() +{ + _ValidateLayoutData(); + + BSize max = fLayoutData->min; + max.width = B_SIZE_UNLIMITED; + + return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max); +} + + +BSize +BSpinner::PreferredSize() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), + fLayoutData->min); +} + + +BAlignment +BSpinner::LayoutAlignment() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeAlignment(ExplicitAlignment(), + BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER)); +} + + +BLayoutItem* +BSpinner::CreateLabelLayoutItem() +{ + if (fLayoutData->label_layout_item == NULL) + fLayoutData->label_layout_item = new LabelLayoutItem(this); + + return fLayoutData->label_layout_item; +} + + +BLayoutItem* +BSpinner::CreateTextViewLayoutItem() +{ + if (fLayoutData->text_view_layout_item == NULL) + fLayoutData->text_view_layout_item = new TextViewLayoutItem(this); + + return fLayoutData->text_view_layout_item; +} + + +BTextView* +BSpinner::TextView() const +{ + return dynamic_cast(fTextView); +} + + +// #pragma mark - BSpinner protected methods + + +status_t +BSpinner::AllArchived(BMessage* into) const +{ + status_t result; + if ((result = BView::AllArchived(into)) != B_OK) + return result; + + BArchiver archiver(into); + + BArchivable* textViewItem = fLayoutData->text_view_layout_item; + if (archiver.IsArchived(textViewItem)) + result = archiver.AddArchivable(kTextViewItemField, textViewItem); + + if (result != B_OK) + return result; + + BArchivable* labelBarItem = fLayoutData->label_layout_item; + if (archiver.IsArchived(labelBarItem)) + result = archiver.AddArchivable(kLabelItemField, labelBarItem); + + return result; +} + + +status_t +BSpinner::AllUnarchived(const BMessage* from) +{ + BUnarchiver unarchiver(from); + + status_t result = B_OK; + if ((result = BView::AllUnarchived(from)) != B_OK) + return result; + + if (unarchiver.IsInstantiated(kTextViewItemField)) { + TextViewLayoutItem*& textViewItem + = fLayoutData->text_view_layout_item; + result = unarchiver.FindObject(kTextViewItemField, + BUnarchiver::B_DONT_ASSUME_OWNERSHIP, textViewItem); + + if (result == B_OK) + textViewItem->SetParent(this); + else + return result; + } + + if (unarchiver.IsInstantiated(kLabelItemField)) { + LabelLayoutItem*& labelItem = fLayoutData->label_layout_item; + result = unarchiver.FindObject(kLabelItemField, + BUnarchiver::B_DONT_ASSUME_OWNERSHIP, labelItem); + + if (result == B_OK) + labelItem->SetParent(this); + } + + return result; +} + + +void +BSpinner::DoLayout() +{ + if ((Flags() & B_SUPPORTS_LAYOUT) == 0) + return; + + if (GetLayout()) { + BView::DoLayout(); + return; + } + + _ValidateLayoutData(); + + BSize size(Bounds().Size()); + if (size.width < fLayoutData->min.width) + size.width = fLayoutData->min.width; + + if (size.height < fLayoutData->min.height) + size.height = fLayoutData->min.height; + + float divider = 0; + if (fLayoutData->label_layout_item != NULL + && fLayoutData->text_view_layout_item != NULL + && fLayoutData->label_layout_item->Frame().IsValid() + && fLayoutData->text_view_layout_item->Frame().IsValid()) { + divider = fLayoutData->text_view_layout_item->Frame().left + - fLayoutData->label_layout_item->Frame().left; + } else if (fLayoutData->label_width > 0) { + divider = fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(); + } + fDivider = divider; + + BRect dirty(fTextView->Frame()); + _LayoutTextView(); + + // invalidate dirty region + dirty = dirty | fTextView->Frame(); + dirty = dirty | fIncrement->Frame(); + dirty = dirty | fDecrement->Frame(); + + Invalidate(dirty); +} + + +void +BSpinner::LayoutInvalidated(bool descendants) +{ + if (fLayoutData != NULL) + fLayoutData->valid = false; +} + + +// #pragma mark - BSpinner private methods + + +void +BSpinner::_DrawLabel(BRect updateRect) +{ + BRect rect(Bounds()); + rect.right = fDivider; + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + _ValidateLayoutData(); + + const char* label = Label(); + if (label == NULL) + return; + + // horizontal position + float x; + switch (fAlignment) { + case B_ALIGN_RIGHT: + x = fDivider - fLayoutData->label_width - 3.0f; + break; + + case B_ALIGN_CENTER: + x = fDivider - roundf(fLayoutData->label_width / 2.0f); + break; + + default: + x = 0.0f; + break; + } + + // vertical position + font_height& fontHeight = fLayoutData->font_info; + float y = rect.top + + roundf((rect.Height() + 1.0f - fontHeight.ascent + - fontHeight.descent) / 2.0f) + + fontHeight.ascent + kFrameMargin * 2; + + uint32 flags = 0; + if (!IsEnabled()) + flags |= BControlLook::B_DISABLED; + + be_control_look->DrawLabel(this, label, LowColor(), flags, BPoint(x, y)); +} + + +void +BSpinner::_DrawTextView(BRect updateRect) +{ + BRect rect = fTextView->Frame(); + rect.InsetBy(-kFrameMargin, -kFrameMargin); + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 flags = 0; + if (!IsEnabled()) + flags |= BControlLook::B_DISABLED; + + if (fTextView->IsFocus() && Window()->IsActive()) + flags |= BControlLook::B_FOCUSED; + + be_control_look->DrawTextControlBorder(this, rect, updateRect, base, + flags); +} + + +void +BSpinner::_InitObject() +{ + rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(backgroundColor); + SetLowColor(backgroundColor); + + fAlignment = B_ALIGN_LEFT; + if (Label() != NULL) { + fDivider = StringWidth(Label()) + + be_control_look->DefaultLabelSpacing(); + } else + fDivider = 0.0f; + + fIsEnabled = true; + + fMaxValue = 100.0; + fMinValue = 0.0; + fPrecision = 2; + fStep = 1.0; + fValue = 0.0; + + BRect rect(Bounds()); + fLayoutData = new LayoutData(rect.Width(), rect.Height()); + + rect.left = fDivider; + rect.InsetBy(kFrameMargin, kFrameMargin); + rect.right -= rect.Height(); + BRect textRect(rect.OffsetToCopy(B_ORIGIN)); + + fTextView = new SpinnerTextView(rect, textRect); + AddChild(fTextView); + + float halfHeight = rect.Height() / 2.0f; + + rect.left = rect.right + kFrameMargin; + rect.right = rect.left + rect.Height(); + rect.top -= 1.0f; + rect.bottom = rect.top + halfHeight; + + fIncrement = new SpinnerArrow(rect, "increment", ARROW_UP); + AddChild(fIncrement); + + rect.bottom = fTextView->Frame().bottom; + rect.top = rect.bottom - halfHeight; + + fDecrement = new SpinnerArrow(rect, "decrement", ARROW_DOWN); + AddChild(fDecrement); + + uint32 navigableFlags = Flags() & B_NAVIGABLE; + if (navigableFlags != 0) + BView::SetFlags(Flags() & ~B_NAVIGABLE); +} + + +void +BSpinner::_LayoutTextView() +{ + BRect frame; + if (fLayoutData->text_view_layout_item != NULL) { + frame = fLayoutData->text_view_layout_item->FrameInParent(); + } else { + frame = Bounds(); + frame.left = fDivider; + } + frame.InsetBy(kFrameMargin, kFrameMargin); + // we are stroking the frame around the text view, + // which is 2 pixels wide + frame.right -= frame.Height(); + + fTextView->MoveTo(frame.left, frame.top); + fTextView->ResizeTo(frame.Width(), frame.Height()); + fTextView->SetTextRect(frame.OffsetToCopy(B_ORIGIN)); + + float halfHeight = frame.Height() / 2; + + frame.left = frame.right + kFrameMargin; + frame.right = frame.left + frame.Height(); + frame.top -= 1; + frame.bottom = frame.top + halfHeight; + + fIncrement->ResizeTo(frame.Width(), frame.Height()); + fIncrement->MoveTo(frame.LeftTop()); + + frame.bottom = fTextView->Frame().bottom; + frame.top = frame.bottom - halfHeight; + + fDecrement->ResizeTo(frame.Width(), frame.Height()); + fDecrement->MoveTo(frame.LeftTop()); +} + + +void +BSpinner::_UpdateFrame() +{ + if (fLayoutData->label_layout_item == NULL + || fLayoutData->text_view_layout_item == NULL) { + return; + } + + BRect labelFrame = fLayoutData->label_layout_item->Frame(); + BRect textViewFrame = fLayoutData->text_view_layout_item->Frame(); + + if (!labelFrame.IsValid() || !textViewFrame.IsValid()) + return; + + // update divider + fDivider = textViewFrame.left - labelFrame.left; + + BRect frame = textViewFrame | labelFrame; + MoveTo(frame.left, frame.top); + BSize oldSize = Bounds().Size(); + ResizeTo(frame.Width(), frame.Height()); + BSize newSize = Bounds().Size(); + + // If the size changes, ResizeTo() will trigger a relayout, otherwise + // we need to do that explicitly. + if (newSize != oldSize) + Relayout(); +} + + +void +BSpinner::_UpdateTextViewColors(bool enable) +{ + rgb_color textColor; + rgb_color backgroundColor; + BFont font; + + fTextView->GetFontAndColor(0, &font); + + if (enable) + textColor = ui_color(B_DOCUMENT_TEXT_COLOR); + else { + textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_DISABLED_LABEL_TINT); + } + + fTextView->SetFontAndColor(&font, B_FONT_ALL, &textColor); + + if (enable) + backgroundColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + else { + backgroundColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_LIGHTEN_2_TINT); + } + + fTextView->SetViewColor(backgroundColor); + fTextView->SetLowColor(backgroundColor); +} + + +void +BSpinner::_ValidateLayoutData() +{ + if (fLayoutData->valid) + return; + + font_height fontHeight = fLayoutData->font_info; + GetFontHeight(&fontHeight); + + if (Label() != NULL) { + fLayoutData->label_width = StringWidth(Label()); + fLayoutData->label_height = ceilf(fontHeight.ascent + + fontHeight.descent + fontHeight.leading); + } else { + fLayoutData->label_width = 0; + fLayoutData->label_height = 0; + } + + float divider = 0; + if (fLayoutData->label_width > 0) { + divider = ceilf(fLayoutData->label_width + + be_control_look->DefaultLabelSpacing()); + } + + if ((Flags() & B_SUPPORTS_LAYOUT) == 0) + divider = std::max(divider, fDivider); + + char* format; + asprintf(&format, "%%.%" B_PRId32 "f", fPrecision); + char* maxValue; + asprintf(&maxValue, format, fMaxValue); + char* minValue; + asprintf(&minValue, format, fMinValue); + float longestValue = ceilf(std::max(fTextView->StringWidth(maxValue), + fTextView->StringWidth(minValue))); + free(format); + free(maxValue); + free(minValue); + + float textWidth = ceilf(std::max(longestValue, + fTextView->StringWidth("99999"))); + + float textViewHeight = fTextView->LineHeight(0) + kFrameMargin * 2; + float textViewWidth = textWidth + textViewHeight; + + fLayoutData->text_view_width = textViewWidth; + fLayoutData->text_view_height = textViewHeight; + + BSize min(textViewWidth, textViewHeight); + if (divider > 0.0f) + min.width += divider; + + if (fLayoutData->label_height > min.height) + min.height = fLayoutData->label_height; + + fLayoutData->min = min; + fLayoutData->valid = true; + + ResetLayoutInvalidation(); +} + + +// FBC padding + +void BSpinner::_ReservedSpinner20() {} +void BSpinner::_ReservedSpinner19() {} +void BSpinner::_ReservedSpinner18() {} +void BSpinner::_ReservedSpinner17() {} +void BSpinner::_ReservedSpinner16() {} +void BSpinner::_ReservedSpinner15() {} +void BSpinner::_ReservedSpinner14() {} +void BSpinner::_ReservedSpinner13() {} +void BSpinner::_ReservedSpinner12() {} +void BSpinner::_ReservedSpinner11() {} +void BSpinner::_ReservedSpinner10() {} +void BSpinner::_ReservedSpinner9() {} +void BSpinner::_ReservedSpinner8() {} +void BSpinner::_ReservedSpinner7() {} +void BSpinner::_ReservedSpinner6() {} +void BSpinner::_ReservedSpinner5() {} +void BSpinner::_ReservedSpinner4() {} +void BSpinner::_ReservedSpinner3() {} +void BSpinner::_ReservedSpinner2() {} +void BSpinner::_ReservedSpinner1() {} From a3fa81bd03537343e59b375946838e363dbd3a74 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 10 Mar 2014 20:27:58 -0400 Subject: [PATCH 054/125] Update Screen prefs to use BSpinner class --- src/preferences/screen/ScreenWindow.cpp | 141 ++++++++++-------------- src/preferences/screen/ScreenWindow.h | 19 ++-- 2 files changed, 64 insertions(+), 96 deletions(-) diff --git a/src/preferences/screen/ScreenWindow.cpp b/src/preferences/screen/ScreenWindow.cpp index c3bfb28696..2037b9491f 100644 --- a/src/preferences/screen/ScreenWindow.cpp +++ b/src/preferences/screen/ScreenWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2013, Haiku, Inc. + * Copyright 2001-2014 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -164,14 +165,14 @@ screen_errors(status_t status) } -// #pragma mark - +// #pragma mark - ScreenWindow ScreenWindow::ScreenWindow(ScreenSettings* settings) : BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Screen"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE - | B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES), + | B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES), fIsVesa(false), fBootWorkspaceApplied(false), fOtherRefresh(NULL), @@ -194,7 +195,7 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings) // we need the "Current Workspace" first to get its height - BPopUpMenu *popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"), + BPopUpMenu* popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"), true, true); fAllWorkspacesItem = new BMenuItem(B_TRANSLATE("All workspaces"), new BMessage(WORKSPACE_CHECK_MSG)); @@ -234,34 +235,34 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings) B_TRANSLATE("Workspaces")); workspaces->SetAlignment(B_ALIGN_CENTER); - fColumnsControl = new BTextControl(B_TRANSLATE("Columns:"), "0", + fColumnsControl = new BSpinner("columns", B_TRANSLATE("Columns:"), new BMessage(kMsgWorkspaceColumnsChanged)); - fColumnsControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); - fRowsControl = new BTextControl(B_TRANSLATE("Rows:"), "0", - new BMessage(kMsgWorkspaceRowsChanged)); - fRowsControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); + fColumnsControl->SetAlignment(B_ALIGN_RIGHT); + fColumnsControl->SetPrecision(0); + fColumnsControl->SetRange(1, 32); + + fRowsControl = new BSpinner("rows", B_TRANSLATE("Rows:"), + new BMessage(kMsgWorkspaceRowsChanged)); + fRowsControl->SetAlignment(B_ALIGN_RIGHT); + fRowsControl->SetPrecision(0); + fRowsControl->SetRange(1, 32); + + uint32 columns; + uint32 rows; + BPrivate::get_workspaces_layout(&columns, &rows); + fColumnsControl->SetValue(columns); + fRowsControl->SetValue(rows); - float tiny = be_control_look->DefaultItemSpacing() / 4; screenBox->AddChild(BLayoutBuilder::Group<>() .AddGroup(B_VERTICAL, B_USE_SMALL_SPACING) .Add(workspaces) - .AddGrid(0.0, tiny) + .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) // columns .Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0) - .Add(BSpaceLayoutItem::CreateHorizontalStrut( - B_USE_SMALL_SPACING), 1, 0) - .Add(fColumnsControl->CreateTextViewLayoutItem(), 2, 0) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(tiny), 3, 0) - .Add(_CreateColumnRowButton(true, false), 4, 0) - .Add(_CreateColumnRowButton(true, true), 5, 0) + .Add(fColumnsControl->CreateTextViewLayoutItem(), 1, 0) // rows .Add(fRowsControl->CreateLabelLayoutItem(), 0, 1) - .Add(BSpaceLayoutItem::CreateHorizontalStrut( - B_USE_SMALL_SPACING), 1, 1) - .Add(fRowsControl->CreateTextViewLayoutItem(), 2, 1) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(tiny), 3, 1) - .Add(_CreateColumnRowButton(false, false), 4, 1) - .Add(_CreateColumnRowButton(false, true), 5, 1) + .Add(fRowsControl->CreateTextViewLayoutItem(), 1, 1) .End() .End() .View()); @@ -872,17 +873,33 @@ ScreenWindow::_UpdateWorkspaceButtons() uint32 rows; BPrivate::get_workspaces_layout(&columns, &rows); - char text[32]; - snprintf(text, sizeof(text), "%" B_PRId32, columns); - fColumnsControl->SetText(text); + // Set the max values enabling/disabling the up/down arrows - snprintf(text, sizeof(text), "%" B_PRId32, rows); - fRowsControl->SetText(text); + if (rows == 1) + fColumnsControl->SetMaxValue(32); + else if (rows == 2) + fColumnsControl->SetMaxValue(16); + else if (rows <= 4) + fColumnsControl->SetMaxValue(8); + else if (rows <= 8) + fColumnsControl->SetMaxValue(4); + else if (rows <= 16) + fColumnsControl->SetMaxValue(2); + else if (rows <= 32) + fColumnsControl->SetMaxValue(1); - _GetColumnRowButton(true, false)->SetEnabled(columns != 1 && rows != 32); - _GetColumnRowButton(true, true)->SetEnabled((columns + 1) * rows < 32); - _GetColumnRowButton(false, false)->SetEnabled(rows != 1 && columns != 32); - _GetColumnRowButton(false, true)->SetEnabled(columns * (rows + 1) < 32); + if (columns == 1) + fRowsControl->SetMaxValue(32); + else if (columns == 2) + fRowsControl->SetMaxValue(16); + else if (columns <= 4) + fRowsControl->SetMaxValue(8); + else if (columns <= 8) + fRowsControl->SetMaxValue(4); + else if (columns <= 16) + fRowsControl->SetMaxValue(2); + else if (columns <= 32) + fRowsControl->SetMaxValue(1); } @@ -918,51 +935,33 @@ ScreenWindow::MessageReceived(BMessage* message) _CheckApplyEnabled(); break; - case kMsgWorkspaceLayoutChanged: - { - int32 deltaX = 0; - int32 deltaY = 0; - message->FindInt32("delta_x", &deltaX); - message->FindInt32("delta_y", &deltaY); - - if (deltaX == 0 && deltaY == 0) - break; - - uint32 newColumns; - uint32 newRows; - BPrivate::get_workspaces_layout(&newColumns, &newRows); - - newColumns += deltaX; - newRows += deltaY; - BPrivate::set_workspaces_layout(newColumns, newRows); - - _UpdateWorkspaceButtons(); - _CheckApplyEnabled(); - break; - } - case kMsgWorkspaceColumnsChanged: { - uint32 newColumns = strtoul(fColumnsControl->Text(), NULL, 10); + uint32 newColumns = (uint32)fColumnsControl->Value(); uint32 rows; BPrivate::get_workspaces_layout(NULL, &rows); BPrivate::set_workspaces_layout(newColumns, rows); _UpdateWorkspaceButtons(); + fRowsControl->SetValue(rows); + // enables/disables up/down arrows _CheckApplyEnabled(); + break; } case kMsgWorkspaceRowsChanged: { - uint32 newRows = strtoul(fRowsControl->Text(), NULL, 10); + uint32 newRows = (uint32)fRowsControl->Value(); uint32 columns; BPrivate::get_workspaces_layout(&columns, NULL); BPrivate::set_workspaces_layout(columns, newRows); _UpdateWorkspaceButtons(); + fColumnsControl->SetValue(columns); + // enables/disables up/down arrows _CheckApplyEnabled(); break; } @@ -1133,7 +1132,6 @@ ScreenWindow::MessageReceived(BMessage* message) default: BWindow::MessageReceived(message); - break; } } @@ -1169,33 +1167,6 @@ ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const } -BButton* -ScreenWindow::_CreateColumnRowButton(bool columns, bool plus) -{ - BMessage* message = new BMessage(kMsgWorkspaceLayoutChanged); - message->AddInt32("delta_x", columns ? (plus ? 1 : -1) : 0); - message->AddInt32("delta_y", !columns ? (plus ? 1 : -1) : 0); - - BButton* button = new BButton(plus ? "+" : "\xe2\x88\x92", message); - button->SetFontSize(be_plain_font->Size() * 0.9); - - BSize size = button->MinSize(); - size.width = button->StringWidth("+") + 16; - button->SetExplicitMinSize(size); - button->SetExplicitMaxSize(size); - - fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)] = button; - return button; -} - - -BButton* -ScreenWindow::_GetColumnRowButton(bool columns, bool plus) -{ - return fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)]; -} - - void ScreenWindow::_BuildSupportedColorSpaces() { diff --git a/src/preferences/screen/ScreenWindow.h b/src/preferences/screen/ScreenWindow.h index 1d24134b1e..1b8b14b232 100644 --- a/src/preferences/screen/ScreenWindow.h +++ b/src/preferences/screen/ScreenWindow.h @@ -1,12 +1,13 @@ /* - * Copyright 2001-2009, Haiku. + * Copyright 2001-2014 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Rafael Romo - * Stefano Ceccherini (burton666@libero.it) - * Thomas Kurschel + * Stefano Ceccherini, burton666@libero.it * Axel Dörfler, axeld@pinc-software.de + * Thomas Kurschel + * Rafael Romo + * John Scipione, jscipione@gmail.com */ #ifndef SCREEN_WINDOW_H #define SCREEN_WINDOW_H @@ -20,8 +21,8 @@ class BBox; class BPopUpMenu; class BMenuField; +class BSpinner; class BStringView; -class BTextControl; class RefreshWindow; class MonitorView; @@ -39,9 +40,6 @@ public: virtual void ScreenChanged(BRect frame, color_space mode); private: - BButton* _CreateColumnRowButton(bool columns, bool plus); - BButton* _GetColumnRowButton(bool columns, bool plus); - void _BuildSupportedColorSpaces(); void _CheckApplyEnabled(); @@ -74,9 +72,8 @@ private: MonitorView* fMonitorView; BMenuItem* fAllWorkspacesItem; - BTextControl* fColumnsControl; - BTextControl* fRowsControl; - BButton* fWorkspacesButtons[4]; + BSpinner* fColumnsControl; + BSpinner* fRowsControl; uint32 fSupportedColorSpaces; BMenuItem* fUserSelectedColorSpace; From 4f114575567d850a2dff8d4d5238549a6d537cc6 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Thu, 20 Mar 2014 17:42:53 -0400 Subject: [PATCH 055/125] Deskbar: Add spinners to preferences --- src/apps/deskbar/PreferencesWindow.cpp | 76 ++++++++------------------ src/apps/deskbar/PreferencesWindow.h | 8 +-- 2 files changed, 26 insertions(+), 58 deletions(-) diff --git a/src/apps/deskbar/PreferencesWindow.cpp b/src/apps/deskbar/PreferencesWindow.cpp index 480d7e2196..ea88ed5116 100644 --- a/src/apps/deskbar/PreferencesWindow.cpp +++ b/src/apps/deskbar/PreferencesWindow.cpp @@ -10,8 +10,6 @@ #include "PreferencesWindow.h" -#include - #include #include #include @@ -31,7 +29,7 @@ #include #include #include -#include +#include #include #include "BarApp.h" @@ -66,11 +64,11 @@ PreferencesWindow::PreferencesWindow(BRect frame) fMenuRecentFolders = new BCheckBox(B_TRANSLATE("Recent folders:"), new BMessage(kUpdateRecentCounts)); - fMenuRecentDocumentCount = new BTextControl(NULL, NULL, + fMenuRecentDocumentCount = new BSpinner("recent documents", NULL, new BMessage(kUpdateRecentCounts)); - fMenuRecentApplicationCount = new BTextControl(NULL, NULL, + fMenuRecentApplicationCount = new BSpinner("recent applications", NULL, new BMessage(kUpdateRecentCounts)); - fMenuRecentFolderCount = new BTextControl(NULL, NULL, + fMenuRecentFolderCount = new BSpinner("recent folders", NULL, new BMessage(kUpdateRecentCounts)); // Applications controls @@ -103,46 +101,26 @@ PreferencesWindow::PreferencesWindow(BRect frame) new BMessage(kAutoHide)); // Menu settings - BTextView* docTextView = fMenuRecentDocumentCount->TextView(); - BTextView* appTextView = fMenuRecentApplicationCount->TextView(); - BTextView* folderTextView = fMenuRecentFolderCount->TextView(); - - for (int32 i = 0; i < 256; i++) { - if (!isdigit(i)) { - docTextView->DisallowChar(i); - appTextView->DisallowChar(i); - folderTextView->DisallowChar(i); - } - } - - docTextView->SetMaxBytes(4); - appTextView->SetMaxBytes(4); - folderTextView->SetMaxBytes(4); - - int32 docCount = fSettings.recentDocsCount; - int32 appCount = fSettings.recentAppsCount; - int32 folderCount = fSettings.recentFoldersCount; - fMenuRecentDocuments->SetValue(fSettings.recentDocsEnabled); fMenuRecentDocumentCount->SetEnabled(fSettings.recentDocsEnabled); + fMenuRecentDocumentCount->SetPrecision(0); + fMenuRecentDocumentCount->SetRange(0, 50); + fMenuRecentDocumentCount->SetStep(1); + fMenuRecentDocumentCount->SetValue(fSettings.recentDocsCount); fMenuRecentApplications->SetValue(fSettings.recentAppsEnabled); fMenuRecentApplicationCount->SetEnabled(fSettings.recentAppsEnabled); + fMenuRecentApplicationCount->SetPrecision(0); + fMenuRecentApplicationCount->SetRange(0, 50); + fMenuRecentApplicationCount->SetStep(1); + fMenuRecentApplicationCount->SetValue(fSettings.recentAppsCount); fMenuRecentFolders->SetValue(fSettings.recentFoldersEnabled); fMenuRecentFolderCount->SetEnabled(fSettings.recentFoldersEnabled); - - BString docString; - BString appString; - BString folderString; - - docString << docCount; - appString << appCount; - folderString << folderCount; - - fMenuRecentDocumentCount->SetText(docString.String()); - fMenuRecentApplicationCount->SetText(appString.String()); - fMenuRecentFolderCount->SetText(folderString.String()); + fMenuRecentFolderCount->SetPrecision(0); + fMenuRecentFolderCount->SetRange(0, 50); + fMenuRecentFolderCount->SetStep(1); + fMenuRecentFolderCount->SetValue(fSettings.recentFoldersCount); // Applications settings fAppsSort->SetValue(fSettings.sortRunningApps); @@ -516,21 +494,15 @@ PreferencesWindow::_UpdatePreferences(desk_settings* settings) updateRecentCounts = true; } if (current->recentDocsCount != settings->recentDocsCount) { - BString docString; - docString << settings->recentDocsCount; - fMenuRecentDocumentCount->SetText(docString.String()); + fMenuRecentDocumentCount->SetValue(settings->recentDocsCount); updateRecentCounts = true; } if (current->recentFoldersCount != settings->recentFoldersCount) { - BString folderString; - folderString << settings->recentFoldersCount; - fMenuRecentFolderCount->SetText(folderString.String()); + fMenuRecentFolderCount->SetValue(settings->recentFoldersCount); updateRecentCounts = true; } if (current->recentAppsCount != settings->recentAppsCount) { - BString appString; - appString << settings->recentAppsCount; - fMenuRecentApplicationCount->SetText(appString.String()); + fMenuRecentApplicationCount->SetValue(settings->recentAppsCount); updateRecentCounts = true; } if (current->alwaysOnTop != settings->alwaysOnTop) { @@ -556,13 +528,9 @@ PreferencesWindow::_UpdateRecentCounts() { BMessage message(kUpdateRecentCounts); - int32 docCount = atoi(fMenuRecentDocumentCount->Text()); - int32 appCount = atoi(fMenuRecentApplicationCount->Text()); - int32 folderCount = atoi(fMenuRecentFolderCount->Text()); - - message.AddInt32("documents", max_c(0, docCount)); - message.AddInt32("applications", max_c(0, appCount)); - message.AddInt32("folders", max_c(0, folderCount)); + message.AddInt32("documents", fMenuRecentDocumentCount->Value()); + message.AddInt32("applications", fMenuRecentApplicationCount->Value()); + message.AddInt32("folders", fMenuRecentFolderCount->Value()); message.AddBool("documentsEnabled", fMenuRecentDocuments->Value()); message.AddBool("applicationsEnabled", fMenuRecentApplications->Value()); diff --git a/src/apps/deskbar/PreferencesWindow.h b/src/apps/deskbar/PreferencesWindow.h index 4a8beaea96..6daf790c8e 100644 --- a/src/apps/deskbar/PreferencesWindow.h +++ b/src/apps/deskbar/PreferencesWindow.h @@ -34,7 +34,7 @@ class BFile; class BMessage; class BRadioButton; class BSlider; -class BTextControl; +class BSpinner; class PreferencesWindow : public BWindow { @@ -67,9 +67,9 @@ private: BCheckBox* fMenuRecentApplications; BCheckBox* fMenuRecentFolders; - BTextControl* fMenuRecentDocumentCount; - BTextControl* fMenuRecentApplicationCount; - BTextControl* fMenuRecentFolderCount; + BSpinner* fMenuRecentDocumentCount; + BSpinner* fMenuRecentApplicationCount; + BSpinner* fMenuRecentFolderCount; BCheckBox* fAppsSort; BCheckBox* fAppsSortTrackerFirst; From 49a4e7f6857c8769d3cfba5df2705c2b4dd13c03 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Fri, 18 Apr 2014 18:21:45 -0400 Subject: [PATCH 056/125] WebPositive: Use BSpinner to set days of history setting Also rename fDaysInHistoryMenuControl to just fDaysInHistory --- src/apps/webpositive/SettingsWindow.cpp | 55 ++++++++----------------- src/apps/webpositive/SettingsWindow.h | 4 +- 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 70bdf84cf7..6c62d11bd8 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -303,18 +304,14 @@ SettingsWindow::_CreateGeneralPage(float spacing) fNewTabBehaviorMenu = new BMenuField("new tab behavior", B_TRANSLATE("New tabs:"), newTabBehaviorMenu); - fDaysInHistoryMenuControl = new BTextControl("days in history", - B_TRANSLATE("Number of days to keep links in History menu:"), "", + fDaysInHistory = new BSpinner("days in history", + B_TRANSLATE("Number of days to keep links in History menu:"), new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); - fDaysInHistoryMenuControl->SetModificationMessage( - new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); - BString maxHistoryAge; - maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); - fDaysInHistoryMenuControl->SetText(maxHistoryAge.String()); - for (uchar i = 0; i < '0'; i++) - fDaysInHistoryMenuControl->TextView()->DisallowChar(i); - for (uchar i = '9' + 1; i <= 128; i++) - fDaysInHistoryMenuControl->TextView()->DisallowChar(i); + fDaysInHistory->SetPrecision(0); + fDaysInHistory->SetRange(1, 35); + fDaysInHistory->SetStep(1); + fDaysInHistory->SetValue( + BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", B_TRANSLATE("Show tabs if only one page is open"), @@ -360,7 +357,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(fAutoHideInterfaceInFullscreenMode) .Add(fAutoHidePointer) .Add(fShowHomeButton) - .Add(fDaysInHistoryMenuControl) + .Add(fDaysInHistory) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .SetInsets(spacing, spacing, spacing, spacing) @@ -580,7 +577,7 @@ SettingsWindow::_CanApplySettings() const canApply = canApply || ((fShowHomeButton->Value() == B_CONTROL_ON) != fSettings->GetValue(kSettingsKeyShowHomeButton, true)); - canApply = canApply || (_MaxHistoryAge() + canApply = canApply || (fDaysInHistory->Value() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); // New window policy @@ -639,12 +636,8 @@ void SettingsWindow::_ApplySettings() { // Store general settings - int32 maxHistoryAge = _MaxHistoryAge(); - BString text; - text << maxHistoryAge; - fDaysInHistoryMenuControl->SetText(text.String()); - BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); - + BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge( + (uint32)fDaysInHistory->Value()); fSettings->SetValue(kSettingsKeyStartPageURL, fStartPageControl->Text()); fSettings->SetValue(kSettingsKeySearchPageURL, fSearchPageControl->Text()); fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text()); @@ -712,7 +705,6 @@ SettingsWindow::_ApplySettings() // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); - _ValidateControlsEnabledStatus(); } @@ -738,9 +730,8 @@ SettingsWindow::_RevertSettings() fShowHomeButton->SetValue( fSettings->GetValue(kSettingsKeyShowHomeButton, true)); - BString text; - text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); - fDaysInHistoryMenuControl->SetText(text.String()); + fDaysInHistory->SetValue( + BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); // New window policy uint32 newWindowPolicy = fSettings->GetValue(kSettingsKeyNewWindowPolicy, @@ -800,9 +791,9 @@ SettingsWindow::_RevertSettings() false)); fProxyAddressControl->SetText(fSettings->GetValue(kSettingsKeyProxyAddress, "")); - text = ""; - text << fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0); - fProxyPortControl->SetText(text.String()); + BString keyProxyPort; + keyProxyPort << fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0); + fProxyPortControl->SetText(keyProxyPort.String()); fUseProxyAuthCheckBox->SetValue(fSettings->GetValue(kSettingsKeyUseProxyAuth, false)); fProxyUsernameControl->SetText(fSettings->GetValue(kSettingsKeyProxyUsername, @@ -865,18 +856,6 @@ SettingsWindow::_NewTabPolicy() const } -int32 -SettingsWindow::_MaxHistoryAge() const -{ - int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text()); - if (maxHistoryAge <= 0) - maxHistoryAge = 1; - if (maxHistoryAge >= 35) - maxHistoryAge = 35; - return maxHistoryAge; -} - - void SettingsWindow::_SetSizesMenuValue(BMenu* menu, int32 value) { diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index eabfc5a460..4511c5a33e 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -13,6 +13,7 @@ class BCheckBox; class BMenu; class BMenuField; class BMenuItem; +class BSpinner; class BTextControl; class FontSelectionView; class SettingsMessage; @@ -46,7 +47,6 @@ private: uint32 _NewWindowPolicy() const; uint32 _NewTabPolicy() const; - int32 _MaxHistoryAge() const; void _SetSizesMenuValue(BMenu* menu, int32 value); int32 _SizesMenuValue(BMenu* menu) const; @@ -73,7 +73,7 @@ private: BMenuItem* fNewTabBehaviorOpenSearchItem; BMenuItem* fNewTabBehaviorOpenBlankItem; - BTextControl* fDaysInHistoryMenuControl; + BSpinner* fDaysInHistory; BCheckBox* fShowTabsIfOnlyOnePage; BCheckBox* fAutoHideInterfaceInFullscreenMode; BCheckBox* fAutoHidePointer; From 963d585e35c846ce769c88957d5420199384af3c Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 9 Mar 2015 16:29:52 -0400 Subject: [PATCH 057/125] Spinner: Improve look and feel This arranges the buttons to the right of the text box horizontally and also updates the background color and arrow cool to give feed back when moused over the button, disabled, and pressed. Used be_control_look arrows to match arrows used elsewhere (such as scrollbars). The background darkens on mouse over if enabled, the arrow is drawn darker when the mouse is down, and lighter if disabled. --- src/kits/interface/Spinner.cpp | 155 +++++++++++++++------------------ 1 file changed, 69 insertions(+), 86 deletions(-) diff --git a/src/kits/interface/Spinner.cpp b/src/kits/interface/Spinner.cpp index 1176c4ad35..3c6486c537 100644 --- a/src/kits/interface/Spinner.cpp +++ b/src/kits/interface/Spinner.cpp @@ -1,7 +1,7 @@ /* * Copyright 2004 DarkWyrm * Copyright 2013 FeemanLou - * Copyright 2014 Haiku, Inc. All rights reserved. + * Copyright 2014-2015 Haiku, Inc. All rights reserved. * * Distributed under the terms of the MIT license. * @@ -391,9 +391,9 @@ SpinnerArrow::SpinnerArrow(BRect frame, const char* name, fIsMouseOver(false), fRepeatDelay(100000) { - rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR); - SetViewColor(backgroundColor); - SetLowColor(backgroundColor); + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); } @@ -429,54 +429,43 @@ SpinnerArrow::Draw(BRect updateRect) BView::Draw(updateRect); - float tint; + float fgTint; if (!fIsEnabled) - tint = B_DARKEN_1_TINT; + fgTint = B_DARKEN_1_TINT; else if (fIsMouseDown) - tint = B_DARKEN_MAX_TINT; - else if (fIsMouseOver) - tint = B_DARKEN_3_TINT; + fgTint = B_DARKEN_MAX_TINT; else - tint = B_DARKEN_2_TINT; + fgTint = B_DARKEN_3_TINT; - rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR); - SetHighColor(tint_color(backgroundColor, tint)); + float bgTint; + if (fIsEnabled && fIsMouseOver) + bgTint = B_DARKEN_1_TINT; + else + bgTint = B_NO_TINT; - // draw a gradient background - BGradientLinear gradient; - gradient.AddColor(tint_color(backgroundColor, B_LIGHTEN_2_TINT), 0); - gradient.AddColor(backgroundColor, 255); - gradient.SetStart(rect.LeftTop()); - gradient.SetEnd(rect.LeftBottom()); - FillRect(rect, gradient); + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); - // draw the border - StrokeRect(rect); + uint32 borders = be_control_look->B_TOP_BORDER + | be_control_look->B_BOTTOM_BORDER; + if (fArrowDirection == ARROW_UP) + borders |= be_control_look->B_LEFT_BORDER; + else + borders |= be_control_look->B_RIGHT_BORDER; + + // draw the button + be_control_look->DrawButtonFrame(this, rect, updateRect, + tint_color(bgColor, fgTint), bgColor, 0, borders); + be_control_look->DrawButtonBackground(this, rect, updateRect, + tint_color(bgColor, bgTint), 0, borders); + + rect.InsetBy(0.0f, 1.0f); + uint32 arrowDirection = fArrowDirection == ARROW_UP + ? be_control_look->B_UP_ARROW + : be_control_look->B_DOWN_ARROW; // draw the arrow - BPoint point1; - BPoint point2; - BPoint point3; - if (fArrowDirection == ARROW_UP) { - point1.x = ceilf(rect.Width() / 2); - point1.y = rect.top + 1.0f; - - point2.x = point1.x - 3.0f; - point2.y = rect.bottom - 2.0f; - - point3.x = point1.x + 3.0f; - point3.y = rect.bottom - 2.0f; - } else { - point1.x = ceilf(rect.Width() / 2); - point1.y = rect.bottom - 1.0f; - - point2.x = point1.x - 3.0f; - point2.y = rect.top + 2.0f; - - point3.x = point1.x + 3.0f; - point3.y = rect.top + 2.0f; - } - FillTriangle(point1, point2, point3); + be_control_look->DrawArrowShape(this, rect, updateRect, bgColor, + arrowDirection, 0, fgTint); } @@ -585,9 +574,9 @@ SpinnerTextView::SpinnerTextView(BRect rect, BRect textRect) B_WILL_DRAW | B_NAVIGABLE), fParent(NULL) { - rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR); - SetViewColor(backgroundColor); - SetLowColor(backgroundColor); + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); SetAlignment(B_ALIGN_RIGHT); for (uint32 c = 0; c <= 42; c++) @@ -1640,9 +1629,9 @@ BSpinner::_DrawTextView(BRect updateRect) void BSpinner::_InitObject() { - rgb_color backgroundColor = ui_color(B_PANEL_BACKGROUND_COLOR); - SetViewColor(backgroundColor); - SetLowColor(backgroundColor); + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); fAlignment = B_ALIGN_LEFT; if (Label() != NULL) { @@ -1664,24 +1653,22 @@ BSpinner::_InitObject() rect.left = fDivider; rect.InsetBy(kFrameMargin, kFrameMargin); - rect.right -= rect.Height(); + rect.right -= rect.Height() * 2 + kFrameMargin + 1.0f; BRect textRect(rect.OffsetToCopy(B_ORIGIN)); fTextView = new SpinnerTextView(rect, textRect); AddChild(fTextView); - float halfHeight = rect.Height() / 2.0f; + rect.InsetBy(0.0f, -kFrameMargin); - rect.left = rect.right + kFrameMargin; - rect.right = rect.left + rect.Height(); - rect.top -= 1.0f; - rect.bottom = rect.top + halfHeight; + rect.left = rect.right + kFrameMargin * 2; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; fIncrement = new SpinnerArrow(rect, "increment", ARROW_UP); AddChild(fIncrement); - rect.bottom = fTextView->Frame().bottom; - rect.top = rect.bottom - halfHeight; + rect.left = rect.right + 1.0f; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; fDecrement = new SpinnerArrow(rect, "decrement", ARROW_DOWN); AddChild(fDecrement); @@ -1695,37 +1682,33 @@ BSpinner::_InitObject() void BSpinner::_LayoutTextView() { - BRect frame; + BRect rect; if (fLayoutData->text_view_layout_item != NULL) { - frame = fLayoutData->text_view_layout_item->FrameInParent(); + rect = fLayoutData->text_view_layout_item->FrameInParent(); } else { - frame = Bounds(); - frame.left = fDivider; + rect = Bounds(); + rect.left = fDivider; } - frame.InsetBy(kFrameMargin, kFrameMargin); - // we are stroking the frame around the text view, - // which is 2 pixels wide - frame.right -= frame.Height(); + rect.InsetBy(kFrameMargin, kFrameMargin); + rect.right -= rect.Height() * 2 + kFrameMargin + 1.0f; - fTextView->MoveTo(frame.left, frame.top); - fTextView->ResizeTo(frame.Width(), frame.Height()); - fTextView->SetTextRect(frame.OffsetToCopy(B_ORIGIN)); + fTextView->MoveTo(rect.left, rect.top); + fTextView->ResizeTo(rect.Width(), rect.Height()); + fTextView->SetTextRect(rect.OffsetToCopy(B_ORIGIN)); - float halfHeight = frame.Height() / 2; + rect.InsetBy(0.0f, -kFrameMargin); - frame.left = frame.right + kFrameMargin; - frame.right = frame.left + frame.Height(); - frame.top -= 1; - frame.bottom = frame.top + halfHeight; + rect.left = rect.right + kFrameMargin * 2; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; - fIncrement->ResizeTo(frame.Width(), frame.Height()); - fIncrement->MoveTo(frame.LeftTop()); + fIncrement->ResizeTo(rect.Width(), rect.Height()); + fIncrement->MoveTo(rect.LeftTop()); - frame.bottom = fTextView->Frame().bottom; - frame.top = frame.bottom - halfHeight; + rect.left = rect.right + 1.0f; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; - fDecrement->ResizeTo(frame.Width(), frame.Height()); - fDecrement->MoveTo(frame.LeftTop()); + fDecrement->ResizeTo(rect.Width(), rect.Height()); + fDecrement->MoveTo(rect.LeftTop()); } @@ -1763,7 +1746,7 @@ void BSpinner::_UpdateTextViewColors(bool enable) { rgb_color textColor; - rgb_color backgroundColor; + rgb_color bgColor; BFont font; fTextView->GetFontAndColor(0, &font); @@ -1778,14 +1761,14 @@ BSpinner::_UpdateTextViewColors(bool enable) fTextView->SetFontAndColor(&font, B_FONT_ALL, &textColor); if (enable) - backgroundColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + bgColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR); else { - backgroundColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + bgColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT); } - fTextView->SetViewColor(backgroundColor); - fTextView->SetLowColor(backgroundColor); + fTextView->SetViewColor(bgColor); + fTextView->SetLowColor(bgColor); } @@ -1832,7 +1815,7 @@ BSpinner::_ValidateLayoutData() fTextView->StringWidth("99999"))); float textViewHeight = fTextView->LineHeight(0) + kFrameMargin * 2; - float textViewWidth = textWidth + textViewHeight; + float textViewWidth = textWidth + textViewHeight * 2; fLayoutData->text_view_width = textViewWidth; fLayoutData->text_view_height = textViewHeight; From e4df9afe58254b9965663ae8abef8f67259786ff Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 9 Mar 2015 19:50:52 -0400 Subject: [PATCH 058/125] Spinner: Use plus/minus instead of arrows Eliminate the border between the buttons --- src/kits/interface/Spinner.cpp | 76 +++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/src/kits/interface/Spinner.cpp b/src/kits/interface/Spinner.cpp index 3c6486c537..e1a6284a42 100644 --- a/src/kits/interface/Spinner.cpp +++ b/src/kits/interface/Spinner.cpp @@ -230,15 +230,15 @@ static property_info sProperties[] = { typedef enum { - ARROW_UP, - ARROW_DOWN -} arrow_direction; + SPINNER_INCREMENT, + SPINNER_DECREMENT +} spinner_direction; class SpinnerArrow : public BView { public: SpinnerArrow(BRect frame, const char* name, - arrow_direction direction); + spinner_direction direction); virtual ~SpinnerArrow(); virtual void AttachedToWindow(); @@ -256,7 +256,7 @@ private: void _DoneTracking(BPoint where); void _Track(BPoint where, uint32); - arrow_direction fArrowDirection; + spinner_direction fSpinnerDirection; BSpinner* fParent; bool fIsEnabled; bool fIsMouseDown; @@ -381,10 +381,10 @@ struct BSpinner::LayoutData { SpinnerArrow::SpinnerArrow(BRect frame, const char* name, - arrow_direction direction) + spinner_direction direction) : BView(frame, name, B_FOLLOW_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW), - fArrowDirection(direction), + fSpinnerDirection(direction), fParent(NULL), fIsEnabled(true), fIsMouseDown(false), @@ -444,13 +444,19 @@ SpinnerArrow::Draw(BRect updateRect) bgTint = B_NO_TINT; rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + if (bgColor.red + bgColor.green + bgColor.blue <= 128 * 3) { + // if dark background make the tint lighter + fgTint = 2.0f - fgTint; + bgTint = 2.0f - bgTint; + } uint32 borders = be_control_look->B_TOP_BORDER | be_control_look->B_BOTTOM_BORDER; - if (fArrowDirection == ARROW_UP) - borders |= be_control_look->B_LEFT_BORDER; - else + + if (fSpinnerDirection == SPINNER_INCREMENT) borders |= be_control_look->B_RIGHT_BORDER; + else + borders |= be_control_look->B_LEFT_BORDER; // draw the button be_control_look->DrawButtonFrame(this, rect, updateRect, @@ -458,14 +464,28 @@ SpinnerArrow::Draw(BRect updateRect) be_control_look->DrawButtonBackground(this, rect, updateRect, tint_color(bgColor, bgTint), 0, borders); - rect.InsetBy(0.0f, 1.0f); - uint32 arrowDirection = fArrowDirection == ARROW_UP - ? be_control_look->B_UP_ARROW - : be_control_look->B_DOWN_ARROW; + BFont font; + fParent->GetFont(&font); + float inset = floorf(font.Size() / 4); + rect.InsetBy(inset, inset); - // draw the arrow - be_control_look->DrawArrowShape(this, rect, updateRect, bgColor, - arrowDirection, 0, fgTint); + if (rect.IntegerWidth() % 2 != 0) + rect.right -= 1; + + if (rect.IntegerHeight() % 2 != 0) + rect.bottom -= 1; + + SetHighColor(tint_color(bgColor, fgTint)); + + // draw the +/- + float halfHeight = floorf(rect.Height() / 2); + StrokeLine(BPoint(rect.left, rect.top + halfHeight), + BPoint(rect.right, rect.top + halfHeight)); + if (fSpinnerDirection == SPINNER_INCREMENT) { + float halfWidth = floorf(rect.Width() / 2); + StrokeLine(BPoint(rect.left + halfWidth, rect.top), + BPoint(rect.left + halfWidth, rect.bottom)); + } } @@ -543,7 +563,7 @@ SpinnerArrow::_Track(BPoint where, uint32) } fIsMouseDown = true; - double step = fArrowDirection == ARROW_UP + double step = fSpinnerDirection == SPINNER_INCREMENT ? fParent->Step() : -fParent->Step(); double newValue = fParent->Value() + step; @@ -1653,7 +1673,7 @@ BSpinner::_InitObject() rect.left = fDivider; rect.InsetBy(kFrameMargin, kFrameMargin); - rect.right -= rect.Height() * 2 + kFrameMargin + 1.0f; + rect.right -= rect.Height() * 2 + kFrameMargin * 2 + 1.0f; BRect textRect(rect.OffsetToCopy(B_ORIGIN)); fTextView = new SpinnerTextView(rect, textRect); @@ -1664,14 +1684,14 @@ BSpinner::_InitObject() rect.left = rect.right + kFrameMargin * 2; rect.right = rect.left + rect.Height() - kFrameMargin * 2; - fIncrement = new SpinnerArrow(rect, "increment", ARROW_UP); - AddChild(fIncrement); + fDecrement = new SpinnerArrow(rect, "decrement", SPINNER_DECREMENT); + AddChild(fDecrement); rect.left = rect.right + 1.0f; rect.right = rect.left + rect.Height() - kFrameMargin * 2; - fDecrement = new SpinnerArrow(rect, "decrement", ARROW_DOWN); - AddChild(fDecrement); + fIncrement = new SpinnerArrow(rect, "increment", SPINNER_INCREMENT); + AddChild(fIncrement); uint32 navigableFlags = Flags() & B_NAVIGABLE; if (navigableFlags != 0) @@ -1690,7 +1710,7 @@ BSpinner::_LayoutTextView() rect.left = fDivider; } rect.InsetBy(kFrameMargin, kFrameMargin); - rect.right -= rect.Height() * 2 + kFrameMargin + 1.0f; + rect.right -= rect.Height() * 2 + kFrameMargin * 2 + 1.0f; fTextView->MoveTo(rect.left, rect.top); fTextView->ResizeTo(rect.Width(), rect.Height()); @@ -1701,14 +1721,14 @@ BSpinner::_LayoutTextView() rect.left = rect.right + kFrameMargin * 2; rect.right = rect.left + rect.Height() - kFrameMargin * 2; - fIncrement->ResizeTo(rect.Width(), rect.Height()); - fIncrement->MoveTo(rect.LeftTop()); + fDecrement->ResizeTo(rect.Width(), rect.Height()); + fDecrement->MoveTo(rect.LeftTop()); rect.left = rect.right + 1.0f; rect.right = rect.left + rect.Height() - kFrameMargin * 2; - fDecrement->ResizeTo(rect.Width(), rect.Height()); - fDecrement->MoveTo(rect.LeftTop()); + fIncrement->ResizeTo(rect.Width(), rect.Height()); + fIncrement->MoveTo(rect.LeftTop()); } From a9385e8e2eb59a89b7c7d50ea9bcf1aaa645ae1b Mon Sep 17 00:00:00 2001 From: John Scipione Date: Tue, 10 Mar 2015 19:18:38 -0400 Subject: [PATCH 059/125] Spinner: Move ValueChanged up ... along with the other hook methods --- headers/private/interface/Spinner.h | 3 ++- src/kits/interface/Spinner.cpp | 13 ++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/headers/private/interface/Spinner.h b/headers/private/interface/Spinner.h index 18801e74c7..8e2bbf4bee 100644 --- a/headers/private/interface/Spinner.h +++ b/headers/private/interface/Spinner.h @@ -52,10 +52,11 @@ public: virtual void AttachedToWindow(); virtual void Draw(BRect updateRect); virtual void FrameResized(float width, float height); + virtual void ValueChanged(); + virtual void MakeFocus(bool focus = true); virtual void ResizeToPreferred(); virtual void SetFlags(uint32 flags); - virtual void ValueChanged(); virtual void WindowActivated(bool active); alignment Alignment() const { return fAlignment; }; diff --git a/src/kits/interface/Spinner.cpp b/src/kits/interface/Spinner.cpp index e1a6284a42..44d5339f6f 100644 --- a/src/kits/interface/Spinner.cpp +++ b/src/kits/interface/Spinner.cpp @@ -1175,6 +1175,12 @@ BSpinner::FrameResized(float width, float height) void +BSpinner::ValueChanged() +{ + // hook method - does nothing +} + + BSpinner::MakeFocus(bool focus) { fTextView->MakeFocus(focus); @@ -1217,13 +1223,6 @@ BSpinner::SetFlags(uint32 flags) } -void -BSpinner::ValueChanged() -{ - // hook method - does nothing -} - - void BSpinner::WindowActivated(bool active) { From d1229383468f5d62f70d336cbb5eca8468b2b249 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Tue, 10 Mar 2015 19:23:43 -0400 Subject: [PATCH 060/125] Spinner: Generalize actions into methods Add an Increment(), Decrement(), and SetValueFromText() method. These can be overridden by derived classes. --- headers/private/interface/Spinner.h | 3 + src/kits/interface/Spinner.cpp | 87 +++++++++++++---------------- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/headers/private/interface/Spinner.h b/headers/private/interface/Spinner.h index 8e2bbf4bee..50e01bc7f9 100644 --- a/headers/private/interface/Spinner.h +++ b/headers/private/interface/Spinner.h @@ -54,9 +54,12 @@ public: virtual void FrameResized(float width, float height); virtual void ValueChanged(); + virtual void Decrement(); + virtual void Increment(); virtual void MakeFocus(bool focus = true); virtual void ResizeToPreferred(); virtual void SetFlags(uint32 flags); + virtual void SetValueFromText(); virtual void WindowActivated(bool active); alignment Alignment() const { return fAlignment; }; diff --git a/src/kits/interface/Spinner.cpp b/src/kits/interface/Spinner.cpp index 44d5339f6f..c3d4c057a8 100644 --- a/src/kits/interface/Spinner.cpp +++ b/src/kits/interface/Spinner.cpp @@ -276,8 +276,6 @@ public: virtual void MakeFocus(bool focus); private: - void _SetValueToText(); - BSpinner* fParent; }; @@ -563,22 +561,9 @@ SpinnerArrow::_Track(BPoint where, uint32) } fIsMouseDown = true; - double step = fSpinnerDirection == SPINNER_INCREMENT - ? fParent->Step() - : -fParent->Step(); - double newValue = fParent->Value() + step; - if (newValue < fParent->MinValue()) { - // new value is below lower bound, clip to lower bound - fParent->SetValue(fParent->MinValue()); - } else if (newValue>fParent->MaxValue()) { - // new value is above upper bound, clip to upper bound - fParent->SetValue(fParent->MaxValue()); - } else { - // new value is in range - fParent->SetValue(newValue); - } - fParent->Invoke(); - fParent->Invalidate(); + fSpinnerDirection == SPINNER_INCREMENT + ? fParent->Increment() + : fParent->Decrement(); snooze(fRepeatDelay); fRepeatDelay = 10000; @@ -642,7 +627,7 @@ SpinnerTextView::KeyDown(const char* bytes, int32 numBytes) switch (bytes[0]) { case B_ENTER: case B_SPACE: - _SetValueToText(); + fParent->SetValueFromText(); break; case B_TAB: @@ -651,18 +636,13 @@ SpinnerTextView::KeyDown(const char* bytes, int32 numBytes) case B_UP_ARROW: case B_PAGE_UP: + fParent->Increment(); + break; + case B_DOWN_ARROW: case B_PAGE_DOWN: - { - double step = fParent->Step(); - if (*bytes == B_DOWN_ARROW || *bytes == B_PAGE_DOWN) - step *= -1; - - fParent->SetValue(fParent->Value() + step); - fParent->Invoke(); - fParent->Invalidate(); + fParent->Decrement(); break; - } default: BTextView::KeyDown(bytes, numBytes); @@ -675,28 +655,15 @@ SpinnerTextView::MakeFocus(bool focus) { BTextView::MakeFocus(focus); - if (focus) - SelectAll(); - else - _SetValueToText(); - - if (fParent != NULL) - fParent->_DrawTextView(fParent->Bounds()); -} - - -// #pragma mark - SpinnerTextView private methods - - -void -SpinnerTextView::_SetValueToText() -{ if (fParent == NULL) return; - fParent->SetValue(roundTo(atof(Text()), fParent->Precision())); - fParent->Invoke(); - fParent->Invalidate(); + if (focus) + SelectAll(); + else + fParent->SetValueFromText(); + + fParent->_DrawTextView(fParent->Bounds()); } @@ -1181,6 +1148,21 @@ BSpinner::ValueChanged() } +void +BSpinner::Decrement() +{ + SetValue(Value() - Step()); +} + + +void +BSpinner::Increment() +{ + SetValue(Value() + Step()); +} + + +void BSpinner::MakeFocus(bool focus) { fTextView->MakeFocus(focus); @@ -1358,9 +1340,20 @@ BSpinner::SetValue(double value) fValue = value; ValueChanged(); + + Invoke(); + Invalidate(); } +void +BSpinner::SetValueFromText() +{ + SetValue(roundTo(atof(TextView()->Text()), Precision())); +} + + + bool BSpinner::IsDecrementEnabled() const { From a0ba79fbff0d2a8ce0f008362d5e8832c1d994c2 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Wed, 11 Mar 2015 17:17:16 -0400 Subject: [PATCH 061/125] Split BSpinner into BAbstractSpinner and... 2 concrete classes which are currently implemented: * BSpinner (works on int32s) * BDecimalSpinner (works on doubles) In addition BAbstractSpinner now inherits from BControl instead of BView/BInvoker. This allowed for code simplification at the cost of needing to cast for the decimal version because SetValue(int32 value) comes from BControl. Also, add a spinner_button_style enum with 3 options: * SPINNER_BUTTON_HORIZONTAL_ARROWS * SPINNER_BUTTON_VERTICAL_ARROWS * SPINNER_BUTTON_PLUS_MINUS which sets the spinner arrows to either use horizontal arrows (left/right) vertical arrows, (up/down), or +/- symbols (the default). If the spinner button is using horizontal arrows you can decrement and increment the spinner value by pushing control+left/right, otherwise you can increment and decrement by pushing up or down. The reason for needing control is so that you can move the cursor in the textbox otherwise. Switch the 3 apps that are currently using BSpinners to use the integer variety in Deskbar preferences, WebPostive preferences, and Screen preferences. --- headers/private/interface/AbstractSpinner.h | 168 ++ headers/private/interface/DecimalSpinner.h | 96 ++ headers/private/interface/Spinner.h | 139 +- src/apps/deskbar/PreferencesWindow.cpp | 6 - src/apps/webpositive/SettingsWindow.cpp | 2 - src/kits/interface/AbstractSpinner.cpp | 1690 +++++++++++++++++++ src/kits/interface/DecimalSpinner.cpp | 372 ++++ src/kits/interface/Jamfile | 2 + src/kits/interface/Spinner.cpp | 1663 +----------------- src/preferences/screen/ScreenWindow.cpp | 2 - 10 files changed, 2401 insertions(+), 1739 deletions(-) create mode 100644 headers/private/interface/AbstractSpinner.h create mode 100644 headers/private/interface/DecimalSpinner.h create mode 100644 src/kits/interface/AbstractSpinner.cpp create mode 100644 src/kits/interface/DecimalSpinner.cpp diff --git a/headers/private/interface/AbstractSpinner.h b/headers/private/interface/AbstractSpinner.h new file mode 100644 index 0000000000..9d961b1260 --- /dev/null +++ b/headers/private/interface/AbstractSpinner.h @@ -0,0 +1,168 @@ +/* + * Copyright 2004 DarkWyrm + * Copyright 2013 FeemanLou + * Copyright 2014-2015 Haiku, Inc. All rights reserved. + * + * Distributed under the terms of the MIT license. + * + * Originally written by DarkWyrm + * Updated by FreemanLou as part of Google GCI 2013 + * + * Authors: + * DarkWyrm, darkwyrm@earthlink.net + * FeemanLou + * John Scipione, jscipione@gmail.com + */ +#ifndef _ABSTRACT_SPINNER_H +#define _ABSTRACT_SPINNER_H + + +#include + + +typedef enum { + SPINNER_BUTTON_HORIZONTAL_ARROWS, + SPINNER_BUTTON_VERTICAL_ARROWS, + SPINNER_BUTTON_PLUS_MINUS +} spinner_button_style; + + +class BTextView; +class SpinnerButton; +class SpinnerTextView; + + +/*! BAbstractSpinner provides an input whose value can be nudged up or down + by way of two small buttons on the right. +*/ +class BAbstractSpinner : public BControl { +public: + BAbstractSpinner(BRect frame, const char* name, + const char* label, BMessage* message, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BAbstractSpinner(const char* name, const char* label, + BMessage* message, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BAbstractSpinner(BMessage* data); + virtual ~BAbstractSpinner(); + + static BArchivable* Instantiate(BMessage* data); + virtual status_t Archive(BMessage* data, bool deep = true) const; + + virtual status_t GetSupportedSuites(BMessage* message); + virtual BHandler* ResolveSpecifier(BMessage* message, int32 index, + BMessage* specifier, int32 form, + const char* property); + + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); + virtual void FrameResized(float width, float height); + virtual void ValueChanged(); + + virtual void Decrement() = 0; + virtual void Increment() = 0; + virtual void MakeFocus(bool focus = true); + virtual void ResizeToPreferred(); + virtual void SetFlags(uint32 flags); + virtual void WindowActivated(bool active); + + alignment Alignment() const { return fAlignment; }; + virtual void SetAlignment(alignment align); + + spinner_button_style ButtonStyle() const { return fButtonStyle; }; + virtual void SetButtonStyle(spinner_button_style buttonStyle); + + float Divider() const { return fDivider; }; + virtual void SetDivider(float position); + + virtual void SetEnabled(bool enable); + + virtual void SetLabel(const char* label); + + virtual void SetValueFromText() = 0; + + bool IsDecrementEnabled() const; + virtual void SetDecrementEnabled(bool enable); + + bool IsIncrementEnabled() const; + virtual void SetIncrementEnabled(bool enable); + + virtual BSize MinSize(); + virtual BSize MaxSize(); + virtual BSize PreferredSize(); + virtual BAlignment LayoutAlignment(); + + BLayoutItem* CreateLabelLayoutItem(); + BLayoutItem* CreateTextViewLayoutItem(); + + BTextView* TextView() const; + +private: + // FBC padding + virtual void _ReservedAbstractSpinner20(); + virtual void _ReservedAbstractSpinner19(); + virtual void _ReservedAbstractSpinner18(); + virtual void _ReservedAbstractSpinner17(); + virtual void _ReservedAbstractSpinner16(); + virtual void _ReservedAbstractSpinner15(); + virtual void _ReservedAbstractSpinner14(); + virtual void _ReservedAbstractSpinner13(); + virtual void _ReservedAbstractSpinner12(); + virtual void _ReservedAbstractSpinner11(); + virtual void _ReservedAbstractSpinner10(); + virtual void _ReservedAbstractSpinner9(); + virtual void _ReservedAbstractSpinner8(); + virtual void _ReservedAbstractSpinner7(); + virtual void _ReservedAbstractSpinner6(); + virtual void _ReservedAbstractSpinner5(); + virtual void _ReservedAbstractSpinner4(); + virtual void _ReservedAbstractSpinner3(); + virtual void _ReservedAbstractSpinner2(); + virtual void _ReservedAbstractSpinner1(); + +protected: + virtual status_t AllArchived(BMessage* into) const; + virtual status_t AllUnarchived(const BMessage* from); + + virtual void LayoutInvalidated(bool descendants); + virtual void DoLayout(); + +private: + class LabelLayoutItem; + class TextViewLayoutItem; + struct LayoutData; + + friend class SpinnerButton; + friend class SpinnerTextView; + + friend class LabelLayoutItem; + friend class TextViewLayoutItem; + friend struct LayoutData; + + void _DrawLabel(BRect updateRect); + void _DrawTextView(BRect updateRect); + void _InitObject(); + void _LayoutTextView(); + void _UpdateFrame(); + void _UpdateTextViewColors(bool enable); + void _ValidateLayoutData(); + + BAbstractSpinner& operator=(const BAbstractSpinner& other); + + alignment fAlignment; + spinner_button_style fButtonStyle; + float fDivider; + + LayoutData* fLayoutData; + + SpinnerTextView* fTextView; + SpinnerButton* fIncrement; + SpinnerButton* fDecrement; + + // FBC padding + uint32 _reserved[20]; +}; + + +#endif // _ABSTRACT_SPINNER_H diff --git a/headers/private/interface/DecimalSpinner.h b/headers/private/interface/DecimalSpinner.h new file mode 100644 index 0000000000..46161c70bd --- /dev/null +++ b/headers/private/interface/DecimalSpinner.h @@ -0,0 +1,96 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ +#ifndef _DECIMAL_SPINNER_H +#define _DECIMAL_SPINNER_H + + +#include + + +class BDecimalSpinner : public BAbstractSpinner { +public: + BDecimalSpinner(BRect frame, const char* name, + const char* label, BMessage* message, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BDecimalSpinner(const char* name, const char* label, + BMessage* message, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BDecimalSpinner(BMessage* data); + virtual ~BDecimalSpinner(); + + static BArchivable* Instantiate(BMessage* data); + virtual status_t Archive(BMessage* data, bool deep = true) const; + + virtual status_t GetSupportedSuites(BMessage* message); + + virtual void AttachedToWindow(); + + virtual void Increment(); + virtual void Decrement(); + + virtual void SetEnabled(bool enable); + + uint32 Precision() const { return fPrecision; }; + virtual void SetPrecision(uint32 precision) { fPrecision = precision; }; + + double MaxValue() const { return fMaxValue; } + virtual void SetMaxValue(double max); + + double MinValue() const { return fMinValue; } + virtual void SetMinValue(double min); + + void Range(double* min, double* max); + virtual void SetRange(double min, double max); + + double Step() const { return fStep; } + virtual void SetStep(double step) { fStep = step; }; + + double Value() const { return fValue; }; + virtual void SetValue(int32 value); + virtual void SetValue(double value); + virtual void SetValueFromText(); + +private: + // FBC padding + virtual void _ReservedDecimalSpinner20(); + virtual void _ReservedDecimalSpinner19(); + virtual void _ReservedDecimalSpinner18(); + virtual void _ReservedDecimalSpinner17(); + virtual void _ReservedDecimalSpinner16(); + virtual void _ReservedDecimalSpinner15(); + virtual void _ReservedDecimalSpinner14(); + virtual void _ReservedDecimalSpinner13(); + virtual void _ReservedDecimalSpinner12(); + virtual void _ReservedDecimalSpinner11(); + virtual void _ReservedDecimalSpinner10(); + virtual void _ReservedDecimalSpinner9(); + virtual void _ReservedDecimalSpinner8(); + virtual void _ReservedDecimalSpinner7(); + virtual void _ReservedDecimalSpinner6(); + virtual void _ReservedDecimalSpinner5(); + virtual void _ReservedDecimalSpinner4(); + virtual void _ReservedDecimalSpinner3(); + virtual void _ReservedDecimalSpinner2(); + virtual void _ReservedDecimalSpinner1(); + +private: + void _InitObject(); + + double fMinValue; + double fMaxValue; + double fStep; + double fValue; + uint32 fPrecision; + + // FBC padding + uint32 _reserved[20]; +}; + + +#endif // _DECIMAL_SPINNER_H diff --git a/headers/private/interface/Spinner.h b/headers/private/interface/Spinner.h index 50e01bc7f9..e106ded902 100644 --- a/headers/private/interface/Spinner.h +++ b/headers/private/interface/Spinner.h @@ -1,35 +1,18 @@ /* - * Copyright 2004 DarkWyrm - * Copyright 2013 FeemanLou - * Copyright 2014 Haiku, Inc. All rights reserved. - * + * Copyright 2015 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT license. * - * Originally written by DarkWyrm - * Updated by FreemanLou as part of Google GCI 2013 - * * Authors: - * DarkWyrm, darkwyrm@earthlink.net - * FeemanLou * John Scipione, jscipione@gmail.com */ -#ifndef SPINNER_H -#define SPINNER_H +#ifndef _SPINNER_H +#define _SPINNER_H -#include -#include +#include -class BTextView; -class SpinnerArrow; -class SpinnerTextView; - - -/*! BSpinner provides a numeric input whose value can be nudged up or down - by way of two small buttons on the right. -*/ -class BSpinner : public BView, public BInvoker { +class BSpinner : public BAbstractSpinner { public: BSpinner(BRect frame, const char* name, const char* label, BMessage* message, @@ -44,69 +27,27 @@ public: static BArchivable* Instantiate(BMessage* data); virtual status_t Archive(BMessage* data, bool deep = true) const; + virtual void Increment(); + virtual void Decrement(); + virtual status_t GetSupportedSuites(BMessage* message); - virtual BHandler* ResolveSpecifier(BMessage* message, int32 index, - BMessage* specifier, int32 form, - const char* property); virtual void AttachedToWindow(); - virtual void Draw(BRect updateRect); - virtual void FrameResized(float width, float height); - virtual void ValueChanged(); - virtual void Decrement(); - virtual void Increment(); - virtual void MakeFocus(bool focus = true); - virtual void ResizeToPreferred(); - virtual void SetFlags(uint32 flags); - virtual void SetValueFromText(); - virtual void WindowActivated(bool active); - - alignment Alignment() const { return fAlignment; }; - virtual void SetAlignment(alignment align); - - float Divider() const { return fDivider; }; - virtual void SetDivider(float position); - - bool IsEnabled() const { return fIsEnabled; }; virtual void SetEnabled(bool enable); - const char* Label() const { return fLabel; }; - virtual void SetLabel(const char* text); + int32 MaxValue() const { return fMaxValue; } + virtual void SetMaxValue(int32 max); - uint32 Precision() const { return fPrecision; }; - virtual void SetPrecision(uint32 precision) { fPrecision = precision; }; + int32 MinValue() const { return fMinValue; } + virtual void SetMinValue(int32 min); - double MaxValue() const { return fMaxValue; } - virtual void SetMaxValue(double max); + void Range(int32* min, int32* max); + virtual void SetRange(int32 min, int32 max); - double MinValue() const { return fMinValue; } - virtual void SetMinValue(double min); - - void Range(double* min, double* max); - virtual void SetRange(double min, double max); - - double Step() const { return fStep; } - virtual void SetStep(double step) { fStep = step; }; - - double Value() const { return fValue; }; - virtual void SetValue(double value); - - bool IsDecrementEnabled() const; - virtual void SetDecrementEnabled(bool enable); - - bool IsIncrementEnabled() const; - virtual void SetIncrementEnabled(bool enable); - - virtual BSize MinSize(); - virtual BSize MaxSize(); - virtual BSize PreferredSize(); - virtual BAlignment LayoutAlignment(); - - BLayoutItem* CreateLabelLayoutItem(); - BLayoutItem* CreateTextViewLayoutItem(); - - BTextView* TextView() const; + int32 Value() const { return fValue; }; + virtual void SetValue(int32 value); + virtual void SetValueFromText(); private: // FBC padding @@ -131,54 +72,16 @@ private: virtual void _ReservedSpinner2(); virtual void _ReservedSpinner1(); -protected: - virtual status_t AllArchived(BMessage* into) const; - virtual status_t AllUnarchived(const BMessage* from); - - virtual void LayoutInvalidated(bool descendants); - virtual void DoLayout(); - private: - class LabelLayoutItem; - class TextViewLayoutItem; - struct LayoutData; - - friend class SpinnerArrow; - friend class SpinnerTextView; - - friend class LabelLayoutItem; - friend class TextViewLayoutItem; - friend struct LayoutData; - - void _DrawLabel(BRect updateRect); - void _DrawTextView(BRect updateRect); void _InitObject(); - void _LayoutTextView(); - void _UpdateFrame(); - void _UpdateTextViewColors(bool enable); - void _ValidateLayoutData(); - BSpinner& operator=(const BSpinner& other); - - alignment fAlignment; - float fDivider; - bool fIsEnabled; - const char* fLabel; - double fMinValue; - double fMaxValue; - double fStep; - double fValue; - uint32 fPrecision; - - LayoutData* fLayoutData; - - SpinnerTextView* fTextView; - SpinnerArrow* fIncrement; - SpinnerArrow* fDecrement; + int32 fMinValue; + int32 fMaxValue; + int32 fValue; // FBC padding uint32 _reserved[20]; }; -#endif // SPINNER_H +#endif // _SPINNER_H diff --git a/src/apps/deskbar/PreferencesWindow.cpp b/src/apps/deskbar/PreferencesWindow.cpp index ea88ed5116..c3be5d630b 100644 --- a/src/apps/deskbar/PreferencesWindow.cpp +++ b/src/apps/deskbar/PreferencesWindow.cpp @@ -103,23 +103,17 @@ PreferencesWindow::PreferencesWindow(BRect frame) // Menu settings fMenuRecentDocuments->SetValue(fSettings.recentDocsEnabled); fMenuRecentDocumentCount->SetEnabled(fSettings.recentDocsEnabled); - fMenuRecentDocumentCount->SetPrecision(0); fMenuRecentDocumentCount->SetRange(0, 50); - fMenuRecentDocumentCount->SetStep(1); fMenuRecentDocumentCount->SetValue(fSettings.recentDocsCount); fMenuRecentApplications->SetValue(fSettings.recentAppsEnabled); fMenuRecentApplicationCount->SetEnabled(fSettings.recentAppsEnabled); - fMenuRecentApplicationCount->SetPrecision(0); fMenuRecentApplicationCount->SetRange(0, 50); - fMenuRecentApplicationCount->SetStep(1); fMenuRecentApplicationCount->SetValue(fSettings.recentAppsCount); fMenuRecentFolders->SetValue(fSettings.recentFoldersEnabled); fMenuRecentFolderCount->SetEnabled(fSettings.recentFoldersEnabled); - fMenuRecentFolderCount->SetPrecision(0); fMenuRecentFolderCount->SetRange(0, 50); - fMenuRecentFolderCount->SetStep(1); fMenuRecentFolderCount->SetValue(fSettings.recentFoldersCount); // Applications settings diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 6c62d11bd8..ae71aee8f2 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -307,9 +307,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) fDaysInHistory = new BSpinner("days in history", B_TRANSLATE("Number of days to keep links in History menu:"), new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); - fDaysInHistory->SetPrecision(0); fDaysInHistory->SetRange(1, 35); - fDaysInHistory->SetStep(1); fDaysInHistory->SetValue( BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); diff --git a/src/kits/interface/AbstractSpinner.cpp b/src/kits/interface/AbstractSpinner.cpp new file mode 100644 index 0000000000..1a1c31bb85 --- /dev/null +++ b/src/kits/interface/AbstractSpinner.cpp @@ -0,0 +1,1690 @@ +/* + * Copyright 2004 DarkWyrm + * Copyright 2013 FeemanLou + * Copyright 2014-2015 Haiku, Inc. All rights reserved. + * + * Distributed under the terms of the MIT license. + * + * Originally written by DarkWyrm + * Updated by FreemanLou as part of Google GCI 2013 + * + * Authors: + * DarkWyrm, darkwyrm@earthlink.net + * FeemanLou + * John Scipione, jscipione@gmail.com + */ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Thread.h" + + +static const float kFrameMargin = 2.0f; + +const char* const kFrameField = "BAbstractSpinner:layoutItem:frame"; +const char* const kLabelItemField = "BAbstractSpinner:labelItem"; +const char* const kTextViewItemField = "BAbstractSpinner:textViewItem"; + + +static property_info sProperties[] = { + { + "Align", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the alignment of the spinner label.", + 0, + { B_INT32_TYPE } + }, + { + "Align", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the alignment of the spinner label.", + 0, + { B_INT32_TYPE } + }, + + { + "ButtonStyle", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the style of the spinner buttons.", + 0, + { B_INT32_TYPE } + }, + { + "ButtonStyle", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the style of the spinner buttons.", + 0, + { B_INT32_TYPE } + }, + + { + "Divider", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the divider position of the spinner.", + 0, + { B_FLOAT_TYPE } + }, + { + "Divider", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the divider position of the spinner.", + 0, + { B_FLOAT_TYPE } + }, + + { + "Enabled", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns whether or not the spinner is enabled.", + 0, + { B_BOOL_TYPE } + }, + { + "Enabled", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets whether or not the spinner is enabled.", + 0, + { B_BOOL_TYPE } + }, + + { + "Label", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the spinner label.", + 0, + { B_STRING_TYPE } + }, + { + "Label", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the spinner label.", + 0, + { B_STRING_TYPE } + }, + + { + "Message", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the spinner invocation message.", + 0, + { B_MESSAGE_TYPE } + }, + { + "Message", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the spinner invocation message.", + 0, + { B_MESSAGE_TYPE } + }, + + { 0 } +}; + + +typedef enum { + SPINNER_INCREMENT, + SPINNER_DECREMENT +} spinner_direction; + + +class SpinnerButton : public BView { +public: + SpinnerButton(BRect frame, const char* name, + spinner_direction direction); + virtual ~SpinnerButton(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void Draw(BRect updateRect); + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* message); + + bool IsEnabled() const { return fIsEnabled; } + virtual void SetEnabled(bool enable) { fIsEnabled = enable; }; + +private: + void _DoneTracking(BPoint where); + void _Track(BPoint where, uint32); + + spinner_direction fSpinnerDirection; + BAbstractSpinner* fParent; + bool fIsEnabled; + bool fIsMouseDown; + bool fIsMouseOver; + bigtime_t fRepeatDelay; +}; + + +class SpinnerTextView : public BTextView { +public: + SpinnerTextView(BRect rect, BRect textRect); + virtual ~SpinnerTextView(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void KeyDown(const char* bytes, int32 numBytes); + virtual void MakeFocus(bool focus); + +private: + BAbstractSpinner* fParent; +}; + + +class BAbstractSpinner::LabelLayoutItem : public BAbstractLayoutItem { +public: + LabelLayoutItem(BAbstractSpinner* parent); + LabelLayoutItem(BMessage* archive); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + void SetParent(BAbstractSpinner* parent); + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + BRect FrameInParent() const; + + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* from); + +private: + BAbstractSpinner* fParent; + BRect fFrame; +}; + + +class BAbstractSpinner::TextViewLayoutItem : public BAbstractLayoutItem { +public: + TextViewLayoutItem(BAbstractSpinner* parent); + TextViewLayoutItem(BMessage* archive); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + void SetParent(BAbstractSpinner* parent); + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + BRect FrameInParent() const; + + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* from); + +private: + BAbstractSpinner* fParent; + BRect fFrame; +}; + + +struct BAbstractSpinner::LayoutData { + LayoutData(float width, float height) + : + label_layout_item(NULL), + text_view_layout_item(NULL), + label_width(0), + label_height(0), + text_view_width(0), + text_view_height(0), + previous_width(width), + previous_height(height), + valid(false) + { + } + + LabelLayoutItem* label_layout_item; + TextViewLayoutItem* text_view_layout_item; + + font_height font_info; + + float label_width; + float label_height; + float text_view_width; + float text_view_height; + + float previous_width; + float previous_height; + + BSize min; + BAlignment alignment; + + bool valid; +}; + + +// #pragma mark - SpinnerButton + + +SpinnerButton::SpinnerButton(BRect frame, const char* name, + spinner_direction direction) + : + BView(frame, name, B_FOLLOW_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW), + fSpinnerDirection(direction), + fParent(NULL), + fIsEnabled(true), + fIsMouseDown(false), + fIsMouseOver(false), + fRepeatDelay(100000) +{ + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); +} + + +SpinnerButton::~SpinnerButton() +{ +} + + +void +SpinnerButton::AttachedToWindow() +{ + fParent = static_cast(Parent()); + + BView::AttachedToWindow(); +} + + +void +SpinnerButton::DetachedFromWindow() +{ + fParent = NULL; + + BView::DetachedFromWindow(); +} + + +void +SpinnerButton::Draw(BRect updateRect) +{ + BRect rect(Bounds()); + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + BView::Draw(updateRect); + + float fgTint; + if (!fIsEnabled) + fgTint = B_DARKEN_1_TINT; + else if (fIsMouseDown) + fgTint = B_DARKEN_MAX_TINT; + else + fgTint = B_DARKEN_3_TINT; + + float bgTint; + if (fIsEnabled && fIsMouseOver) + bgTint = B_DARKEN_1_TINT; + else + bgTint = B_NO_TINT; + + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + if (bgColor.red + bgColor.green + bgColor.blue <= 128 * 3) { + // if dark background make the tint lighter + fgTint = 2.0f - fgTint; + bgTint = 2.0f - bgTint; + } + + uint32 borders = be_control_look->B_TOP_BORDER + | be_control_look->B_BOTTOM_BORDER; + + if (fSpinnerDirection == SPINNER_INCREMENT) + borders |= be_control_look->B_RIGHT_BORDER; + else + borders |= be_control_look->B_LEFT_BORDER; + + // draw the button + be_control_look->DrawButtonFrame(this, rect, updateRect, + tint_color(bgColor, fgTint), bgColor, 0, borders); + be_control_look->DrawButtonBackground(this, rect, updateRect, + tint_color(bgColor, bgTint), 0, borders); + + switch (fParent->ButtonStyle()) { + case SPINNER_BUTTON_HORIZONTAL_ARROWS: + { + int32 arrowDirection = fSpinnerDirection == SPINNER_INCREMENT + ? be_control_look->B_RIGHT_ARROW + : be_control_look->B_LEFT_ARROW; + + rect.InsetBy(0.0f, 1.0f); + be_control_look->DrawArrowShape(this, rect, updateRect, bgColor, + arrowDirection, 0, fgTint); + break; + } + + case SPINNER_BUTTON_VERTICAL_ARROWS: + { + int32 arrowDirection = fSpinnerDirection == SPINNER_INCREMENT + ? be_control_look->B_UP_ARROW + : be_control_look->B_DOWN_ARROW; + + rect.InsetBy(0.0f, 1.0f); + be_control_look->DrawArrowShape(this, rect, updateRect, bgColor, + arrowDirection, 0, fgTint); + break; + } + + default: + case SPINNER_BUTTON_PLUS_MINUS: + { + BFont font; + fParent->GetFont(&font); + float inset = floorf(font.Size() / 4); + rect.InsetBy(inset, inset); + + if (rect.IntegerWidth() % 2 != 0) + rect.right -= 1; + + if (rect.IntegerHeight() % 2 != 0) + rect.bottom -= 1; + + SetHighColor(tint_color(bgColor, fgTint)); + + // draw the +/- + float halfHeight = floorf(rect.Height() / 2); + StrokeLine(BPoint(rect.left, rect.top + halfHeight), + BPoint(rect.right, rect.top + halfHeight)); + if (fSpinnerDirection == SPINNER_INCREMENT) { + float halfWidth = floorf(rect.Width() / 2); + StrokeLine(BPoint(rect.left + halfWidth, rect.top), + BPoint(rect.left + halfWidth, rect.bottom)); + } + } + } +} + + +void +SpinnerButton::MouseDown(BPoint where) +{ + if (fIsEnabled) { + fIsMouseDown = true; + Invalidate(); + fRepeatDelay = 100000; + MouseDownThread::TrackMouse(this, + &SpinnerButton::_DoneTracking, &SpinnerButton::_Track); + } + + BView::MouseDown(where); +} + + +void +SpinnerButton::MouseMoved(BPoint where, uint32 transit, + const BMessage* message) +{ + switch (transit) { + case B_ENTERED_VIEW: + case B_INSIDE_VIEW: + { + BPoint where; + uint32 buttons; + GetMouse(&where, &buttons); + fIsMouseOver = Bounds().Contains(where) && buttons == 0; + if (!fIsMouseDown) + Invalidate(); + + break; + } + + case B_EXITED_VIEW: + case B_OUTSIDE_VIEW: + fIsMouseOver = false; + MouseUp(Bounds().LeftTop()); + break; + } + + BView::MouseMoved(where, transit, message); +} + + +void +SpinnerButton::MouseUp(BPoint where) +{ + fIsMouseDown = false; + Invalidate(); + + BView::MouseUp(where); +} + + +// #pragma mark - SpinnerButton private methods + + +void +SpinnerButton::_DoneTracking(BPoint where) +{ + if (fIsMouseDown || !Bounds().Contains(where)) + fIsMouseDown = false; +} + + +void +SpinnerButton::_Track(BPoint where, uint32) +{ + if (fParent == NULL || !Bounds().Contains(where)) { + fIsMouseDown = false; + return; + } + fIsMouseDown = true; + + fSpinnerDirection == SPINNER_INCREMENT + ? fParent->Increment() + : fParent->Decrement(); + + snooze(fRepeatDelay); + fRepeatDelay = 10000; +} + + +// #pragma mark - SpinnerTextView + + +SpinnerTextView::SpinnerTextView(BRect rect, BRect textRect) + : + BTextView(rect, "textview", textRect, B_FOLLOW_ALL, + B_WILL_DRAW | B_NAVIGABLE), + fParent(NULL) +{ + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); +} + + +SpinnerTextView::~SpinnerTextView() +{ +} + + +void +SpinnerTextView::AttachedToWindow() +{ + fParent = static_cast(Parent()); + + BTextView::AttachedToWindow(); +} + + +void +SpinnerTextView::DetachedFromWindow() +{ + fParent = NULL; + + BTextView::DetachedFromWindow(); +} + + +void +SpinnerTextView::KeyDown(const char* bytes, int32 numBytes) +{ + if (fParent == NULL) { + BTextView::KeyDown(bytes, numBytes); + return; + } + + switch (bytes[0]) { + case B_ENTER: + case B_SPACE: + fParent->SetValueFromText(); + break; + + case B_TAB: + fParent->KeyDown(bytes, numBytes); + break; + + case B_LEFT_ARROW: + if (fParent->ButtonStyle() == SPINNER_BUTTON_HORIZONTAL_ARROWS + && (modifiers() & B_CONTROL_KEY) != 0) { + // need to hold down control, otherwise can't move cursor + fParent->Decrement(); + } else + BTextView::KeyDown(bytes, numBytes); + break; + + case B_UP_ARROW: + if (fParent->ButtonStyle() != SPINNER_BUTTON_HORIZONTAL_ARROWS) + fParent->Increment(); + else + BTextView::KeyDown(bytes, numBytes); + break; + + case B_RIGHT_ARROW: + if (fParent->ButtonStyle() == SPINNER_BUTTON_HORIZONTAL_ARROWS + && (modifiers() & B_CONTROL_KEY) != 0) { + // need to hold down control, otherwise can't move cursor + fParent->Increment(); + } else + BTextView::KeyDown(bytes, numBytes); + break; + + case B_DOWN_ARROW: + if (fParent->ButtonStyle() != SPINNER_BUTTON_HORIZONTAL_ARROWS) + fParent->Decrement(); + else + BTextView::KeyDown(bytes, numBytes); + break; + + default: + BTextView::KeyDown(bytes, numBytes); + break; + } +} + + +void +SpinnerTextView::MakeFocus(bool focus) +{ + BTextView::MakeFocus(focus); + + if (fParent == NULL) + return; + + if (focus) + SelectAll(); + else + fParent->SetValueFromText(); + + fParent->_DrawTextView(fParent->Bounds()); +} + + +// #pragma mark - BAbstractSpinner::LabelLayoutItem + + +BAbstractSpinner::LabelLayoutItem::LabelLayoutItem(BAbstractSpinner* parent) + : + fParent(parent), + fFrame() +{ +} + + +BAbstractSpinner::LabelLayoutItem::LabelLayoutItem(BMessage* from) + : + BAbstractLayoutItem(from), + fParent(NULL), + fFrame() +{ + from->FindRect(kFrameField, &fFrame); +} + + +bool +BAbstractSpinner::LabelLayoutItem::IsVisible() +{ + return !fParent->IsHidden(fParent); +} + + +void +BAbstractSpinner::LabelLayoutItem::SetVisible(bool visible) +{ +} + + +BRect +BAbstractSpinner::LabelLayoutItem::Frame() +{ + return fFrame; +} + + +void +BAbstractSpinner::LabelLayoutItem::SetFrame(BRect frame) +{ + fFrame = frame; + fParent->_UpdateFrame(); +} + + +void +BAbstractSpinner::LabelLayoutItem::SetParent(BAbstractSpinner* parent) +{ + fParent = parent; +} + + +BView* +BAbstractSpinner::LabelLayoutItem::View() +{ + return fParent; +} + + +BSize +BAbstractSpinner::LabelLayoutItem::BaseMinSize() +{ + fParent->_ValidateLayoutData(); + + if (fParent->Label() == NULL) + return BSize(-1.0f, -1.0f); + + return BSize(fParent->fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(), + fParent->fLayoutData->label_height); +} + + +BSize +BAbstractSpinner::LabelLayoutItem::BaseMaxSize() +{ + return BaseMinSize(); +} + + +BSize +BAbstractSpinner::LabelLayoutItem::BasePreferredSize() +{ + return BaseMinSize(); +} + + +BAlignment +BAbstractSpinner::LabelLayoutItem::BaseAlignment() +{ + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); +} + + +BRect +BAbstractSpinner::LabelLayoutItem::FrameInParent() const +{ + return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); +} + + +status_t +BAbstractSpinner::LabelLayoutItem::Archive(BMessage* into, bool deep) const +{ + BArchiver archiver(into); + status_t result = BAbstractLayoutItem::Archive(into, deep); + + if (result == B_OK) + result = into->AddRect(kFrameField, fFrame); + + return archiver.Finish(result); +} + + +BArchivable* +BAbstractSpinner::LabelLayoutItem::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "BAbstractSpinner::LabelLayoutItem")) + return new LabelLayoutItem(from); + + return NULL; +} + + +// #pragma mark - BAbstractSpinner::TextViewLayoutItem + + +BAbstractSpinner::TextViewLayoutItem::TextViewLayoutItem(BAbstractSpinner* parent) + : + fParent(parent), + fFrame() +{ + SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); +} + + +BAbstractSpinner::TextViewLayoutItem::TextViewLayoutItem(BMessage* from) + : + BAbstractLayoutItem(from), + fParent(NULL), + fFrame() +{ + from->FindRect(kFrameField, &fFrame); +} + + +bool +BAbstractSpinner::TextViewLayoutItem::IsVisible() +{ + return !fParent->IsHidden(fParent); +} + + +void +BAbstractSpinner::TextViewLayoutItem::SetVisible(bool visible) +{ + // not allowed +} + + +BRect +BAbstractSpinner::TextViewLayoutItem::Frame() +{ + return fFrame; +} + + +void +BAbstractSpinner::TextViewLayoutItem::SetFrame(BRect frame) +{ + fFrame = frame; + fParent->_UpdateFrame(); +} + + +void +BAbstractSpinner::TextViewLayoutItem::SetParent(BAbstractSpinner* parent) +{ + fParent = parent; +} + + +BView* +BAbstractSpinner::TextViewLayoutItem::View() +{ + return fParent; +} + + +BSize +BAbstractSpinner::TextViewLayoutItem::BaseMinSize() +{ + fParent->_ValidateLayoutData(); + + BSize size(fParent->fLayoutData->text_view_width, + fParent->fLayoutData->text_view_height); + + return size; +} + + +BSize +BAbstractSpinner::TextViewLayoutItem::BaseMaxSize() +{ + return BaseMinSize(); +} + + +BSize +BAbstractSpinner::TextViewLayoutItem::BasePreferredSize() +{ + return BaseMinSize(); +} + + +BAlignment +BAbstractSpinner::TextViewLayoutItem::BaseAlignment() +{ + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); +} + + +BRect +BAbstractSpinner::TextViewLayoutItem::FrameInParent() const +{ + return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); +} + + +status_t +BAbstractSpinner::TextViewLayoutItem::Archive(BMessage* into, bool deep) const +{ + BArchiver archiver(into); + status_t result = BAbstractLayoutItem::Archive(into, deep); + + if (result == B_OK) + result = into->AddRect(kFrameField, fFrame); + + return archiver.Finish(result); +} + + +BArchivable* +BAbstractSpinner::TextViewLayoutItem::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "BAbstractSpinner::TextViewLayoutItem")) + return new LabelLayoutItem(from); + + return NULL; +} + + +// #pragma mark - BAbstractSpinner + + +BAbstractSpinner::BAbstractSpinner(BRect frame, const char* name, const char* label, + BMessage* message, uint32 resizingMode, uint32 flags) + : + BControl(frame, name, label, message, resizingMode, + flags | B_WILL_DRAW | B_FRAME_EVENTS) +{ + _InitObject(); +} + + +BAbstractSpinner::BAbstractSpinner(const char* name, const char* label, BMessage* message, + uint32 flags) + : + BControl(name, label, message, flags | B_WILL_DRAW | B_FRAME_EVENTS) +{ + _InitObject(); +} + + +BAbstractSpinner::BAbstractSpinner(BMessage* data) + : + BControl(data), + fButtonStyle(SPINNER_BUTTON_PLUS_MINUS) +{ + _InitObject(); + + if (data->FindInt32("_align") != B_OK) + fAlignment = B_ALIGN_LEFT; + + if (data->FindInt32("_button_style") != B_OK) + fButtonStyle = SPINNER_BUTTON_PLUS_MINUS; + + if (data->FindInt32("_divider") != B_OK) + fDivider = 0.0f; +} + + +BAbstractSpinner::~BAbstractSpinner() +{ + delete fLayoutData; + fLayoutData = NULL; +} + + +BArchivable* +BAbstractSpinner::Instantiate(BMessage* data) +{ + // cannot instantiate an abstract spinner + return NULL; +} + + +status_t +BAbstractSpinner::Archive(BMessage* data, bool deep) const +{ + status_t status = BControl::Archive(data, deep); + data->AddString("class", "Spinner"); + + if (status == B_OK) + status = data->AddInt32("_align", fAlignment); + + if (status == B_OK) + data->AddInt32("_button_style", fButtonStyle); + + if (status == B_OK) + status = data->AddFloat("_divider", fDivider); + + return status; +} + + +status_t +BAbstractSpinner::GetSupportedSuites(BMessage* message) +{ + message->AddString("suites", "suite/vnd.Haiku-spinner"); + + BPropertyInfo prop_info(sProperties); + message->AddFlat("messages", &prop_info); + + return BView::GetSupportedSuites(message); +} + + +BHandler* +BAbstractSpinner::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier, + int32 form, const char* property) +{ + return BView::ResolveSpecifier(message, index, specifier, form, + property); +} + + +void +BAbstractSpinner::AttachedToWindow() +{ + if (!Messenger().IsValid()) + SetTarget(Window()); + + BControl::SetValue(Value()); + // sets the text and enables or disables the arrows + + _UpdateTextViewColors(IsEnabled()); + fTextView->MakeEditable(IsEnabled()); + + BView::AttachedToWindow(); +} + + +void +BAbstractSpinner::Draw(BRect updateRect) +{ + _DrawLabel(updateRect); + _DrawTextView(updateRect); + fIncrement->Invalidate(); + fDecrement->Invalidate(); +} + + +void +BAbstractSpinner::FrameResized(float width, float height) +{ + BView::FrameResized(width, height); + + // TODO: this causes flickering still... + + // changes in width + + BRect bounds = Bounds(); + + if (bounds.Width() > fLayoutData->previous_width) { + // invalidate the region between the old and the new right border + BRect rect = bounds; + rect.left += fLayoutData->previous_width - kFrameMargin; + rect.right--; + Invalidate(rect); + } else if (bounds.Width() < fLayoutData->previous_width) { + // invalidate the region of the new right border + BRect rect = bounds; + rect.left = rect.right - kFrameMargin; + Invalidate(rect); + } + + // changes in height + + if (bounds.Height() > fLayoutData->previous_height) { + // invalidate the region between the old and the new bottom border + BRect rect = bounds; + rect.top += fLayoutData->previous_height - kFrameMargin; + rect.bottom--; + Invalidate(rect); + // invalidate label area + rect = bounds; + rect.right = fDivider; + Invalidate(rect); + } else if (bounds.Height() < fLayoutData->previous_height) { + // invalidate the region of the new bottom border + BRect rect = bounds; + rect.top = rect.bottom - kFrameMargin; + Invalidate(rect); + // invalidate label area + rect = bounds; + rect.right = fDivider; + Invalidate(rect); + } + + fLayoutData->previous_width = bounds.Width(); + fLayoutData->previous_height = bounds.Height(); +} + + +void +BAbstractSpinner::ValueChanged() +{ + // hook method - does nothing +} + + +void +BAbstractSpinner::MakeFocus(bool focus) +{ + fTextView->MakeFocus(focus); +} + + +void +BAbstractSpinner::ResizeToPreferred() +{ + BView::ResizeToPreferred(); + + const char* label = Label(); + if (label != NULL) { + fDivider = ceilf(StringWidth(label)) + + be_control_look->DefaultLabelSpacing(); + } else + fDivider = 0.0f; + + _LayoutTextView(); +} + + +void +BAbstractSpinner::SetFlags(uint32 flags) +{ + // If the textview is navigable, set it to not navigable if needed, + // else if it is not navigable, set it to navigable if needed + if (fTextView->Flags() & B_NAVIGABLE) { + if (!(flags & B_NAVIGABLE)) + fTextView->SetFlags(fTextView->Flags() & ~B_NAVIGABLE); + } else { + if (flags & B_NAVIGABLE) + fTextView->SetFlags(fTextView->Flags() | B_NAVIGABLE); + } + + // Don't make this one navigable + flags &= ~B_NAVIGABLE; + + BView::SetFlags(flags); +} + + +void +BAbstractSpinner::WindowActivated(bool active) +{ + _DrawTextView(fTextView->Frame()); +} + + +void +BAbstractSpinner::SetAlignment(alignment align) +{ + fAlignment = align; +} + + +void +BAbstractSpinner::SetButtonStyle(spinner_button_style buttonStyle) +{ + fButtonStyle = buttonStyle; +} + + +void +BAbstractSpinner::SetDivider(float position) +{ + position = roundf(position); + + float delta = fDivider - position; + if (delta == 0.0f) + return; + + fDivider = position; + + if ((Flags() & B_SUPPORTS_LAYOUT) != 0) { + // We should never get here, since layout support means, we also + // layout the divider, and don't use this method at all. + Relayout(); + } else { + _LayoutTextView(); + Invalidate(); + } +} + + +void +BAbstractSpinner::SetEnabled(bool enable) +{ + if (IsEnabled() == enable) + return; + + BControl::SetEnabled(enable); + + fTextView->MakeEditable(enable); + if (enable) + fTextView->SetFlags(fTextView->Flags() | B_NAVIGABLE); + else + fTextView->SetFlags(fTextView->Flags() & ~B_NAVIGABLE); + + _UpdateTextViewColors(enable); + fTextView->Invalidate(); + + _LayoutTextView(); + Invalidate(); + if (Window() != NULL) + Window()->UpdateIfNeeded(); +} + + +void +BAbstractSpinner::SetLabel(const char* label) +{ + BControl::SetLabel(label); + + if (Window() != NULL) + Window()->UpdateIfNeeded(); +} + + +bool +BAbstractSpinner::IsDecrementEnabled() const +{ + return fDecrement->IsEnabled(); +} + + +void +BAbstractSpinner::SetDecrementEnabled(bool enable) +{ + if (IsDecrementEnabled() == enable) + return; + + fDecrement->SetEnabled(enable); + fDecrement->Invalidate(); +} + + +bool +BAbstractSpinner::IsIncrementEnabled() const +{ + return fIncrement->IsEnabled(); +} + + +void +BAbstractSpinner::SetIncrementEnabled(bool enable) +{ + if (IsIncrementEnabled() == enable) + return; + + fIncrement->SetEnabled(enable); + fIncrement->Invalidate(); +} + + +BSize +BAbstractSpinner::MinSize() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeSize(ExplicitMinSize(), fLayoutData->min); +} + + +BSize +BAbstractSpinner::MaxSize() +{ + _ValidateLayoutData(); + + BSize max = fLayoutData->min; + max.width = B_SIZE_UNLIMITED; + + return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max); +} + + +BSize +BAbstractSpinner::PreferredSize() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), + fLayoutData->min); +} + + +BAlignment +BAbstractSpinner::LayoutAlignment() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeAlignment(ExplicitAlignment(), + BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER)); +} + + +BLayoutItem* +BAbstractSpinner::CreateLabelLayoutItem() +{ + if (fLayoutData->label_layout_item == NULL) + fLayoutData->label_layout_item = new LabelLayoutItem(this); + + return fLayoutData->label_layout_item; +} + + +BLayoutItem* +BAbstractSpinner::CreateTextViewLayoutItem() +{ + if (fLayoutData->text_view_layout_item == NULL) + fLayoutData->text_view_layout_item = new TextViewLayoutItem(this); + + return fLayoutData->text_view_layout_item; +} + + +BTextView* +BAbstractSpinner::TextView() const +{ + return dynamic_cast(fTextView); +} + + +// #pragma mark - BAbstractSpinner protected methods + + +status_t +BAbstractSpinner::AllArchived(BMessage* into) const +{ + status_t result; + if ((result = BControl::AllArchived(into)) != B_OK) + return result; + + BArchiver archiver(into); + + BArchivable* textViewItem = fLayoutData->text_view_layout_item; + if (archiver.IsArchived(textViewItem)) + result = archiver.AddArchivable(kTextViewItemField, textViewItem); + + if (result != B_OK) + return result; + + BArchivable* labelBarItem = fLayoutData->label_layout_item; + if (archiver.IsArchived(labelBarItem)) + result = archiver.AddArchivable(kLabelItemField, labelBarItem); + + return result; +} + + +status_t +BAbstractSpinner::AllUnarchived(const BMessage* from) +{ + BUnarchiver unarchiver(from); + + status_t result = B_OK; + if ((result = BControl::AllUnarchived(from)) != B_OK) + return result; + + if (unarchiver.IsInstantiated(kTextViewItemField)) { + TextViewLayoutItem*& textViewItem + = fLayoutData->text_view_layout_item; + result = unarchiver.FindObject(kTextViewItemField, + BUnarchiver::B_DONT_ASSUME_OWNERSHIP, textViewItem); + + if (result == B_OK) + textViewItem->SetParent(this); + else + return result; + } + + if (unarchiver.IsInstantiated(kLabelItemField)) { + LabelLayoutItem*& labelItem = fLayoutData->label_layout_item; + result = unarchiver.FindObject(kLabelItemField, + BUnarchiver::B_DONT_ASSUME_OWNERSHIP, labelItem); + + if (result == B_OK) + labelItem->SetParent(this); + } + + return result; +} + + +void +BAbstractSpinner::DoLayout() +{ + if ((Flags() & B_SUPPORTS_LAYOUT) == 0) + return; + + if (GetLayout()) { + BControl::DoLayout(); + return; + } + + _ValidateLayoutData(); + + BSize size(Bounds().Size()); + if (size.width < fLayoutData->min.width) + size.width = fLayoutData->min.width; + + if (size.height < fLayoutData->min.height) + size.height = fLayoutData->min.height; + + float divider = 0; + if (fLayoutData->label_layout_item != NULL + && fLayoutData->text_view_layout_item != NULL + && fLayoutData->label_layout_item->Frame().IsValid() + && fLayoutData->text_view_layout_item->Frame().IsValid()) { + divider = fLayoutData->text_view_layout_item->Frame().left + - fLayoutData->label_layout_item->Frame().left; + } else if (fLayoutData->label_width > 0) { + divider = fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(); + } + fDivider = divider; + + BRect dirty(fTextView->Frame()); + _LayoutTextView(); + + // invalidate dirty region + dirty = dirty | fTextView->Frame(); + dirty = dirty | fIncrement->Frame(); + dirty = dirty | fDecrement->Frame(); + + Invalidate(dirty); +} + + +void +BAbstractSpinner::LayoutInvalidated(bool descendants) +{ + if (fLayoutData != NULL) + fLayoutData->valid = false; +} + + +// #pragma mark - BAbstractSpinner private methods + + +void +BAbstractSpinner::_DrawLabel(BRect updateRect) +{ + BRect rect(Bounds()); + rect.right = fDivider; + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + _ValidateLayoutData(); + + const char* label = Label(); + if (label == NULL) + return; + + // horizontal position + float x; + switch (fAlignment) { + case B_ALIGN_RIGHT: + x = fDivider - fLayoutData->label_width - 3.0f; + break; + + case B_ALIGN_CENTER: + x = fDivider - roundf(fLayoutData->label_width / 2.0f); + break; + + default: + x = 0.0f; + break; + } + + // vertical position + font_height& fontHeight = fLayoutData->font_info; + float y = rect.top + + roundf((rect.Height() + 1.0f - fontHeight.ascent + - fontHeight.descent) / 2.0f) + + fontHeight.ascent + kFrameMargin * 2; + + uint32 flags = 0; + if (!IsEnabled()) + flags |= BControlLook::B_DISABLED; + + be_control_look->DrawLabel(this, label, LowColor(), flags, BPoint(x, y)); +} + + +void +BAbstractSpinner::_DrawTextView(BRect updateRect) +{ + BRect rect = fTextView->Frame(); + rect.InsetBy(-kFrameMargin, -kFrameMargin); + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 flags = 0; + if (!IsEnabled()) + flags |= BControlLook::B_DISABLED; + + if (fTextView->IsFocus() && Window()->IsActive()) + flags |= BControlLook::B_FOCUSED; + + be_control_look->DrawTextControlBorder(this, rect, updateRect, base, + flags); +} + + +void +BAbstractSpinner::_InitObject() +{ + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); + + fAlignment = B_ALIGN_LEFT; + fButtonStyle = SPINNER_BUTTON_PLUS_MINUS; + + if (Label() != NULL) { + fDivider = StringWidth(Label()) + + be_control_look->DefaultLabelSpacing(); + } else + fDivider = 0.0f; + + BControl::SetEnabled(true); + BControl::SetValue(0); + + BRect rect(Bounds()); + fLayoutData = new LayoutData(rect.Width(), rect.Height()); + + rect.left = fDivider; + rect.InsetBy(kFrameMargin, kFrameMargin); + rect.right -= rect.Height() * 2 + kFrameMargin * 2 + 1.0f; + BRect textRect(rect.OffsetToCopy(B_ORIGIN)); + + fTextView = new SpinnerTextView(rect, textRect); + AddChild(fTextView); + + rect.InsetBy(0.0f, -kFrameMargin); + + rect.left = rect.right + kFrameMargin * 2; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; + + fDecrement = new SpinnerButton(rect, "decrement", SPINNER_DECREMENT); + AddChild(fDecrement); + + rect.left = rect.right + 1.0f; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; + + fIncrement = new SpinnerButton(rect, "increment", SPINNER_INCREMENT); + AddChild(fIncrement); + + uint32 navigableFlags = Flags() & B_NAVIGABLE; + if (navigableFlags != 0) + BControl::SetFlags(Flags() & ~B_NAVIGABLE); +} + + +void +BAbstractSpinner::_LayoutTextView() +{ + BRect rect; + if (fLayoutData->text_view_layout_item != NULL) { + rect = fLayoutData->text_view_layout_item->FrameInParent(); + } else { + rect = Bounds(); + rect.left = fDivider; + } + rect.InsetBy(kFrameMargin, kFrameMargin); + rect.right -= rect.Height() * 2 + kFrameMargin * 2 + 1.0f; + + fTextView->MoveTo(rect.left, rect.top); + fTextView->ResizeTo(rect.Width(), rect.Height()); + fTextView->SetTextRect(rect.OffsetToCopy(B_ORIGIN)); + + rect.InsetBy(0.0f, -kFrameMargin); + + rect.left = rect.right + kFrameMargin * 2; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; + + fDecrement->ResizeTo(rect.Width(), rect.Height()); + fDecrement->MoveTo(rect.LeftTop()); + + rect.left = rect.right + 1.0f; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; + + fIncrement->ResizeTo(rect.Width(), rect.Height()); + fIncrement->MoveTo(rect.LeftTop()); +} + + +void +BAbstractSpinner::_UpdateFrame() +{ + if (fLayoutData->label_layout_item == NULL + || fLayoutData->text_view_layout_item == NULL) { + return; + } + + BRect labelFrame = fLayoutData->label_layout_item->Frame(); + BRect textViewFrame = fLayoutData->text_view_layout_item->Frame(); + + if (!labelFrame.IsValid() || !textViewFrame.IsValid()) + return; + + // update divider + fDivider = textViewFrame.left - labelFrame.left; + + BRect frame = textViewFrame | labelFrame; + MoveTo(frame.left, frame.top); + BSize oldSize = Bounds().Size(); + ResizeTo(frame.Width(), frame.Height()); + BSize newSize = Bounds().Size(); + + // If the size changes, ResizeTo() will trigger a relayout, otherwise + // we need to do that explicitly. + if (newSize != oldSize) + Relayout(); +} + + +void +BAbstractSpinner::_UpdateTextViewColors(bool enable) +{ + rgb_color textColor; + rgb_color bgColor; + BFont font; + + fTextView->GetFontAndColor(0, &font); + + if (enable) + textColor = ui_color(B_DOCUMENT_TEXT_COLOR); + else { + textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_DISABLED_LABEL_TINT); + } + + fTextView->SetFontAndColor(&font, B_FONT_ALL, &textColor); + + if (enable) + bgColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + else { + bgColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_LIGHTEN_2_TINT); + } + + fTextView->SetViewColor(bgColor); + fTextView->SetLowColor(bgColor); +} + + +void +BAbstractSpinner::_ValidateLayoutData() +{ + if (fLayoutData->valid) + return; + + font_height fontHeight = fLayoutData->font_info; + GetFontHeight(&fontHeight); + + if (Label() != NULL) { + fLayoutData->label_width = StringWidth(Label()); + fLayoutData->label_height = ceilf(fontHeight.ascent + + fontHeight.descent + fontHeight.leading); + } else { + fLayoutData->label_width = 0; + fLayoutData->label_height = 0; + } + + float divider = 0; + if (fLayoutData->label_width > 0) { + divider = ceilf(fLayoutData->label_width + + be_control_look->DefaultLabelSpacing()); + } + + if ((Flags() & B_SUPPORTS_LAYOUT) == 0) + divider = std::max(divider, fDivider); + + float minTextWidth = fTextView->StringWidth("99999"); + + float textViewHeight = fTextView->LineHeight(0) + kFrameMargin * 2; + float textViewWidth = minTextWidth + textViewHeight * 2; + + fLayoutData->text_view_width = textViewWidth; + fLayoutData->text_view_height = textViewHeight; + + BSize min(textViewWidth, textViewHeight); + if (divider > 0.0f) + min.width += divider; + + if (fLayoutData->label_height > min.height) + min.height = fLayoutData->label_height; + + fLayoutData->min = min; + fLayoutData->valid = true; + + ResetLayoutInvalidation(); +} + + +// FBC padding + +void BAbstractSpinner::_ReservedAbstractSpinner20() {} +void BAbstractSpinner::_ReservedAbstractSpinner19() {} +void BAbstractSpinner::_ReservedAbstractSpinner18() {} +void BAbstractSpinner::_ReservedAbstractSpinner17() {} +void BAbstractSpinner::_ReservedAbstractSpinner16() {} +void BAbstractSpinner::_ReservedAbstractSpinner15() {} +void BAbstractSpinner::_ReservedAbstractSpinner14() {} +void BAbstractSpinner::_ReservedAbstractSpinner13() {} +void BAbstractSpinner::_ReservedAbstractSpinner12() {} +void BAbstractSpinner::_ReservedAbstractSpinner11() {} +void BAbstractSpinner::_ReservedAbstractSpinner10() {} +void BAbstractSpinner::_ReservedAbstractSpinner9() {} +void BAbstractSpinner::_ReservedAbstractSpinner8() {} +void BAbstractSpinner::_ReservedAbstractSpinner7() {} +void BAbstractSpinner::_ReservedAbstractSpinner6() {} +void BAbstractSpinner::_ReservedAbstractSpinner5() {} +void BAbstractSpinner::_ReservedAbstractSpinner4() {} +void BAbstractSpinner::_ReservedAbstractSpinner3() {} +void BAbstractSpinner::_ReservedAbstractSpinner2() {} +void BAbstractSpinner::_ReservedAbstractSpinner1() {} diff --git a/src/kits/interface/DecimalSpinner.cpp b/src/kits/interface/DecimalSpinner.cpp new file mode 100644 index 0000000000..e772b53e59 --- /dev/null +++ b/src/kits/interface/DecimalSpinner.cpp @@ -0,0 +1,372 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ + + +#include + +#include +#include + +#include +#include + + +static double +roundTo(double value, uint32 n) +{ + return floor(value * pow(10.0, n) + 0.5) / pow(10.0, n); +} + + +static property_info sProperties[] = { + { + "MaxValue", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the maximum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "MaxValue", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the maximum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "MinValue", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the minimum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "MinValue", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the minimum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "Precision", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the number of decimal places of precision of the spinner.", + 0, + { B_UINT32_TYPE } + }, + { + "Precision", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the number of decimal places of precision of the spinner.", + 0, + { B_UINT32_TYPE } + }, + + { + "Step", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the step size of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "Step", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the step size of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "Value", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "Value", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { 0 } +}; + + +// #pragma mark - BDecimalSpinner + + +BDecimalSpinner::BDecimalSpinner(BRect frame, const char* name, + const char* label, BMessage* message, uint32 resizingMode, uint32 flags) + : + BAbstractSpinner(frame, name, label, message, resizingMode, flags) +{ + _InitObject(); +} + + +BDecimalSpinner::BDecimalSpinner(const char* name, const char* label, + BMessage* message, uint32 flags) + : + BAbstractSpinner(name, label, message, flags) +{ + _InitObject(); +} + + +BDecimalSpinner::BDecimalSpinner(BMessage* data) + : + BAbstractSpinner(data) +{ + _InitObject(); + + if (data->FindDouble("_max", &fMaxValue) != B_OK) + fMinValue = 100.0; + + if (data->FindDouble("_min", &fMinValue) != B_OK) + fMinValue = 0.0; + + if (data->FindUInt32("_precision", &fPrecision) != B_OK) + fPrecision = 2; + + if (data->FindDouble("_step", &fStep) != B_OK) + fStep = 1.0; + + if (data->FindDouble("_val", &fValue) != B_OK) + fValue = 0.0; +} + + +BDecimalSpinner::~BDecimalSpinner() +{ +} + + +BArchivable* +BDecimalSpinner::Instantiate(BMessage* data) +{ + if (validate_instantiation(data, "DecimalSpinner")) + return new BDecimalSpinner(data); + + return NULL; +} + + +status_t +BDecimalSpinner::Archive(BMessage* data, bool deep) const +{ + status_t status = BAbstractSpinner::Archive(data, deep); + data->AddString("class", "DecimalSpinner"); + + if (status == B_OK) + status = data->AddDouble("_max", fMaxValue); + + if (status == B_OK) + status = data->AddDouble("_min", fMinValue); + + if (status == B_OK) + status = data->AddUInt32("_precision", fPrecision); + + if (status == B_OK) + status = data->AddDouble("_step", fStep); + + if (status == B_OK) + status = data->AddDouble("_val", fValue); + + return status; +} + + +status_t +BDecimalSpinner::GetSupportedSuites(BMessage* message) +{ + message->AddString("suites", "suite/vnd.Haiku-decimal-spinner"); + + BPropertyInfo prop_info(sProperties); + message->AddFlat("messages", &prop_info); + + return BView::GetSupportedSuites(message); +} + + +void +BDecimalSpinner::AttachedToWindow() +{ + SetValue(fValue); + + BAbstractSpinner::AttachedToWindow(); +} + + +void +BDecimalSpinner::Decrement() +{ + SetValue(Value() - Step()); +} + + +void +BDecimalSpinner::Increment() +{ + SetValue(Value() + Step()); +} + + +void +BDecimalSpinner::SetEnabled(bool enable) +{ + if (IsEnabled() == enable) + return; + + SetIncrementEnabled(enable && Value() < fMaxValue); + SetDecrementEnabled(enable && Value() > fMinValue); + + BAbstractSpinner::SetEnabled(enable); +} + + +void +BDecimalSpinner::SetMaxValue(double max) +{ + fMaxValue = max; + if (fValue > fMaxValue) + SetValue(fMaxValue); +} + + +void +BDecimalSpinner::SetMinValue(double min) +{ + fMinValue = min; + if (fValue < fMinValue) + SetValue(fMinValue); +} + + +void +BDecimalSpinner::Range(double* min, double* max) +{ + *min = fMinValue; + *max = fMaxValue; +} + + +void +BDecimalSpinner::SetRange(double min, double max) +{ + SetMinValue(min); + SetMaxValue(max); +} + + +void +BDecimalSpinner::SetValue(int32 value) +{ + SetValue((double)value); +} + + +void +BDecimalSpinner::SetValue(double value) +{ + // clip to range + if (value < fMinValue) + value = fMinValue; + else if (value > fMaxValue) + value = fMaxValue; + + // update the text view + char* format; + asprintf(&format, "%%.%" B_PRId32 "f", fPrecision); + char* valueString; + asprintf(&valueString, format, value); + TextView()->SetText(valueString); + free(format); + free(valueString); + + // update the up and down arrows + SetIncrementEnabled(IsEnabled() && value < fMaxValue); + SetDecrementEnabled(IsEnabled() && value > fMinValue); + + if (value == fValue) + return; + + fValue = value; + ValueChanged(); + + Invoke(); + Invalidate(); +} + + +void +BDecimalSpinner::SetValueFromText() +{ + SetValue(roundTo(atof(TextView()->Text()), Precision())); +} + + +// #pragma mark - BDecimalSpinner private methods + + +void +BDecimalSpinner::_InitObject() +{ + fMaxValue = 100.0; + fMinValue = 0.0; + fPrecision = 2; + fStep = 1.0; + fValue = 0.0; + + TextView()->SetAlignment(B_ALIGN_RIGHT); + for (uint32 c = 0; c <= 42; c++) + TextView()->DisallowChar(c); + + TextView()->DisallowChar('/'); + for (uint32 c = 58; c <= 127; c++) + TextView()->DisallowChar(c); +} + + +// FBC padding + +void BDecimalSpinner::_ReservedDecimalSpinner20() {} +void BDecimalSpinner::_ReservedDecimalSpinner19() {} +void BDecimalSpinner::_ReservedDecimalSpinner18() {} +void BDecimalSpinner::_ReservedDecimalSpinner17() {} +void BDecimalSpinner::_ReservedDecimalSpinner16() {} +void BDecimalSpinner::_ReservedDecimalSpinner15() {} +void BDecimalSpinner::_ReservedDecimalSpinner14() {} +void BDecimalSpinner::_ReservedDecimalSpinner13() {} +void BDecimalSpinner::_ReservedDecimalSpinner12() {} +void BDecimalSpinner::_ReservedDecimalSpinner11() {} +void BDecimalSpinner::_ReservedDecimalSpinner10() {} +void BDecimalSpinner::_ReservedDecimalSpinner9() {} +void BDecimalSpinner::_ReservedDecimalSpinner8() {} +void BDecimalSpinner::_ReservedDecimalSpinner7() {} +void BDecimalSpinner::_ReservedDecimalSpinner6() {} +void BDecimalSpinner::_ReservedDecimalSpinner5() {} +void BDecimalSpinner::_ReservedDecimalSpinner4() {} +void BDecimalSpinner::_ReservedDecimalSpinner3() {} +void BDecimalSpinner::_ReservedDecimalSpinner2() {} +void BDecimalSpinner::_ReservedDecimalSpinner1() {} diff --git a/src/kits/interface/Jamfile b/src/kits/interface/Jamfile index 79a00d0d00..cec0540f17 100644 --- a/src/kits/interface/Jamfile +++ b/src/kits/interface/Jamfile @@ -42,6 +42,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { AboutWindow.cpp AbstractLayout.cpp AbstractLayoutItem.cpp + AbstractSpinner.cpp AffineTransform.cpp Alert.cpp Alignment.cpp @@ -60,6 +61,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { ControlLook.cpp DecorInfo.cpp Deskbar.cpp + DecimalSpinner.cpp Dragger.cpp Font.cpp Gradient.cpp diff --git a/src/kits/interface/Spinner.cpp b/src/kits/interface/Spinner.cpp index c3d4c057a8..e6d6a63b71 100644 --- a/src/kits/interface/Spinner.cpp +++ b/src/kits/interface/Spinner.cpp @@ -1,152 +1,30 @@ /* - * Copyright 2004 DarkWyrm - * Copyright 2013 FeemanLou - * Copyright 2014-2015 Haiku, Inc. All rights reserved. - * + * Copyright 2015 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT license. * - * Originally written by DarkWyrm - * Updated by FreemanLou as part of Google GCI 2013 - * * Authors: - * DarkWyrm, darkwyrm@earthlink.net - * FeemanLou * John Scipione, jscipione@gmail.com */ -#include "Spinner.h" +#include -#include -#include +#include #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include #include -#include - -#include "Thread.h" - - -static const float kFrameMargin = 2.0f; - -const char* const kFrameField = "BSpinner:layoutItem:frame"; -const char* const kLabelItemField = "BSpinner:labelItem"; -const char* const kTextViewItemField = "BSpinner:textViewItem"; - - -static double -roundTo(double value, uint32 n) -{ - return floor(value * pow(10.0, n) + 0.5) / pow(10.0, n); -} static property_info sProperties[] = { - { - "Align", - { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, - "Returns the alignment of the spinner label.", - 0, - { B_INT32_TYPE } - }, - { - "Align", - { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0}, - "Sets the alignment of the spinner label.", - 0, - { B_INT32_TYPE } - }, - - { - "Divider", - { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, - "Returns the divider position of the spinner.", - 0, - { B_FLOAT_TYPE } - }, - { - "Divider", - { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0}, - "Sets the divider position of the spinner.", - 0, - { B_FLOAT_TYPE } - }, - - { - "Enabled", - { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, - "Returns whether or not the spinner is enabled.", - 0, - { B_BOOL_TYPE } - }, - { - "Enabled", - { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0}, - "Sets whether or not the spinner is enabled.", - 0, - { B_BOOL_TYPE } - }, - - { - "Label", - { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, - "Returns the spinner label.", - 0, - { B_STRING_TYPE } - }, - { - "Label", - { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0}, - "Sets the spinner label.", - 0, - { B_STRING_TYPE } - }, - - { - "Message", - { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, - "Returns the spinner invocation message.", - 0, - { B_MESSAGE_TYPE } - }, - { - "Message", - { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0}, - "Sets the spinner invocation message.", - 0, - { B_MESSAGE_TYPE } - }, - { "MaxValue", { B_GET_PROPERTY, 0 }, { B_DIRECT_SPECIFIER, 0 }, "Returns the maximum value of the spinner.", 0, - { B_DOUBLE_TYPE } + { B_INT32_TYPE } }, { "MaxValue", @@ -154,7 +32,7 @@ static property_info sProperties[] = { { B_DIRECT_SPECIFIER, 0}, "Sets the maximum value of the spinner.", 0, - { B_DOUBLE_TYPE } + { B_INT32_TYPE } }, { @@ -163,7 +41,7 @@ static property_info sProperties[] = { { B_DIRECT_SPECIFIER, 0 }, "Returns the minimum value of the spinner.", 0, - { B_DOUBLE_TYPE } + { B_INT32_TYPE } }, { "MinValue", @@ -171,41 +49,7 @@ static property_info sProperties[] = { { B_DIRECT_SPECIFIER, 0}, "Sets the minimum value of the spinner.", 0, - { B_DOUBLE_TYPE } - }, - - { - "Precision", - { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0}, - "Sets the number of decimal places of precision of the spinner.", - 0, - { B_UINT32_TYPE } - }, - { - "Precision", - { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, - "Returns the number of decimal places of precision of the spinner.", - 0, - { B_UINT32_TYPE } - }, - - { - "Step", - { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, - "Returns the step size of the spinner.", - 0, - { B_DOUBLE_TYPE } - }, - { - "Step", - { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0}, - "Sets the step size of the spinner.", - 0, - { B_DOUBLE_TYPE } + { B_INT32_TYPE } }, { @@ -214,7 +58,7 @@ static property_info sProperties[] = { { B_DIRECT_SPECIFIER, 0 }, "Returns the value of the spinner.", 0, - { B_DOUBLE_TYPE } + { B_INT32_TYPE } }, { "Value", @@ -222,774 +66,53 @@ static property_info sProperties[] = { { B_DIRECT_SPECIFIER, 0}, "Sets the value of the spinner.", 0, - { B_DOUBLE_TYPE } + { B_INT32_TYPE } }, { 0 } }; -typedef enum { - SPINNER_INCREMENT, - SPINNER_DECREMENT -} spinner_direction; - - -class SpinnerArrow : public BView { -public: - SpinnerArrow(BRect frame, const char* name, - spinner_direction direction); - virtual ~SpinnerArrow(); - - virtual void AttachedToWindow(); - virtual void DetachedFromWindow(); - virtual void Draw(BRect updateRect); - virtual void MouseDown(BPoint where); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* message); - - bool IsEnabled() const { return fIsEnabled; } - virtual void SetEnabled(bool enable) { fIsEnabled = enable; }; - -private: - void _DoneTracking(BPoint where); - void _Track(BPoint where, uint32); - - spinner_direction fSpinnerDirection; - BSpinner* fParent; - bool fIsEnabled; - bool fIsMouseDown; - bool fIsMouseOver; - bigtime_t fRepeatDelay; -}; - - -class SpinnerTextView : public BTextView { -public: - SpinnerTextView(BRect rect, BRect textRect); - virtual ~SpinnerTextView(); - - virtual void AttachedToWindow(); - virtual void DetachedFromWindow(); - virtual void KeyDown(const char* bytes, int32 numBytes); - virtual void MakeFocus(bool focus); - -private: - BSpinner* fParent; -}; - - -class BSpinner::LabelLayoutItem : public BAbstractLayoutItem { -public: - LabelLayoutItem(BSpinner* parent); - LabelLayoutItem(BMessage* archive); - - virtual bool IsVisible(); - virtual void SetVisible(bool visible); - - virtual BRect Frame(); - virtual void SetFrame(BRect frame); - - void SetParent(BSpinner* parent); - virtual BView* View(); - - virtual BSize BaseMinSize(); - virtual BSize BaseMaxSize(); - virtual BSize BasePreferredSize(); - virtual BAlignment BaseAlignment(); - - BRect FrameInParent() const; - - virtual status_t Archive(BMessage* into, bool deep = true) const; - static BArchivable* Instantiate(BMessage* from); - -private: - BSpinner* fParent; - BRect fFrame; -}; - - -class BSpinner::TextViewLayoutItem : public BAbstractLayoutItem { -public: - TextViewLayoutItem(BSpinner* parent); - TextViewLayoutItem(BMessage* archive); - - virtual bool IsVisible(); - virtual void SetVisible(bool visible); - - virtual BRect Frame(); - virtual void SetFrame(BRect frame); - - void SetParent(BSpinner* parent); - virtual BView* View(); - - virtual BSize BaseMinSize(); - virtual BSize BaseMaxSize(); - virtual BSize BasePreferredSize(); - virtual BAlignment BaseAlignment(); - - BRect FrameInParent() const; - - virtual status_t Archive(BMessage* into, bool deep = true) const; - static BArchivable* Instantiate(BMessage* from); - -private: - BSpinner* fParent; - BRect fFrame; -}; - - -struct BSpinner::LayoutData { - LayoutData(float width, float height) - : - label_layout_item(NULL), - text_view_layout_item(NULL), - label_width(0), - label_height(0), - text_view_width(0), - text_view_height(0), - previous_width(width), - previous_height(height), - valid(false) - { - } - - LabelLayoutItem* label_layout_item; - TextViewLayoutItem* text_view_layout_item; - - font_height font_info; - - float label_width; - float label_height; - float text_view_width; - float text_view_height; - - float previous_width; - float previous_height; - - BSize min; - BAlignment alignment; - - bool valid; -}; - - -// #pragma mark - SpinnerArrow - - -SpinnerArrow::SpinnerArrow(BRect frame, const char* name, - spinner_direction direction) - : - BView(frame, name, B_FOLLOW_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW), - fSpinnerDirection(direction), - fParent(NULL), - fIsEnabled(true), - fIsMouseDown(false), - fIsMouseOver(false), - fRepeatDelay(100000) -{ - rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); - SetViewColor(bgColor); - SetLowColor(bgColor); -} - - -SpinnerArrow::~SpinnerArrow() -{ -} - - -void -SpinnerArrow::AttachedToWindow() -{ - fParent = static_cast(Parent()); - - BView::AttachedToWindow(); -} - - -void -SpinnerArrow::DetachedFromWindow() -{ - fParent = NULL; - - BView::DetachedFromWindow(); -} - - -void -SpinnerArrow::Draw(BRect updateRect) -{ - BRect rect(Bounds()); - if (!rect.IsValid() || !rect.Intersects(updateRect)) - return; - - BView::Draw(updateRect); - - float fgTint; - if (!fIsEnabled) - fgTint = B_DARKEN_1_TINT; - else if (fIsMouseDown) - fgTint = B_DARKEN_MAX_TINT; - else - fgTint = B_DARKEN_3_TINT; - - float bgTint; - if (fIsEnabled && fIsMouseOver) - bgTint = B_DARKEN_1_TINT; - else - bgTint = B_NO_TINT; - - rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); - if (bgColor.red + bgColor.green + bgColor.blue <= 128 * 3) { - // if dark background make the tint lighter - fgTint = 2.0f - fgTint; - bgTint = 2.0f - bgTint; - } - - uint32 borders = be_control_look->B_TOP_BORDER - | be_control_look->B_BOTTOM_BORDER; - - if (fSpinnerDirection == SPINNER_INCREMENT) - borders |= be_control_look->B_RIGHT_BORDER; - else - borders |= be_control_look->B_LEFT_BORDER; - - // draw the button - be_control_look->DrawButtonFrame(this, rect, updateRect, - tint_color(bgColor, fgTint), bgColor, 0, borders); - be_control_look->DrawButtonBackground(this, rect, updateRect, - tint_color(bgColor, bgTint), 0, borders); - - BFont font; - fParent->GetFont(&font); - float inset = floorf(font.Size() / 4); - rect.InsetBy(inset, inset); - - if (rect.IntegerWidth() % 2 != 0) - rect.right -= 1; - - if (rect.IntegerHeight() % 2 != 0) - rect.bottom -= 1; - - SetHighColor(tint_color(bgColor, fgTint)); - - // draw the +/- - float halfHeight = floorf(rect.Height() / 2); - StrokeLine(BPoint(rect.left, rect.top + halfHeight), - BPoint(rect.right, rect.top + halfHeight)); - if (fSpinnerDirection == SPINNER_INCREMENT) { - float halfWidth = floorf(rect.Width() / 2); - StrokeLine(BPoint(rect.left + halfWidth, rect.top), - BPoint(rect.left + halfWidth, rect.bottom)); - } -} - - -void -SpinnerArrow::MouseDown(BPoint where) -{ - if (fIsEnabled) { - fIsMouseDown = true; - Invalidate(); - fRepeatDelay = 100000; - MouseDownThread::TrackMouse(this, - &SpinnerArrow::_DoneTracking, &SpinnerArrow::_Track); - } - - BView::MouseDown(where); -} - - -void -SpinnerArrow::MouseMoved(BPoint where, uint32 transit, - const BMessage* message) -{ - switch (transit) { - case B_ENTERED_VIEW: - case B_INSIDE_VIEW: - { - BPoint where; - uint32 buttons; - GetMouse(&where, &buttons); - fIsMouseOver = Bounds().Contains(where) && buttons == 0; - if (!fIsMouseDown) - Invalidate(); - - break; - } - - case B_EXITED_VIEW: - case B_OUTSIDE_VIEW: - fIsMouseOver = false; - MouseUp(Bounds().LeftTop()); - break; - } - - BView::MouseMoved(where, transit, message); -} - - -void -SpinnerArrow::MouseUp(BPoint where) -{ - fIsMouseDown = false; - Invalidate(); - - BView::MouseUp(where); -} - - -// #pragma mark - SpinnerArrow private methods - - -void -SpinnerArrow::_DoneTracking(BPoint where) -{ - if (fIsMouseDown || !Bounds().Contains(where)) - fIsMouseDown = false; -} - - -void -SpinnerArrow::_Track(BPoint where, uint32) -{ - if (fParent == NULL || !Bounds().Contains(where)) { - fIsMouseDown = false; - return; - } - fIsMouseDown = true; - - fSpinnerDirection == SPINNER_INCREMENT - ? fParent->Increment() - : fParent->Decrement(); - - snooze(fRepeatDelay); - fRepeatDelay = 10000; -} - - -// #pragma mark - SpinnerTextView - - -SpinnerTextView::SpinnerTextView(BRect rect, BRect textRect) - : - BTextView(rect, "textview", textRect, B_FOLLOW_ALL, - B_WILL_DRAW | B_NAVIGABLE), - fParent(NULL) -{ - rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); - SetViewColor(bgColor); - SetLowColor(bgColor); - - SetAlignment(B_ALIGN_RIGHT); - for (uint32 c = 0; c <= 42; c++) - DisallowChar(c); - - DisallowChar('/'); - for (uint32 c = 58; c <= 127; c++) - DisallowChar(c); -} - - -SpinnerTextView::~SpinnerTextView() -{ -} - - -void -SpinnerTextView::AttachedToWindow() -{ - fParent = static_cast(Parent()); - - BTextView::AttachedToWindow(); -} - - -void -SpinnerTextView::DetachedFromWindow() -{ - fParent = NULL; - - BTextView::DetachedFromWindow(); -} - - -void -SpinnerTextView::KeyDown(const char* bytes, int32 numBytes) -{ - if (fParent == NULL) { - BTextView::KeyDown(bytes, numBytes); - return; - } - - switch (bytes[0]) { - case B_ENTER: - case B_SPACE: - fParent->SetValueFromText(); - break; - - case B_TAB: - fParent->KeyDown(bytes, numBytes); - break; - - case B_UP_ARROW: - case B_PAGE_UP: - fParent->Increment(); - break; - - case B_DOWN_ARROW: - case B_PAGE_DOWN: - fParent->Decrement(); - break; - - default: - BTextView::KeyDown(bytes, numBytes); - } -} - - -void -SpinnerTextView::MakeFocus(bool focus) -{ - BTextView::MakeFocus(focus); - - if (fParent == NULL) - return; - - if (focus) - SelectAll(); - else - fParent->SetValueFromText(); - - fParent->_DrawTextView(fParent->Bounds()); -} - - -// #pragma mark - BSpinner::LabelLayoutItem - - -BSpinner::LabelLayoutItem::LabelLayoutItem(BSpinner* parent) - : - fParent(parent), - fFrame() -{ -} - - -BSpinner::LabelLayoutItem::LabelLayoutItem(BMessage* from) - : - BAbstractLayoutItem(from), - fParent(NULL), - fFrame() -{ - from->FindRect(kFrameField, &fFrame); -} - - -bool -BSpinner::LabelLayoutItem::IsVisible() -{ - return !fParent->IsHidden(fParent); -} - - -void -BSpinner::LabelLayoutItem::SetVisible(bool visible) -{ -} - - -BRect -BSpinner::LabelLayoutItem::Frame() -{ - return fFrame; -} - - -void -BSpinner::LabelLayoutItem::SetFrame(BRect frame) -{ - fFrame = frame; - fParent->_UpdateFrame(); -} - - -void -BSpinner::LabelLayoutItem::SetParent(BSpinner* parent) -{ - fParent = parent; -} - - -BView* -BSpinner::LabelLayoutItem::View() -{ - return fParent; -} - - -BSize -BSpinner::LabelLayoutItem::BaseMinSize() -{ - fParent->_ValidateLayoutData(); - - if (fParent->Label() == NULL) - return BSize(-1.0f, -1.0f); - - return BSize(fParent->fLayoutData->label_width - + be_control_look->DefaultLabelSpacing(), - fParent->fLayoutData->label_height); -} - - -BSize -BSpinner::LabelLayoutItem::BaseMaxSize() -{ - return BaseMinSize(); -} - - -BSize -BSpinner::LabelLayoutItem::BasePreferredSize() -{ - return BaseMinSize(); -} - - -BAlignment -BSpinner::LabelLayoutItem::BaseAlignment() -{ - return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); -} - - -BRect -BSpinner::LabelLayoutItem::FrameInParent() const -{ - return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); -} - - -status_t -BSpinner::LabelLayoutItem::Archive(BMessage* into, bool deep) const -{ - BArchiver archiver(into); - status_t result = BAbstractLayoutItem::Archive(into, deep); - - if (result == B_OK) - result = into->AddRect(kFrameField, fFrame); - - return archiver.Finish(result); -} - - -BArchivable* -BSpinner::LabelLayoutItem::Instantiate(BMessage* from) -{ - if (validate_instantiation(from, "BSpinner::LabelLayoutItem")) - return new LabelLayoutItem(from); - - return NULL; -} - - -// #pragma mark - BSpinner::TextViewLayoutItem - - -BSpinner::TextViewLayoutItem::TextViewLayoutItem(BSpinner* parent) - : - fParent(parent), - fFrame() -{ - SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); -} - - -BSpinner::TextViewLayoutItem::TextViewLayoutItem(BMessage* from) - : - BAbstractLayoutItem(from), - fParent(NULL), - fFrame() -{ - from->FindRect(kFrameField, &fFrame); -} - - -bool -BSpinner::TextViewLayoutItem::IsVisible() -{ - return !fParent->IsHidden(fParent); -} - - -void -BSpinner::TextViewLayoutItem::SetVisible(bool visible) -{ - // not allowed -} - - -BRect -BSpinner::TextViewLayoutItem::Frame() -{ - return fFrame; -} - - -void -BSpinner::TextViewLayoutItem::SetFrame(BRect frame) -{ - fFrame = frame; - fParent->_UpdateFrame(); -} - - -void -BSpinner::TextViewLayoutItem::SetParent(BSpinner* parent) -{ - fParent = parent; -} - - -BView* -BSpinner::TextViewLayoutItem::View() -{ - return fParent; -} - - -BSize -BSpinner::TextViewLayoutItem::BaseMinSize() -{ - fParent->_ValidateLayoutData(); - - BSize size(fParent->fLayoutData->text_view_width, - fParent->fLayoutData->text_view_height); - return size; -} - - -BSize -BSpinner::TextViewLayoutItem::BaseMaxSize() -{ - return BaseMinSize(); -} - - -BSize -BSpinner::TextViewLayoutItem::BasePreferredSize() -{ - return BaseMinSize(); -} - - -BAlignment -BSpinner::TextViewLayoutItem::BaseAlignment() -{ - return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); -} - - -BRect -BSpinner::TextViewLayoutItem::FrameInParent() const -{ - return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); -} - - -status_t -BSpinner::TextViewLayoutItem::Archive(BMessage* into, bool deep) const -{ - BArchiver archiver(into); - status_t result = BAbstractLayoutItem::Archive(into, deep); - - if (result == B_OK) - result = into->AddRect(kFrameField, fFrame); - - return archiver.Finish(result); -} - - -BArchivable* -BSpinner::TextViewLayoutItem::Instantiate(BMessage* from) -{ - if (validate_instantiation(from, "BSpinner::TextViewLayoutItem")) - return new LabelLayoutItem(from); - - return NULL; -} - - // #pragma mark - BSpinner BSpinner::BSpinner(BRect frame, const char* name, const char* label, BMessage* message, uint32 resizingMode, uint32 flags) : - BView(frame, name, resizingMode, flags | B_WILL_DRAW | B_FRAME_EVENTS), - fLabel(label) + BAbstractSpinner(frame, name, label, message, resizingMode, flags) { - SetMessage(message); _InitObject(); } -BSpinner::BSpinner(const char* name, const char* label, BMessage* message, - uint32 flags) +BSpinner::BSpinner(const char* name, const char* label, + BMessage* message, uint32 flags) : - BView(name, flags | B_WILL_DRAW | B_FRAME_EVENTS), - fLabel(label) + BAbstractSpinner(name, label, message, flags) { - SetMessage(message); _InitObject(); } BSpinner::BSpinner(BMessage* data) : - BView(data) + BAbstractSpinner(data) { _InitObject(); - if (data->FindInt32("_align") != B_OK) - fAlignment = B_ALIGN_LEFT; + if (data->FindInt32("_max", &fMaxValue) != B_OK) + fMinValue = INT32_MAX; - if (data->FindInt32("_divider") != B_OK) - fDivider = 0.0f; + if (data->FindInt32("_min", &fMinValue) != B_OK) + fMinValue = INT32_MIN; - if (data->FindBool("_enabled") != B_OK) - fIsEnabled = true; - - if (data->FindString("_label", &fLabel) != B_OK) - fLabel = NULL; - - BMessage* message = NULL; - if (data->FindMessage("_message", message) == B_OK) - SetMessage(message); - - if (data->FindDouble("_max", &fMaxValue) != B_OK) - fMinValue = 100.0; - - if (data->FindDouble("_min", &fMinValue) != B_OK) - fMinValue = 0.0; - - if (data->FindUInt32("_precision", &fPrecision) != B_OK) - fPrecision = 2; - - if (data->FindDouble("_step", &fStep) != B_OK) - fStep = 1.0; - - if (data->FindDouble("_value", &fValue) != B_OK) - fValue = 0.0; + if (data->FindInt32("_val", &fValue) != B_OK) + fValue = 0; } BSpinner::~BSpinner() { - delete fLayoutData; - fLayoutData = NULL; } @@ -1006,38 +129,17 @@ BSpinner::Instantiate(BMessage* data) status_t BSpinner::Archive(BMessage* data, bool deep) const { - status_t status = BView::Archive(data, deep); + status_t status = BAbstractSpinner::Archive(data, deep); data->AddString("class", "Spinner"); if (status == B_OK) - status = data->AddInt32("_align", fAlignment); + status = data->AddInt32("_max", fMaxValue); if (status == B_OK) - status = data->AddFloat("_divider", fDivider); + status = data->AddInt32("_min", fMinValue); if (status == B_OK) - status = data->AddBool("_enabled", fIsEnabled); - - if (status == B_OK && fLabel != NULL) - status = data->AddString("_label", fLabel); - - if (status == B_OK && Message() != NULL) - status = data->AddMessage("_message", Message()); - - if (status == B_OK) - status = data->AddDouble("_max", fMaxValue); - - if (status == B_OK) - status = data->AddDouble("_min", fMinValue); - - if (status == B_OK) - status = data->AddUInt32("_precision", fPrecision); - - if (status == B_OK) - status = data->AddDouble("_step", fStep); - - if (status == B_OK) - status = data->AddDouble("_value", fValue); + status = data->AddInt32("_val", fValue); return status; } @@ -1046,7 +148,7 @@ BSpinner::Archive(BMessage* data, bool deep) const status_t BSpinner::GetSupportedSuites(BMessage* message) { - message->AddString("suites", "suite/vnd.Haiku-spinner"); + message->AddString("suites", "suite/vnd.Haiku-intenger-spinner"); BPropertyInfo prop_info(sProperties); message->AddFlat("messages", &prop_info); @@ -1055,189 +157,26 @@ BSpinner::GetSupportedSuites(BMessage* message) } -BHandler* -BSpinner::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier, - int32 form, const char* property) -{ - return BView::ResolveSpecifier(message, index, specifier, form, - property); -} - - void BSpinner::AttachedToWindow() { - if (!Messenger().IsValid()) - SetTarget(Window()); - SetValue(fValue); - // sets the text and enables or disables the arrows - _UpdateTextViewColors(IsEnabled()); - fTextView->MakeEditable(IsEnabled()); - BView::AttachedToWindow(); -} - - -void -BSpinner::Draw(BRect updateRect) -{ - _DrawLabel(updateRect); - _DrawTextView(updateRect); - fIncrement->Invalidate(); - fDecrement->Invalidate(); -} - - -void -BSpinner::FrameResized(float width, float height) -{ - BView::FrameResized(width, height); - - // TODO: this causes flickering still... - - // changes in width - - BRect bounds = Bounds(); - - if (bounds.Width() > fLayoutData->previous_width) { - // invalidate the region between the old and the new right border - BRect rect = bounds; - rect.left += fLayoutData->previous_width - kFrameMargin; - rect.right--; - Invalidate(rect); - } else if (bounds.Width() < fLayoutData->previous_width) { - // invalidate the region of the new right border - BRect rect = bounds; - rect.left = rect.right - kFrameMargin; - Invalidate(rect); - } - - // changes in height - - if (bounds.Height() > fLayoutData->previous_height) { - // invalidate the region between the old and the new bottom border - BRect rect = bounds; - rect.top += fLayoutData->previous_height - kFrameMargin; - rect.bottom--; - Invalidate(rect); - // invalidate label area - rect = bounds; - rect.right = fDivider; - Invalidate(rect); - } else if (bounds.Height() < fLayoutData->previous_height) { - // invalidate the region of the new bottom border - BRect rect = bounds; - rect.top = rect.bottom - kFrameMargin; - Invalidate(rect); - // invalidate label area - rect = bounds; - rect.right = fDivider; - Invalidate(rect); - } - - fLayoutData->previous_width = bounds.Width(); - fLayoutData->previous_height = bounds.Height(); -} - - -void -BSpinner::ValueChanged() -{ - // hook method - does nothing + BAbstractSpinner::AttachedToWindow(); } void BSpinner::Decrement() { - SetValue(Value() - Step()); + SetValue(Value() - 1); } void BSpinner::Increment() { - SetValue(Value() + Step()); -} - - -void -BSpinner::MakeFocus(bool focus) -{ - fTextView->MakeFocus(focus); -} - - -void -BSpinner::ResizeToPreferred() -{ - BView::ResizeToPreferred(); - - const char* label = Label(); - if (label != NULL) { - fDivider = ceilf(StringWidth(label)) - + be_control_look->DefaultLabelSpacing(); - } else - fDivider = 0.0f; - - _LayoutTextView(); -} - - -void -BSpinner::SetFlags(uint32 flags) -{ - // If the textview is navigable, set it to not navigable if needed, - // else if it is not navigable, set it to navigable if needed - if (fTextView->Flags() & B_NAVIGABLE) { - if (!(flags & B_NAVIGABLE)) - fTextView->SetFlags(fTextView->Flags() & ~B_NAVIGABLE); - } else { - if (flags & B_NAVIGABLE) - fTextView->SetFlags(fTextView->Flags() | B_NAVIGABLE); - } - - // Don't make this one navigable - flags &= ~B_NAVIGABLE; - - BView::SetFlags(flags); -} - - -void -BSpinner::WindowActivated(bool active) -{ - _DrawTextView(fTextView->Frame()); -} - - -void -BSpinner::SetAlignment(alignment align) -{ - fAlignment = align; -} - - -void -BSpinner::SetDivider(float position) -{ - position = roundf(position); - - float delta = fDivider - position; - if (delta == 0.0f) - return; - - fDivider = position; - - if ((Flags() & B_SUPPORTS_LAYOUT) != 0) { - // We should never get here, since layout support means, we also - // layout the divider, and don't use this method at all. - Relayout(); - } else { - _LayoutTextView(); - Invalidate(); - } + SetValue(Value() + 1); } @@ -1247,40 +186,15 @@ BSpinner::SetEnabled(bool enable) if (IsEnabled() == enable) return; - fIsEnabled = enable; - fTextView->MakeEditable(enable); - if (enable) - fTextView->SetFlags(fTextView->Flags() | B_NAVIGABLE); - else - fTextView->SetFlags(fTextView->Flags() & ~B_NAVIGABLE); + SetIncrementEnabled(enable && Value() < fMaxValue); + SetDecrementEnabled(enable && Value() > fMinValue); - _UpdateTextViewColors(enable); - fTextView->Invalidate(); - SetIncrementEnabled(enable && fValue < fMaxValue); - SetDecrementEnabled(enable && fValue > fMinValue); - - _LayoutTextView(); - Invalidate(); - if (Window() != NULL) - Window()->UpdateIfNeeded(); + BAbstractSpinner::SetEnabled(enable); } void -BSpinner::SetLabel(const char* label) -{ - fLabel = label; - if (Window() != NULL) { - Invalidate(); - Window()->UpdateIfNeeded(); - } - - InvalidateLayout(); -} - - -void -BSpinner::SetMaxValue(double max) +BSpinner::SetMaxValue(int32 max) { fMaxValue = max; if (fValue > fMaxValue) @@ -1289,7 +203,7 @@ BSpinner::SetMaxValue(double max) void -BSpinner::SetMinValue(double min) +BSpinner::SetMinValue(int32 min) { fMinValue = min; if (fValue < fMinValue) @@ -1298,7 +212,7 @@ BSpinner::SetMinValue(double min) void -BSpinner::Range(double* min, double* max) +BSpinner::Range(int32* min, int32* max) { *min = fMinValue; *max = fMaxValue; @@ -1306,7 +220,7 @@ BSpinner::Range(double* min, double* max) void -BSpinner::SetRange(double min, double max) +BSpinner::SetRange(int32 min, int32 max) { SetMinValue(min); SetMaxValue(max); @@ -1314,7 +228,7 @@ BSpinner::SetRange(double min, double max) void -BSpinner::SetValue(double value) +BSpinner::SetValue(int32 value) { // clip to range if (value < fMinValue) @@ -1323,13 +237,9 @@ BSpinner::SetValue(double value) value = fMaxValue; // update the text view - char* format; - asprintf(&format, "%%.%" B_PRId32 "f", fPrecision); - char* valueString; - asprintf(&valueString, format, value); - fTextView->SetText(valueString); - free(format); - free(valueString); + BString valueString; + valueString << value; + TextView()->SetText(valueString.String()); // update the up and down arrows SetIncrementEnabled(IsEnabled() && value < fMaxValue); @@ -1349,500 +259,31 @@ BSpinner::SetValue(double value) void BSpinner::SetValueFromText() { - SetValue(roundTo(atof(TextView()->Text()), Precision())); -} - - - -bool -BSpinner::IsDecrementEnabled() const -{ - return fDecrement->IsEnabled(); -} - - -void -BSpinner::SetDecrementEnabled(bool enable) -{ - if (IsDecrementEnabled() == enable) - return; - - fDecrement->SetEnabled(enable); - fDecrement->Invalidate(); -} - - -bool -BSpinner::IsIncrementEnabled() const -{ - return fIncrement->IsEnabled(); -} - - -void -BSpinner::SetIncrementEnabled(bool enable) -{ - if (IsIncrementEnabled() == enable) - return; - - fIncrement->SetEnabled(enable); - fIncrement->Invalidate(); -} - - -BSize -BSpinner::MinSize() -{ - _ValidateLayoutData(); - return BLayoutUtils::ComposeSize(ExplicitMinSize(), fLayoutData->min); -} - - -BSize -BSpinner::MaxSize() -{ - _ValidateLayoutData(); - - BSize max = fLayoutData->min; - max.width = B_SIZE_UNLIMITED; - - return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max); -} - - -BSize -BSpinner::PreferredSize() -{ - _ValidateLayoutData(); - return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), - fLayoutData->min); -} - - -BAlignment -BSpinner::LayoutAlignment() -{ - _ValidateLayoutData(); - return BLayoutUtils::ComposeAlignment(ExplicitAlignment(), - BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER)); -} - - -BLayoutItem* -BSpinner::CreateLabelLayoutItem() -{ - if (fLayoutData->label_layout_item == NULL) - fLayoutData->label_layout_item = new LabelLayoutItem(this); - - return fLayoutData->label_layout_item; -} - - -BLayoutItem* -BSpinner::CreateTextViewLayoutItem() -{ - if (fLayoutData->text_view_layout_item == NULL) - fLayoutData->text_view_layout_item = new TextViewLayoutItem(this); - - return fLayoutData->text_view_layout_item; -} - - -BTextView* -BSpinner::TextView() const -{ - return dynamic_cast(fTextView); -} - - -// #pragma mark - BSpinner protected methods - - -status_t -BSpinner::AllArchived(BMessage* into) const -{ - status_t result; - if ((result = BView::AllArchived(into)) != B_OK) - return result; - - BArchiver archiver(into); - - BArchivable* textViewItem = fLayoutData->text_view_layout_item; - if (archiver.IsArchived(textViewItem)) - result = archiver.AddArchivable(kTextViewItemField, textViewItem); - - if (result != B_OK) - return result; - - BArchivable* labelBarItem = fLayoutData->label_layout_item; - if (archiver.IsArchived(labelBarItem)) - result = archiver.AddArchivable(kLabelItemField, labelBarItem); - - return result; -} - - -status_t -BSpinner::AllUnarchived(const BMessage* from) -{ - BUnarchiver unarchiver(from); - - status_t result = B_OK; - if ((result = BView::AllUnarchived(from)) != B_OK) - return result; - - if (unarchiver.IsInstantiated(kTextViewItemField)) { - TextViewLayoutItem*& textViewItem - = fLayoutData->text_view_layout_item; - result = unarchiver.FindObject(kTextViewItemField, - BUnarchiver::B_DONT_ASSUME_OWNERSHIP, textViewItem); - - if (result == B_OK) - textViewItem->SetParent(this); - else - return result; - } - - if (unarchiver.IsInstantiated(kLabelItemField)) { - LabelLayoutItem*& labelItem = fLayoutData->label_layout_item; - result = unarchiver.FindObject(kLabelItemField, - BUnarchiver::B_DONT_ASSUME_OWNERSHIP, labelItem); - - if (result == B_OK) - labelItem->SetParent(this); - } - - return result; -} - - -void -BSpinner::DoLayout() -{ - if ((Flags() & B_SUPPORTS_LAYOUT) == 0) - return; - - if (GetLayout()) { - BView::DoLayout(); - return; - } - - _ValidateLayoutData(); - - BSize size(Bounds().Size()); - if (size.width < fLayoutData->min.width) - size.width = fLayoutData->min.width; - - if (size.height < fLayoutData->min.height) - size.height = fLayoutData->min.height; - - float divider = 0; - if (fLayoutData->label_layout_item != NULL - && fLayoutData->text_view_layout_item != NULL - && fLayoutData->label_layout_item->Frame().IsValid() - && fLayoutData->text_view_layout_item->Frame().IsValid()) { - divider = fLayoutData->text_view_layout_item->Frame().left - - fLayoutData->label_layout_item->Frame().left; - } else if (fLayoutData->label_width > 0) { - divider = fLayoutData->label_width - + be_control_look->DefaultLabelSpacing(); - } - fDivider = divider; - - BRect dirty(fTextView->Frame()); - _LayoutTextView(); - - // invalidate dirty region - dirty = dirty | fTextView->Frame(); - dirty = dirty | fIncrement->Frame(); - dirty = dirty | fDecrement->Frame(); - - Invalidate(dirty); -} - - -void -BSpinner::LayoutInvalidated(bool descendants) -{ - if (fLayoutData != NULL) - fLayoutData->valid = false; + SetValue(atol(TextView()->Text())); } // #pragma mark - BSpinner private methods -void -BSpinner::_DrawLabel(BRect updateRect) -{ - BRect rect(Bounds()); - rect.right = fDivider; - if (!rect.IsValid() || !rect.Intersects(updateRect)) - return; - - _ValidateLayoutData(); - - const char* label = Label(); - if (label == NULL) - return; - - // horizontal position - float x; - switch (fAlignment) { - case B_ALIGN_RIGHT: - x = fDivider - fLayoutData->label_width - 3.0f; - break; - - case B_ALIGN_CENTER: - x = fDivider - roundf(fLayoutData->label_width / 2.0f); - break; - - default: - x = 0.0f; - break; - } - - // vertical position - font_height& fontHeight = fLayoutData->font_info; - float y = rect.top - + roundf((rect.Height() + 1.0f - fontHeight.ascent - - fontHeight.descent) / 2.0f) - + fontHeight.ascent + kFrameMargin * 2; - - uint32 flags = 0; - if (!IsEnabled()) - flags |= BControlLook::B_DISABLED; - - be_control_look->DrawLabel(this, label, LowColor(), flags, BPoint(x, y)); -} - - -void -BSpinner::_DrawTextView(BRect updateRect) -{ - BRect rect = fTextView->Frame(); - rect.InsetBy(-kFrameMargin, -kFrameMargin); - if (!rect.IsValid() || !rect.Intersects(updateRect)) - return; - - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - uint32 flags = 0; - if (!IsEnabled()) - flags |= BControlLook::B_DISABLED; - - if (fTextView->IsFocus() && Window()->IsActive()) - flags |= BControlLook::B_FOCUSED; - - be_control_look->DrawTextControlBorder(this, rect, updateRect, base, - flags); -} - - void BSpinner::_InitObject() { - rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); - SetViewColor(bgColor); - SetLowColor(bgColor); + fMaxValue = INT32_MIN; + fMinValue = INT32_MAX; + fValue = 0; - fAlignment = B_ALIGN_LEFT; - if (Label() != NULL) { - fDivider = StringWidth(Label()) - + be_control_look->DefaultLabelSpacing(); - } else - fDivider = 0.0f; + TextView()->SetAlignment(B_ALIGN_RIGHT); + for (uint32 c = 0; c <= 42; c++) + TextView()->DisallowChar(c); - fIsEnabled = true; + TextView()->DisallowChar(','); - fMaxValue = 100.0; - fMinValue = 0.0; - fPrecision = 2; - fStep = 1.0; - fValue = 0.0; + for (uint32 c = 46; c <= 47; c++) + TextView()->DisallowChar(c); - BRect rect(Bounds()); - fLayoutData = new LayoutData(rect.Width(), rect.Height()); - - rect.left = fDivider; - rect.InsetBy(kFrameMargin, kFrameMargin); - rect.right -= rect.Height() * 2 + kFrameMargin * 2 + 1.0f; - BRect textRect(rect.OffsetToCopy(B_ORIGIN)); - - fTextView = new SpinnerTextView(rect, textRect); - AddChild(fTextView); - - rect.InsetBy(0.0f, -kFrameMargin); - - rect.left = rect.right + kFrameMargin * 2; - rect.right = rect.left + rect.Height() - kFrameMargin * 2; - - fDecrement = new SpinnerArrow(rect, "decrement", SPINNER_DECREMENT); - AddChild(fDecrement); - - rect.left = rect.right + 1.0f; - rect.right = rect.left + rect.Height() - kFrameMargin * 2; - - fIncrement = new SpinnerArrow(rect, "increment", SPINNER_INCREMENT); - AddChild(fIncrement); - - uint32 navigableFlags = Flags() & B_NAVIGABLE; - if (navigableFlags != 0) - BView::SetFlags(Flags() & ~B_NAVIGABLE); -} - - -void -BSpinner::_LayoutTextView() -{ - BRect rect; - if (fLayoutData->text_view_layout_item != NULL) { - rect = fLayoutData->text_view_layout_item->FrameInParent(); - } else { - rect = Bounds(); - rect.left = fDivider; - } - rect.InsetBy(kFrameMargin, kFrameMargin); - rect.right -= rect.Height() * 2 + kFrameMargin * 2 + 1.0f; - - fTextView->MoveTo(rect.left, rect.top); - fTextView->ResizeTo(rect.Width(), rect.Height()); - fTextView->SetTextRect(rect.OffsetToCopy(B_ORIGIN)); - - rect.InsetBy(0.0f, -kFrameMargin); - - rect.left = rect.right + kFrameMargin * 2; - rect.right = rect.left + rect.Height() - kFrameMargin * 2; - - fDecrement->ResizeTo(rect.Width(), rect.Height()); - fDecrement->MoveTo(rect.LeftTop()); - - rect.left = rect.right + 1.0f; - rect.right = rect.left + rect.Height() - kFrameMargin * 2; - - fIncrement->ResizeTo(rect.Width(), rect.Height()); - fIncrement->MoveTo(rect.LeftTop()); -} - - -void -BSpinner::_UpdateFrame() -{ - if (fLayoutData->label_layout_item == NULL - || fLayoutData->text_view_layout_item == NULL) { - return; - } - - BRect labelFrame = fLayoutData->label_layout_item->Frame(); - BRect textViewFrame = fLayoutData->text_view_layout_item->Frame(); - - if (!labelFrame.IsValid() || !textViewFrame.IsValid()) - return; - - // update divider - fDivider = textViewFrame.left - labelFrame.left; - - BRect frame = textViewFrame | labelFrame; - MoveTo(frame.left, frame.top); - BSize oldSize = Bounds().Size(); - ResizeTo(frame.Width(), frame.Height()); - BSize newSize = Bounds().Size(); - - // If the size changes, ResizeTo() will trigger a relayout, otherwise - // we need to do that explicitly. - if (newSize != oldSize) - Relayout(); -} - - -void -BSpinner::_UpdateTextViewColors(bool enable) -{ - rgb_color textColor; - rgb_color bgColor; - BFont font; - - fTextView->GetFontAndColor(0, &font); - - if (enable) - textColor = ui_color(B_DOCUMENT_TEXT_COLOR); - else { - textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), - B_DISABLED_LABEL_TINT); - } - - fTextView->SetFontAndColor(&font, B_FONT_ALL, &textColor); - - if (enable) - bgColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR); - else { - bgColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), - B_LIGHTEN_2_TINT); - } - - fTextView->SetViewColor(bgColor); - fTextView->SetLowColor(bgColor); -} - - -void -BSpinner::_ValidateLayoutData() -{ - if (fLayoutData->valid) - return; - - font_height fontHeight = fLayoutData->font_info; - GetFontHeight(&fontHeight); - - if (Label() != NULL) { - fLayoutData->label_width = StringWidth(Label()); - fLayoutData->label_height = ceilf(fontHeight.ascent - + fontHeight.descent + fontHeight.leading); - } else { - fLayoutData->label_width = 0; - fLayoutData->label_height = 0; - } - - float divider = 0; - if (fLayoutData->label_width > 0) { - divider = ceilf(fLayoutData->label_width - + be_control_look->DefaultLabelSpacing()); - } - - if ((Flags() & B_SUPPORTS_LAYOUT) == 0) - divider = std::max(divider, fDivider); - - char* format; - asprintf(&format, "%%.%" B_PRId32 "f", fPrecision); - char* maxValue; - asprintf(&maxValue, format, fMaxValue); - char* minValue; - asprintf(&minValue, format, fMinValue); - float longestValue = ceilf(std::max(fTextView->StringWidth(maxValue), - fTextView->StringWidth(minValue))); - free(format); - free(maxValue); - free(minValue); - - float textWidth = ceilf(std::max(longestValue, - fTextView->StringWidth("99999"))); - - float textViewHeight = fTextView->LineHeight(0) + kFrameMargin * 2; - float textViewWidth = textWidth + textViewHeight * 2; - - fLayoutData->text_view_width = textViewWidth; - fLayoutData->text_view_height = textViewHeight; - - BSize min(textViewWidth, textViewHeight); - if (divider > 0.0f) - min.width += divider; - - if (fLayoutData->label_height > min.height) - min.height = fLayoutData->label_height; - - fLayoutData->min = min; - fLayoutData->valid = true; - - ResetLayoutInvalidation(); + for (uint32 c = 58; c <= 127; c++) + TextView()->DisallowChar(c); } diff --git a/src/preferences/screen/ScreenWindow.cpp b/src/preferences/screen/ScreenWindow.cpp index 2037b9491f..3ccc5a3890 100644 --- a/src/preferences/screen/ScreenWindow.cpp +++ b/src/preferences/screen/ScreenWindow.cpp @@ -238,13 +238,11 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings) fColumnsControl = new BSpinner("columns", B_TRANSLATE("Columns:"), new BMessage(kMsgWorkspaceColumnsChanged)); fColumnsControl->SetAlignment(B_ALIGN_RIGHT); - fColumnsControl->SetPrecision(0); fColumnsControl->SetRange(1, 32); fRowsControl = new BSpinner("rows", B_TRANSLATE("Rows:"), new BMessage(kMsgWorkspaceRowsChanged)); fRowsControl->SetAlignment(B_ALIGN_RIGHT); - fRowsControl->SetPrecision(0); fRowsControl->SetRange(1, 32); uint32 columns; From 25af167e8f1d33b0931741434a814a59765505eb Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sat, 20 Jun 2015 16:14:53 -0700 Subject: [PATCH 062/125] Spinner: Tweak the spinner button colors * Tint the button text 1.777f which yields #303030 for the text color which produces a nice dark grey but-not-quite-black color. In testing black text is too dark and B_DARKEN_4_TINT (1.555f) yields #606060 which is too light. #303030 is a compromise between the two. * The button text gets darkened to black on mouse down and the button background gets darkened to B_DARKEN_1_TINT on hover as before, but the frame color is no longer affected --- the button frame tinted by B_DARKEN_1_TINT always (yielding standard Haiku button frame color). --- src/kits/interface/AbstractSpinner.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/kits/interface/AbstractSpinner.cpp b/src/kits/interface/AbstractSpinner.cpp index 1a1c31bb85..576697a835 100644 --- a/src/kits/interface/AbstractSpinner.cpp +++ b/src/kits/interface/AbstractSpinner.cpp @@ -349,13 +349,15 @@ SpinnerButton::Draw(BRect updateRect) BView::Draw(updateRect); + float frameTint = B_DARKEN_1_TINT; + float fgTint; if (!fIsEnabled) fgTint = B_DARKEN_1_TINT; else if (fIsMouseDown) fgTint = B_DARKEN_MAX_TINT; else - fgTint = B_DARKEN_3_TINT; + fgTint = 1.777f; // 216 --> 48.2 (48) float bgTint; if (fIsEnabled && fIsMouseOver) @@ -366,6 +368,7 @@ SpinnerButton::Draw(BRect updateRect) rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); if (bgColor.red + bgColor.green + bgColor.blue <= 128 * 3) { // if dark background make the tint lighter + frameTint = 2.0f - frameTint; fgTint = 2.0f - fgTint; bgTint = 2.0f - bgTint; } @@ -380,7 +383,7 @@ SpinnerButton::Draw(BRect updateRect) // draw the button be_control_look->DrawButtonFrame(this, rect, updateRect, - tint_color(bgColor, fgTint), bgColor, 0, borders); + tint_color(bgColor, frameTint), bgColor, 0, borders); be_control_look->DrawButtonBackground(this, rect, updateRect, tint_color(bgColor, bgTint), 0, borders); From 1deb22eb4bc0b7e58fa9feccc94fab9eb63d52ab Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 23 Aug 2015 09:19:35 +0200 Subject: [PATCH 063/125] PowerStatus: style fixes. --- src/apps/powerstatus/PowerStatusView.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/apps/powerstatus/PowerStatusView.cpp b/src/apps/powerstatus/PowerStatusView.cpp index ca46b4672c..2b7cc98aff 100644 --- a/src/apps/powerstatus/PowerStatusView.cpp +++ b/src/apps/powerstatus/PowerStatusView.cpp @@ -230,14 +230,14 @@ PowerStatusView::_DrawBattery(BRect rect) SetScale(std::min(Bounds().Width(), Bounds().Height()) / 16); static const BPoint points[] = { - BPoint(2,13), - BPoint(9,5), - BPoint(9,7), - BPoint(16,2), - BPoint(8,11), - BPoint(8,9) + BPoint(2, 13), + BPoint(9, 5), + BPoint(9, 7), + BPoint(16, 2), + BPoint(8, 11), + BPoint(8, 9) }; - FillPolygon(points,6); + FillPolygon(points, 6); SetScale(1); SetDrawingMode(B_OP_OVER); From dfb3208fa3856c5c6d582fb826b7c991c67fa54d Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 22 Aug 2015 23:05:45 +0200 Subject: [PATCH 064/125] registrar: Whitespace and style cleanup only. Generally this code still looks horrible (both from a style and from a complexity point of view) and should eventually be reworked. --- .../registrar/mime/CreateAppMetaMimeThread.h | 4 +- .../registrar/mime/MimeUpdateThread.cpp | 64 +++++++------- .../registrar/mime/RegistrarThread.cpp | 27 +++--- src/servers/registrar/mime/RegistrarThread.h | 26 +++--- .../registrar/mime/RegistrarThreadManager.cpp | 86 ++++++++++--------- .../registrar/mime/RegistrarThreadManager.h | 15 ++-- 6 files changed, 116 insertions(+), 106 deletions(-) diff --git a/src/servers/registrar/mime/CreateAppMetaMimeThread.h b/src/servers/registrar/mime/CreateAppMetaMimeThread.h index 797ec63afa..4ec491a6fd 100644 --- a/src/servers/registrar/mime/CreateAppMetaMimeThread.h +++ b/src/servers/registrar/mime/CreateAppMetaMimeThread.h @@ -1,10 +1,10 @@ //---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered +// This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS license. //--------------------------------------------------------------------- /*! \file CreateAppMetaMimeThread.h - CreateAppMetaMimeThread interface declaration + CreateAppMetaMimeThread interface declaration */ #ifndef _CREATE_APP_META_MIME_THREAD_H diff --git a/src/servers/registrar/mime/MimeUpdateThread.cpp b/src/servers/registrar/mime/MimeUpdateThread.cpp index 5b530fbc1b..733e8a9703 100644 --- a/src/servers/registrar/mime/MimeUpdateThread.cpp +++ b/src/servers/registrar/mime/MimeUpdateThread.cpp @@ -42,10 +42,11 @@ namespace Mime { If \a replyee is non-NULL and construction succeeds, the MimeThreadObject assumes resposibility for its deletion. - - Also, if \c non-NULL, \a replyee is expected to be a \c B_REG_MIME_UPDATE_MIME_INFO - or a \c B_REG_MIME_CREATE_APP_META_MIME message with a \c true \c "synchronous" - field detached from the registrar's mime manager looper (though this is not verified). + + Also, if \c non-NULL, \a replyee is expected to be a + \c B_REG_MIME_UPDATE_MIME_INFO or a \c B_REG_MIME_CREATE_APP_META_MIME + message with a \c true \c "synchronous" field detached from the registrar's + mime manager looper (though this is not verified). The message will be replied to at the end of the thread's execution. */ MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority, @@ -65,9 +66,9 @@ MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority, /*! \brief Destroys the MimeUpdateThread object. - If the object was properly initialized (i.e. InitCheck() returns \c B_OK) and - the replyee message passed to the constructor was \c non-NULL, the replyee - message is deleted. + If the object was properly initialized (i.e. InitCheck() returns \c B_OK) + and the replyee message passed to the constructor was \c non-NULL, the + replyee message is deleted. */ MimeUpdateThread::~MimeUpdateThread() { @@ -122,20 +123,21 @@ MimeUpdateThread::ThreadFunction() // Notify the thread manager to make a cleanup run if (!err) { BMessage msg(B_REG_MIME_UPDATE_THREAD_FINISHED); - status_t error = fManagerMessenger.SendMessage(&msg, (BHandler*)NULL, 500000); + status_t error = fManagerMessenger.SendMessage(&msg, (BHandler*)NULL, + 500000); if (error) - OUT("WARNING: ThreadManager::ThreadEntryFunction(): Termination notification " - "failed with error 0x%" B_PRIx32 "\n", error); + OUT("WARNING: ThreadManager::ThreadEntryFunction(): Termination" + " notification failed with error 0x%" B_PRIx32 "\n", error); } - DBG(OUT("(id: %ld) exiting mime update thread with result 0x%" B_PRIx32 "\n", - find_thread(NULL), err)); + DBG(OUT("(id: %ld) exiting mime update thread with result 0x%" B_PRIx32 + "\n", find_thread(NULL), err)); return err; } /*! \brief Returns true if the given device supports attributes, false if not (or if an error occurs while determining). - + Device numbers and their corresponding support info are cached in a std::list to save unnecessarily \c statvfs()ing devices that have already been statvfs()ed (which might otherwise happen quite often @@ -152,13 +154,12 @@ MimeUpdateThread::DeviceSupportsAttributes(dev_t device) // See if an entry for this device already exists std::list< std::pair >::iterator i; for (i = fAttributeSupportList.begin(); - i != fAttributeSupportList.end(); - i++) + i != fAttributeSupportList.end(); i++) { if (i->first == device) return i->second; } - + bool result = false; // If we get here, no such device is yet in our list, @@ -175,24 +176,24 @@ MimeUpdateThread::DeviceSupportsAttributes(dev_t device) else fAttributeSupportList.push_back(p); } - - return result; + + return result; } // UpdateEntry -/*! \brief Updates the given entry and then recursively updates all the entry's child - entries if the entry is a directory and \c fRecursive is true. +/*! \brief Updates the given entry and then recursively updates all the entry's + child entries if the entry is a directory and \c fRecursive is true. */ status_t MimeUpdateThread::UpdateEntry(const entry_ref *ref) { status_t err = ref ? B_OK : B_BAD_VALUE; bool entryIsDir = false; - + // Look to see if we're being terminated if (!err && fShouldExit) err = B_CANCELED; - + // Before we update, make sure this entry lives on a device that supports // attributes. If not, we skip it and any of its children for // updates (we don't signal an error, however). @@ -202,7 +203,7 @@ MimeUpdateThread::UpdateEntry(const entry_ref *ref) // (DeviceSupportsAttributes(ref->device) ? "yes" : "no")); if (!err && (device_is_root_device(ref->device) - || DeviceSupportsAttributes(ref->device))) { + || DeviceSupportsAttributes(ref->device))) { // Update this entry if (!err) { // R5 appears to ignore whether or not the update succeeds. @@ -211,8 +212,8 @@ MimeUpdateThread::UpdateEntry(const entry_ref *ref) // If we're recursing and this is a directory, update // each of the directory's children as well - if (!err && fRecursive && entryIsDir) { - BDirectory dir; + if (!err && fRecursive && entryIsDir) { + BDirectory dir; err = dir.SetTo(ref); if (!err) { entry_ref childRef; @@ -222,16 +223,15 @@ MimeUpdateThread::UpdateEntry(const entry_ref *ref) // If we've come to the end of the directory listing, // it's not an error. if (err == B_ENTRY_NOT_FOUND) - err = B_OK; + err = B_OK; break; - } else { - err = UpdateEntry(&childRef); - } - } - } + } else + err = UpdateEntry(&childRef); + } + } } } - return err; + return err; } } // namespace Mime diff --git a/src/servers/registrar/mime/RegistrarThread.cpp b/src/servers/registrar/mime/RegistrarThread.cpp index b50faec77e..2ce9af6f72 100644 --- a/src/servers/registrar/mime/RegistrarThread.cpp +++ b/src/servers/registrar/mime/RegistrarThread.cpp @@ -15,27 +15,28 @@ /*! \class RegistrarThread \brief Base thread class for threads spawned and managed by the registrar - */ // constructor /*! \brief Creates a new RegistrarThread object, spawning the object's thread. - + Call Run() to actually get the thread running. - + \param name The desired name of the new thread \param priority The desired priority of the new thread \param managerMessenger A BMessenger to the thread manager to which this thread does or will belong. */ -RegistrarThread::RegistrarThread(const char *name, int32 priority, BMessenger managerMessenger) - : fManagerMessenger(managerMessenger) - , fShouldExit(false) - , fIsFinished(false) - , fStatus(B_NO_INIT) - , fId(-1) - , fPriority(priority) +RegistrarThread::RegistrarThread(const char *name, int32 priority, + BMessenger managerMessenger) + : + fManagerMessenger(managerMessenger), + fShouldExit(false), + fIsFinished(false), + fStatus(B_NO_INIT), + fId(-1), + fPriority(priority) { fName[0] = 0; status_t err = name && fManagerMessenger.IsValid() ? B_OK : B_BAD_VALUE; @@ -71,7 +72,7 @@ RegistrarThread::Run() fId = spawn_thread(&RegistrarThread::EntryFunction, fName, fPriority, (void*)this); err = fId >= 0 ? B_OK : fId; - if (err == B_OK) + if (err == B_OK) err = resume_thread(fId); } return err; @@ -86,13 +87,13 @@ RegistrarThread::Id() const } // Name -//! Returns the name of the thread +//! Returns the name of the thread const char* RegistrarThread::Name() const { return fName; } - + // AskToExit /*! \brief Signals to thread that it needs to quit politely as soon as possible. diff --git a/src/servers/registrar/mime/RegistrarThread.h b/src/servers/registrar/mime/RegistrarThread.h index 48d9edc37b..42bcde2d7d 100644 --- a/src/servers/registrar/mime/RegistrarThread.h +++ b/src/servers/registrar/mime/RegistrarThread.h @@ -1,10 +1,10 @@ //---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered +// This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS license. //--------------------------------------------------------------------- /*! \file RegistrarThread.h - RegistrarThread interface declaration + RegistrarThread interface declaration */ #ifndef REGISTRAR_THREAD_H @@ -15,30 +15,32 @@ class RegistrarThread { public: - RegistrarThread(const char *name, int32 priority, BMessenger managerMessenger); + RegistrarThread(const char *name, int32 priority, + BMessenger managerMessenger); virtual ~RegistrarThread(); - - virtual status_t InitCheck(); + + virtual status_t InitCheck(); status_t Run(); - + thread_id Id() const; const char* Name() const; - + void AskToExit(); bool IsFinished() const; - + protected: //! The function executed in the object's thread when Run() is called virtual status_t ThreadFunction() = 0; - - BMessenger fManagerMessenger; + + BMessenger fManagerMessenger; bool fShouldExit; // Initially false, may be set to true by AskToExit() - bool fIsFinished; // Initially false, set to true by the thread itself upon completion + bool fIsFinished; // Initially false, set to true by the thread itself + // upon completion private: static int32 EntryFunction(void *data); status_t fStatus; - thread_id fId; + thread_id fId; char fName[B_OS_NAME_LENGTH]; int32 fPriority; }; diff --git a/src/servers/registrar/mime/RegistrarThreadManager.cpp b/src/servers/registrar/mime/RegistrarThreadManager.cpp index 7c924d9058..504c75fc3e 100644 --- a/src/servers/registrar/mime/RegistrarThreadManager.cpp +++ b/src/servers/registrar/mime/RegistrarThreadManager.cpp @@ -24,8 +24,8 @@ using namespace BPrivate; /*! \class RegistrarThreadManager - \brief RegistrarThreadManager is the master of all threads spawned by the registrar - + \brief RegistrarThreadManager is the master of all threads spawned by the + registrar */ //! Creates a new RegistrarThreadManager object @@ -35,8 +35,8 @@ RegistrarThreadManager::RegistrarThreadManager() } // destructor -/*! \brief Destroys the RegistrarThreadManager object, killing and deleting any still - running threads. +/*! \brief Destroys the RegistrarThreadManager object, killing and deleting any + still running threads. */ RegistrarThreadManager::~RegistrarThreadManager() { @@ -44,9 +44,11 @@ RegistrarThreadManager::~RegistrarThreadManager() } // MessageReceived -/*! \brief Handles \c B_REG_MIME_UPDATE_THREAD_FINISHED messages, passing on all others. +/*! \brief Handles \c B_REG_MIME_UPDATE_THREAD_FINISHED messages, passing on all + others. - Each \c B_REG_MIME_UPDATE_THREAD_FINISHED message triggers a call to CleanupThreads(). + Each \c B_REG_MIME_UPDATE_THREAD_FINISHED message triggers a call to + CleanupThreads(). */ void RegistrarThreadManager::MessageReceived(BMessage* message) @@ -57,7 +59,7 @@ RegistrarThreadManager::MessageReceived(BMessage* message) CleanupThreads(); break; } - + default: { BHandler::MessageReceived(message); @@ -71,15 +73,16 @@ RegistrarThreadManager::MessageReceived(BMessage* message) RegistrarThreadManager object. \param thread Pointer to a newly allocated \c RegistrarThread object. - - If the result of the function is \c B_OK, the \c RegistrarThreadManager object - assumes ownership of \a thread; if the result is an error code, it + + If the result of the function is \c B_OK, the \c RegistrarThreadManager + object assumes ownership of \a thread; if the result is an error code, it does not. - + \return - \c B_OK: success - - \c B_NO_MORE_THREADS: the number of concurrently allowed threads (defined by - RegistrarThreadManager::kThreadLimit) has already been reached + - \c B_NO_MORE_THREADS: the number of concurrently allowed threads (defined + by RegistrarThreadManager::kThreadLimit) has + already been reached - \c B_BAD_THREAD_STATE: the thread has already been launched - other error code: failure */ @@ -110,14 +113,14 @@ RegistrarThreadManager::LaunchThread(RegistrarThread *thread) } } if (!err) - DBG(OUT("RegistrarThreadManager::LaunchThread(): launched new '%s' thread, " - "id %ld\n", thread->Name(), thread->Id())); + DBG(OUT("RegistrarThreadManager::LaunchThread(): launched new '%s'" + " thread, id %ld\n", thread->Name(), thread->Id())); return err; } // CleanupThreads /*! \brief Frees the resources of any threads that are no longer running - + \todo This function should perhaps be triggered periodically by a BMessageRunner once we have our own BMessageRunner implementation. */ @@ -128,18 +131,19 @@ RegistrarThreadManager::CleanupThreads() for (i = fThreads.begin(); i != fThreads.end(); ) { if (*i) { if ((*i)->IsFinished()) { - DBG(OUT("RegistrarThreadManager::CleanupThreads(): Cleaning up thread %ld\n", - (*i)->Id())); + DBG(OUT("RegistrarThreadManager::CleanupThreads(): Cleaning up" + " thread %ld\n", (*i)->Id())); RemoveThread(i); // adjusts i } else ++i; } else { - OUT("WARNING: RegistrarThreadManager::CleanupThreads(): NULL mime_update_thread_shared_data " - "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + OUT("WARNING: RegistrarThreadManager::CleanupThreads(): NULL" + " mime_update_thread_shared_data pointer found in and removed" + " from RegistrarThreadManager::fThreads list\n"); i = fThreads.erase(i); } - } + } return B_OK; } @@ -157,28 +161,29 @@ RegistrarThreadManager::ShutdownThreads() for (i = fThreads.begin(); i != fThreads.end(); ) { if (*i) { if ((*i)->IsFinished()) { - DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Cleaning up thread %ld\n", - (*i)->Id())); + DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Cleaning up" + " thread %ld\n", (*i)->Id())); RemoveThread(i); // adjusts i } else { - DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Shutting down thread %ld\n", - (*i)->Id())); + DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Shutting" + " down thread %ld\n", (*i)->Id())); (*i)->AskToExit(); ++i; } } else { - OUT("WARNING: RegistrarThreadManager::ShutdownThreads(): NULL mime_update_thread_shared_data " - "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + OUT("WARNING: RegistrarThreadManager::ShutdownThreads(): NULL" + " mime_update_thread_shared_data pointer found in and removed" + " from RegistrarThreadManager::fThreads list\n"); i = fThreads.erase(i); } } - + /*! \todo We may want to iterate back through the list at this point, snooze for a moment if find an unfinished thread, and kill it if it still isn't finished by the time we're done snoozing. */ - + return B_OK; } @@ -195,21 +200,22 @@ RegistrarThreadManager::KillThreads() for (i = fThreads.begin(); i != fThreads.end(); ) { if (*i) { if (!(*i)->IsFinished()) { - DBG(OUT("RegistrarThreadManager::KillThreads(): Killing thread %ld\n", - (*i)->Id())); + DBG(OUT("RegistrarThreadManager::KillThreads(): Killing thread" + " %ld\n", (*i)->Id())); status_t err = kill_thread((*i)->Id()); if (err) - OUT("WARNING: RegistrarThreadManager::KillThreads(): kill_thread(%" - B_PRId32 ") failed with error code 0x%" B_PRIx32 "\n", - (*i)->Id(), err); - } - DBG(OUT("RegistrarThreadManager::KillThreads(): Cleaning up thread %ld\n", - (*i)->Id())); + OUT("WARNING: RegistrarThreadManager::KillThreads():" + " kill_thread(%" B_PRId32 ") failed with error code" + " 0x%" B_PRIx32 "\n", (*i)->Id(), err); + } + DBG(OUT("RegistrarThreadManager::KillThreads(): Cleaning up thread" + " %ld\n", (*i)->Id())); RemoveThread(i); // adjusts i } else { - OUT("WARNING: RegistrarThreadManager::KillThreads(): NULL mime_update_thread_shared_data " - "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + OUT("WARNING: RegistrarThreadManager::KillThreads(): NULL" + " mime_update_thread_shared_data pointer found in and removed" + " from RegistrarThreadManager::fThreads list\n"); i = fThreads.erase(i); } } @@ -222,7 +228,7 @@ RegistrarThreadManager::KillThreads() This is not necessarily a count of how many threads are actually running, as threads may remain in the thread list that are finished and waiting to be cleaned up. - + \return The number of threads currently under management */ uint diff --git a/src/servers/registrar/mime/RegistrarThreadManager.h b/src/servers/registrar/mime/RegistrarThreadManager.h index 6dcc59ccd5..7f395a13e5 100644 --- a/src/servers/registrar/mime/RegistrarThreadManager.h +++ b/src/servers/registrar/mime/RegistrarThreadManager.h @@ -1,10 +1,10 @@ //---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered +// This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS license. //--------------------------------------------------------------------- /*! \file RegistrarThreadManager.h - RegistrarThreadManager interface declaration + RegistrarThreadManager interface declaration */ #ifndef REGISTRAR_THREAD_MANAGER_H @@ -21,7 +21,7 @@ class RegistrarThreadManager : public BHandler { public: RegistrarThreadManager(); ~RegistrarThreadManager(); - + // BHandler virtuals virtual void MessageReceived(BMessage* message); @@ -30,14 +30,15 @@ public: status_t CleanupThreads(); status_t ShutdownThreads(); status_t KillThreads(); - + uint ThreadCount() const; - + static const int kThreadLimit = 12; private: - std::list::iterator& RemoveThread(std::list::iterator &i); - + std::list::iterator& + RemoveThread(std::list::iterator &i); + std::list fThreads; int32 fThreadCount; }; From 462bfeede0cd123afe2e79d465876289e925ca53 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 23 Aug 2015 11:48:24 +0200 Subject: [PATCH 065/125] registrar: Fix race condition on MimeUpdateThread termination. When the MimeUpdateThread is done, it marks itself as finished and notifies the thread manager to clean up finished threads. Since multiple such threads might finish at the same time and trigger the cleanup notification, other threads that already marked themselves finished but haven't actually exited yet might already be deleted and removed. This would then lead to a use-after-free when they subsequently tried to send their own cleanup message. To solve the race condition, the thread manager will now wait for the thread to actually exit before cleaning it up. The introduction of the launch_daemon has made this race condition more likely due to more applications starting in parallel, each triggering a CreateAppMetaMimeThread which is a subclass of MimeUpdateThread. This commit might therefore fix #12237. --- src/servers/registrar/mime/RegistrarThreadManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/servers/registrar/mime/RegistrarThreadManager.cpp b/src/servers/registrar/mime/RegistrarThreadManager.cpp index 504c75fc3e..9ce7690a5e 100644 --- a/src/servers/registrar/mime/RegistrarThreadManager.cpp +++ b/src/servers/registrar/mime/RegistrarThreadManager.cpp @@ -243,6 +243,9 @@ RegistrarThreadManager::ThreadCount() const std::list::iterator& RegistrarThreadManager::RemoveThread(std::list::iterator &i) { + status_t dummy; + wait_for_thread((*i)->Id(), &dummy); + delete *i; atomic_add(&fThreadCount, -1); return (i = fThreads.erase(i)); From 71cc01b2b1a50fd241c28eae673783412067a7e2 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 23 Aug 2015 12:35:25 +0200 Subject: [PATCH 066/125] registrar: Use the safer strlcpy instead of strcpy. --- src/servers/registrar/mime/RegistrarThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servers/registrar/mime/RegistrarThread.cpp b/src/servers/registrar/mime/RegistrarThread.cpp index 2ce9af6f72..b97d5bf481 100644 --- a/src/servers/registrar/mime/RegistrarThread.cpp +++ b/src/servers/registrar/mime/RegistrarThread.cpp @@ -41,7 +41,7 @@ RegistrarThread::RegistrarThread(const char *name, int32 priority, fName[0] = 0; status_t err = name && fManagerMessenger.IsValid() ? B_OK : B_BAD_VALUE; if (err == B_OK) - strcpy(fName, name); + strlcpy(fName, name, sizeof(fName)); fStatus = err; } From 8074f0b94b25c8a255b4c5bdb579bd0e5d8c09f8 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 23 Aug 2015 12:36:12 +0200 Subject: [PATCH 067/125] launch_daemon: Replace the remaining putenv() calls by setenv(). --- src/servers/launch/LaunchDaemon.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index ef1f295c6b..b64d40aead 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -1262,13 +1262,10 @@ void LaunchDaemon::_SetupEnvironment() { // Determine safemode kernel option - BString safemode = "SAFEMODE="; - safemode << (IsSafeMode() ? "yes" : "no"); - - putenv(safemode.String()); + setenv("SAFEMODE", IsSafeMode() ? "yes" : "no", true); // Default locale settings - putenv("LC_TYPE=en_US.UTF-8"); + setenv("LC_TYPE", "en_US.UTF-8", true); } From 5dbea4697074034e7b5887d3ce8e45aebbe32057 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 23 Aug 2015 13:10:12 +0200 Subject: [PATCH 068/125] libroot_debug: Track freeing thread in guarded heap separatley. Previously the thread member was overwritten with the freeing thread when a page was freed, leading to confusion when hitting unallocated pages due to the debugger message still stating "allocated by thread". Track the freeing thread separately as it might be interesting to know both, which thread initially allocated and which thread eventually freed an allocation. --- .../posix/malloc_debug/guarded_heap.cpp | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp index 63c8ee0b53..6c30a12485 100644 --- a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp +++ b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp @@ -163,7 +163,8 @@ struct guarded_heap_page { size_t allocation_size; void* allocation_base; size_t alignment; - thread_id thread; + thread_id allocating_thread; + thread_id freeing_thread; list_link free_list_link; size_t alloc_stack_trace_depth; size_t free_stack_trace_depth; @@ -316,7 +317,8 @@ guarded_heap_page_allocate(guarded_heap_area& area, size_t startPageIndex, guarded_heap_page& page = area.pages[startPageIndex + i]; page.flags = GUARDED_HEAP_PAGE_FLAG_USED; if (i == 0) { - page.thread = find_thread(NULL); + page.allocating_thread = find_thread(NULL); + page.freeing_thread = -1; page.allocation_size = allocationSize; page.allocation_base = allocationBase; page.alignment = alignment; @@ -326,7 +328,8 @@ guarded_heap_page_allocate(guarded_heap_area& area, size_t startPageIndex, page.free_stack_trace_depth = 0; firstPage = &page; } else { - page.thread = firstPage->thread; + page.allocating_thread = firstPage->allocating_thread; + page.freeing_thread = -1; page.allocation_size = allocationSize; page.allocation_base = allocationBase; page.alignment = alignment; @@ -358,7 +361,7 @@ guarded_heap_free_page(guarded_heap_area& area, size_t pageIndex, else page.flags |= GUARDED_HEAP_PAGE_FLAG_DEAD; - page.thread = find_thread(NULL); + page.freeing_thread = find_thread(NULL); list_add_item(&area.free_list, &page); @@ -525,7 +528,8 @@ guarded_heap_allocate_with_area(size_t size, size_t alignment) page->allocation_base = (void*)(((addr_t)address + pagesNeeded * B_PAGE_SIZE - size) & ~(alignment - 1)); page->alignment = alignment; - page->thread = find_thread(NULL); + page->allocating_thread = find_thread(NULL); + page->freeing_thread = -1; page->alloc_stack_trace_depth = guarded_heap_fill_stack_trace( page->stack_trace, sStackTraceDepth, 2); page->free_stack_trace_depth = 0; @@ -811,7 +815,8 @@ dump_guarded_heap_page(guarded_heap_page& page) printf("allocation size: %" B_PRIuSIZE "\n", page.allocation_size); printf("allocation base: %p\n", page.allocation_base); printf("alignment: %" B_PRIuSIZE "\n", page.alignment); - printf("allocating thread: %" B_PRId32 "\n", page.thread); + printf("allocating thread: %" B_PRId32 "\n", page.allocating_thread); + printf("freeing thread: %" B_PRId32 "\n", page.freeing_thread); } @@ -862,9 +867,10 @@ dump_guarded_heap_page(void* address, bool doPanic) panic("thread %" B_PRId32 " tried accessing address %p which is " \ state " (base: 0x%" B_PRIxADDR ", size: %" B_PRIuSIZE \ ", alignment: %" B_PRIuSIZE ", allocated by thread: %" \ - B_PRId32 ")", find_thread(NULL), address, \ - page.allocation_base, page.allocation_size, page.alignment, \ - page.thread) + B_PRId32 ", freed by thread: %" B_PRId32 ")", \ + find_thread(NULL), address, page.allocation_base, \ + page.allocation_size, page.alignment, page.allocating_thread, \ + page.freeing_thread) if ((page.flags & GUARDED_HEAP_PAGE_FLAG_USED) == 0) DO_PANIC("not allocated"); @@ -980,7 +986,7 @@ dump_allocations(guarded_heap& heap, bool statsOnly, thread_id thread) continue; } - if (thread >= 0 && thread != page.thread) + if (thread >= 0 && thread != page.allocating_thread) continue; allocationCount++; @@ -991,8 +997,8 @@ dump_allocations(guarded_heap& heap, bool statsOnly, thread_id thread) print_stdout("allocation: base: %p; size: %" B_PRIuSIZE "; thread: %" B_PRId32 "; alignment: %" B_PRIuSIZE "\n", - page.allocation_base, page.allocation_size, page.thread, - page.alignment); + page.allocation_base, page.allocation_size, + page.allocating_thread, page.alignment); guarded_heap_print_stack_trace(page.stack_trace, page.alloc_stack_trace_depth); From 8b9bb054f46a2500dfc4216dca18096da737debc Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 23 Aug 2015 13:19:12 +0200 Subject: [PATCH 069/125] libroot_debug: Replace two more uses of printf in guarded heap. Use the internal print_stdout() instead as done when printing the stack traces. --- src/system/libroot/posix/malloc_debug/guarded_heap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp index 6c30a12485..3a552bd5af 100644 --- a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp +++ b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp @@ -260,14 +260,14 @@ static void guarded_heap_print_stack_traces(guarded_heap_page& page) { if (page.alloc_stack_trace_depth > 0) { - printf("alloc stack trace (%" B_PRIuSIZE "):\n", + print_stdout("alloc stack trace (%" B_PRIuSIZE "):\n", page.alloc_stack_trace_depth); guarded_heap_print_stack_trace(page.stack_trace, page.alloc_stack_trace_depth); } if (page.free_stack_trace_depth > 0) { - printf("free stack trace (%" B_PRIuSIZE "):\n", + print_stdout("free stack trace (%" B_PRIuSIZE "):\n", page.free_stack_trace_depth); guarded_heap_print_stack_trace( &page.stack_trace[page.alloc_stack_trace_depth], From f11d686c96f7ac06b9ea411367548d34229548a3 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 23 Aug 2015 15:02:22 +0200 Subject: [PATCH 070/125] launch_daemon: Remove extra quoting around env variables. The extra quotes aren't needed and cause problems when not parsed through a shell. For example LD_PRELOAD which is handled by the runtime_loader directly failed to work as there was no way to remove the extra single quotes. Note that quotes and single quotes can still be added to the variables through respective quoting in the driver settings syntax. --- src/servers/launch/BaseJob.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/servers/launch/BaseJob.cpp b/src/servers/launch/BaseJob.cpp index 3dc5d93b25..ef27fa134d 100644 --- a/src/servers/launch/BaseJob.cpp +++ b/src/servers/launch/BaseJob.cpp @@ -151,7 +151,7 @@ BaseJob::SetEnvironment(const BMessage& message) } BString variable = name; - variable << "='"; + variable << "="; const char* argument; for (int32 argumentIndex = 0; message.FindString(name, argumentIndex, @@ -160,7 +160,6 @@ BaseJob::SetEnvironment(const BMessage& message) variable << " "; variable += argument; } - variable << "'"; fEnvironment.Add(variable); } From 579efee783fc5953886153d91b48adca1144f08d Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Mon, 24 Aug 2015 15:50:57 +1200 Subject: [PATCH 071/125] package server: fix off-by-one error in RemoveLastComponent() --- src/servers/package/FSUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servers/package/FSUtils.h b/src/servers/package/FSUtils.h index 0a1f0c4cab..004d3cdb1e 100644 --- a/src/servers/package/FSUtils.h +++ b/src/servers/package/FSUtils.h @@ -157,7 +157,7 @@ public: else if (index == 0) fPath.Truncate(1); else - fPath.Truncate(index - 1); + fPath.Truncate(index); return *this; } From 7ed2a4437610d5a342d3d2a9950311cbc5e89a9e Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 24 Aug 2015 09:33:36 +0200 Subject: [PATCH 072/125] Fix naming --- src/add-ons/kernel/network/stack/interfaces.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/add-ons/kernel/network/stack/interfaces.cpp b/src/add-ons/kernel/network/stack/interfaces.cpp index 0a6bebd8bb..ab2fa2d52a 100644 --- a/src/add-ons/kernel/network/stack/interfaces.cpp +++ b/src/add-ons/kernel/network/stack/interfaces.cpp @@ -935,13 +935,13 @@ Interface::SetDown() if ((flags & IFF_UP) == 0) return; - RecursiveLocker interfacesLock(sLock); + RecursiveLocker interfacesLocker(sLock); if (IsBusy()) return; SetBusy(true); - interfacesLock.Unlock(); + interfacesLocker.Unlock(); DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); while (domain_datalink* datalink = iterator.Next()) { From a6fb27a3f621d6e471ab56f6ea22f068d3a6b781 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 24 Aug 2015 10:03:54 +0200 Subject: [PATCH 073/125] Improved comment. Added TODO --- src/preferences/media/MidiSettingsView.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/preferences/media/MidiSettingsView.cpp b/src/preferences/media/MidiSettingsView.cpp index 5310a4d9ca..32e3c854d2 100644 --- a/src/preferences/media/MidiSettingsView.cpp +++ b/src/preferences/media/MidiSettingsView.cpp @@ -91,6 +91,8 @@ MidiSettingsView::MessageReceived(BMessage* message) void MidiSettingsView::_RetrieveSoftSynthList() { + // TODO: Duplicated code between here + // and BSoftSynth::SetDefaultInstrumentsFile BStringList paths; status_t status = BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, "synth", paths); @@ -108,9 +110,10 @@ MidiSettingsView::_RetrieveSoftSynthList() BNode node(&entry); BNodeInfo nodeInfo(&node); char mimeType[B_MIME_TYPE_LENGTH]; - // TODO: For some reason this doesn't work + // TODO: For some reason the mimetype check fails. + // maybe because the file hasn't yet been sniffed and recognized? if (nodeInfo.GetType(mimeType) == B_OK - /*&& !strcmp(mimeType, "audio/x-soundfont")*/) { + /*&& !strcmp(mimeType, "audio/x-soundfont")*/) { BPath fullPath = paths.StringAt(i).String(); fullPath.Append(entry.Name()); fListView->AddItem(new BStringItem(fullPath.Path())); From 65b4405eccf4d9cf1800e1ad327d0635ce044a26 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 24 Aug 2015 10:04:17 +0200 Subject: [PATCH 074/125] BSoftSynth: Fixed auto selection of soundfont. When no midi settings file was available, BSoftSynth should use the well known TimGM6mb.sf2 soundfont. This wasn't working, since the code looked in the wrong path (we have to append "synth" to the path returned by find_directory). In case this SF is not present, now we try harder not to fail, and look for any soundfont available in the system and user directories. Fixes ticket #12325 although the selected soundfont is not written to the user settings file. --- src/kits/midi/SoftSynth.cpp | 48 ++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/kits/midi/SoftSynth.cpp b/src/kits/midi/SoftSynth.cpp index 905aa3dd2f..baacf9944f 100644 --- a/src/kits/midi/SoftSynth.cpp +++ b/src/kits/midi/SoftSynth.cpp @@ -14,9 +14,13 @@ #include #include +#include #include #include +#include +#include #include +#include #include #include @@ -100,6 +104,8 @@ BSoftSynth::IsLoaded(void) const status_t BSoftSynth::SetDefaultInstrumentsFile() { + // TODO: Duplicated code, check MidiSettingsView::_LoadSettings() and + // MidiSettingsView::_RetrieveSoftSynthList() // We first search for a setting file (or symlink to it) // in the user settings directory char buffer[512]; @@ -112,18 +118,48 @@ BSoftSynth::SetDefaultInstrumentsFile() char soundFont[512]; sscanf(buffer, "# Midi Settings\n soundfont = %s\n", soundFont); - return SetInstrumentsFile(soundFont); + if (SetInstrumentsFile(soundFont) == B_OK) + return B_OK; } } - // TODO: Use the first soundfont found in the synth directory - // instead of hardcoding + // Try a well-known (and usually present on a default install) soft synth if (find_directory(B_SYNTH_DIRECTORY, &path, false, NULL) == B_OK) { - path.Append("TimGM6mb.sf2"); - return SetInstrumentsFile(path.Path()); + path.Append("synth/TimGM6mb.sf2"); + if (SetInstrumentsFile(path.Path()) == B_OK) + return B_OK; } - // TODO: Write the settings file + // Just use the first soundfont we find + BStringList paths; + status_t status = BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, + "synth", paths); + + if (status != B_OK) + return B_ERROR; + + for (int32 i = 0; i < paths.CountStrings(); i++) { + BDirectory directory(paths.StringAt(i).String()); + BEntry entry; + if (directory.InitCheck() != B_OK) + continue; + while (directory.GetNextEntry(&entry) == B_OK) { + BNode node(&entry); + BNodeInfo nodeInfo(&node); + char mimeType[B_MIME_TYPE_LENGTH]; + // TODO: For some reason the mimetype check fails. + // maybe because the file hasn't yet been sniffed and recognized? + if (nodeInfo.GetType(mimeType) == B_OK + /*&& !strcmp(mimeType, "audio/x-soundfont")*/) { + BPath fullPath = paths.StringAt(i).String(); + fullPath.Append(entry.Name()); + if (SetInstrumentsFile(fullPath.Path()) == B_OK) + return B_OK; + } + } + } + + // TODO: Write the settings file ? return B_ERROR; } From 2f41383c3bf2993545ffc687afbc82196a95f5e0 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 24 Aug 2015 10:21:31 +0200 Subject: [PATCH 075/125] BBitmap: Archive the data also if "deep" is not set Fixes #12326 --- src/kits/interface/Bitmap.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/kits/interface/Bitmap.cpp b/src/kits/interface/Bitmap.cpp index 33f60ca16b..42da316733 100644 --- a/src/kits/interface/Bitmap.cpp +++ b/src/kits/interface/Bitmap.cpp @@ -429,16 +429,15 @@ BBitmap::Archive(BMessage* data, bool deep) const break; } } - // Note: R5 does not archive the data if B_BITMAP_IS_CONTIGUOUS is - // true and it does save all formats as B_RAW_TYPE and it does save - // the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to - // the BeBook) - if (ret == B_OK) { - const_cast(this)->_AssertPointer(); - ret = data->AddData("_data", B_RAW_TYPE, fBasePointer, fSize); - } } - + // Note: R5 does not archive the data if B_BITMAP_IS_CONTIGUOUS is + // true and it does save all formats as B_RAW_TYPE and it does save + // the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to + // the BeBook) + if (ret == B_OK) { + const_cast(this)->_AssertPointer(); + ret = data->AddData("_data", B_RAW_TYPE, fBasePointer, fSize); + } return ret; } From 3ffaf5c26351492618e7ec3e8bb9ceb7ab629490 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 24 Aug 2015 10:23:28 +0200 Subject: [PATCH 076/125] MidiSettingsView: renamed box label Renamed box label from "SoundFont" to "Available SoundFonts", hopefully improves the user experience by making it clearer that this is a list of the available soundfonts. --- src/preferences/media/MidiSettingsView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preferences/media/MidiSettingsView.cpp b/src/preferences/media/MidiSettingsView.cpp index 32e3c854d2..52a10d4c4b 100644 --- a/src/preferences/media/MidiSettingsView.cpp +++ b/src/preferences/media/MidiSettingsView.cpp @@ -37,7 +37,7 @@ MidiSettingsView::MidiSettingsView() SettingsView() { BBox* defaultsBox = new BBox("SoundFont"); - defaultsBox->SetLabel(B_TRANSLATE("SoundFont")); + defaultsBox->SetLabel(B_TRANSLATE("Available SoundFonts")); BGridView* defaultsGridView = new BGridView(); fListView = new BListView(B_SINGLE_SELECTION_LIST); From c34e5f4dd555c3f27d12ca84095239ec8392470d Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 24 Aug 2015 17:18:26 +0200 Subject: [PATCH 077/125] B_BIG_SYNTH_FILE and B_LITTLE_SYNTH_FILE are deprecated. Small style change in midi headers. --- headers/os/midi/Midi.h | 3 +-- headers/os/midi/MidiDefs.h | 2 ++ headers/os/midi/MidiPort.h | 3 +-- headers/os/midi/MidiStore.h | 3 +-- headers/os/midi/MidiSynth.h | 3 +-- headers/os/midi/MidiSynthFile.h | 3 +-- headers/os/midi/MidiText.h | 3 +-- 7 files changed, 8 insertions(+), 12 deletions(-) diff --git a/headers/os/midi/Midi.h b/headers/os/midi/Midi.h index 2e41f05faa..fcada5b26a 100644 --- a/headers/os/midi/Midi.h +++ b/headers/os/midi/Midi.h @@ -10,8 +10,7 @@ class BList; class BMidiLocalProducer; class BMidiLocalConsumer; -class BMidi -{ +class BMidi { public: BMidi(); diff --git a/headers/os/midi/MidiDefs.h b/headers/os/midi/MidiDefs.h index a4d44c582c..4afb40390e 100644 --- a/headers/os/midi/MidiDefs.h +++ b/headers/os/midi/MidiDefs.h @@ -15,6 +15,8 @@ /* Synthesizer things */ #define B_SYNTH_DIRECTORY B_SYSTEM_DATA_DIRECTORY + +/* Deprecated */ #define B_BIG_SYNTH_FILE "synth/big_synth.sy" #define B_LITTLE_SYNTH_FILE "synth/little_synth.sy" diff --git a/headers/os/midi/MidiPort.h b/headers/os/midi/MidiPort.h index af86f6fd98..9a3c68b199 100644 --- a/headers/os/midi/MidiPort.h +++ b/headers/os/midi/MidiPort.h @@ -9,8 +9,7 @@ class BMidiProducer; namespace BPrivate { class BMidiPortGlue; } -class BMidiPort : public BMidi -{ +class BMidiPort : public BMidi { public: BMidiPort(const char* name = NULL); diff --git a/headers/os/midi/MidiStore.h b/headers/os/midi/MidiStore.h index e519a2727a..47c45ca84f 100644 --- a/headers/os/midi/MidiStore.h +++ b/headers/os/midi/MidiStore.h @@ -12,8 +12,7 @@ class BFile; class BList; class BMidiEvent; -class BMidiStore : public BMidi -{ +class BMidiStore : public BMidi { public: BMidiStore(); diff --git a/headers/os/midi/MidiSynth.h b/headers/os/midi/MidiSynth.h index c85f8b5f53..a9556901be 100644 --- a/headers/os/midi/MidiSynth.h +++ b/headers/os/midi/MidiSynth.h @@ -9,8 +9,7 @@ class BSynth; -class BMidiSynth : public BMidi -{ +class BMidiSynth : public BMidi { public: BMidiSynth(); diff --git a/headers/os/midi/MidiSynthFile.h b/headers/os/midi/MidiSynthFile.h index ffd0cb321e..7964b0872c 100644 --- a/headers/os/midi/MidiSynthFile.h +++ b/headers/os/midi/MidiSynthFile.h @@ -10,8 +10,7 @@ typedef void (*synth_file_hook)(int32 arg); class BMidiStore; -class BMidiSynthFile : public BMidiSynth -{ +class BMidiSynthFile : public BMidiSynth { public: BMidiSynthFile(); diff --git a/headers/os/midi/MidiText.h b/headers/os/midi/MidiText.h index 8a18593943..a70638d449 100644 --- a/headers/os/midi/MidiText.h +++ b/headers/os/midi/MidiText.h @@ -6,8 +6,7 @@ #include #include -class BMidiText : public BMidi -{ +class BMidiText : public BMidi { public: BMidiText(); From 9a36e655d71c73c317a02ee1c16185970d77abb4 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Tue, 25 Aug 2015 12:38:40 +0200 Subject: [PATCH 078/125] radeon_hd: Add missing id for Radeon HD 8490 --- src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp b/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp index e58455a68a..2f2df49c7e 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp @@ -229,11 +229,12 @@ const struct supported_device { {0x6767, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD Caicos"}, {0x6768, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD Caicos"}, {0x6770, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 6400"}, - {0x6778, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD Caicos"}, - {0x6779, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 6450"}, + {0x6778, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7470/8470"}, + {0x6779, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 6450/7450/8450"}, {0x68fa, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7350"}, {0x677b, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7400"}, {0x6772, 5, 0, RADEON_CAICOS, CHIP_APU, "Radeon HD 7400A"}, + {0x6771, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 8490"}, // Turks {0x6740, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD 6770M"}, {0x6741, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD 6650M"}, From d9971ae7aace9f9a3fd44558ebb64c706ce3bf11 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Wed, 26 Aug 2015 16:35:18 +0200 Subject: [PATCH 079/125] Media: Show alert while media services restart --- src/preferences/media/MediaWindow.cpp | 24 ++++++++++++++++-------- src/preferences/media/MediaWindow.h | 2 ++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/preferences/media/MediaWindow.cpp b/src/preferences/media/MediaWindow.cpp index 30ab05126e..7efd90d9c9 100644 --- a/src/preferences/media/MediaWindow.cpp +++ b/src/preferences/media/MediaWindow.cpp @@ -12,7 +12,6 @@ #include -#include #include #include #include @@ -185,7 +184,8 @@ MediaWindow::MediaWindow(BRect frame) fVideoInputs(5, true), fVideoOutputs(5, true), fInitCheck(B_OK), - fRestartThread(-1) + fRestartThread(-1), + fRestartAlert(NULL) { _InitWindow(); @@ -307,13 +307,16 @@ MediaWindow::UpdateOutputListItem(MediaListItem::media_type type, bool MediaWindow::QuitRequested() { - status_t exit = B_OK; if (fRestartThread > 0) { - wait_for_thread(fRestartThread, &exit); - if (exit != B_OK) { - fprintf(stderr, "MediaWindow::QuitRequested wait_for_thread" - " returned with an error: %s\n", strerror(exit)); - } + BString text(B_TRANSLATE("Quitting Media now will stop" + "restarting the media services. Flaky or unavailable media" + "functionality is likely the result.")); + + fRestartAlert = new BAlert(B_TRANSLATE("Warning!"), text, + B_TRANSLATE("Quit anyway"), NULL, NULL, + B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT); + + fRestartAlert->Go(); } // Stop watching the MediaRoster fCurrentNode.SetTo(NULL); @@ -658,6 +661,11 @@ MediaWindow::_RestartMediaServices(void* data) shutdown_media_server(); launch_media_server(); + if (window->fRestartAlert != NULL + && window->fRestartAlert->Lock()) { + window->fRestartAlert->Quit(); + } + return window->PostMessage(ML_RESTART_THREAD_FINISHED); } diff --git a/src/preferences/media/MediaWindow.h b/src/preferences/media/MediaWindow.h index 5d75867de9..a9390bf080 100644 --- a/src/preferences/media/MediaWindow.h +++ b/src/preferences/media/MediaWindow.h @@ -10,6 +10,7 @@ #define MEDIA_WINDOW_H +#include #include #include #include @@ -109,6 +110,7 @@ private: status_t fInitCheck; thread_id fRestartThread; + BAlert* fRestartAlert; }; From dfe056fd6a5218b77449842bdb8c8b9099b836f7 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Tue, 25 Aug 2015 22:57:34 +0200 Subject: [PATCH 080/125] BMediaEventLooper: Continue code improvements. --- src/kits/media/MediaEventLooper.cpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/kits/media/MediaEventLooper.cpp b/src/kits/media/MediaEventLooper.cpp index bf3c8d0012..c5928454d9 100644 --- a/src/kits/media/MediaEventLooper.cpp +++ b/src/kits/media/MediaEventLooper.cpp @@ -215,7 +215,6 @@ BMediaEventLooper::ControlLoop() status_t err; bigtime_t waitUntil = B_INFINITE_TIMEOUT; - bigtime_t tempLateness = 0; bool hasRealtime = false; bool hasEvent = false; @@ -237,11 +236,11 @@ BMediaEventLooper::ControlLoop() err = fRealTimeQueue.RemoveFirstEvent(&event); if (err == B_OK) { - tempLateness -= TimeSource()->RealTime(); - if (tempLateness < 0) - tempLateness = 0; + bigtime_t lateness = waitUntil - TimeSource()->RealTime(); + if (lateness < 0) + lateness = 0; - DispatchEvent(&event, tempLateness, hasRealtime); + DispatchEvent(&event, lateness, hasRealtime); } } else if (err != B_OK) return; @@ -255,29 +254,23 @@ BMediaEventLooper::ControlLoop() if (hasEvent) { waitUntil = TimeSource()->RealTimeFor( - fEventQueue.FirstEvent()->event_time, + fEventQueue.FirstEventTime(), fEventLatency + fSchedulingLatency); } else if (!hasRealtime) { waitUntil = B_INFINITE_TIMEOUT; continue; } - if (hasEvent && hasRealtime) { - if (fRealTimeQueue.FirstEventTime() - - fSchedulingLatency <= waitUntil) { + if (hasRealtime) { + bigtime_t realtimeWait = fRealTimeQueue.FirstEventTime() + - fSchedulingLatency; + + if (!hasEvent || realtimeWait <= waitUntil) { + waitUntil = realtimeWait; hasEvent = false; } else hasRealtime = false; } - - if (hasRealtime) { - waitUntil = fRealTimeQueue.FirstEventTime() - - fSchedulingLatency; - } - - tempLateness = waitUntil; - if (waitUntil < TimeSource()->RealTime()) - waitUntil = 0; } } From ae9cbf9c4e167470b47964059e90c2b0881367eb Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Tue, 25 Aug 2015 22:58:18 +0200 Subject: [PATCH 081/125] MediaNode: Wait for 0 time if the absolute timeout is in the past --- src/kits/media/MediaNode.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/kits/media/MediaNode.cpp b/src/kits/media/MediaNode.cpp index bece94a000..ab68d927f5 100644 --- a/src/kits/media/MediaNode.cpp +++ b/src/kits/media/MediaNode.cpp @@ -343,6 +343,10 @@ BMediaNode::WaitForMessage(bigtime_t waitUntil, uint32 flags, char data[B_MEDIA_MESSAGE_SIZE]; int32 message; ssize_t size; + + if (waitUntil < TimeSource()->RealTime()) + waitUntil = 0; + while (true) { size = read_port_etc(ControlPort(), &message, data, sizeof(data), B_ABSOLUTE_TIMEOUT, waitUntil); From ee5575d9b34ba547c0677a9b90bda2ebc066acee Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 26 Aug 2015 21:33:41 +0200 Subject: [PATCH 082/125] BRoster: Apply no-registrar mode in a few more cases. Avoids some more attempts at communicating with the registrar if the no-registrar flag has been set. --- src/kits/app/Roster.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index 1a8c76900b..deaef0b4a6 100644 --- a/src/kits/app/Roster.cpp +++ b/src/kits/app/Roster.cpp @@ -2068,7 +2068,7 @@ BRoster::_ResolveApp(const char* inType, entry_ref* ref, } // create meta mime - if (error == B_OK) { + if (!fNoRegistrar && error == B_OK) { BPath path; if (path.SetTo(&appRef) == B_OK) create_app_meta_mime(path.Path(), false, true, false); @@ -2077,7 +2077,7 @@ BRoster::_ResolveApp(const char* inType, entry_ref* ref, // set the app hint on the type -- but only if the file has the // respective signature, otherwise unset the app hint BAppFileInfo appFileInfo; - if (error == B_OK) { + if (!fNoRegistrar && error == B_OK) { char signature[B_MIME_TYPE_LENGTH]; if (appFileInfo.SetTo(&appFile) == B_OK && appFileInfo.GetSignature(signature) == B_OK) { @@ -2482,6 +2482,9 @@ BRoster::_GetFileType(const entry_ref* file, BNodeInfo* nodeInfo, if (nodeInfo->GetType(mimeType) == B_OK) return B_OK; + if (fNoRegistrar) + return B_NO_INIT; + // Try to update the file's MIME info and just read the updated type. // If that fails, sniff manually. BPath path; From 14156a33ac0233f4233546080d6b975618b331fa Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 26 Aug 2015 21:39:15 +0200 Subject: [PATCH 083/125] launch_daemon: Delegate launch data replies to Job. Previously the LaunchDaemon would send out its own team id when a given job was not yet launched, leading to invalid BMessengers once the port owner changed to the actually launched team. The launch of the target team and the launch data replies were also not synchronized, which could lead to the launched team getting a reply pointing to the launch_daemon when requesting data for itself. This is the case for the BRoster init of the registrar. The fix in hrev49561 therefore didn't always work, because the registrar would sometimes get the launch_daemon team id instead of the id of itself. It would later try talking to the launch_daemon, which obviously never replied, leading to #12237. The LaunchDaemon now delegates the launch data reply to the Job instead. The Job either replies directly, in case it has already been launched, or queues the reply for when the launch completes. This causes launch data requesters to block until the launch attempt is completed, but won't block the LaunchDaemon message loop. This commit introduces the seperate fLaunchStatus to properly handle the ambiguity of fTeam being < 0, which is the case for both, when no launch was attempted and when the launch failed. This new field now determines what IsLaunched() returns and how launch data replies are handled. The new launch status is additionally protected by the launch status lock, which will later probably be made broader in scope to protect against race conditions once service monitoring is implemented. --- src/servers/launch/Job.cpp | 85 ++++++++++++++++++++++++++--- src/servers/launch/Job.h | 13 +++++ src/servers/launch/LaunchDaemon.cpp | 34 ++++++------ 3 files changed, 107 insertions(+), 25 deletions(-) diff --git a/src/servers/launch/Job.cpp b/src/servers/launch/Job.cpp index 7432921aaf..5cb9c985b2 100644 --- a/src/servers/launch/Job.cpp +++ b/src/servers/launch/Job.cpp @@ -27,8 +27,11 @@ Job::Job(const char* name) fCreateDefaultPort(false), fInitStatus(B_NO_INIT), fTeam(-1), - fTarget(NULL) + fLaunchStatus(B_NO_INIT), + fTarget(NULL), + fPendingLaunchDataReplies(0, false) { + mutex_init(&fLaunchStatusLock, "launch status lock"); } @@ -40,8 +43,12 @@ Job::Job(const Job& other) fCreateDefaultPort(other.CreateDefaultPort()), fInitStatus(B_NO_INIT), fTeam(-1), - fTarget(other.Target()) + fLaunchStatus(B_NO_INIT), + fTarget(other.Target()), + fPendingLaunchDataReplies(0, false) { + mutex_init(&fLaunchStatusLock, "launch status lock"); + fCondition = other.fCondition; // TODO: copy events //fEvent = other.fEvent; @@ -343,16 +350,21 @@ Job::Launch() // Launch by signature BString signature("application/"); signature << Name(); - return BRoster::Private().Launch(signature.String(), NULL, NULL, - 0, NULL, &environment[0], &fTeam); + + status_t status = BRoster::Private().Launch(signature.String(), NULL, + NULL, 0, NULL, &environment[0], &fTeam); + _SetLaunchStatus(status); + return status; } // Build argument vector entry_ref ref; status_t status = get_ref_for_path(fArguments.StringAt(0).String(), &ref); - if (status != B_OK) + if (status != B_OK) { + _SetLaunchStatus(status); return status; + } std::vector args; @@ -365,15 +377,28 @@ Job::Launch() } // Launch via entry_ref - return BRoster::Private().Launch(NULL, &ref, NULL, count, &args[0], + status = BRoster::Private().Launch(NULL, &ref, NULL, count, &args[0], &environment[0], &fTeam); + _SetLaunchStatus(status); + return status; } bool Job::IsLaunched() const { - return fTeam >= 0; + return fLaunchStatus != B_NO_INIT; +} + + +status_t +Job::HandleGetLaunchData(BMessage* message) +{ + MutexLocker launchLocker(fLaunchStatusLock); + if (IsLaunched()) + return _SendLaunchDataReply(message); + + return fPendingLaunchDataReplies.AddItem(message) ? B_OK : B_NO_MEMORY; } @@ -434,3 +459,49 @@ Job::_AddStringList(std::vector& array, const BStringList& list) array.push_back(list.StringAt(index).String()); } } + + +void +Job::_SetLaunchStatus(status_t launchStatus) +{ + MutexLocker launchLocker(fLaunchStatusLock); + fLaunchStatus = launchStatus != B_NO_INIT ? launchStatus : B_ERROR; + launchLocker.Unlock(); + + _SendPendingLaunchDataReplies(); +} + + +status_t +Job::_SendLaunchDataReply(BMessage* message) +{ + BMessage reply(fTeam < 0 ? fTeam : (uint32)B_OK); + if (reply.what == B_OK) { + reply.AddInt32("team", fTeam); + + PortMap::const_iterator iterator = fPortMap.begin(); + for (; iterator != fPortMap.end(); iterator++) { + BString name; + if (iterator->second.HasString("name")) + name << iterator->second.GetString("name") << "_"; + name << "port"; + + reply.AddInt32(name.String(), + iterator->second.GetInt32("port", -1)); + } + } + + message->SendReply(&reply); + delete message; + return B_OK; +} + + +void +Job::_SendPendingLaunchDataReplies() +{ + for (int32 i = 0; i < fPendingLaunchDataReplies.CountItems(); i++) + _SendLaunchDataReply(fPendingLaunchDataReplies.ItemAt(i)); + + fPendingLaunchDataReplies.MakeEmpty(); +} diff --git a/src/servers/launch/Job.h b/src/servers/launch/Job.h index e2ee0b4d0f..63afeae97a 100644 --- a/src/servers/launch/Job.h +++ b/src/servers/launch/Job.h @@ -15,6 +15,8 @@ #include #include +#include + using namespace BSupportKit; class BMessage; @@ -68,6 +70,8 @@ public: status_t Launch(); bool IsLaunched() const; + status_t HandleGetLaunchData(BMessage* message); + protected: virtual status_t Execute(); @@ -78,6 +82,11 @@ private: void _AddStringList(std::vector& array, const BStringList& list); + void _SetLaunchStatus(status_t launchStatus); + + status_t _SendLaunchDataReply(BMessage* message); + void _SendPendingLaunchDataReplies(); + private: BStringList fArguments; BStringList fRequirements; @@ -87,8 +96,12 @@ private: PortMap fPortMap; status_t fInitStatus; team_id fTeam; + status_t fLaunchStatus; + mutex fLaunchStatusLock; ::Target* fTarget; ::Condition* fCondition; + BObjectList + fPendingLaunchDataReplies; }; diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index b64d40aead..f9733f916c 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -483,31 +483,29 @@ LaunchDaemon::_HandleGetLaunchData(BMessage* message) launchJob = false; } } - } + } else + launchJob = false; + bool ownsMessage = false; if (reply.what == B_OK) { - // If the job has not been launched yet, we'll pass on our - // team here. The rationale behind this is that this team - // will temporarily own the synchronous reply ports. - reply.AddInt32("team", job->Team() < 0 - ? current_team() : job->Team()); - - PortMap::const_iterator iterator = job->Ports().begin(); - for (; iterator != job->Ports().end(); iterator++) { - BString name; - if (iterator->second.HasString("name")) - name << iterator->second.GetString("name") << "_"; - name << "port"; - - reply.AddInt32(name.String(), - iterator->second.GetInt32("port", -1)); - } - // Launch the job if it hasn't been launched already if (launchJob) _LaunchJob(job); + + DetachCurrentMessage(); + status_t result = job->HandleGetLaunchData(message); + if (result == B_OK) { + // Replying is delegated to the job. + return; + } + + ownsMessage = true; + reply.what = result; } + message->SendReply(&reply); + if (ownsMessage) + delete message; } From da1815146999aa993efcf62669ccfc3f552c978b Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Wed, 26 Aug 2015 20:53:36 +0200 Subject: [PATCH 084/125] Revert "MediaNode: Wait for 0 time if the absolute timeout is in the past" This reverts commit ae9cbf9c4e167470b47964059e90c2b0881367eb. * Thanks to Pawel Dziepak for reporting! --- src/kits/media/MediaNode.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/kits/media/MediaNode.cpp b/src/kits/media/MediaNode.cpp index ab68d927f5..bece94a000 100644 --- a/src/kits/media/MediaNode.cpp +++ b/src/kits/media/MediaNode.cpp @@ -343,10 +343,6 @@ BMediaNode::WaitForMessage(bigtime_t waitUntil, uint32 flags, char data[B_MEDIA_MESSAGE_SIZE]; int32 message; ssize_t size; - - if (waitUntil < TimeSource()->RealTime()) - waitUntil = 0; - while (true) { size = read_port_etc(ControlPort(), &message, data, sizeof(data), B_ABSOLUTE_TIMEOUT, waitUntil); From 1ea54e567e1dcb60302e6a685c0ab99ed27bad16 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 25 Aug 2015 10:25:10 -0400 Subject: [PATCH 085/125] docs/user: BAlert: Fix incorrect ::TextView() docs. TextView() returns *the* BTextView the BAlert is using, not a new TextView with the contents of the BAlert (which is what this seemed to imply). --- docs/user/interface/Alert.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user/interface/Alert.dox b/docs/user/interface/Alert.dox index b92ec9ad79..d4be24c132 100644 --- a/docs/user/interface/Alert.dox +++ b/docs/user/interface/Alert.dox @@ -227,7 +227,7 @@ int32 button_index = alert->Go(); See button_width for details. \param spacing Determines how the buttons are spaced. Options are \li \c B_EVEN_SPACING - \li \c B_OFFSET_SPACING + \li \c B_OFFSET_SPACING See button_spacing for details. \param type Constant that determines which alert icon is displayed. @@ -408,7 +408,7 @@ int32 button_index = alert->Go(); /*! \fn BTextView* BAlert::TextView() const - \brief Returns a TextView containing the text of the Alert. + \brief Returns the Alert's TextView. \since BeOS R3 */ From 41f43d568fa1f2af68bd3209850cb0b349b49ff4 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Wed, 26 Aug 2015 14:36:59 -0400 Subject: [PATCH 086/125] Screen: Rework AlertView to just use BAlert. Fixes #12330. --- src/preferences/screen/AlertView.cpp | 176 ------------------------ src/preferences/screen/AlertView.h | 39 ------ src/preferences/screen/AlertWindow.cpp | 109 +++++++++++---- src/preferences/screen/AlertWindow.h | 29 ++-- src/preferences/screen/Jamfile | 4 +- src/preferences/screen/ScreenWindow.cpp | 8 +- 6 files changed, 105 insertions(+), 260 deletions(-) delete mode 100644 src/preferences/screen/AlertView.cpp delete mode 100644 src/preferences/screen/AlertView.h diff --git a/src/preferences/screen/AlertView.cpp b/src/preferences/screen/AlertView.cpp deleted file mode 100644 index 7d50749b85..0000000000 --- a/src/preferences/screen/AlertView.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2001-2008, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * Rafael Romo - * Stefano Ceccherini (burton666@libero.it) - * Axel Dörfler, axeld@pinc-software.de - */ - - -#include "AlertView.h" -#include "Constants.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -#undef B_TRANSLATION_CONTEXT -#define B_TRANSLATION_CONTEXT "Screen" - - -AlertView::AlertView(BRect frame, const char *name) - : BView(frame, name, B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED), - // we will wait 12 seconds until we send a message - fSeconds(12) -{ - SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - fBitmap = InitIcon(); - - BRect rect(60, 8, 400, 36); - BStringView *stringView = new BStringView(rect, NULL, - B_TRANSLATE("Do you wish to keep these settings?")); - stringView->SetFont(be_bold_font); - stringView->ResizeToPreferred(); - AddChild(stringView); - - rect = stringView->Frame(); - rect.OffsetBy(0, rect.Height()); - fCountdownView = new BStringView(rect, "countdown", NULL); - UpdateCountdownView(); - fCountdownView->ResizeToPreferred(); - AddChild(fCountdownView); - - BButton* keepButton = new BButton(rect, "keep", B_TRANSLATE("Keep"), - new BMessage(BUTTON_KEEP_MSG), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); - keepButton->ResizeToPreferred(); - AddChild(keepButton); - - BButton* button = new BButton(rect, "undo", B_TRANSLATE("Undo"), - new BMessage(BUTTON_UNDO_MSG), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); - button->ResizeToPreferred(); - AddChild(button); - - // we're resizing ourselves to the right size - // (but we're not implementing GetPreferredSize(), bad style!) - float width = stringView->Frame().right; - if (fCountdownView->Frame().right > width) - width = fCountdownView->Frame().right; - if (width < Bounds().Width()) - width = Bounds().Width(); - - float height - = fCountdownView->Frame().bottom + 24 + button->Bounds().Height(); - ResizeTo(width, height); - - keepButton->MoveTo(Bounds().Width() - 8 - keepButton->Bounds().Width(), - Bounds().Height() - 8 - keepButton->Bounds().Height()); - button->MoveTo(keepButton->Frame().left - button->Bounds().Width() - 8, - keepButton->Frame().top); - - keepButton->MakeDefault(true); -} - - -void -AlertView::AttachedToWindow() -{ - // the view displays a decrementing counter - // (until the user must take action) - Window()->SetPulseRate(1000000); - // every second - - SetEventMask(B_KEYBOARD_EVENTS); -} - - -void -AlertView::Draw(BRect updateRect) -{ - rgb_color dark = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), - B_DARKEN_1_TINT); - SetHighColor(dark); - - FillRect(BRect(0.0, 0.0, 30.0, Bounds().bottom)); - - if (fBitmap != NULL) { - SetDrawingMode(B_OP_ALPHA); - DrawBitmap(fBitmap, BPoint(18.0, 6.0)); - SetDrawingMode(B_OP_COPY); - } -} - - -void -AlertView::Pulse() -{ - if (--fSeconds == 0) - Window()->PostMessage(BUTTON_UNDO_MSG); - else - UpdateCountdownView(); -} - - -void -AlertView::KeyDown(const char* bytes, int32 numBytes) -{ - if (numBytes == 1 && bytes[0] == B_ESCAPE) - Window()->PostMessage(BUTTON_UNDO_MSG); -} - - -void -AlertView::UpdateCountdownView() -{ - BString string; - string = B_TRANSLATE("Settings will revert in %seconds."); - - BTimeUnitFormat format; - BString tmp; - format.Format(tmp, fSeconds, B_TIME_UNIT_SECOND); - - string.ReplaceFirst("%seconds", tmp); - fCountdownView->SetText(string.String()); -} - - -BBitmap* -AlertView::InitIcon() -{ - // This is how BAlert gets to its icon - BBitmap* icon = NULL; - BPath path; - if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) == B_OK) { - path.Append("app_server"); - BResources resources; - BFile file; - if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK - && resources.SetTo(&file) == B_OK) { - size_t size; - const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, - "warn", &size); - if (data) { - icon = new BBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32); - if (BIconUtils::GetVectorIcon((const uint8*)data, size, icon) - != B_OK) { - delete icon; - icon = NULL; - } - } - } - } - - return icon; -} diff --git a/src/preferences/screen/AlertView.h b/src/preferences/screen/AlertView.h deleted file mode 100644 index 66432b3c42..0000000000 --- a/src/preferences/screen/AlertView.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2001-2005, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * Rafael Romo - * Stefano Ceccherini (burton666@libero.it) - * Axel Dörfler, axeld@pinc-software.de - */ -#ifndef ALERT_VIEW_H -#define ALERT_VIEW_H - - -#include -#include - -class BBitmap; -class BStringView; - - -class AlertView : public BView { - public: - AlertView(BRect frame, const char* name); - - virtual void AttachedToWindow(); - virtual void Draw(BRect updateRect); - virtual void Pulse(); - virtual void KeyDown(const char* bytes, int32 numBytes); - - private: - void UpdateCountdownView(); - BBitmap* InitIcon(); - - BStringView* fCountdownView; - BBitmap* fBitmap; - int32 fSeconds; -}; - -#endif /* ALERT_VIEW_H */ diff --git a/src/preferences/screen/AlertWindow.cpp b/src/preferences/screen/AlertWindow.cpp index 51943fd429..8d9ec10469 100644 --- a/src/preferences/screen/AlertWindow.cpp +++ b/src/preferences/screen/AlertWindow.cpp @@ -1,60 +1,117 @@ /* - * Copyright 2001-2006, Haiku. + * Copyright 2001-2015, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Rafael Romo * Stefano Ceccherini (burton666@libero.it) * Axel Dörfler, axeld@pinc-software.de + * Augustin Cavalier */ + #include "AlertWindow.h" -#include "AlertView.h" #include "Constants.h" +#include #include +#include +#include #include -#include +#include #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Screen" -AlertWindow::AlertWindow(BMessenger target) - : BWindow(BRect(100.0, 100.0, 400.0, 193.0), B_TRANSLATE("Undo"), - B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, - B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES), - fTarget(target) +AlertWindow::AlertWindow(BMessenger handler) + : BAlert(B_TRANSLATE("Confirm changes"), + "", B_TRANSLATE("Undo"), B_TRANSLATE("Keep")), + // we will wait 12 seconds until we send a message + fSeconds(12), + fHandler(handler) { - fAlertView = new AlertView(Bounds(), "AlertView"); - - ResizeTo(fAlertView->Bounds().Width(), fAlertView->Bounds().Height()); - AddChild(fAlertView); - - // center window on screen - BScreen screen(this); - MoveTo(screen.Frame().left + (screen.Frame().Width() - Frame().Width()) / 2, - screen.Frame().top + (screen.Frame().Height() - Frame().Height()) / 2); + SetType(B_WARNING_ALERT); + SetPulseRate(1000000); + TextView()->SetStylable(true); + TextView()->GetFontAndColor(0, &fOriginalFont); + fFont = fOriginalFont; + fFont.SetFace(B_BOLD_FACE); + UpdateCountdownView(); } void -AlertWindow::MessageReceived(BMessage *message) +AlertWindow::DispatchMessage(BMessage* message, BHandler* handler) +{ + if (message->what == B_PULSE) { + if (--fSeconds == 0) { + fHandler.SendMessage(BUTTON_UNDO_MSG); + PostMessage(B_QUIT_REQUESTED); + Hide(); + } else + UpdateCountdownView(); + } + + BAlert::DispatchMessage(message, handler); +} + + +void +AlertWindow::MessageReceived(BMessage* message) { switch (message->what) { - case BUTTON_KEEP_MSG: - fTarget.SendMessage(MAKE_INITIAL_MSG); - PostMessage(B_QUIT_REQUESTED); + case 'ALTB': // alert button message + { + int32 which; + if (message->FindInt32("which", &which) == B_OK) { + if (which == 1) + fHandler.SendMessage(MAKE_INITIAL_MSG); + else if (which == 0) + fHandler.SendMessage(BUTTON_UNDO_MSG); + PostMessage(B_QUIT_REQUESTED); + Hide(); + } break; + } - case BUTTON_UNDO_MSG: - fTarget.SendMessage(BUTTON_UNDO_MSG); - PostMessage(B_QUIT_REQUESTED); - break; + case B_KEY_DOWN: + { + int8 val; + if (message->FindInt8("byte", &val) == B_OK && val == B_ESCAPE) { + fHandler.SendMessage(BUTTON_UNDO_MSG); + PostMessage(B_QUIT_REQUESTED); + Hide(); + break; + } + // fall through + } default: - BWindow::MessageReceived(message); + BAlert::MessageReceived(message); break; } } + + +void +AlertWindow::UpdateCountdownView() +{ + BString str1 = B_TRANSLATE("Do you wish to keep these settings?"); + BString string = str1; + string += "\n"; + string += B_TRANSLATE("Settings will revert in %seconds."); + + BTimeUnitFormat format; + BString tmp; + format.Format(tmp, fSeconds, B_TIME_UNIT_SECOND); + + string.ReplaceFirst("%seconds", tmp); + // The below is black magic, do not touch. We really need to refactor + // BTextView sometime... + TextView()->SetFontAndColor(0, str1.Length() + 1, &fOriginalFont, + B_FONT_ALL); + TextView()->SetText(string.String()); + TextView()->SetFontAndColor(0, str1.Length(), &fFont, B_FONT_ALL); +} diff --git a/src/preferences/screen/AlertWindow.h b/src/preferences/screen/AlertWindow.h index d216757073..48a4d00282 100644 --- a/src/preferences/screen/AlertWindow.h +++ b/src/preferences/screen/AlertWindow.h @@ -1,34 +1,39 @@ /* - * Copyright 2001-2005, Haiku. + * Copyright 2001-2015, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Rafael Romo * Stefano Ceccherini (burton666@libero.it) * Axel Dörfler, axeld@pinc-software.de + * Augustin Cavalier */ #ifndef ALERT_WINDOW_H #define ALERT_WINDOW_H -#include +#include +#include #include +#include + +class BWindow; -class BMessageRunner; -class BButton; -class AlertView; - - -class AlertWindow : public BWindow { +class AlertWindow : public BAlert { public: - AlertWindow(BMessenger target); + AlertWindow(BMessenger handler); - virtual void MessageReceived(BMessage *message); + virtual void MessageReceived(BMessage* message); + virtual void DispatchMessage(BMessage* message, BHandler* handler); private: - BMessenger fTarget; - AlertView* fAlertView; + void UpdateCountdownView(); + + int32 fSeconds; + BMessenger fHandler; + BFont fOriginalFont; + BFont fFont; }; #endif /* ALERT_WINDOW_H */ diff --git a/src/preferences/screen/Jamfile b/src/preferences/screen/Jamfile index d2370cd486..ba8bc57e53 100644 --- a/src/preferences/screen/Jamfile +++ b/src/preferences/screen/Jamfile @@ -1,14 +1,13 @@ SubDir HAIKU_TOP src preferences screen ; -SetSubDirSupportedPlatformsBeOSCompatible ; AddSubDirSupportedPlatforms libbe_test ; UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders [ FDirName graphics radeon ] ; UsePrivateHeaders interface ; +SubDirC++Flags -O0 -g ; Preference Screen : - AlertView.cpp AlertWindow.cpp MonitorView.cpp multimon.cpp @@ -31,7 +30,6 @@ if $(TARGET_PLATFORM) = libbe_test { DoCatalogs Screen : x-vnd.Haiku-Screen : - AlertView.cpp AlertWindow.cpp RefreshSlider.cpp RefreshWindow.cpp diff --git a/src/preferences/screen/ScreenWindow.cpp b/src/preferences/screen/ScreenWindow.cpp index 3ccc5a3890..29f38ddb39 100644 --- a/src/preferences/screen/ScreenWindow.cpp +++ b/src/preferences/screen/ScreenWindow.cpp @@ -1185,7 +1185,7 @@ void ScreenWindow::_CheckApplyEnabled() { bool applyEnabled = true; - + if (fSelected == fActive) { applyEnabled = false; if (fAllWorkspacesItem->IsMarked()) { @@ -1200,7 +1200,7 @@ ScreenWindow::_CheckApplyEnabled() } } } - + fApplyButton->SetEnabled(applyEnabled); uint32 columns; @@ -1336,8 +1336,8 @@ ScreenWindow::_Apply() fActive = fSelected; // TODO: only show alert when this is an unknown mode - BWindow* window = new AlertWindow(this); - window->Show(); + BAlert* window = new AlertWindow(this); + window->Go(NULL); } else { char message[256]; snprintf(message, sizeof(message), From 281409fdc0c74d8bc5c60c5713a8158d0a601a58 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Wed, 26 Aug 2015 15:54:15 -0400 Subject: [PATCH 087/125] Revert accidental addition to Jamfile. --- src/preferences/screen/Jamfile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/preferences/screen/Jamfile b/src/preferences/screen/Jamfile index ba8bc57e53..116d9f2606 100644 --- a/src/preferences/screen/Jamfile +++ b/src/preferences/screen/Jamfile @@ -6,7 +6,6 @@ UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders [ FDirName graphics radeon ] ; UsePrivateHeaders interface ; -SubDirC++Flags -O0 -g ; Preference Screen : AlertWindow.cpp MonitorView.cpp From d6039d2b239d1571ad7ad1d61aedba713c23480e Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Thu, 27 Aug 2015 11:48:10 +0200 Subject: [PATCH 088/125] Midi: Remove some duplicated code Introduced new private read/write_midi_settings() and used them in MidiSettingsView and SoftSynth. --- headers/private/midi/MidiSettings.h | 24 ++++++++ src/kits/midi/Jamfile | 1 + src/kits/midi/MidiSettings.cpp | 68 ++++++++++++++++++++++ src/kits/midi/SoftSynth.cpp | 22 +++---- src/preferences/media/Jamfile | 4 +- src/preferences/media/MidiSettingsView.cpp | 44 ++++---------- 6 files changed, 116 insertions(+), 47 deletions(-) create mode 100644 headers/private/midi/MidiSettings.h create mode 100644 src/kits/midi/MidiSettings.cpp diff --git a/headers/private/midi/MidiSettings.h b/headers/private/midi/MidiSettings.h new file mode 100644 index 0000000000..ddefc318b5 --- /dev/null +++ b/headers/private/midi/MidiSettings.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef MIDI_SETTINGS_PRIVATE_H_ +#define MIDI_SETTINGS_PRIVATE_H_ + +#include +#include + +namespace BPrivate { + +struct midi_settings { + char soundfont_file[B_FILE_NAME_LENGTH]; +}; + +status_t read_midi_settings(struct midi_settings* settings); +status_t write_midi_settings(struct midi_settings settings); + +}; + + +#endif /* MIDI_SETTINGS_PRIVATE_H_ */ diff --git a/src/kits/midi/Jamfile b/src/kits/midi/Jamfile index 85d4e72a82..d6bb5c2a1c 100644 --- a/src/kits/midi/Jamfile +++ b/src/kits/midi/Jamfile @@ -18,6 +18,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { Midi.cpp MidiGlue.cpp MidiPort.cpp + MidiSettings.cpp MidiStore.cpp MidiSynth.cpp MidiSynthFile.cpp diff --git a/src/kits/midi/MidiSettings.cpp b/src/kits/midi/MidiSettings.cpp new file mode 100644 index 0000000000..be1cd00be6 --- /dev/null +++ b/src/kits/midi/MidiSettings.cpp @@ -0,0 +1,68 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include + +#include +#include +#include + +#include +#include +#include + +#define SETTINGS_FILE "midi" + +namespace BPrivate { + +status_t +read_midi_settings(struct midi_settings* settings) +{ + if (settings == NULL) + return B_ERROR; + + char buffer[B_FILE_NAME_LENGTH + 128]; + BPath path; + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + if (status != B_OK) + return status; + + path.Append("midi"); + BFile file(path.Path(), B_READ_ONLY); + if (file.InitCheck() != B_OK + || file.Read(buffer, sizeof(buffer)) <= 0) + return B_ERROR; + + sscanf(buffer, "# Midi Settings\n soundfont = %s\n", + settings->soundfont_file); + + return B_OK; +} + + +status_t +write_midi_settings(struct midi_settings settings) +{ + char buffer[B_FILE_NAME_LENGTH + 128]; + snprintf(buffer, sizeof(buffer), "# Midi Settings\n soundfont = %s\n", + settings.soundfont_file); + + BPath path; + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + if (status != B_OK) + return status; + + path.Append(SETTINGS_FILE); + BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); + + size_t bufferSize = strlen(buffer); + if (file.InitCheck() != B_OK + || file.Write(buffer, bufferSize) != (ssize_t)bufferSize) + return B_ERROR; + + return B_OK; +} + +} diff --git a/src/kits/midi/SoftSynth.cpp b/src/kits/midi/SoftSynth.cpp index baacf9944f..a7c003cc4b 100644 --- a/src/kits/midi/SoftSynth.cpp +++ b/src/kits/midi/SoftSynth.cpp @@ -21,9 +21,12 @@ #include #include #include + #include #include +#include + #include "debug.h" #include "MidiGlue.h" // for MAKE_BIGTIME #include "SoftSynth.h" @@ -108,22 +111,15 @@ BSoftSynth::SetDefaultInstrumentsFile() // MidiSettingsView::_RetrieveSoftSynthList() // We first search for a setting file (or symlink to it) // in the user settings directory - char buffer[512]; - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { - path.Append("midi"); - BFile file(path.Path(), B_READ_ONLY); - if (file.InitCheck() == B_OK - && file.Read(buffer, sizeof(buffer)) > 0) { - char soundFont[512]; - sscanf(buffer, "# Midi Settings\n soundfont = %s\n", - soundFont); - if (SetInstrumentsFile(soundFont) == B_OK) - return B_OK; - } + + struct BPrivate::midi_settings settings; + if (BPrivate::read_midi_settings(&settings) == B_OK) { + if (SetInstrumentsFile(settings.soundfont_file) == B_OK) + return B_OK; } // Try a well-known (and usually present on a default install) soft synth + BPath path; if (find_directory(B_SYNTH_DIRECTORY, &path, false, NULL) == B_OK) { path.Append("synth/TimGM6mb.sf2"); if (SetInstrumentsFile(path.Path()) == B_OK) diff --git a/src/preferences/media/Jamfile b/src/preferences/media/Jamfile index f4f9fffe49..9bff322326 100644 --- a/src/preferences/media/Jamfile +++ b/src/preferences/media/Jamfile @@ -6,7 +6,7 @@ if ! $(TARGET_PLATFORM_HAIKU_COMPATIBLE) { SubDirC++Flags -fmultiple-symbol-spaces ; } -UsePrivateHeaders media shared ; +UsePrivateHeaders media midi shared ; Preference Media : Media.cpp @@ -15,7 +15,7 @@ Preference Media : MediaViews.cpp MediaWindow.cpp MidiSettingsView.cpp - : media be localestub [ TargetLibsupc++ ] + : media midi be localestub [ TargetLibsupc++ ] : media.rdef ; diff --git a/src/preferences/media/MidiSettingsView.cpp b/src/preferences/media/MidiSettingsView.cpp index 52a10d4c4b..cdf0fbb662 100644 --- a/src/preferences/media/MidiSettingsView.cpp +++ b/src/preferences/media/MidiSettingsView.cpp @@ -5,6 +5,8 @@ #include "MidiSettingsView.h" +#include + #include #include #include @@ -27,8 +29,6 @@ #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Midi View" -#define SETTINGS_FILE "midi" - const static uint32 kSelectSoundFont = 'SeSf'; @@ -126,25 +126,13 @@ MidiSettingsView::_RetrieveSoftSynthList() void MidiSettingsView::_LoadSettings() { - // TODO: Duplicated code between here - // and BSoftSynth::SetDefaultInstrumentsFile - char buffer[512]; - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { - path.Append(SETTINGS_FILE); - BFile file(path.Path(), B_READ_ONLY); - if (file.InitCheck() == B_OK) { - file.Read(buffer, sizeof(buffer)); - char soundFont[512]; - sscanf(buffer, "# Midi Settings\n soundfont = %s\n", - soundFont); - - for (int32 i = 0; i < fListView->CountItems(); i++) { - BStringItem* item = (BStringItem*)fListView->ItemAt(i); - if (!strcmp(item->Text(), soundFont)) { - fListView->Select(i); - break; - } + struct BPrivate::midi_settings settings; + if (BPrivate::read_midi_settings(&settings) == B_OK) { + for (int32 i = 0; i < fListView->CountItems(); i++) { + BStringItem* item = (BStringItem*)fListView->ItemAt(i); + if (!strcmp(item->Text(), settings.soundfont_file)) { + fListView->Select(i); + break; } } } @@ -162,16 +150,8 @@ MidiSettingsView::_SaveSettings() if (item == NULL) return; - char buffer[512]; - snprintf(buffer, 512, "# Midi Settings\n soundfont = %s\n", - item->Text()); - - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { - path.Append(SETTINGS_FILE); - BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); - if (file.InitCheck() == B_OK) - file.Write(buffer, strlen(buffer)); - } + struct BPrivate::midi_settings settings; + strlcpy(settings.soundfont_file, item->Text(), sizeof(settings.soundfont_file)); + BPrivate::write_midi_settings(settings); } From 90cdf5e42e888bb80eabe4770c7c34149ad60f02 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Thu, 27 Aug 2015 19:38:44 +0200 Subject: [PATCH 089/125] BMediaNode::WaitForMessage: protect it over negative timeouts --- src/kits/media/MediaNode.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/kits/media/MediaNode.cpp b/src/kits/media/MediaNode.cpp index bece94a000..c7b5f21f16 100644 --- a/src/kits/media/MediaNode.cpp +++ b/src/kits/media/MediaNode.cpp @@ -343,6 +343,13 @@ BMediaNode::WaitForMessage(bigtime_t waitUntil, uint32 flags, char data[B_MEDIA_MESSAGE_SIZE]; int32 message; ssize_t size; + + // TODO: Investigate on this issue + if (waitUntil < 0) { + TRACE("BMediaNode::WaitForMessage: Negative timeout!\n"); + waitUntil = 0; + } + while (true) { size = read_port_etc(ControlPort(), &message, data, sizeof(data), B_ABSOLUTE_TIMEOUT, waitUntil); From be7d9d3f5d23570f02de6853c781a9a56b13397b Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Thu, 27 Aug 2015 19:40:00 +0200 Subject: [PATCH 090/125] BMediaEventLooper: With B_WOULD_BLOCK we may still handle an event --- src/kits/media/MediaEventLooper.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/kits/media/MediaEventLooper.cpp b/src/kits/media/MediaEventLooper.cpp index c5928454d9..c9c006d287 100644 --- a/src/kits/media/MediaEventLooper.cpp +++ b/src/kits/media/MediaEventLooper.cpp @@ -228,11 +228,12 @@ BMediaEventLooper::ControlLoop() return; err = WaitForMessage(waitUntil); - if (err == B_TIMED_OUT) { + if (err == B_TIMED_OUT + || err == B_WOULD_BLOCK) { media_timed_event event; if (hasEvent) err = fEventQueue.RemoveFirstEvent(&event); - else + else if (hasRealtime) err = fRealTimeQueue.RemoveFirstEvent(&event); if (err == B_OK) { From d15321ff907a1203836c9f5ecedd977fe1d9720a Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Fri, 28 Aug 2015 17:25:17 +0200 Subject: [PATCH 091/125] BMediaRoster::Roster Use BAutolock --- src/kits/media/MediaRoster.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 6799b01d7a..4268720846 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -44,6 +44,7 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus " #include +#include #include #include #include @@ -83,6 +84,7 @@ struct RosterNotification { static bool sServerIsUp = false; static List sNotificationList; +static BLocker sInitLocker("BMediaRoster::Roster locker"); } // namespace media } // namespace BPrivate @@ -2188,10 +2190,14 @@ BMediaRoster::UnregisterNode(BMediaNode* node) /*static*/ BMediaRoster* BMediaRoster::Roster(status_t* out_error) { - static BLocker locker("BMediaRoster::Roster locker"); - locker.Lock(); + BAutolock lock(sInitLocker); + + if (!lock.IsLocked()) + return NULL; + if (out_error) *out_error = B_OK; + if (sDefaultInstance == NULL) { status_t err; sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err); @@ -2207,7 +2213,6 @@ BMediaRoster::Roster(status_t* out_error) *out_error = err; } } - locker.Unlock(); return sDefaultInstance; } From 1c3d7e0c688650e6b100f36a0472a7a5d45358b0 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Fri, 28 Aug 2015 17:30:52 +0200 Subject: [PATCH 092/125] MixerControl: Add more safeness for Roster() errors --- src/bin/desklink/MixerControl.cpp | 24 ++++++++++++++---------- src/bin/desklink/MixerControl.h | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/bin/desklink/MixerControl.cpp b/src/bin/desklink/MixerControl.cpp index dea3fa52e6..81cb36cbd3 100644 --- a/src/bin/desklink/MixerControl.cpp +++ b/src/bin/desklink/MixerControl.cpp @@ -28,8 +28,10 @@ MixerControl::MixerControl(int32 volumeWhich) fMuteParameter(NULL), fMin(0.0f), fMax(0.0f), - fStep(0.0f) + fStep(0.0f), + fRoster(NULL) { + fRoster = BMediaRoster::Roster(); } @@ -47,22 +49,22 @@ MixerControl::Connect(int32 volumeWhich, float* _value, const char** _error) _Disconnect(); status_t status = B_OK; - // BMediaRoster::Roster() doesn't set it if all is ok const char* errorString = NULL; - BMediaRoster* roster = BMediaRoster::Roster(&status); + if (fRoster == NULL) + fRoster = BMediaRoster::Roster(&status); - if (BMediaRoster::IsRunning() && roster != NULL + if (BMediaRoster::IsRunning() && fRoster != NULL && status == B_OK) { switch (volumeWhich) { case VOLUME_USE_MIXER: - status = roster->GetAudioMixer(&fGainMediaNode); + status = fRoster->GetAudioMixer(&fGainMediaNode); break; case VOLUME_USE_PHYS_OUTPUT: - status = roster->GetAudioOutput(&fGainMediaNode); + status = fRoster->GetAudioOutput(&fGainMediaNode); break; } if (status == B_OK) { - status = roster->GetParameterWebFor(fGainMediaNode, &fParameterWeb); + status = fRoster->GetParameterWebFor(fGainMediaNode, &fParameterWeb); if (status == B_OK) { // Finding the Mixer slider in the audio output ParameterWeb int32 numParams = fParameterWeb->CountParameters(); @@ -252,9 +254,11 @@ MixerControl::_Disconnect() fParameterWeb = NULL; fMixerParameter = NULL; - BMediaRoster* roster = BMediaRoster::CurrentRoster(); - if (roster != NULL && fGainMediaNode != media_node::null) - roster->ReleaseNode(fGainMediaNode); + if (fRoster == NULL) + fRoster = BMediaRoster::Roster(); + + if (fRoster != NULL && fGainMediaNode != media_node::null) + fRoster->ReleaseNode(fGainMediaNode); fGainMediaNode = media_node::null; } diff --git a/src/bin/desklink/MixerControl.h b/src/bin/desklink/MixerControl.h index 62d2dca621..68fd1254e6 100644 --- a/src/bin/desklink/MixerControl.h +++ b/src/bin/desklink/MixerControl.h @@ -56,6 +56,7 @@ private: float fMin; float fMax; float fStep; + BMediaRoster* fRoster; }; #endif // MIXER_CONTROL_H From 5d8765c0af90461ec6f9278592c000940db2b46e Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Fri, 28 Aug 2015 17:32:14 +0200 Subject: [PATCH 093/125] media_server: No need to call Roster() every time --- src/servers/media/DefaultManager.cpp | 82 +++++++++++++++------------- src/servers/media/DefaultManager.h | 2 + 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/servers/media/DefaultManager.cpp b/src/servers/media/DefaultManager.cpp index 6354189564..6e00e93ca8 100644 --- a/src/servers/media/DefaultManager.cpp +++ b/src/servers/media/DefaultManager.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -46,7 +45,8 @@ const char *kDefaultManagerSettingsFile = "MDefaultManager"; DefaultManager::DefaultManager() - : fMixerConnected(false), + : + fMixerConnected(false), fPhysicalVideoOut(-1), fPhysicalVideoIn(-1), fPhysicalAudioOut(-1), @@ -57,7 +57,8 @@ DefaultManager::DefaultManager() fPhysicalAudioOutInputID(0), fRescanThread(-1), fRescanRequested(0), - fRescanLock("rescan default manager") + fRescanLock("rescan default manager"), + fRoster(NULL) { strcpy(fPhysicalAudioOutInputName, "default"); fBeginHeader[0] = 0xab00150b; @@ -66,6 +67,10 @@ DefaultManager::DefaultManager() fEndHeader[0] = 0x7465726d; fEndHeader[1] = 0x6d666c67; fEndHeader[2] = 0x00000002; + + fRoster = BMediaRoster::Roster(); + if (fRoster == NULL) + TRACE("DefaultManager: The roster is NULL\n"); } @@ -393,7 +398,7 @@ DefaultManager::_RescanThread() // Connect the mixer and physical audio out (soundcard) if (!fMixerConnected && fAudioMixer != -1 && fPhysicalAudioOut != -1) { - fMixerConnected = B_OK == _ConnectMixerToOutput(); + fMixerConnected = _ConnectMixerToOutput() == B_OK; if (!fMixerConnected) TRACE("DefaultManager: failed to connect mixer and " "soundcard\n"); @@ -455,7 +460,7 @@ DefaultManager::_FindPhysical(volatile media_node_id *id, uint32 default_type, memset(&format, 0, sizeof(format)); format.type = type; count = MAX_NODE_INFOS; - rv = BMediaRoster::Roster()->GetLiveNodes(&info[0], &count, + rv = fRoster->GetLiveNodes(&info[0], &count, isInput ? NULL : &format, isInput ? &format : NULL, NULL, isInput ? B_BUFFER_PRODUCER | B_PHYSICAL_INPUT : B_BUFFER_CONSUMER | B_PHYSICAL_OUTPUT); @@ -493,7 +498,7 @@ DefaultManager::_FindPhysical(volatile media_node_id *id, uint32 default_type, } if (msg) { // we have a default info msg dormant_node_info dninfo; - if (BMediaRoster::Roster()->GetDormantNodeFor(info[i].node, + if (fRoster->GetDormantNodeFor(info[i].node, &dninfo) != B_OK) { ERROR("Couldn't GetDormantNodeFor\n"); continue; @@ -533,17 +538,17 @@ DefaultManager::_FindTimeSource() */ if (fPhysicalAudioOut != -1) { media_node clone; - if (B_OK == BMediaRoster::Roster()->GetNodeFor(fPhysicalAudioOut, - &clone)) { + if (fRoster->GetNodeFor(fPhysicalAudioOut, + &clone) == B_OK) { if (clone.kind & B_TIME_SOURCE) { fTimeSource = clone.node; - BMediaRoster::Roster()->StartTimeSource(clone, + fRoster->StartTimeSource(clone, system_time() + 1000); - BMediaRoster::Roster()->ReleaseNode(clone); + fRoster->ReleaseNode(clone); TRACE("Default DAC timesource created!\n"); return; } - BMediaRoster::Roster()->ReleaseNode(clone); + fRoster->ReleaseNode(clone); } else { TRACE("Default DAC is not a timesource!\n"); } @@ -556,7 +561,7 @@ DefaultManager::_FindTimeSource() memset(&input, 0, sizeof(input)); input.type = B_MEDIA_RAW_AUDIO; count = MAX_NODE_INFOS; - rv = BMediaRoster::Roster()->GetLiveNodes(&info[0], &count, &input, NULL, NULL, + rv = fRoster->GetLiveNodes(&info[0], &count, &input, NULL, NULL, B_TIME_SOURCE | B_PHYSICAL_OUTPUT); if (rv == B_OK && count >= 1) { for (int i = 0; i < count; i++) @@ -573,7 +578,7 @@ DefaultManager::_FindTimeSource() continue; TRACE("Default DAC timesource \"%s\" created!\n", info[i].name); fTimeSource = info[i].node.node; - BMediaRoster::Roster()->StartTimeSource(info[i].node, + fRoster->StartTimeSource(info[i].node, system_time() + 1000); return; } @@ -593,8 +598,11 @@ DefaultManager::_FindAudioMixer() int32 count; status_t rv; + if (fRoster == NULL) + fRoster = BMediaRoster::Roster(); + count = 1; - rv = BMediaRoster::Roster()->GetLiveNodes(&info, &count, NULL, NULL, NULL, + rv = fRoster->GetLiveNodes(&info, &count, NULL, NULL, NULL, B_BUFFER_PRODUCER | B_BUFFER_CONSUMER | B_SYSTEM_MIXER); if (rv != B_OK || count != 1) { TRACE("Couldn't find audio mixer node\n"); @@ -608,7 +616,6 @@ DefaultManager::_FindAudioMixer() status_t DefaultManager::_ConnectMixerToOutput() { - BMediaRoster *roster; media_node timesource; media_node mixer; media_node soundcard; @@ -623,18 +630,19 @@ DefaultManager::_ConnectMixerToOutput() int32 count; status_t rv; - roster = BMediaRoster::Roster(); + if (fRoster == NULL) + fRoster = BMediaRoster::Roster(); - rv = roster->GetNodeFor(fPhysicalAudioOut, &soundcard); + rv = fRoster->GetNodeFor(fPhysicalAudioOut, &soundcard); if (rv != B_OK) { TRACE("DefaultManager: failed to find soundcard (physical audio " "output)\n"); return B_ERROR; } - rv = roster->GetNodeFor(fAudioMixer, &mixer); + rv = fRoster->GetNodeFor(fAudioMixer, &mixer); if (rv != B_OK) { - roster->ReleaseNode(soundcard); + fRoster->ReleaseNode(soundcard); TRACE("DefaultManager: failed to find mixer\n"); return B_ERROR; } @@ -642,7 +650,7 @@ DefaultManager::_ConnectMixerToOutput() // we now have the mixer and soundcard nodes, // find a free input/output and connect them - rv = roster->GetFreeOutputsFor(mixer, &output, 1, &count, + rv = fRoster->GetFreeOutputsFor(mixer, &output, 1, &count, B_MEDIA_RAW_AUDIO); if (rv != B_OK || count != 1) { TRACE("DefaultManager: can't find free mixer output\n"); @@ -650,7 +658,7 @@ DefaultManager::_ConnectMixerToOutput() goto finish; } - rv = roster->GetFreeInputsFor(soundcard, inputs, MAX_INPUT_INFOS, &count, + rv = fRoster->GetFreeInputsFor(soundcard, inputs, MAX_INPUT_INFOS, &count, B_MEDIA_RAW_AUDIO); if (rv != B_OK || count < 1) { TRACE("DefaultManager: can't find free soundcard inputs\n"); @@ -668,7 +676,7 @@ DefaultManager::_ConnectMixerToOutput() switch (i) { case 0: TRACE("DefaultManager: Trying connect in native format (1)\n"); - if (B_OK != roster->GetFormatFor(input, &format)) { + if (fRoster->GetFormatFor(input, &format) != B_OK) { ERROR("DefaultManager: GetFormatFor failed\n"); continue; } @@ -706,7 +714,7 @@ DefaultManager::_ConnectMixerToOutput() case 4: // BeOS R5 multiaudio node bug workaround TRACE("DefaultManager: Trying connect in native format (2)\n"); - if (B_OK != roster->GetFormatFor(input, &format)) { + if (fRoster->GetFormatFor(input, &format) != B_OK) { ERROR("DefaultManager: GetFormatFor failed\n"); continue; } @@ -718,7 +726,7 @@ DefaultManager::_ConnectMixerToOutput() break; } - rv = roster->Connect(output.source, input.destination, &format, + rv = fRoster->Connect(output.source, input.destination, &format, &newoutput, &newinput); if (rv == B_OK) break; @@ -728,25 +736,25 @@ DefaultManager::_ConnectMixerToOutput() goto finish; } - roster->SetRunModeNode(mixer, BMediaNode::B_INCREASE_LATENCY); - roster->SetRunModeNode(soundcard, BMediaNode::B_RECORDING); + fRoster->SetRunModeNode(mixer, BMediaNode::B_INCREASE_LATENCY); + fRoster->SetRunModeNode(soundcard, BMediaNode::B_RECORDING); - roster->GetTimeSource(×ource); - roster->SetTimeSourceFor(mixer.node, timesource.node); - roster->SetTimeSourceFor(soundcard.node, timesource.node); - roster->PrerollNode(mixer); - roster->PrerollNode(soundcard); + fRoster->GetTimeSource(×ource); + fRoster->SetTimeSourceFor(mixer.node, timesource.node); + fRoster->SetTimeSourceFor(soundcard.node, timesource.node); + fRoster->PrerollNode(mixer); + fRoster->PrerollNode(soundcard); - ts = roster->MakeTimeSourceFor(mixer); + ts = fRoster->MakeTimeSourceFor(mixer); start_at = ts->Now() + 50000; - roster->StartNode(mixer, start_at); - roster->StartNode(soundcard, start_at); + fRoster->StartNode(mixer, start_at); + fRoster->StartNode(soundcard, start_at); ts->Release(); finish: - roster->ReleaseNode(mixer); - roster->ReleaseNode(soundcard); - roster->ReleaseNode(timesource); + fRoster->ReleaseNode(mixer); + fRoster->ReleaseNode(soundcard); + fRoster->ReleaseNode(timesource); return rv; } diff --git a/src/servers/media/DefaultManager.h b/src/servers/media/DefaultManager.h index 826b31d063..a4becac896 100644 --- a/src/servers/media/DefaultManager.h +++ b/src/servers/media/DefaultManager.h @@ -21,6 +21,7 @@ #include "DataExchange.h" #include +#include #include class NodeManager; @@ -76,6 +77,7 @@ private: thread_id fRescanThread; int32 fRescanRequested; BLocker fRescanLock; + BMediaRoster* fRoster; }; #endif // _DEFAULT_MANAGER_H From 8a28f8496597f67b9e0f80c1143398763062239b Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Fri, 28 Aug 2015 18:22:36 +0200 Subject: [PATCH 094/125] Media: Fix restart button alignment --- src/preferences/media/MediaViews.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/preferences/media/MediaViews.cpp b/src/preferences/media/MediaViews.cpp index 87e869679e..f8bb697ef8 100644 --- a/src/preferences/media/MediaViews.cpp +++ b/src/preferences/media/MediaViews.cpp @@ -284,6 +284,7 @@ AudioSettingsView::AudioSettingsView() .Add(defaultsBox) .AddGroup(B_HORIZONTAL) .Add(_MakeVolumeCheckBox()) + .AddGlue() .Add(MakeRestartButton()) .End() .AddGlue(); From 5584c22fdd668cdd7f0193c71cabf1a23fa6d3cf Mon Sep 17 00:00:00 2001 From: Sylvian Kerjean Date: Sat, 8 Aug 2015 14:43:03 -0400 Subject: [PATCH 095/125] AHCI: Fix boot failures due to "Port Connect Change" IRQ storm. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Axel Dörfler --- .../kernel/busses/scsi/ahci/ahci_defs.h | 15 ++++++- .../kernel/busses/scsi/ahci/ahci_port.cpp | 39 +++++++++++++++---- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h index c4b0101c18..e9d49f1703 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h @@ -76,6 +76,19 @@ enum { INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt/Enable }; +typedef struct { + uint16 reserved : 12; + uint8 pmp : 4; // Port Multiplier Port: Not used by AHCI + uint8 spm : 4; // Select Power Management: Not used by AHCI + uint8 ipm : 4; // Interface Power Management Transitions Allowed + uint8 spd : 4; // Speed Allowed + uint8 det : 4; // Device Detection Initialization +} _PACKED scontrol; + +#define TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED 0x300 +#define NO_INITIALIZATION 0 +#define INITIALIZATION 1 + typedef struct { uint32 clb; // Command List Base Address (alignment 1024 byte) @@ -89,7 +102,7 @@ typedef struct { uint32 tfd; // Task File Data uint32 sig; // Signature uint32 ssts; // Serial ATA Status (SCR0: SStatus) - uint32 sctl; // Serial ATA Control (SCR2: SControl) + scontrol sctl; // Serial ATA Control (SCR2: SControl) uint32 serr; // Serial ATA Error (SCR1: SError) **RWC** uint32 sact; // Serial ATA Active (SCR3: SActive) **RW1** uint32 ci; // Command Issue **RW1** diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index a045771926..ed71461694 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -110,7 +110,7 @@ AHCIPort::Init1() // prdt follows after command table // disable transitions to partial or slumber state - fRegs->sctl |= 0x300; + fRegs->sctl.ipm |= TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED; /*TODO Why "|= and not "=" ??*/ // clear IRQ status bits fRegs->is = fRegs->is; @@ -156,7 +156,12 @@ AHCIPort::Init2() TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd); TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); - TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl); + TRACE("sctl.reserved 0x%04" B_PRIx16 "\n", fRegs->sctl.reserved); + TRACE("sctl.pmp 0x%02" B_PRIx8 "\n", fRegs->sctl.pmp); + TRACE("sctl.spm 0x%02" B_PRIx8 "\n", fRegs->sctl.spm); + TRACE("sctl.ipm 0x%02" B_PRIx8 "\n", fRegs->sctl.ipm); + TRACE("sctl.spd 0x%02" B_PRIx8 "\n", fRegs->sctl.spd); + TRACE("sctl.det 0x%02" B_PRIx8 "\n", fRegs->sctl.det); TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd); @@ -212,10 +217,10 @@ AHCIPort::ResetDevice() TRACE("AHCIPort::ResetDevice PORT_CMD_ST set, behaviour undefined\n"); // perform a hard reset - fRegs->sctl = (fRegs->sctl & ~0xf) | 1; + fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ? FlushPostedWrites(); spin(1100); - fRegs->sctl &= ~0xf; + fRegs->sctl.det = NO_INITIALIZATION; FlushPostedWrites(); if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) { @@ -364,10 +369,15 @@ AHCIPort::InterruptErrorHandler(uint32 is) TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08" B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", fIndex, fCommandsActive, is, ci); - - TRACE("ssts 0x%08" B_PRIx32 ", sctl 0x%08" B_PRIx32 ", serr 0x%08" - B_PRIx32 ", sact 0x%08" B_PRIx32 "\n", - fRegs->ssts, fRegs->sctl, fRegs->serr, fRegs->sact); + TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); + TRACE("sctl.reserved 0x%04" B_PRIx16 "\n", fRegs->sctl.reserved); + TRACE("sctl.pmp 0x%02" B_PRIx8 "\n", fRegs->sctl.pmp); + TRACE("sctl.spm 0x%02" B_PRIx8 "\n", fRegs->sctl.spm); + TRACE("sctl.ipm 0x%02" B_PRIx8 "\n", fRegs->sctl.ipm); + TRACE("sctl.spd 0x%02" B_PRIx8 "\n", fRegs->sctl.spd); + TRACE("sctl.det 0x%02" B_PRIx8 "\n", fRegs->sctl.det); + TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); + TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); } // read and clear SError @@ -413,6 +423,19 @@ AHCIPort::InterruptErrorHandler(uint32 is) } if (is & PORT_INT_PC) { TRACE("Port Connect Change\n"); + /* spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT (a COMINIT that is + * not received as a consequence of issuing a COMRESET to the device) */ + + // perform a hard reset + fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ? + FlushPostedWrites(); + spin(1100); // specification says you must wait 1ms + fRegs->sctl.det = NO_INITIALIZATION; + FlushPostedWrites(); + + // clear error bits to clear PxSERR.DIAG.X + fRegs->serr = fRegs->serr; + FlushPostedWrites(); // fResetPort = true; } if (is & PORT_INT_UF) { From df5aeb6dda2dae580e5073d0b80f0b0fd98c3dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 28 Aug 2015 19:22:09 +0200 Subject: [PATCH 096/125] AHCI: fixed constant mixup, minor cleanup. * TRANSITION_... was incorrectly changed from the original patch. * Divided it into two constants, and also prefixed the new constants with the register fields they are valid for. * Fixed incorrect usage of |= and removed the corresponding TODO comments. * Moved some reoccurring code into their own methods. * Added check for the ST bit in the command register for the interrupt hard reset, too. * This closes ticket #12295, thanks Anarchos! --- .../kernel/busses/scsi/ahci/ahci_defs.h | 7 +- .../kernel/busses/scsi/ahci/ahci_port.cpp | 64 +++++++++++-------- .../kernel/busses/scsi/ahci/ahci_port.h | 2 + 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h index e9d49f1703..160cbd7a47 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h @@ -85,9 +85,10 @@ typedef struct { uint8 det : 4; // Device Detection Initialization } _PACKED scontrol; -#define TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED 0x300 -#define NO_INITIALIZATION 0 -#define INITIALIZATION 1 +#define IPM_TRANSITIONS_TO_PARTIAL_DISABLED 0x1 +#define IPM_TRANSITIONS_TO_SLUMBER_DISABLED 0x2 +#define DET_NO_INITIALIZATION 0x0 +#define DET_INITIALIZATION 0x1 typedef struct { diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index ed71461694..2cd4ca5369 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008-2014 Haiku, Inc. All rights reserved. + * Copyright 2008-2015 Haiku, Inc. All rights reserved. * Copyright 2007-2009, Marcus Overhagen. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -110,7 +110,8 @@ AHCIPort::Init1() // prdt follows after command table // disable transitions to partial or slumber state - fRegs->sctl.ipm |= TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED; /*TODO Why "|= and not "=" ??*/ + fRegs->sctl.ipm = IPM_TRANSITIONS_TO_PARTIAL_DISABLED + | IPM_TRANSITIONS_TO_SLUMBER_DISABLED; // clear IRQ status bits fRegs->is = fRegs->is; @@ -213,23 +214,13 @@ AHCIPort::Uninit() void AHCIPort::ResetDevice() { - if (fRegs->cmd & PORT_CMD_ST) - TRACE("AHCIPort::ResetDevice PORT_CMD_ST set, behaviour undefined\n"); - // perform a hard reset - fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ? - FlushPostedWrites(); - spin(1100); - fRegs->sctl.det = NO_INITIALIZATION; - FlushPostedWrites(); + _HardReset(); - if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) { + if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) TRACE("AHCIPort::ResetDevice port %d no device detected\n", fIndex); - } - // clear error bits - fRegs->serr = fRegs->serr; - FlushPostedWrites(); + _ClearErrorRegister(); if (fRegs->ssts & 1) { if (wait_until_set(&fRegs->ssts, 0x3, 500000) < B_OK) { @@ -238,9 +229,7 @@ AHCIPort::ResetDevice() } } - // clear error bits - fRegs->serr = fRegs->serr; - FlushPostedWrites(); + _ClearErrorRegister(); } @@ -423,20 +412,13 @@ AHCIPort::InterruptErrorHandler(uint32 is) } if (is & PORT_INT_PC) { TRACE("Port Connect Change\n"); - /* spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT (a COMINIT that is - * not received as a consequence of issuing a COMRESET to the device) */ + // Spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT // perform a hard reset - fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ? - FlushPostedWrites(); - spin(1100); // specification says you must wait 1ms - fRegs->sctl.det = NO_INITIALIZATION; - FlushPostedWrites(); + _HardReset(); // clear error bits to clear PxSERR.DIAG.X - fRegs->serr = fRegs->serr; - FlushPostedWrites(); -// fResetPort = true; + _ClearErrorRegister(); } if (is & PORT_INT_UF) { TRACE("Unknown FIS\n"); @@ -1247,3 +1229,29 @@ AHCIPort::ScsiGetRestrictions(bool* isATAPI, bool* noAutoSense, "maxBlocks %" B_PRIu32 "\n", fIndex, *isATAPI, *noAutoSense, *maxBlocks); } + + +void +AHCIPort::_HardReset() +{ + if ((fRegs->cmd & PORT_CMD_ST) != 0) { + // We shouldn't perform a reset, but at least document it + TRACE("AHCIPort::_HardReset() PORT_CMD_ST set, behaviour undefined\n"); + } + + fRegs->sctl.det = DET_INITIALIZATION; + FlushPostedWrites(); + spin(1100); + // You must wait 1ms at minimum + fRegs->sctl.det = DET_NO_INITIALIZATION; + FlushPostedWrites(); +} + + +void +AHCIPort::_ClearErrorRegister() +{ + // clear error bits + fRegs->serr = fRegs->serr; + FlushPostedWrites(); +} diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h index c08ea54a1f..7ebb1fcc49 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -51,6 +51,8 @@ private: status_t WaitForTransfer(int *tfd, bigtime_t timeout); void FinishTransfer(); + inline void _HardReset(); + inline void _ClearErrorRegister(); // uint8 * SetCommandFis(volatile command_list_entry *cmd, volatile fis *fis, const void *data, size_t dataSize); status_t FillPrdTable(volatile prd *prdTable, int *prdCount, int prdMax, const void *data, size_t dataSize); From 5b9f6b5485af065913bc747f5c6a21001b275b7f Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 28 Aug 2015 21:28:07 +0200 Subject: [PATCH 097/125] BRoster: Add launchSuspended option to _LaunchApp(). It allows to launch the app, but keep its main thread suspended instead of automatically resuming it. Also add appThread argument which allows to retrieve the main thread of the launched team. --- headers/os/app/Roster.h | 4 +++- headers/private/app/RosterPrivate.h | 5 +++-- src/kits/app/Roster.cpp | 31 ++++++++++++++++++++--------- src/servers/launch/Job.cpp | 4 ++-- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/headers/os/app/Roster.h b/headers/os/app/Roster.h index 559544ebf7..69a11a7777 100644 --- a/headers/os/app/Roster.h +++ b/headers/os/app/Roster.h @@ -183,7 +183,9 @@ private: const BList* messageList, int argc, const char* const* args, const char** environment, - team_id* appTeam) const; + team_id* appTeam, + thread_id* appThread, + bool launchSuspended) const; status_t _UpdateActiveApp(team_id team) const; diff --git a/headers/private/app/RosterPrivate.h b/headers/private/app/RosterPrivate.h index 88006f1706..33c2e507c3 100644 --- a/headers/private/app/RosterPrivate.h +++ b/headers/private/app/RosterPrivate.h @@ -30,9 +30,10 @@ class BRoster::Private { status_t Launch(const char* mimeType, const entry_ref* ref, const BList* messageList, int argc, const char* const* args, - const char** environment, team_id* appTeam) + const char** environment, team_id* appTeam, + thread_id* appThread, bool launchSuspended) { return fRoster->_LaunchApp(mimeType, ref, messageList, argc, - args, environment, appTeam); } + args, environment, appTeam, appThread, launchSuspended); } status_t ShutDown(bool reboot, bool confirm, bool synchronous) { return fRoster->_ShutDown(reboot, confirm, synchronous); } diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index deaef0b4a6..df8ec689d1 100644 --- a/src/kits/app/Roster.cpp +++ b/src/kits/app/Roster.cpp @@ -923,7 +923,7 @@ BRoster::Launch(const char* mimeType, BMessage* initialMessage, messageList.AddItem(initialMessage); return _LaunchApp(mimeType, NULL, &messageList, 0, NULL, - (const char**)environ, _appTeam); + (const char**)environ, _appTeam, NULL, false); } @@ -935,7 +935,7 @@ BRoster::Launch(const char* mimeType, BList* messageList, return B_BAD_VALUE; return _LaunchApp(mimeType, NULL, messageList, 0, NULL, - (const char**)environ, _appTeam); + (const char**)environ, _appTeam, NULL, false); } @@ -947,7 +947,7 @@ BRoster::Launch(const char* mimeType, int argc, const char* const* args, return B_BAD_VALUE; return _LaunchApp(mimeType, NULL, NULL, argc, args, (const char**)environ, - _appTeam); + _appTeam, NULL, false); } @@ -963,7 +963,7 @@ BRoster::Launch(const entry_ref* ref, const BMessage* initialMessage, messageList.AddItem(const_cast(initialMessage)); return _LaunchApp(NULL, ref, &messageList, 0, NULL, (const char**)environ, - _appTeam); + _appTeam, NULL, false); } @@ -975,7 +975,7 @@ BRoster::Launch(const entry_ref* ref, const BList* messageList, return B_BAD_VALUE; return _LaunchApp(NULL, ref, messageList, 0, NULL, (const char**)environ, - appTeam); + appTeam, NULL, false); } @@ -987,7 +987,7 @@ BRoster::Launch(const entry_ref* ref, int argc, const char* const* args, return B_BAD_VALUE; return _LaunchApp(NULL, ref, NULL, argc, args, (const char**)environ, - appTeam); + appTeam, NULL, false); } @@ -1800,6 +1800,10 @@ BRoster::_UpdateActiveApp(team_id team) const \c B_REFS_RECEIVED message, if no arguments are supplied via \a argc and \args. + If \a launchSuspended is set to true, the main thread of the loaded app + (returned in \a appThread) is kept in the suspended state and not + automatically resumed. + \param mimeType MIME type for which the application shall be launched. May be \c NULL. \param ref entry_ref referring to the file for which an application shall @@ -1811,6 +1815,10 @@ BRoster::_UpdateActiveApp(team_id team) const to the launched application. \param appTeam Pointer to a pre-allocated team_id variable to be set to the team ID of the launched application. + \param appThread Pointer to a pre-allocated thread_id variable to + be set to the thread ID of the launched main thread. + \param launchSuspended Indicates whether to keep the app thread in the + suspended state or resume it. \return A status code. \retval B_OK Everything went fine. @@ -1828,7 +1836,8 @@ BRoster::_UpdateActiveApp(team_id team) const status_t BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, const BList* messageList, int argc, const char* const* args, - const char** environment, team_id* _appTeam) const + const char** environment, team_id* _appTeam, + thread_id* _appThread, bool launchSuspended) const { DBG(OUT("BRoster::_LaunchApp()")); @@ -1856,6 +1865,7 @@ BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, status_t error = B_OK; ArgVector argVector; team_id team = -1; + thread_id appThread = -1; do { // find the app @@ -1900,7 +1910,7 @@ BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, if (error == B_OK && !alreadyRunning) { DBG(OUT(" token: %lu\n", appToken)); // load the app image - thread_id appThread = load_image(argVector.Count(), + appThread = load_image(argVector.Count(), const_cast(argVector.Args()), environment); // get the app team @@ -1922,7 +1932,7 @@ BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, DBG(OUT(" set thread and team: %s (%lx)\n", strerror(error), error)); // resume the launched team - if (error == B_OK) + if (error == B_OK && !launchSuspended) error = resume_thread(appThread); DBG(OUT(" resume thread: %s (%lx)\n", strerror(error), error)); @@ -1983,6 +1993,9 @@ BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, error = B_ALREADY_RUNNING; else if (_appTeam) *_appTeam = team; + + if (_appThread != NULL) + *_appThread = appThread; } DBG(OUT("BRoster::_LaunchApp() done: %s (%lx)\n", diff --git a/src/servers/launch/Job.cpp b/src/servers/launch/Job.cpp index 5cb9c985b2..374a526dd9 100644 --- a/src/servers/launch/Job.cpp +++ b/src/servers/launch/Job.cpp @@ -352,7 +352,7 @@ Job::Launch() signature << Name(); status_t status = BRoster::Private().Launch(signature.String(), NULL, - NULL, 0, NULL, &environment[0], &fTeam); + NULL, 0, NULL, &environment[0], &fTeam, NULL, false); _SetLaunchStatus(status); return status; } @@ -378,7 +378,7 @@ Job::Launch() // Launch via entry_ref status = BRoster::Private().Launch(NULL, &ref, NULL, count, &args[0], - &environment[0], &fTeam); + &environment[0], &fTeam, NULL, false); _SetLaunchStatus(status); return status; } From 5cf6c0fd3b9fe36a587bd712eade8045ea4cc723 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 28 Aug 2015 22:18:04 +0200 Subject: [PATCH 098/125] launch_daemon: Create/inject ports on launch instead of upfront. The application is now launched suspended and the ports are created and transferred to the launched team before its main thread is resumed. The ports are therefore owned by the launched team instead of the launch_daemon. This is important when sending messages by area, as the port owner is used to determine where the data area needs to be transferred to. This commit therefore fixes #12285. Note that it is still possible to get at the ports with find_port() while they are still owned by the launch_daemon. This should not be a problem however, as these ports are not supposed to be found this way but only through BLaunchRoster::GetData(), which is synchronized with the above process. Creating the ports in the launch_daemon still has the benefit of returning valid communication ports earlier, i.e. without having to wait for the launched application to actually become ready. --- src/servers/launch/Job.cpp | 131 ++++++++++++++++++++++--------------- src/servers/launch/Job.h | 8 +++ 2 files changed, 87 insertions(+), 52 deletions(-) diff --git a/src/servers/launch/Job.cpp b/src/servers/launch/Job.cpp index 374a526dd9..13ccd9cec1 100644 --- a/src/servers/launch/Job.cpp +++ b/src/servers/launch/Job.cpp @@ -244,50 +244,6 @@ Job::Init(const Finder& finder, std::set& dependencies) } } - // Create ports - // TODO: prefix system ports with "system:" - - bool defaultPort = false; - - for (PortMap::iterator iterator = fPortMap.begin(); - iterator != fPortMap.end(); iterator++) { - BString name(Name()); - const char* suffix = iterator->second.GetString("name"); - if (suffix != NULL) - name << ':' << suffix; - else - defaultPort = true; - - const int32 capacity = iterator->second.GetInt32("capacity", - B_LOOPER_PORT_DEFAULT_CAPACITY); - - port_id port = create_port(capacity, name.String()); - if (port < 0) { - fInitStatus = port; - break; - } - iterator->second.SetInt32("port", port); - - if (name == "x-vnd.haiku-registrar:auth") { - // Allow the launch_daemon to access the registrar authentication - BPrivate::set_registrar_authentication_port(port); - } - } - - if (fInitStatus == B_OK && fCreateDefaultPort && !defaultPort) { - BMessage data; - data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY); - - port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name()); - if (port < 0) { - // TODO: log error - fInitStatus = port; - } else { - data.SetInt32("port", port); - AddPort(data); - } - } - return fInitStatus; } @@ -351,10 +307,7 @@ Job::Launch() BString signature("application/"); signature << Name(); - status_t status = BRoster::Private().Launch(signature.String(), NULL, - NULL, 0, NULL, &environment[0], &fTeam, NULL, false); - _SetLaunchStatus(status); - return status; + return _Launch(signature.String(), NULL, 0, NULL, &environment[0]); } // Build argument vector @@ -377,10 +330,7 @@ Job::Launch() } // Launch via entry_ref - status = BRoster::Private().Launch(NULL, &ref, NULL, count, &args[0], - &environment[0], &fTeam, NULL, false); - _SetLaunchStatus(status); - return status; + return _Launch(NULL, &ref, count, &args[0], &environment[0]); } @@ -505,3 +455,80 @@ Job::_SendPendingLaunchDataReplies() fPendingLaunchDataReplies.MakeEmpty(); } + + +status_t +Job::_CreateAndTransferPorts() +{ + // TODO: prefix system ports with "system:" + + bool defaultPort = false; + + for (PortMap::iterator iterator = fPortMap.begin(); + iterator != fPortMap.end(); iterator++) { + BString name(Name()); + const char* suffix = iterator->second.GetString("name"); + if (suffix != NULL) + name << ':' << suffix; + else + defaultPort = true; + + const int32 capacity = iterator->second.GetInt32("capacity", + B_LOOPER_PORT_DEFAULT_CAPACITY); + + port_id port = create_port(capacity, name.String()); + if (port < 0) + return port; + + status_t result = set_port_owner(port, fTeam); + if (result != B_OK) + return result; + + iterator->second.SetInt32("port", port); + + if (name == "x-vnd.haiku-registrar:auth") { + // Allow the launch_daemon to access the registrar authentication + BPrivate::set_registrar_authentication_port(port); + } + } + + if (fCreateDefaultPort && !defaultPort) { + BMessage data; + data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY); + + port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name()); + if (port < 0) + return port; + + status_t result = set_port_owner(port, fTeam); + if (result != B_OK) + return result; + + data.SetInt32("port", port); + AddPort(data); + } + + return B_OK; +} + + +status_t +Job::_Launch(const char* signature, entry_ref* ref, int argCount, + const char* const* args, const char** environment) +{ + thread_id mainThread = -1; + status_t result = BRoster::Private().Launch(signature, ref, NULL, argCount, + args, environment, &fTeam, &mainThread, true); + + if (result == B_OK) { + result = _CreateAndTransferPorts(); + + if (result == B_OK) + resume_thread(mainThread); + else + kill_thread(mainThread); + } + + _SetLaunchStatus(result); + return result; +} diff --git a/src/servers/launch/Job.h b/src/servers/launch/Job.h index 63afeae97a..137491db49 100644 --- a/src/servers/launch/Job.h +++ b/src/servers/launch/Job.h @@ -24,6 +24,8 @@ class BMessage; class Finder; class Target; +struct entry_ref; + typedef std::map PortMap; @@ -87,6 +89,12 @@ private: status_t _SendLaunchDataReply(BMessage* message); void _SendPendingLaunchDataReplies(); + status_t _CreateAndTransferPorts(); + + status_t _Launch(const char* signature, entry_ref* ref, + int argCount, const char* const* args, + const char** environment); + private: BStringList fArguments; BStringList fRequirements; From 796e1fd04f0a4b1a306a760aed57f29902fd923c Mon Sep 17 00:00:00 2001 From: autonielx Date: Sat, 29 Aug 2015 06:36:31 +0200 Subject: [PATCH 099/125] Update translations from Pootle --- data/catalogs/kits/tracker/de.catkeys | 3 ++- data/catalogs/kits/tracker/fr.catkeys | 3 ++- data/catalogs/kits/tracker/hu.catkeys | 3 ++- data/catalogs/kits/tracker/ja.catkeys | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/data/catalogs/kits/tracker/de.catkeys b/data/catalogs/kits/tracker/de.catkeys index 061712602d..ac4100ac7e 100644 --- a/data/catalogs/kits/tracker/de.catkeys +++ b/data/catalogs/kits/tracker/de.catkeys @@ -1,4 +1,4 @@ -1 german x-vnd.Haiku-libtracker 3987439873 +1 german x-vnd.Haiku-libtracker 1787267522 OK WidgetAttributeText OK Add-ons FilePanelPriv Add-ons Mount settings… ContainerWindow Einhänge-Einstellungen… @@ -19,6 +19,7 @@ Modified QueryPoseView Geändert Created ContainerWindow Erstellt Error %error loading add-On %name. ContainerWindow Fehler %error beim Laden von Add-On %name. If you %ifYouDoAction the settings folder, %osName may not behave properly!\n\nAre you sure you want to do this? FSUtils Wird der Settings-Ordner %ifYouDoAction, kann %osName vielleicht nicht mehr fehlerfrei arbeiten! +Skip all FSUtils Alle überspringen contains SelectionWindow enthält Sorry, you can't save things at the root of your system. FilePanelPriv Im Root-Verzeichnis des Systems kann leider nichts gespeichert werden. Show shared volumes on Desktop SettingsView Netzwerk-Laufwerke auf dem Desktop zeigen diff --git a/data/catalogs/kits/tracker/fr.catkeys b/data/catalogs/kits/tracker/fr.catkeys index 2c71f3aa77..24073de9f8 100644 --- a/data/catalogs/kits/tracker/fr.catkeys +++ b/data/catalogs/kits/tracker/fr.catkeys @@ -1,4 +1,4 @@ -1 french x-vnd.Haiku-libtracker 4204393626 +1 french x-vnd.Haiku-libtracker 2004221275 OK WidgetAttributeText OK Add-ons FilePanelPriv Extensions Mount settings… ContainerWindow Réglages du montage… @@ -19,6 +19,7 @@ Modified QueryPoseView Modifié Created ContainerWindow Créé Error %error loading add-On %name. ContainerWindow Erreur %error au chargement de l’extension %name. If you %ifYouDoAction the settings folder, %osName may not behave properly!\n\nAre you sure you want to do this? FSUtils Si vous %ifYouDoAction le dossier des réglages, %osName pourrait ne pas se comporter correctement !\n\nÊtes vous sûr de vouloir effectuer cette opération ? +Skip all FSUtils Tout ignorer contains SelectionWindow contient Sorry, you can't save things at the root of your system. FilePanelPriv Désolé, vous ne pouvez rien sauvegarder à la racine de votre système. Show shared volumes on Desktop SettingsView Afficher les volumes partagés sur le Bureau diff --git a/data/catalogs/kits/tracker/hu.catkeys b/data/catalogs/kits/tracker/hu.catkeys index a8724421a3..a1728d3eb0 100644 --- a/data/catalogs/kits/tracker/hu.catkeys +++ b/data/catalogs/kits/tracker/hu.catkeys @@ -1,4 +1,4 @@ -1 hungarian x-vnd.Haiku-libtracker 4204393626 +1 hungarian x-vnd.Haiku-libtracker 2004221275 OK WidgetAttributeText Rendben Add-ons FilePanelPriv Kiegészítők Mount settings… ContainerWindow Csatolási beállítások… @@ -19,6 +19,7 @@ Modified QueryPoseView Módosítva Created ContainerWindow Létrehozva Error %error loading add-On %name. ContainerWindow Hiba a bővítmény (%name) betöltése közben: %error. If you %ifYouDoAction the settings folder, %osName may not behave properly!\n\nAre you sure you want to do this? FSUtils Ha %ifYouDoAction a beállítások mappát, akkor lehet, hogy a %osName nem fog megfelelően működni!\n\nBiztosan folytatni akarja? +Skip all FSUtils Mindet kihagyja contains SelectionWindow tartalmaz Sorry, you can't save things at the root of your system. FilePanelPriv Sajnos nem lehet a rendszer gyökérmappájába menteni. Show shared volumes on Desktop SettingsView Megosztott lemezek megjelenítése az Asztalon diff --git a/data/catalogs/kits/tracker/ja.catkeys b/data/catalogs/kits/tracker/ja.catkeys index 0105412e1e..d58c101164 100644 --- a/data/catalogs/kits/tracker/ja.catkeys +++ b/data/catalogs/kits/tracker/ja.catkeys @@ -1,4 +1,4 @@ -1 japanese x-vnd.Haiku-libtracker 4204393626 +1 japanese x-vnd.Haiku-libtracker 2004221275 OK WidgetAttributeText OK Add-ons FilePanelPriv アドオン Mount settings… ContainerWindow マウント設定… @@ -19,6 +19,7 @@ Modified QueryPoseView 更新日時 Created ContainerWindow 作成日時 Error %error loading add-On %name. ContainerWindow %nameアドオンの読み込み中に%errorエラーが発生 If you %ifYouDoAction the settings folder, %osName may not behave properly!\n\nAre you sure you want to do this? FSUtils settings フォルダーを%ifYouDoActionした場合、%osName が正常に動作しなくなる可能性があります。\n\n続けますか? +Skip all FSUtils すべてスキップ contains SelectionWindow 含む Sorry, you can't save things at the root of your system. FilePanelPriv システムのルートフォルダーに保存は許可されていません。 Show shared volumes on Desktop SettingsView 共有ディスクをデスクトップに表示する From e10d416e692354b37f4d9a0461f5690b2c4d1be4 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sat, 29 Aug 2015 08:27:20 +0200 Subject: [PATCH 100/125] Improved warning alert. Spaces were missing. --- src/preferences/media/MediaWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/preferences/media/MediaWindow.cpp b/src/preferences/media/MediaWindow.cpp index 7efd90d9c9..1275a6a502 100644 --- a/src/preferences/media/MediaWindow.cpp +++ b/src/preferences/media/MediaWindow.cpp @@ -308,9 +308,9 @@ bool MediaWindow::QuitRequested() { if (fRestartThread > 0) { - BString text(B_TRANSLATE("Quitting Media now will stop" - "restarting the media services. Flaky or unavailable media" - "functionality is likely the result.")); + BString text(B_TRANSLATE("Quitting Media now will stop the " + "restarting of the media services. Flaky or unavailable media " + "functionality is the likely result.")); fRestartAlert = new BAlert(B_TRANSLATE("Warning!"), text, B_TRANSLATE("Quit anyway"), NULL, NULL, From b92e2c086f7df99f8fe66464d4a4208a1b933c88 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Aug 2015 10:04:12 +0200 Subject: [PATCH 101/125] keystore_server: Resize request windows to preferred size. Long application signatures and paths could previously take up too much space, causing the buttons to be cut off or become completely invisible. Actually fixes #11367. --- src/servers/keystore/AppAccessRequestWindow.cpp | 3 ++- src/servers/keystore/KeyRequestWindow.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/servers/keystore/AppAccessRequestWindow.cpp b/src/servers/keystore/AppAccessRequestWindow.cpp index 1a0292afc9..c05b29b006 100644 --- a/src/servers/keystore/AppAccessRequestWindow.cpp +++ b/src/servers/keystore/AppAccessRequestWindow.cpp @@ -142,7 +142,7 @@ AppAccessRequestWindow::AppAccessRequestWindow(const char* keyringName, const char* signature, const char* path, const char* accessString, bool appIsNew, bool appWasUpdated) : - BWindow(BRect(50, 50, 269, 302), B_TRANSLATE("Application keyring access"), + BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Application keyring access"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS), fRequestView(NULL), @@ -208,6 +208,7 @@ AppAccessRequestWindow::MessageReceived(BMessage* message) status_t AppAccessRequestWindow::RequestAppAccess(bool& allowAlways) { + ResizeToPreferred(); CenterOnScreen(); Show(); diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index 76466577da..2105a8caf7 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -152,7 +152,7 @@ private: KeyRequestWindow::KeyRequestWindow() : - BWindow(BRect(50, 50, 269, 302), B_TRANSLATE("Unlock keyring"), + BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Unlock keyring"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS), fRequestView(NULL), @@ -218,6 +218,7 @@ KeyRequestWindow::RequestKey(const BString& keyringName, BMessage& keyMessage) { fRequestView->SetUp(keyringName); + ResizeToPreferred(); CenterOnScreen(); Show(); From 515e648d7b334571c7831a638e9e59934c85ada3 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Aug 2015 10:10:48 +0200 Subject: [PATCH 102/125] keystore_server: Use B_CLOSE_ON_ESCAPE in request dialogs. Instead of doing it manually. --- src/servers/keystore/AppAccessRequestWindow.cpp | 17 ++--------------- src/servers/keystore/AppAccessRequestWindow.h | 2 -- src/servers/keystore/KeyRequestWindow.cpp | 17 ++--------------- src/servers/keystore/KeyRequestWindow.h | 2 -- 4 files changed, 4 insertions(+), 34 deletions(-) diff --git a/src/servers/keystore/AppAccessRequestWindow.cpp b/src/servers/keystore/AppAccessRequestWindow.cpp index c05b29b006..b4edf58263 100644 --- a/src/servers/keystore/AppAccessRequestWindow.cpp +++ b/src/servers/keystore/AppAccessRequestWindow.cpp @@ -144,7 +144,8 @@ AppAccessRequestWindow::AppAccessRequestWindow(const char* keyringName, : BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Application keyring access"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS - | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS), + | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS + | B_CLOSE_ON_ESCAPE), fRequestView(NULL), fDoneSem(-1), fResult(kMessageDisallow) @@ -175,20 +176,6 @@ AppAccessRequestWindow::~AppAccessRequestWindow() } -void -AppAccessRequestWindow::DispatchMessage(BMessage* message, BHandler* handler) -{ - int8 key; - if (message->what == B_KEY_DOWN - && message->FindInt8("byte", 0, &key) == B_OK - && key == B_ESCAPE) { - PostMessage(kMessageDisallow); - } - - BWindow::DispatchMessage(message, handler); -} - - void AppAccessRequestWindow::MessageReceived(BMessage* message) { diff --git a/src/servers/keystore/AppAccessRequestWindow.h b/src/servers/keystore/AppAccessRequestWindow.h index e8fbee8a5b..d8f952a1d2 100644 --- a/src/servers/keystore/AppAccessRequestWindow.h +++ b/src/servers/keystore/AppAccessRequestWindow.h @@ -23,8 +23,6 @@ public: bool appWasUpdated); virtual ~AppAccessRequestWindow(); -virtual void DispatchMessage(BMessage* message, - BHandler* handler); virtual void MessageReceived(BMessage* message); status_t RequestAppAccess(bool& allowAlways); diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index 2105a8caf7..bbad08d2f3 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -154,7 +154,8 @@ KeyRequestWindow::KeyRequestWindow() : BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Unlock keyring"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS - | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS), + | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS + | B_CLOSE_ON_ESCAPE), fRequestView(NULL), fDoneSem(-1), fResult(B_ERROR) @@ -184,20 +185,6 @@ KeyRequestWindow::~KeyRequestWindow() } -void -KeyRequestWindow::DispatchMessage(BMessage* message, BHandler* handler) -{ - int8 key; - if (message->what == B_KEY_DOWN - && message->FindInt8("byte", 0, &key) == B_OK - && key == B_ESCAPE) { - PostMessage(kMessageCancel); - } - - BWindow::DispatchMessage(message, handler); -} - - void KeyRequestWindow::MessageReceived(BMessage* message) { diff --git a/src/servers/keystore/KeyRequestWindow.h b/src/servers/keystore/KeyRequestWindow.h index 8c535d6e78..a9336abb9e 100644 --- a/src/servers/keystore/KeyRequestWindow.h +++ b/src/servers/keystore/KeyRequestWindow.h @@ -18,8 +18,6 @@ public: KeyRequestWindow(); virtual ~KeyRequestWindow(); -virtual void DispatchMessage(BMessage* message, - BHandler* handler); virtual void MessageReceived(BMessage* message); status_t RequestKey(const BString& keyringName, From bc5a7a37499482758a11a463cc00f876edce69f0 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Aug 2015 10:13:15 +0200 Subject: [PATCH 103/125] keystore_server: Fix crash on request window close. The outside waiting mechanism is responsible for quitting the dialog so prevent it from quitting itself. --- src/servers/keystore/AppAccessRequestWindow.cpp | 9 +++++++++ src/servers/keystore/AppAccessRequestWindow.h | 1 + src/servers/keystore/KeyRequestWindow.cpp | 9 +++++++++ src/servers/keystore/KeyRequestWindow.h | 1 + 4 files changed, 20 insertions(+) diff --git a/src/servers/keystore/AppAccessRequestWindow.cpp b/src/servers/keystore/AppAccessRequestWindow.cpp index b4edf58263..dc77e4ce0a 100644 --- a/src/servers/keystore/AppAccessRequestWindow.cpp +++ b/src/servers/keystore/AppAccessRequestWindow.cpp @@ -176,6 +176,15 @@ AppAccessRequestWindow::~AppAccessRequestWindow() } +bool +AppAccessRequestWindow::QuitRequested() +{ + fResult = kMessageDisallow; + release_sem(fDoneSem); + return false; +} + + void AppAccessRequestWindow::MessageReceived(BMessage* message) { diff --git a/src/servers/keystore/AppAccessRequestWindow.h b/src/servers/keystore/AppAccessRequestWindow.h index d8f952a1d2..b1b8b1a030 100644 --- a/src/servers/keystore/AppAccessRequestWindow.h +++ b/src/servers/keystore/AppAccessRequestWindow.h @@ -23,6 +23,7 @@ public: bool appWasUpdated); virtual ~AppAccessRequestWindow(); +virtual bool QuitRequested(); virtual void MessageReceived(BMessage* message); status_t RequestAppAccess(bool& allowAlways); diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index bbad08d2f3..6d93408d58 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -185,6 +185,15 @@ KeyRequestWindow::~KeyRequestWindow() } +bool +KeyRequestWindow::QuitRequested() +{ + fResult = B_CANCELED; + release_sem(fDoneSem); + return false; +} + + void KeyRequestWindow::MessageReceived(BMessage* message) { diff --git a/src/servers/keystore/KeyRequestWindow.h b/src/servers/keystore/KeyRequestWindow.h index a9336abb9e..2301aaa06b 100644 --- a/src/servers/keystore/KeyRequestWindow.h +++ b/src/servers/keystore/KeyRequestWindow.h @@ -18,6 +18,7 @@ public: KeyRequestWindow(); virtual ~KeyRequestWindow(); +virtual bool QuitRequested(); virtual void MessageReceived(BMessage* message); status_t RequestKey(const BString& keyringName, From c0c883cf8e35433ce0b89bd160741446302efa9e Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Aug 2015 11:00:39 +0200 Subject: [PATCH 104/125] BMessage: Fix precedence of KMessage vs. size check. A KMessage request always needs to be honoured, regardless of the data size. KMessage does not currently protect against messages that are too large, but this needs to be solved in KMessage when it becomes a problem. --- src/kits/app/Message.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/kits/app/Message.cpp b/src/kits/app/Message.cpp index aa7729cff7..d1824937e7 100644 --- a/src/kits/app/Message.cpp +++ b/src/kits/app/Message.cpp @@ -2132,6 +2132,13 @@ BMessage::_SendMessage(port_id port, team_id portOwner, int32 token, return B_NO_MEMORY; } #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST + } else if ((fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE) != 0) { + KMessage toMessage; + result = BPrivate::MessageAdapter::ConvertToKMessage(this, toMessage); + if (result != B_OK) + return result; + + return toMessage.SendTo(port, token); } else if (fHeader->data_size > B_PAGE_SIZE * 10) { // ToDo: bind the above size to the max port message size // use message passing by area for such a large message @@ -2166,13 +2173,6 @@ BMessage::_SendMessage(port_id port, team_id portOwner, int32 token, header->message_area = transfered; } #endif - } else if ((fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE) != 0) { - KMessage toMessage; - result = BPrivate::MessageAdapter::ConvertToKMessage(this, toMessage); - if (result != B_OK) - return result; - - return toMessage.SendTo(port, token); } else { size = FlattenedSize(); buffer = (char*)malloc(size); From e2eb9b7baf9cb3e1178868758219d4d36c0c6ad3 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Sat, 29 Aug 2015 14:27:38 +0200 Subject: [PATCH 105/125] Removed empty line --- src/kits/interface/Alert.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/kits/interface/Alert.cpp b/src/kits/interface/Alert.cpp index 422692771d..ad370d2654 100644 --- a/src/kits/interface/Alert.cpp +++ b/src/kits/interface/Alert.cpp @@ -264,7 +264,6 @@ BAlert::SetShortcut(int32 index, char key) char BAlert::Shortcut(int32 index) const { - if (index >= 0 && (size_t)index < fKeys.size()) return fKeys[index]; From 1805bbf29bceca563985ff377f2b153c46057c2b Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Sat, 29 Aug 2015 15:16:17 +0200 Subject: [PATCH 106/125] BPrintJob: fixed crash. Since hrev49481, BAlert sets its default button in Go(), and not in the constructor. So DefaultButton() will return NULL if Go() hasn't been called yet. Moreover, BAlert now centers itself on screen in Go() and not in the costructor, so move it away from screen after the Go() call. Fixes #12271, although there should be a nicer way to implement this. --- src/kits/interface/PrintJob.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/kits/interface/PrintJob.cpp b/src/kits/interface/PrintJob.cpp index 0a5ad29f7c..2c5997551c 100644 --- a/src/kits/interface/PrintJob.cpp +++ b/src/kits/interface/PrintJob.cpp @@ -747,12 +747,22 @@ PrintServerMessenger::~PrintServerMessenger() void PrintServerMessenger::RejectUserInput() { + // TODO: This code is sort of a hack: + // It creates a BAlert then moves it out of the screen to + // block user input. fHiddenApplicationModalWindow = new BAlert("bogus", "app_modal", "OK"); - fHiddenApplicationModalWindow->DefaultButton()->SetEnabled(false); - fHiddenApplicationModalWindow->SetDefaultButton(NULL); + BButton* defaultButton = fHiddenApplicationModalWindow->DefaultButton(); + if (defaultButton != NULL) { + // TODO: Doing this is useless, since BAlert now sets its + // default button on Go(). + defaultButton->SetEnabled(false); + fHiddenApplicationModalWindow->SetDefaultButton(NULL); + } fHiddenApplicationModalWindow->SetFlags(fHiddenApplicationModalWindow->Flags() | B_CLOSE_ON_ESCAPE); - fHiddenApplicationModalWindow->MoveTo(-65000, -65000); fHiddenApplicationModalWindow->Go(NULL); + + // Moved here because now BAlert centers itself on screen in Go(). + fHiddenApplicationModalWindow->MoveTo(-65000, -65000); } @@ -867,7 +877,6 @@ PrintServerMessenger::MessengerThread(void* data) return B_ERROR; } - BMessage reply; if (printServer.SendMessage(request, &reply) != B_OK || reply.what != 'okok' ) { From 48b2cb377123257347d43438525b04504ce04b68 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Sat, 29 Aug 2015 13:17:46 +0200 Subject: [PATCH 107/125] BMediaRoster: Pass unhandled messages to the base class * While it shouldn't be a big problem, the bebook states that it's very important to do so. --- src/kits/media/MediaRoster.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 4268720846..22552bf20d 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -3460,9 +3460,13 @@ BMediaRoster::MessageReceived(BMessage* message) node->DeleteHook(node); // we don't call Release(), see above! return; } + + default: + printf("BMediaRoster::MessageReceived: unknown message!\n"); + message->PrintToStream(); + BLooper::MessageReceived(message); + break; } - printf("BMediaRoster::MessageReceived: unknown message!\n"); - message->PrintToStream(); } From b11eb89c2d4df40207a9b8e4d7099d356dcc89ec Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Aug 2015 19:02:36 +0200 Subject: [PATCH 108/125] Add system_time bin command which just prints system_time(). This can be used by scripts to do verious performance measurements. Specifically it can be used to measure the boot time since it represents the uptime. --- build/jam/images/definitions/minimum | 2 +- src/bin/system_time.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/bin/system_time.cpp diff --git a/build/jam/images/definitions/minimum b/build/jam/images/definitions/minimum index fa836795e7..04c2b8d815 100644 --- a/build/jam/images/definitions/minimum +++ b/build/jam/images/definitions/minimum @@ -26,7 +26,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures route safemode screen_blanker screeninfo screenmode setarch setmime settype setversion setvolume shutdown - strace su sysinfo + strace su sysinfo system_time tcptester telnet telnetd top traceroute trash unchop unmount diff --git a/src/bin/system_time.cpp b/src/bin/system_time.cpp new file mode 100644 index 0000000000..128df6b754 --- /dev/null +++ b/src/bin/system_time.cpp @@ -0,0 +1,19 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ + +#include + +#include + + +int +main(int argc, char* argv[]) +{ + printf("%" B_PRIdBIGTIME "\n", system_time()); + return 0; +} From 5ce7069d156df977c21ff82f557a260d8d9cc5a2 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Aug 2015 19:05:18 +0200 Subject: [PATCH 109/125] Add script that prints the uptime after waiting for all servers. It waits for the message port of each application to become available using waitfor and then waits for the application to actually reply using hey. This establishes the criterion of the boot process being complete as "all servers (and Tracker & Deskbar) are started and respond to messages". --- src/tests/misc/boot_time_logger.sh | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 src/tests/misc/boot_time_logger.sh diff --git a/src/tests/misc/boot_time_logger.sh b/src/tests/misc/boot_time_logger.sh new file mode 100755 index 0000000000..f1a88d8e76 --- /dev/null +++ b/src/tests/misc/boot_time_logger.sh @@ -0,0 +1,34 @@ +#!/bin/sh + + +# Send a message to and wait for a reply from all servers to determine when +# everything's ready. +SIGNATURES=" + application/x-vnd.haiku-registrar + application/x-vnd.Haiku-mount_server + application/x-vnd.Haiku-powermanagement + application/x-vnd.Haiku-cddb_daemon + application/x-vnd.Haiku-midi_server + application/x-vnd.haiku-net_server + application/x-vnd.Haiku-debug_server + application/x-vnd.Be-PSRV + application/x-vnd.haiku-package_daemon + application/x-vnd.Haiku-notification_server + application/x-vnd.Be-input_server + application/x-vnd.Be.media-server + application/x-vnd.Be.addon-host + application/x-vnd.Be-TRAK + application/x-vnd.Be-TSKB" + +for SIGNATURE in $SIGNATURES +do + waitfor -m $SIGNATURE + hey -s $SIGNATURE get + if [ $? -ne 0 ] + then + echo "Failed to get a reply for $SIGNATURE" + exit 1 + fi +done + +system_time From 0a6d59595114ebc6adaeefc45ecbc9eab340cc7e Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Aug 2015 19:33:27 +0200 Subject: [PATCH 110/125] Add system_time to the Jamfile, missed in hrev49598. --- src/bin/Jamfile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bin/Jamfile b/src/bin/Jamfile index e9d29fb28e..3768ac2fb6 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -48,6 +48,7 @@ StdBinCommands release.c renice.c rescan.c + system_time.cpp unchop.c uptime.cpp vmstat.cpp From 75d1eb3a59ce0ae53733ca8b05536ed75804223f Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 16 Aug 2015 20:44:00 +0200 Subject: [PATCH 111/125] assert.h: reintroduce headers guard for function declarations. The POSIX standard requires us to allow assert.h to be included multiple times with differnt values of NDEBUG. So we can't have a global header guard on the files. However, we must also make sure that we don't declare functions multiple times in that case. Re-introduce an header guard on the part of the file where we declare functions, only. Fixes lots of warnings when building Netsurf. --- headers/posix/assert.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/headers/posix/assert.h b/headers/posix/assert.h index d916e02e60..628cd4c843 100644 --- a/headers/posix/assert.h +++ b/headers/posix/assert.h @@ -3,19 +3,19 @@ * Distributed under the terms of the MIT License. */ -/* Include guards are omitted, as assert.h is required +/* Include guards are only on part of the file, as assert.h is required to support being included multiple times. - + E.g. the following is required to be valid: - + #undef NDEBUG #include - + assert(0); // this assertion will be triggered - + #define NDEBUG #include - + assert(0); // this assertion will not be triggered */ @@ -24,6 +24,9 @@ #ifndef NDEBUG /* defining NDEBUG disables assert() functionality */ +#ifndef _ASSERT_H_ +#define _ASSERT_H_ + #ifdef __cplusplus extern "C" { #endif @@ -40,6 +43,8 @@ extern void __assert_perror_fail(int error, const char *file, } #endif +#endif /* !_ASSERT_H_ */ + #define assert(assertion) \ ((assertion) ? (void)0 : __assert_fail(#assertion, __FILE__, __LINE__, __PRETTY_FUNCTION__)) From 0717601a7f0ae5185e857c8da2bb6f888d36e4c2 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 29 Aug 2015 23:08:37 +0200 Subject: [PATCH 112/125] ffmpeg encoder: do not use deprecatred function Replace avcodec_encode_audio with avcodec_encode_audio2. The latter provides us with more information on the encoded data, so we can avoid guessing things on our own. It also handles memory allocations on its own, which fix some cases where we would provide a too small buffer. --- .../media/plugins/ffmpeg/AVCodecEncoder.cpp | 93 +++++++++++++------ 1 file changed, 64 insertions(+), 29 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp index 910b30b7fc..647674630b 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp @@ -591,43 +591,78 @@ status_t AVCodecEncoder::_EncodeAudio(const uint8* buffer, size_t bufferSize, int64 frameCount, media_encode_info* info) { - // Encode one audio chunk/frame. The bufferSize has already been adapted - // to the needed size for fContext->frame_size, or we are writing raw - // audio. - int usedBytes = avcodec_encode_audio(fContext, fChunkBuffer, - bufferSize, reinterpret_cast(buffer)); + status_t ret; - if (usedBytes < 0) { - TRACE(" avcodec_encode_audio() failed: %d\n", usedBytes); - return B_ERROR; + // Encode one audio chunk/frame. + AVPacket packet; + av_init_packet(&packet); + // By leaving these NULL, we let the encoder allocate memory as it needs. + // This way we don't risk iving a too small buffer. + packet.data = NULL; + packet.size = 0; + + // We need to wrap our input data into an AVFrame structure. + AVFrame frame; + int gotPacket = 0; + + if (buffer) { + avcodec_get_frame_defaults(&frame); + + frame.nb_samples = frameCount; + + ret = avcodec_fill_audio_frame(&frame, fContext->channels, + fContext->sample_fmt, (const uint8_t *) buffer, bufferSize, 1); + + if (ret != 0) + return B_ERROR; + + /* Set the presentation time of the frame */ + frame.pts = (bigtime_t)(fFramesWritten * 1000000LL + / fInputFormat.u.raw_audio.frame_rate); + fFramesWritten += frame.nb_samples; + + ret = avcodec_encode_audio2(fContext, &packet, &frame, &gotPacket); + } else { + // If called with NULL, ask the encoder to flush any buffers it may + // have pending. + ret = avcodec_encode_audio2(fContext, &packet, NULL, &gotPacket); } - if (usedBytes == 0) - return B_OK; -// // Maybe we need to use this PTS to calculate start_time: -// if (fContext->coded_frame->pts != kNoPTSValue) { -// TRACE(" codec frame PTS: %lld (codec time_base: %d/%d)\n", -// fContext->coded_frame->pts, fContext->time_base.num, -// fContext->time_base.den); -// } else { -// TRACE(" codec frame PTS: N/A (codec time_base: %d/%d)\n", -// fContext->time_base.num, fContext->time_base.den); -// } + if (buffer && frame.extended_data != frame.data) + av_freep(&frame.extended_data); - // Setup media_encode_info, most important is the time stamp. - info->start_time = (bigtime_t)(fFramesWritten * 1000000LL - / fInputFormat.u.raw_audio.frame_rate); - info->flags = B_MEDIA_KEY_FRAME; - - // Write the chunk - status_t ret = WriteChunk(fChunkBuffer, usedBytes, info); - if (ret != B_OK) { - TRACE(" error writing chunk: %s\n", strerror(ret)); - return ret; + if (ret != 0) { + TRACE(" avcodec_encode_audio() failed: %ld\n", ret); + return B_ERROR; } fFramesWritten += frameCount; + if (gotPacket) { + if (fContext->coded_frame) { + // Store information about the coded frame in the context. + fContext->coded_frame->pts = packet.pts; + fContext->coded_frame->key_frame = !!(packet.flags & AV_PKT_FLAG_KEY); + } + + // Setup media_encode_info, most important is the time stamp. + info->start_time = packet.pts; + + if (packet.flags & AV_PKT_FLAG_KEY) + info->flags = B_MEDIA_KEY_FRAME; + else + info->flags = 0; + + // We got a packet out of the encoder, write it to the output stream + ret = WriteChunk(packet.data, packet.size, info); + if (ret != B_OK) { + TRACE(" error writing chunk: %s\n", strerror(ret)); + av_free_packet(&packet); + return ret; + } + } + + av_free_packet(&packet); return B_OK; } From a84dc7543a6cbf8ce625aa416673161072722e43 Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Sun, 30 Aug 2015 12:58:16 +1200 Subject: [PATCH 113/125] BAlert: move setting default button into AddButton(). This properly fixes the crash in #12271, introduced by hrev49481. --- src/kits/interface/Alert.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/kits/interface/Alert.cpp b/src/kits/interface/Alert.cpp index ad370d2654..0140f84fcb 100644 --- a/src/kits/interface/Alert.cpp +++ b/src/kits/interface/Alert.cpp @@ -377,6 +377,7 @@ BAlert::AddButton(const char* label, char key) fButtons.push_back(button); fKeys.push_back(key); + SetDefaultButton(button); fButtonLayout->AddView(button); } @@ -643,8 +644,6 @@ BAlert::_Prepare() if (CountButtons() == 0) debugger("BAlerts must have at least one button."); - SetDefaultButton(ButtonAt(CountButtons() - 1)); - float fontFactor = be_plain_font->Size() / 11.0f; if (fIconView->Bitmap() == NULL) From 21c3286b628fd447b9470eca1eab464e85fa9571 Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Sun, 30 Aug 2015 14:02:54 +1200 Subject: [PATCH 114/125] BAlert: make SetShortcut() work again. In hrev49481, the call to AddCommonFilter was accidentally removed, preventing SetShortcut() from working. The filter has also been updated to enumerate all buttons, rather than a maximum of the first three. --- src/kits/interface/Alert.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/kits/interface/Alert.cpp b/src/kits/interface/Alert.cpp index 0140f84fcb..d203aa94c7 100644 --- a/src/kits/interface/Alert.cpp +++ b/src/kits/interface/Alert.cpp @@ -520,6 +520,8 @@ BAlert::_Init(const char* text, const char* button0, const char* button1, AddButton(button0); AddButton(button1); AddButton(button2); + + AddCommonFilter(new(std::nothrow) _BAlertFilter_(this)); } @@ -810,7 +812,7 @@ _BAlertFilter_::Filter(BMessage* msg, BHandler** target) if (msg->what == B_KEY_DOWN) { char byte; if (msg->FindInt8("byte", (int8*)&byte) == B_OK) { - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < fAlert->CountButtons(); ++i) { if (byte == fAlert->Shortcut(i) && fAlert->ButtonAt(i)) { char space = ' '; fAlert->ButtonAt(i)->KeyDown(&space, 1); From d7a9cbde916858d81a49f59d7da3f6a4ed953931 Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Sun, 30 Aug 2015 14:39:36 +1200 Subject: [PATCH 115/125] BAlert: don't center ourselves if we've already been positioned. --- src/kits/interface/Alert.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/kits/interface/Alert.cpp b/src/kits/interface/Alert.cpp index d203aa94c7..411792ded1 100644 --- a/src/kits/interface/Alert.cpp +++ b/src/kits/interface/Alert.cpp @@ -691,6 +691,11 @@ BAlert::_Prepare() ResizeToPreferred(); + // Return early if we've already been moved... + if (Frame().left != 0 && Frame().right != 0) + return; + + // otherwise center ourselves on-top of parent window/screen BWindow* parent = dynamic_cast(BLooper::LooperForThread( find_thread(NULL))); const BRect frame = parent != NULL ? parent->Frame() From 8f3d6d192f9b5d69a487cb353ac8561f7e75bcd3 Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Sun, 30 Aug 2015 14:41:16 +1200 Subject: [PATCH 116/125] Revert "BPrintJob: fixed crash." This reverts commit 1805bbf29bceca563985ff377f2b153c46057c2b. --- src/kits/interface/PrintJob.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/kits/interface/PrintJob.cpp b/src/kits/interface/PrintJob.cpp index 2c5997551c..0a5ad29f7c 100644 --- a/src/kits/interface/PrintJob.cpp +++ b/src/kits/interface/PrintJob.cpp @@ -747,22 +747,12 @@ PrintServerMessenger::~PrintServerMessenger() void PrintServerMessenger::RejectUserInput() { - // TODO: This code is sort of a hack: - // It creates a BAlert then moves it out of the screen to - // block user input. fHiddenApplicationModalWindow = new BAlert("bogus", "app_modal", "OK"); - BButton* defaultButton = fHiddenApplicationModalWindow->DefaultButton(); - if (defaultButton != NULL) { - // TODO: Doing this is useless, since BAlert now sets its - // default button on Go(). - defaultButton->SetEnabled(false); - fHiddenApplicationModalWindow->SetDefaultButton(NULL); - } + fHiddenApplicationModalWindow->DefaultButton()->SetEnabled(false); + fHiddenApplicationModalWindow->SetDefaultButton(NULL); fHiddenApplicationModalWindow->SetFlags(fHiddenApplicationModalWindow->Flags() | B_CLOSE_ON_ESCAPE); - fHiddenApplicationModalWindow->Go(NULL); - - // Moved here because now BAlert centers itself on screen in Go(). fHiddenApplicationModalWindow->MoveTo(-65000, -65000); + fHiddenApplicationModalWindow->Go(NULL); } @@ -877,6 +867,7 @@ PrintServerMessenger::MessengerThread(void* data) return B_ERROR; } + BMessage reply; if (printServer.SendMessage(request, &reply) != B_OK || reply.what != 'okok' ) { From d316ccc7e3ca50880468fe6a11d0dc27992959ef Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 30 Aug 2015 10:50:32 +0200 Subject: [PATCH 117/125] ahci: Whitespace and line length cleanup only. --- .../kernel/busses/scsi/ahci/ahci_defs.h | 133 +++++++++--------- 1 file changed, 69 insertions(+), 64 deletions(-) diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h index 160cbd7a47..547c3018de 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h @@ -29,20 +29,21 @@ enum { CAP_SALP = (1 << 26), // Supports Aggressive Link Power Management CAP_SAL = (1 << 25), // Supports Activity LED CAP_SCLO = (1 << 24), // Supports Command List Override - CAP_ISS_MASK = 0xf, // Interface Speed Support + CAP_ISS_MASK = 0xf, // Interface Speed Support CAP_ISS_SHIFT = 20, - CAP_SNZO = (1 << 19), // Supports Non-Zero DMA Offsets - CAP_SAM = (1 << 18), // Supports AHCI mode only - CAP_SPM = (1 << 17), // Supports Port Multiplier - CAP_FBSS = (1 << 16), // FIS-based Switching Supported - CAP_PMD = (1 << 15), // PIO Multiple DRQ Block - CAP_SSC = (1 << 14), // Slumber State Capable - CAP_PSC = (1 << 13), // Partial State Capable - CAP_NCS_MASK = 0x1f, // Number of Command Slots (zero-based number) + CAP_SNZO = (1 << 19), // Supports Non-Zero DMA Offsets + CAP_SAM = (1 << 18), // Supports AHCI mode only + CAP_SPM = (1 << 17), // Supports Port Multiplier + CAP_FBSS = (1 << 16), // FIS-based Switching Supported + CAP_PMD = (1 << 15), // PIO Multiple DRQ Block + CAP_SSC = (1 << 14), // Slumber State Capable + CAP_PSC = (1 << 13), // Partial State Capable + CAP_NCS_MASK = 0x1f, // Number of Command Slots + // (zero-based number) CAP_NCS_SHIFT = 8, - CAP_CCCS = (1 << 7), // Command Completion Coalescing Supported - CAP_EMS = (1 << 6), // Enclosure Management Supported - CAP_SXS = (1 << 5), // Supports External SATA + CAP_CCCS = (1 << 7), // Command Completion Coalescing Supported + CAP_EMS = (1 << 6), // Enclosure Management Supported + CAP_SXS = (1 << 5), // Supports External SATA CAP_NP_MASK = 0x1f, // Number of Ports (zero-based number) CAP_NP_SHIFT = 0, }; @@ -73,16 +74,17 @@ enum { INT_SDB = (1 << 3), // Set Device Bits Interrupt/Enable INT_DS = (1 << 2), // DMA Setup FIS Interrupt/Enable INT_PS = (1 << 1), // PIO Setup FIS Interrupt/Enable - INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt/Enable + INT_DHR = (1 << 0), // Device to Host Register FIS + // Interrupt/Enable }; typedef struct { uint16 reserved : 12; - uint8 pmp : 4; // Port Multiplier Port: Not used by AHCI - uint8 spm : 4; // Select Power Management: Not used by AHCI - uint8 ipm : 4; // Interface Power Management Transitions Allowed - uint8 spd : 4; // Speed Allowed - uint8 det : 4; // Device Detection Initialization + uint8 pmp : 4; // Port Multiplier Port: Not used by AHCI + uint8 spm : 4; // Select Power Management: Not used by AHCI + uint8 ipm : 4; // Interface Power Management Transitions Allowed + uint8 spd : 4; // Speed Allowed + uint8 det : 4; // Device Detection Initialization } _PACKED scontrol; #define IPM_TRANSITIONS_TO_PARTIAL_DISABLED 0x1 @@ -92,14 +94,15 @@ typedef struct { typedef struct { - uint32 clb; // Command List Base Address (alignment 1024 byte) + uint32 clb; // Command List Base Address + // (alignment 1024 byte) uint32 clbu; // Command List Base Address Upper 32-Bits uint32 fb; // FIS Base Address (alignment 256 byte) uint32 fbu; // FIS Base Address Upper 32-Bits uint32 is; // Interrupt Status **RWC** uint32 ie; // Interrupt Enable uint32 cmd; // Command and Status - uint32 res1; // Reserved + uint32 res1; // Reserved uint32 tfd; // Task File Data uint32 sig; // Signature uint32 ssts; // Serial ATA Status (SCR0: SStatus) @@ -116,9 +119,9 @@ typedef struct { enum { - PORT_CMD_ICC_ACTIVE = (1 << 28), // Interface Communication control - PORT_CMD_ICC_SLUMBER = (6 << 28), // Interface Communication control - PORT_CMD_ICC_MASK = (0xf<<28), // Interface Communication control + PORT_CMD_ICC_ACTIVE = (1 << 28), // Interface Communication control + PORT_CMD_ICC_SLUMBER = (6 << 28), // Interface Communication control + PORT_CMD_ICC_MASK = (0xf<<28), // Interface Communication control PORT_CMD_ATAPI = (1 << 24), // Device is ATAPI PORT_CMD_CR = (1 << 15), // Command List Running (DMA active) PORT_CMD_FR = (1 << 14), // FIS Receive Running @@ -150,17 +153,17 @@ enum { PORT_INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt }; -#define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBF | PORT_INT_HBD \ - | PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \ - | PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \ - | PORT_INT_UF) +#define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBF | PORT_INT_HBD \ + | PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \ + | PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \ + | PORT_INT_UF) #define PORT_INT_MASK (PORT_INT_ERROR | PORT_INT_DP | PORT_INT_SDB \ - | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) + | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) enum { - ATA_BSY = 0x80, - ATA_DF = 0x20, + ATA_BSY = 0x80, + ATA_DF = 0x20, ATA_DRQ = 0x08, ATA_ERR = 0x01, }; @@ -168,11 +171,11 @@ enum { enum { PORT_FBS_DWE_SHIFT = 16, // Device With Error - PORT_FBS_DWE_MASK = 0xf, + PORT_FBS_DWE_MASK = 0xf, PORT_FBS_ADO_SHIFT = 12, // Active Device Optimization - PORT_FBS_ADO_MASK = 0xf, + PORT_FBS_ADO_MASK = 0xf, PORT_FBS_DEV_SHIFT = 8, // Device To Issue - PORT_FBS_DEV_MASK = 0xf, + PORT_FBS_DEV_MASK = 0xf, PORT_FBS_SDE = 0x04, // Single Device Error PORT_FBS_DEC = 0x02, // Device Error Clear PORT_FBS_EN = 0x01, // Enable @@ -181,7 +184,7 @@ enum { enum { PORT_DEVSLP_DM_SHIFT = 25, // DITO Multiplier - PORT_DEVSLP_DM_MASK = 0xf, + PORT_DEVSLP_DM_MASK = 0xf, PORT_DEVSLP_DITO_SHIFT = 15, // Device Sleep Idle Timeout PORT_DEVSLP_DITO_MASK = 0x3ff, PORT_DEVSLP_MDAT_SHIFT = 10, // Minimum Device Sleep Assertion Time @@ -194,12 +197,13 @@ enum { enum { - CAP2_DESO = (1 << 5), // DevSleep Entrance from Slumber Only - CAP2_SADM = (1 << 4), // Supports Aggressive Device Sleep Management - CAP2_SDS = (1 << 3), // Supports Device Sleep - CAP2_APST = (1 << 2), // Automatic Partial to Slumber Transitions - CAP2_NVMP = (1 << 1), // NVMHCI Present - CAP2_BOH = (1 << 0), // BIOS/OS Handoff + CAP2_DESO = (1 << 5), // DevSleep Entrance from Slumber Only + CAP2_SADM = (1 << 4), // Supports Aggressive Device Sleep + // Management + CAP2_SDS = (1 << 3), // Supports Device Sleep + CAP2_APST = (1 << 2), // Automatic Partial to Slumber Transitions + CAP2_NVMP = (1 << 1), // NVMHCI Present + CAP2_BOH = (1 << 0), // BIOS/OS Handoff }; @@ -235,21 +239,22 @@ typedef struct { typedef struct { - union { - struct { - uint16 cfl : 5; // command FIS length - uint16 a : 1; // ATAPI - uint16 w : 1; // Write - uint16 p : 1; // Prefetchable - uint16 r : 1; // Reset - uint16 b : 1; // Build In Self Test - uint16 c : 1; // Clear Busy upon R_OK - uint16 : 1; - uint16 pmp : 4; // Port Multiplier Port - uint16 prdtl; // physical region description table length; - } _PACKED; - uint32 prdtl_flags_cfl; - } _PACKED; + union { + struct { + uint16 cfl : 5; // command FIS length + uint16 a : 1; // ATAPI + uint16 w : 1; // Write + uint16 p : 1; // Prefetchable + uint16 r : 1; // Reset + uint16 b : 1; // Build In Self Test + uint16 c : 1; // Clear Busy upon R_OK + uint16 : 1; + uint16 pmp : 4; // Port Multiplier Port + uint16 prdtl; // physical region description table + // length; + } _PACKED; + uint32 prdtl_flags_cfl; + } _PACKED; uint32 prdbc; // PRD Byte Count uint32 ctba; // command table desciptor base address // (alignment 128 byte) @@ -265,16 +270,16 @@ typedef struct { // 1 - C bit (0x80) // 2 - Command // 3 - Features -// 4 - Sector Number (LBA Low, bits 0-7) -// 5 - Cylinder Low (LBA Mid, bits 8-15) -// 6 - Cylinder High (LBA High, bits 16-23) -// 7 - Device / Head (for 28-bit LBA commands, bits 24-27) -// 8 - Sector Number expanded (LBA Low-previous, bits 24-31) -// 9 - Cylinder Low expanded (LBA Mid-previous, bits 32-39) -// 10 - Cylinder High expanded (LBA High-previous, bits 40-47) +// 4 - Sector Number (LBA Low, bits 0-7) +// 5 - Cylinder Low (LBA Mid, bits 8-15) +// 6 - Cylinder High (LBA High, bits 16-23) +// 7 - Device / Head (for 28-bit LBA commands, bits 24-27) +// 8 - Sector Number expanded (LBA Low-previous, bits 24-31) +// 9 - Cylinder Low expanded (LBA Mid-previous, bits 32-39) +// 10 - Cylinder High expanded (LBA High-previous, bits 40-47) // 11 - Features expanded -// 12 - Sector Count (Sector count, bits 0-7) -// 13 - Sector Count expanded (Sector count, bits 8-15) +// 12 - Sector Count (Sector count, bits 0-7) +// 13 - Sector Count expanded (Sector count, bits 8-15) // 14 - Reserved (0) // 15 - Control // 16 - Reserved (0) From cccf804d9691b645621f923102d0d22295f29744 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 30 Aug 2015 11:17:47 +0200 Subject: [PATCH 118/125] ahci: Replace use of bit field with shifts and masks. It's a 32 bit register which needs properly aligned 32 bit writes. Using a bit field does not guarantee that, so replace it with shifts and masks. Should fix #12338. --- .../kernel/busses/scsi/ahci/ahci_defs.h | 27 ++++++++------ .../kernel/busses/scsi/ahci/ahci_port.cpp | 35 ++++++++++--------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h index 547c3018de..b9c8c035e6 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h @@ -78,19 +78,24 @@ enum { // Interrupt/Enable }; -typedef struct { - uint16 reserved : 12; - uint8 pmp : 4; // Port Multiplier Port: Not used by AHCI - uint8 spm : 4; // Select Power Management: Not used by AHCI - uint8 ipm : 4; // Interface Power Management Transitions Allowed - uint8 spd : 4; // Speed Allowed - uint8 det : 4; // Device Detection Initialization -} _PACKED scontrol; + +// Device Detection Initialization +#define SATA_CONTROL_DET_SHIFT 0 +#define SATA_CONTROL_DET_MASK 0x0000000f + +#define DET_NO_INITIALIZATION 0x0 +#define DET_INITIALIZATION 0x1 + +// Speed Allowed +#define SATA_CONTROL_SPD_SHIFT 4 +#define SATA_CONTROL_SPD_MASK 0x000000f0 + +// Interface Power Management Transitions Allowed +#define SATA_CONTROL_IPM_SHIFT 8 +#define SATA_CONTROL_IPM_MASK 0x00000f00 #define IPM_TRANSITIONS_TO_PARTIAL_DISABLED 0x1 #define IPM_TRANSITIONS_TO_SLUMBER_DISABLED 0x2 -#define DET_NO_INITIALIZATION 0x0 -#define DET_INITIALIZATION 0x1 typedef struct { @@ -106,7 +111,7 @@ typedef struct { uint32 tfd; // Task File Data uint32 sig; // Signature uint32 ssts; // Serial ATA Status (SCR0: SStatus) - scontrol sctl; // Serial ATA Control (SCR2: SControl) + uint32 sctl; // Serial ATA Control (SCR2: SControl) uint32 serr; // Serial ATA Error (SCR1: SError) **RWC** uint32 sact; // Serial ATA Active (SCR3: SActive) **RW1** uint32 ci; // Command Issue **RW1** diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index 2cd4ca5369..25ba34ca3c 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -110,8 +110,9 @@ AHCIPort::Init1() // prdt follows after command table // disable transitions to partial or slumber state - fRegs->sctl.ipm = IPM_TRANSITIONS_TO_PARTIAL_DISABLED - | IPM_TRANSITIONS_TO_SLUMBER_DISABLED; + fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_IPM_MASK) + | (IPM_TRANSITIONS_TO_PARTIAL_DISABLED + | IPM_TRANSITIONS_TO_SLUMBER_DISABLED) << SATA_CONTROL_IPM_SHIFT; // clear IRQ status bits fRegs->is = fRegs->is; @@ -157,12 +158,12 @@ AHCIPort::Init2() TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd); TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); - TRACE("sctl.reserved 0x%04" B_PRIx16 "\n", fRegs->sctl.reserved); - TRACE("sctl.pmp 0x%02" B_PRIx8 "\n", fRegs->sctl.pmp); - TRACE("sctl.spm 0x%02" B_PRIx8 "\n", fRegs->sctl.spm); - TRACE("sctl.ipm 0x%02" B_PRIx8 "\n", fRegs->sctl.ipm); - TRACE("sctl.spd 0x%02" B_PRIx8 "\n", fRegs->sctl.spd); - TRACE("sctl.det 0x%02" B_PRIx8 "\n", fRegs->sctl.det); + TRACE("sctl.ipm 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_IPM_MASK) >> SATA_CONTROL_IPM_SHIFT); + TRACE("sctl.spd 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_SPD_MASK) >> SATA_CONTROL_SPD_SHIFT); + TRACE("sctl.det 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_DET_MASK) >> SATA_CONTROL_DET_SHIFT); TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd); @@ -359,12 +360,12 @@ AHCIPort::InterruptErrorHandler(uint32 is) B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", fIndex, fCommandsActive, is, ci); TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); - TRACE("sctl.reserved 0x%04" B_PRIx16 "\n", fRegs->sctl.reserved); - TRACE("sctl.pmp 0x%02" B_PRIx8 "\n", fRegs->sctl.pmp); - TRACE("sctl.spm 0x%02" B_PRIx8 "\n", fRegs->sctl.spm); - TRACE("sctl.ipm 0x%02" B_PRIx8 "\n", fRegs->sctl.ipm); - TRACE("sctl.spd 0x%02" B_PRIx8 "\n", fRegs->sctl.spd); - TRACE("sctl.det 0x%02" B_PRIx8 "\n", fRegs->sctl.det); + TRACE("sctl.ipm 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_IPM_MASK) >> SATA_CONTROL_IPM_SHIFT); + TRACE("sctl.spd 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_SPD_MASK) >> SATA_CONTROL_SPD_SHIFT); + TRACE("sctl.det 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_DET_MASK) >> SATA_CONTROL_DET_SHIFT); TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); } @@ -1239,11 +1240,13 @@ AHCIPort::_HardReset() TRACE("AHCIPort::_HardReset() PORT_CMD_ST set, behaviour undefined\n"); } - fRegs->sctl.det = DET_INITIALIZATION; + fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) + | DET_INITIALIZATION << SATA_CONTROL_DET_SHIFT; FlushPostedWrites(); spin(1100); // You must wait 1ms at minimum - fRegs->sctl.det = DET_NO_INITIALIZATION; + fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) + | DET_NO_INITIALIZATION << SATA_CONTROL_DET_SHIFT; FlushPostedWrites(); } From 0f7e19ce7ec4dfe4d0a4e0b21eb22c4392637568 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 30 Aug 2015 14:53:47 +0200 Subject: [PATCH 119/125] ffmpeg plugin: add support for MOD and other "tracked music" * ffmpeg can handle these through ModPlug * By default, ffmpoeg will not try these formats because the way to detect them are a bit unsafe (4 bytes at a particular offset in the file serve as an identifier). So, hint the sniffing by giving it a filename of ".mod" to get modplug to be used. This does not affect sniffing in the regular way for other formats. * Add some common tracked music formats to the muxer table. * Fix some tracing to use current (as of ffmpeg 0.10) function names and because some variables were renamed. --- .../media/plugins/ffmpeg/AVFormatReader.cpp | 4 +- .../media/plugins/ffmpeg/MuxerTable.cpp | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp index 742976f915..5da841ce59 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp @@ -257,7 +257,7 @@ StreamBase::Open() fContext->pb = fIOContext; // Allocate our context and probe the input format - if (avformat_open_input(&fContext, "", NULL, NULL) < 0) { + if (avformat_open_input(&fContext, ".mod", NULL, NULL) < 0) { TRACE("StreamBase::Open() - avformat_open_input() failed!\n"); // avformat_open_input() frees the context in case of failure fContext = NULL; @@ -1505,7 +1505,7 @@ AVFormatReader::Sniff(int32* _streamCount) streamDeleter.Detach(); #ifdef TRACE_AVFORMAT_READER - dump_format(const_cast(stream->Context()), 0, "", 0); + av_dump_format(const_cast(stream->Context()), 0, "", 0); #endif if (_streamCount != NULL) diff --git a/src/add-ons/media/plugins/ffmpeg/MuxerTable.cpp b/src/add-ons/media/plugins/ffmpeg/MuxerTable.cpp index 2856694b98..ed22c4e303 100644 --- a/src/add-ons/media/plugins/ffmpeg/MuxerTable.cpp +++ b/src/add-ons/media/plugins/ffmpeg/MuxerTable.cpp @@ -318,6 +318,62 @@ const media_file_format gMuxerTable[] = { "webm", { 0 } }, + { + media_file_format::B_READABLE + | media_file_format::B_KNOWS_RAW_AUDIO + | media_file_format::B_KNOWS_ENCODED_AUDIO, + { 0 }, + B_MISC_FORMAT_FAMILY, + 100, + { 0 }, + "audio/xm", + "Fast Tracker eXtended Module", + "xm", + "xm", + { 0 } + }, + { + media_file_format::B_READABLE + | media_file_format::B_KNOWS_RAW_AUDIO + | media_file_format::B_KNOWS_ENCODED_AUDIO, + { 0 }, + B_MISC_FORMAT_FAMILY, + 100, + { 0 }, + "audio/s3m", + "Scream Tracker 3", + "s3m", + "s3m", + { 0 } + }, + { + media_file_format::B_READABLE + | media_file_format::B_KNOWS_RAW_AUDIO + | media_file_format::B_KNOWS_ENCODED_AUDIO, + { 0 }, + B_MISC_FORMAT_FAMILY, + 100, + { 0 }, + "audio/it", + "Impulse Tracker", + "it", + "it", + { 0 } + }, + { + media_file_format::B_READABLE + | media_file_format::B_KNOWS_RAW_AUDIO + | media_file_format::B_KNOWS_ENCODED_AUDIO, + { 0 }, + B_MISC_FORMAT_FAMILY, + 100, + { 0 }, + "audio/x-mod", + "Protracker MOD", + "mod", + "mod", + { 0 } + }, }; const size_t gMuxerCount = sizeof(gMuxerTable) / sizeof(media_file_format); From 9e5c694668556b60e49a49e6708bfb550fc6ce1b Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 30 Aug 2015 16:20:40 +0200 Subject: [PATCH 120/125] ffmpeg plugin: remove more deprecated functions. These were all deprecated between releases 0.6 and 0.10 of ffmpeg, except for one change (renaming of CodecID to AVCodecID) which we can work around with a typedef. The deprecated functions were still available in 0.11, but were removed later on after several years of deprecation. This makes it possible to build our plugin with any ffmpeg version between 0.10 and 2.7, so we can now experiment with updating to 2.7 at least for the gcc4 builds. --- src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp | 12 ++++++++---- src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp | 6 +++--- src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h | 5 +++++ src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp | 12 ++++++++++-- src/add-ons/media/plugins/ffmpeg/CodecTable.cpp | 8 +++++++- src/add-ons/media/plugins/ffmpeg/EncoderTable.h | 5 +++++ src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp | 2 +- 7 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp index ac417f4ded..67d8847c10 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp @@ -57,6 +57,10 @@ // Otherwise the alternative code could simply be removed from this file. #endif +#if __GNUC__ > 2 +typedef AVCodecID CodecID; +#endif + struct wave_format_ex { uint16 format_tag; @@ -409,10 +413,10 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat) if (fRawDecodedAudio->opaque == NULL) return B_NO_MEMORY; - TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, init = %d, " + TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, " "output frame size: %d, count: %ld, rate: %.2f\n", fContext->bit_rate, fContext->sample_rate, fContext->channels, - result, fOutputFrameSize, fOutputFrameCount, fOutputFrameRate); + fOutputFrameSize, fOutputFrameCount, fOutputFrameRate); return B_OK; } @@ -716,7 +720,7 @@ AVCodecDecoder::_DecodeNextAudioFrame() dump_ffframe_audio(fRawDecodedAudio, "ffaudi"); #endif - TRACE_AUDIO(" frame count: %lld current: %lld\n", + TRACE_AUDIO(" frame count: %ld current: %lld\n", fRawDecodedAudio->nb_samples, fFrame); return B_OK; @@ -1193,7 +1197,7 @@ AVCodecDecoder::_DecodeNextVideoFrame() fRawDecodedPicture, &gotVideoFrame, &fTempPacket); if (encodedDataSizeInBytes < 0) { TRACE("[v] AVCodecDecoder: ignoring error in decoding frame %lld:" - " %d\n", fFrame, len); + " %d\n", fFrame, encodedDataSizeInBytes); // NOTE: An error from avcodec_decode_video2() is ignored by the // FFMPEG 0.10.2 example decoding_encoding.c. Only the packet // buffers are flushed accordingly diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp index 647674630b..b30de87542 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp @@ -40,9 +40,9 @@ AVCodecEncoder::AVCodecEncoder(uint32 codecID, int bitRateScale) : Encoder(), fBitRateScale(bitRateScale), - fCodecID((enum CodecID)codecID), + fCodecID((CodecID)codecID), fCodec(NULL), - fOwnContext(avcodec_alloc_context()), + fOwnContext(avcodec_alloc_context3(NULL)), fContext(fOwnContext), fCodecInitStatus(CODEC_INIT_NEEDED), @@ -494,7 +494,7 @@ AVCodecEncoder::_OpenCodecIfNeeded() fContext->strict_std_compliance = -2; // Open the codec - int result = avcodec_open(fContext, fCodec); + int result = avcodec_open2(fContext, fCodec, NULL); if (result >= 0) fCodecInitStatus = CODEC_INIT_DONE; else diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h index 79139f7db4..4056c376cd 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h @@ -17,6 +17,11 @@ extern "C" { #include "EncoderPlugin.h" +#if __GNUC__ > 2 +typedef AVCodecID CodecID; +#endif + + class AVCodecEncoder : public Encoder { public: AVCodecEncoder(uint32 codecID, diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp index 1095a7d7d6..a453dd8d1c 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp @@ -53,6 +53,9 @@ static const size_t kIOBufferSize = 64 * 1024; #define OPEN_CODEC_CONTEXT 1 #define GET_CONTEXT_DEFAULTS 0 +#if __GNUC__ > 2 +typedef AVCodecID CodecID; +#endif // #pragma mark - AVFormatWriter::StreamCookie @@ -109,7 +112,8 @@ AVFormatWriter::StreamCookie::Init(media_format* format, BAutolock _(fStreamLock); fPacket.stream_index = fContext->nb_streams; - fStream = av_new_stream(fContext, fPacket.stream_index); + fStream = avformat_new_stream(fContext, NULL); + fStream->id = fPacket.stream_index; if (fStream == NULL) { TRACE(" failed to add new stream\n"); @@ -200,6 +204,10 @@ AVFormatWriter::StreamCookie::Init(media_format* format, // Now negociate the actual format with the encoder // First check if the requested format is acceptable AVCodec* codec = avcodec_find_encoder(fStream->codec->codec_id); + + if (codec == NULL) + return B_MEDIA_BAD_FORMAT; + const enum AVSampleFormat *p = codec->sample_fmts; for (; *p != -1; p++) { if (*p == fStream->codec->sample_fmt) @@ -466,7 +474,7 @@ AVFormatWriter::CommitHeader() AVCodecContext* codecContext = stream->codec; codecContext->strict_std_compliance = -2; AVCodec* codec = avcodec_find_encoder(codecContext->codec_id); - if (codec == NULL || avcodec_open(codecContext, codec) < 0) { + if (codec == NULL || avcodec_open2(codecContext, codec, NULL) < 0) { TRACE(" stream[%u] - failed to open AVCodecContext\n", i); } TRACE(" stream[%u] time_base: (%d/%d), codec->time_base: (%d/%d)\n", diff --git a/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp b/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp index dd5e0ce5e2..80ee775e75 100644 --- a/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp +++ b/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp @@ -11,9 +11,15 @@ extern "C" { #include "avformat.h" } + +#if __GNUC__ > 2 +typedef AVCodecID CodecID; +#endif + + //XXX: newer versions have it in libavformat/internal.h typedef struct AVCodecTag { - enum CodecID id; + CodecID id; unsigned int tag; } AVCodecTag; diff --git a/src/add-ons/media/plugins/ffmpeg/EncoderTable.h b/src/add-ons/media/plugins/ffmpeg/EncoderTable.h index 2e966de91b..9170116507 100644 --- a/src/add-ons/media/plugins/ffmpeg/EncoderTable.h +++ b/src/add-ons/media/plugins/ffmpeg/EncoderTable.h @@ -13,6 +13,11 @@ extern "C" { } +#if __GNUC__ > 2 +typedef AVCodecID CodecID; +#endif + + struct EncoderDescription { media_codec_info codec_info; media_format_family format_family; diff --git a/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp b/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp index b17304b81f..e3ec9873b0 100644 --- a/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp +++ b/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp @@ -53,7 +53,7 @@ manage_locks(void** _lock, enum AVLockOp operation) case AV_LOCK_CREATE: TRACE(" AV_LOCK_CREATE\n"); *lock = new(std::nothrow) BLocker("FFmpeg lock"); - if (*lock == NULL) + if (*lock == NULL) return 1; break; From f618c89e17deda1047a747bec2685b82eac48b79 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 30 Aug 2015 17:33:00 +0200 Subject: [PATCH 121/125] ffmpeg: detect the library version the right way. * Fixes the build by detecting the library version using the provided constants, instead of guessing from the compiler version. --- src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp | 2 +- src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h | 2 +- src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp | 2 +- src/add-ons/media/plugins/ffmpeg/CodecTable.cpp | 2 +- src/add-ons/media/plugins/ffmpeg/EncoderTable.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp index 67d8847c10..0e724c3580 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp @@ -57,7 +57,7 @@ // Otherwise the alternative code could simply be removed from this file. #endif -#if __GNUC__ > 2 +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) typedef AVCodecID CodecID; #endif diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h index 4056c376cd..c32ea7746b 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h @@ -17,7 +17,7 @@ extern "C" { #include "EncoderPlugin.h" -#if __GNUC__ > 2 +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) typedef AVCodecID CodecID; #endif diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp index a453dd8d1c..939778c87b 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp @@ -53,7 +53,7 @@ static const size_t kIOBufferSize = 64 * 1024; #define OPEN_CODEC_CONTEXT 1 #define GET_CONTEXT_DEFAULTS 0 -#if __GNUC__ > 2 +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) typedef AVCodecID CodecID; #endif diff --git a/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp b/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp index 80ee775e75..b87dc12120 100644 --- a/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp +++ b/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp @@ -12,7 +12,7 @@ extern "C" { } -#if __GNUC__ > 2 +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) typedef AVCodecID CodecID; #endif diff --git a/src/add-ons/media/plugins/ffmpeg/EncoderTable.h b/src/add-ons/media/plugins/ffmpeg/EncoderTable.h index 9170116507..a1bde6b488 100644 --- a/src/add-ons/media/plugins/ffmpeg/EncoderTable.h +++ b/src/add-ons/media/plugins/ffmpeg/EncoderTable.h @@ -13,7 +13,7 @@ extern "C" { } -#if __GNUC__ > 2 +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) typedef AVCodecID CodecID; #endif From 278af8e281390a344b2271a27dffc4a6798200eb Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 30 Aug 2015 18:00:08 +0200 Subject: [PATCH 122/125] ffmpeg: check against correct version constants. 54.23.x is ffmpeg 0.11, which still has "CodecID" (and x>0). --- src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp | 2 +- src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h | 2 +- src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp | 2 +- src/add-ons/media/plugins/ffmpeg/CodecTable.cpp | 2 +- src/add-ons/media/plugins/ffmpeg/EncoderTable.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp index 0e724c3580..48c47d8930 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp @@ -57,7 +57,7 @@ // Otherwise the alternative code could simply be removed from this file. #endif -#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) typedef AVCodecID CodecID; #endif diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h index c32ea7746b..bf23ecb19a 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h @@ -17,7 +17,7 @@ extern "C" { #include "EncoderPlugin.h" -#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) typedef AVCodecID CodecID; #endif diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp index 939778c87b..2121722d4d 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp @@ -53,7 +53,7 @@ static const size_t kIOBufferSize = 64 * 1024; #define OPEN_CODEC_CONTEXT 1 #define GET_CONTEXT_DEFAULTS 0 -#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) typedef AVCodecID CodecID; #endif diff --git a/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp b/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp index b87dc12120..bd04566d7a 100644 --- a/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp +++ b/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp @@ -12,7 +12,7 @@ extern "C" { } -#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) typedef AVCodecID CodecID; #endif diff --git a/src/add-ons/media/plugins/ffmpeg/EncoderTable.h b/src/add-ons/media/plugins/ffmpeg/EncoderTable.h index a1bde6b488..c2d36184b8 100644 --- a/src/add-ons/media/plugins/ffmpeg/EncoderTable.h +++ b/src/add-ons/media/plugins/ffmpeg/EncoderTable.h @@ -13,7 +13,7 @@ extern "C" { } -#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (23 << 8)) +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) typedef AVCodecID CodecID; #endif From a33d19b0a43da117fec9259d55935f99cd445316 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 30 Aug 2015 23:09:44 +0200 Subject: [PATCH 123/125] Update haikuwebkit packages to 1.4.12 on x86[_(gcc2|64)]. --- build/jam/repositories/HaikuPorts/x86 | 4 ++-- build/jam/repositories/HaikuPorts/x86_64 | 4 ++-- build/jam/repositories/HaikuPorts/x86_gcc2 | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/jam/repositories/HaikuPorts/x86 b/build/jam/repositories/HaikuPorts/x86 index cf0a2fee84..41cd7b1842 100644 --- a/build/jam/repositories/HaikuPorts/x86 +++ b/build/jam/repositories/HaikuPorts/x86 @@ -90,8 +90,8 @@ RemotePackageRepository HaikuPorts gutenprint-5.2.10-1 gutenprint_devel-5.2.10-1 gzip-1.6-2 - haikuwebkit-1.4.10-1 - haikuwebkit_devel-1.4.10-1 + haikuwebkit-1.4.12-1 + haikuwebkit_devel-1.4.12-1 help2man-1.46.6-1 htmldoc-1.8.27-3 icu-55.1-4 diff --git a/build/jam/repositories/HaikuPorts/x86_64 b/build/jam/repositories/HaikuPorts/x86_64 index 5f30837cac..2e67ef65af 100644 --- a/build/jam/repositories/HaikuPorts/x86_64 +++ b/build/jam/repositories/HaikuPorts/x86_64 @@ -129,8 +129,8 @@ RemotePackageRepository HaikuPorts gutenprint-5.2.10-1 gutenprint_devel-5.2.10-1 gzip-1.6-2 - haikuwebkit-1.4.10-1 - haikuwebkit_devel-1.4.10-1 + haikuwebkit-1.4.12-1 + haikuwebkit_devel-1.4.12-1 handbrake-0.10.1-1 harfbuzz-0.9.40-1 harfbuzz_devel-0.9.40-1 diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index 7e90023a97..90809a2c3f 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -626,8 +626,8 @@ RemotePackageRepository HaikuPorts graphite2_x86_devel-1.2.4-1 guilib_x86-1.2.1-1 guilib_x86_devel-1.2.1-1 - haikuwebkit_x86-1.4.11-1 - haikuwebkit_x86_devel-1.4.11-1 + haikuwebkit_x86-1.4.12-1 + haikuwebkit_x86_devel-1.4.12-1 harfbuzz_x86-0.9.39-1 harfbuzz_x86_devel-0.9.39-1 icu_x86-55.1-1 From 7d337b23b7a962caac04e6e5b8a03a35b9591394 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Tue, 1 Sep 2015 13:02:07 +0200 Subject: [PATCH 124/125] BMediaRoster: Reintroduce the undertaker class * This has been necessary due to the undefined call order of of static objects. Fixes #12315. * The bug has been caused by the linker which free unused resources, making the BMediaRoster to run in a zombie state. In this state anything such as a message could make the looper to crash. * The class is reintroduced with some differences though, we are going to protect it from another thread calling Roster() while the BMediaRoster is quitting and implement BMediaRosterEx::Quit. * Unregister registrar notifications before we quit our thread. Avoid to uninitialize anything from QuitRequested as it may cause problems. --- headers/private/media/MediaRosterEx.h | 2 ++ src/kits/media/MediaRoster.cpp | 40 +++++++++++++++++++++------ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/headers/private/media/MediaRosterEx.h b/headers/private/media/MediaRosterEx.h index ab8ba22b25..74bec127e5 100644 --- a/headers/private/media/MediaRosterEx.h +++ b/headers/private/media/MediaRosterEx.h @@ -37,6 +37,8 @@ public: BMediaRosterEx(status_t* out_error); virtual ~BMediaRosterEx(); + virtual void Quit(); + status_t SaveNodeConfiguration(BMediaNode* node); status_t LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage* out_msg); diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 22552bf20d..363fa93b63 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -86,6 +86,22 @@ static bool sServerIsUp = false; static List sNotificationList; static BLocker sInitLocker("BMediaRoster::Roster locker"); + +class MediaRosterUndertaker { +public: + ~MediaRosterUndertaker() + { + BAutolock _(sInitLocker); + if (BMediaRoster::CurrentRoster() != NULL + && BMediaRoster::CurrentRoster()->Lock()) { + BMediaRoster::CurrentRoster()->Quit(); + } + } +}; + + +static MediaRosterUndertaker sMediaRosterUndertaker; + } // namespace media } // namespace BPrivate @@ -96,8 +112,8 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error) : BMediaRoster() { - gDormantNodeManager = new DormantNodeManager; - gTimeSourceObjectManager = new TimeSourceObjectManager; + gDormantNodeManager = new DormantNodeManager(); + gTimeSourceObjectManager = new TimeSourceObjectManager(); *_error = BuildConnections(); @@ -111,6 +127,19 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error) } +void +BMediaRosterEx::Quit() +{ + if (be_roster->StopWatching(BMessenger(this, this)) != B_OK) + TRACE("Can't unregister roster notifications"); + + if (sNotificationList.CountItems() != 0) + sNotificationList.MakeEmpty(); + + BMediaRoster::Quit(); +} + + status_t BMediaRosterEx::BuildConnections() { @@ -3474,13 +3503,6 @@ bool BMediaRoster::QuitRequested() { CALLED(); - - if (be_roster->StopWatching(BMessenger(this, this)) != B_OK) - TRACE("Can't unregister roster notifications"); - - if (sNotificationList.CountItems() != 0) - sNotificationList.MakeEmpty(); - return true; } From 38e3fbe3892110c7526db6037cb701fb4e4e0e41 Mon Sep 17 00:00:00 2001 From: Dario Casalinuovo Date: Tue, 1 Sep 2015 15:04:32 +0200 Subject: [PATCH 125/125] BMediaRoster: Remove possibly confusing debug prints * Thanks to Axel and Rene for reviewing! --- src/kits/media/MediaRoster.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 363fa93b63..6351302baf 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -3491,8 +3491,6 @@ BMediaRoster::MessageReceived(BMessage* message) } default: - printf("BMediaRoster::MessageReceived: unknown message!\n"); - message->PrintToStream(); BLooper::MessageReceived(message); break; }