Notification_Server: Added ability to choose position of notifications

The feature gives user ability to choose the position of notifications
out of Follow Deskbar, Lower Right, Lower Left, Upper Right and Upper
Left. Fixes #9749 - Notification_Server: add the ability to choose the
position of notifications (easy).

Signed-off-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
Hrishi Hiraskar 2017-12-11 16:24:02 +05:30 committed by Adrien Destugues
parent e229bf70b8
commit 226f6c8bf1
6 changed files with 197 additions and 35 deletions

View File

@ -6,10 +6,13 @@
#define _NOTIFICATIONS_H #define _NOTIFICATIONS_H
#include <Mime.h> #include <Mime.h>
#include <View.h>
#include <String.h> #include <String.h>
#define kNotificationServerSignature "application/x-vnd.Haiku-notification_server" #define kNotificationServerSignature "application/x-vnd.Haiku-notification_server"
#define B_FOLLOW_DESKBAR B_FOLLOW_NONE
// Messages // Messages
const uint32 kNotificationMessage = 'nssm'; const uint32 kNotificationMessage = 'nssm';
@ -21,6 +24,7 @@ extern const char* kAutoStartName;
extern const char* kTimeoutName; extern const char* kTimeoutName;
extern const char* kWidthName; extern const char* kWidthName;
extern const char* kIconSizeName; extern const char* kIconSizeName;
extern const char* kNotificationPositionName;
// General default settings // General default settings
const bool kDefaultAutoStart = true; const bool kDefaultAutoStart = true;
@ -32,5 +36,6 @@ const float kMinimumWidth = 300.0f;
const float kMaximumWidth = 1000.0f; const float kMaximumWidth = 1000.0f;
const int32 kWidthStep = 50; const int32 kWidthStep = 50;
const icon_size kDefaultIconSize = B_LARGE_ICON; const icon_size kDefaultIconSize = B_LARGE_ICON;
const uint32 kDefaultNotificationPosition = B_FOLLOW_DESKBAR;
#endif // _NOTIFICATIONS_H #endif // _NOTIFICATIONS_H

View File

@ -43,10 +43,27 @@
const uint32 kToggleNotifications = '_TSR'; const uint32 kToggleNotifications = '_TSR';
const uint32 kWidthChanged = '_WIC'; const uint32 kWidthChanged = '_WIC';
const uint32 kTimeoutChanged = '_TIC'; const uint32 kTimeoutChanged = '_TIC';
const uint32 kPositionChanged = '_NPC';
const uint32 kServerChangeTriggered = '_SCT'; const uint32 kServerChangeTriggered = '_SCT';
const BString kSampleMessageID("NotificationsSample"); const BString kSampleMessageID("NotificationsSample");
static int32
notification_position_to_index(uint32 notification_position) {
if (notification_position == B_FOLLOW_NONE)
return 0;
else if (notification_position == (B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM))
return 1;
else if (notification_position == (B_FOLLOW_LEFT | B_FOLLOW_BOTTOM))
return 2;
else if (notification_position == (B_FOLLOW_RIGHT | B_FOLLOW_TOP))
return 3;
else if (notification_position == (B_FOLLOW_LEFT | B_FOLLOW_TOP))
return 4;
return 0;
}
GeneralView::GeneralView(SettingsHost* host) GeneralView::GeneralView(SettingsHost* host)
: :
SettingsPane("general", host) SettingsPane("general", host)
@ -87,10 +104,37 @@ GeneralView::GeneralView(SettingsHost* host)
B_TRANSLATE_COMMENT(minLabel.String(), "Slider low text"), B_TRANSLATE_COMMENT(minLabel.String(), "Slider low text"),
B_TRANSLATE_COMMENT(maxLabel.String(), "Slider high text")); B_TRANSLATE_COMMENT(maxLabel.String(), "Slider high text"));
// Notification Position
fPositionMenu = new BPopUpMenu(B_TRANSLATE("Follow Deskbar"));
const char* positionLabels[] = {
B_TRANSLATE_MARK("Follow Deskbar"),
B_TRANSLATE_MARK("Lower right"),
B_TRANSLATE_MARK("Lower left"),
B_TRANSLATE_MARK("Upper right"),
B_TRANSLATE_MARK("Upper left")
};
const uint32 positions[] = {
B_FOLLOW_DESKBAR, // Follow Deskbar
B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT, // Lower right
B_FOLLOW_BOTTOM | B_FOLLOW_LEFT, // Lower left
B_FOLLOW_TOP | B_FOLLOW_RIGHT, // Upper right
B_FOLLOW_TOP | B_FOLLOW_LEFT // Upper left
};
for (int i=0; i < 5; i++) {
BMessage* message = new BMessage(kPositionChanged);
message->AddInt32(kNotificationPositionName, positions[i]);
fPositionMenu->AddItem(new BMenuItem(B_TRANSLATE_NOCOLLECT(
positionLabels[i]), message));
}
BMenuField* positionField = new BMenuField(B_TRANSLATE("Position:"),
fPositionMenu);
box->AddChild(BLayoutBuilder::Group<>(B_VERTICAL) box->AddChild(BLayoutBuilder::Group<>(B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING) .SetInsets(B_USE_DEFAULT_SPACING)
.Add(fWidthSlider) .Add(fWidthSlider)
.Add(fDurationSlider) .Add(fDurationSlider)
.Add(positionField)
.AddGlue() .AddGlue()
.View()); .View());
@ -108,6 +152,7 @@ GeneralView::AttachedToWindow()
fNotificationBox->SetTarget(this); fNotificationBox->SetTarget(this);
fWidthSlider->SetTarget(this); fWidthSlider->SetTarget(this);
fDurationSlider->SetTarget(this); fDurationSlider->SetTarget(this);
fPositionMenu->SetTargetForItems(this);
} }
@ -134,6 +179,15 @@ GeneralView::MessageReceived(BMessage* msg)
SettingsPane::SettingsChanged(true); SettingsPane::SettingsChanged(true);
break; break;
} }
case kPositionChanged:
{
int32 position;
if (msg->FindInt32(kNotificationPositionName, &position) == B_OK) {
fNewPosition = position;
SettingsPane::SettingsChanged(true);
}
break;
}
default: default:
BView::MessageReceived(msg); BView::MessageReceived(msg);
break; break;
@ -163,6 +217,12 @@ GeneralView::Load(BMessage& settings)
else else
fOriginalIconSize = (icon_size)setting; fOriginalIconSize = (icon_size)setting;
int32 position;
if (settings.FindInt32(kNotificationPositionName, &position) != B_OK)
fOriginalPosition = kDefaultNotificationPosition;
else
fOriginalPosition = position;
_EnableControls(); _EnableControls();
return Revert(); return Revert();
@ -184,6 +244,8 @@ GeneralView::Save(BMessage& settings)
icon_size iconSize = B_LARGE_ICON; icon_size iconSize = B_LARGE_ICON;
settings.AddInt32(kIconSizeName, (int32)iconSize); settings.AddInt32(kIconSizeName, (int32)iconSize);
settings.AddInt32(kNotificationPositionName, (int32)fNewPosition);
return B_OK; return B_OK;
} }
@ -196,6 +258,12 @@ GeneralView::Revert()
fWidthSlider->SetValue(fOriginalWidth / 50); fWidthSlider->SetValue(fOriginalWidth / 50);
_SetWidthLabel(fOriginalWidth); _SetWidthLabel(fOriginalWidth);
fNewPosition = fOriginalPosition;
BMenuItem* item = fPositionMenu->ItemAt(
notification_position_to_index(fNewPosition));
if (item != NULL)
item->SetMarked(true);
return B_OK; return B_OK;
} }
@ -212,6 +280,9 @@ GeneralView::RevertPossible()
if (fOriginalWidth != width) if (fOriginalWidth != width)
return true; return true;
if (fOriginalPosition != fNewPosition)
return true;
return false; return false;
} }
@ -225,6 +296,12 @@ GeneralView::Defaults()
fWidthSlider->SetValue(kDefaultWidth / 50); fWidthSlider->SetValue(kDefaultWidth / 50);
_SetWidthLabel(kDefaultWidth); _SetWidthLabel(kDefaultWidth);
fNewPosition = kDefaultNotificationPosition;
BMenuItem* item = fPositionMenu->ItemAt(
notification_position_to_index(fNewPosition));
if (item != NULL)
item->SetMarked(true);
return B_OK; return B_OK;
} }
@ -239,6 +316,9 @@ GeneralView::DefaultsPossible()
int32 width = fWidthSlider->Value() * 50; int32 width = fWidthSlider->Value() * 50;
if (kDefaultWidth != width) if (kDefaultWidth != width)
return true; return true;
if (kDefaultNotificationPosition != fNewPosition)
return true;
return false; return false;
} }
@ -257,6 +337,10 @@ GeneralView::_EnableControls()
bool enabled = fNotificationBox->Value() == B_CONTROL_ON; bool enabled = fNotificationBox->Value() == B_CONTROL_ON;
fWidthSlider->SetEnabled(enabled); fWidthSlider->SetEnabled(enabled);
fDurationSlider->SetEnabled(enabled); fDurationSlider->SetEnabled(enabled);
BMenuItem* item = fPositionMenu->ItemAt(
notification_position_to_index(fOriginalPosition));
if (item != NULL)
item->SetMarked(true);
} }

View File

@ -12,6 +12,7 @@
#include <Menu.h> #include <Menu.h>
#include <MenuField.h> #include <MenuField.h>
#include <Mime.h> #include <Mime.h>
#include <PopUpMenu.h>
#include <RadioButton.h> #include <RadioButton.h>
#include <Slider.h> #include <Slider.h>
#include <StringView.h> #include <StringView.h>
@ -40,10 +41,14 @@ private:
BCheckBox* fNotificationBox; BCheckBox* fNotificationBox;
BSlider* fDurationSlider; BSlider* fDurationSlider;
BSlider* fWidthSlider; BSlider* fWidthSlider;
BPopUpMenu* fPositionMenu;
int32 fOriginalTimeout; int32 fOriginalTimeout;
float fOriginalWidth; float fOriginalWidth;
icon_size fOriginalIconSize; icon_size fOriginalIconSize;
uint32 fOriginalPosition;
uint32 fNewPosition;
void _EnableControls(); void _EnableControls();
void _SetWidthLabel(int32 value); void _SetWidthLabel(int32 value);

View File

@ -26,7 +26,9 @@
#include <NodeMonitor.h> #include <NodeMonitor.h>
#include <Notifications.h> #include <Notifications.h>
#include <Path.h> #include <Path.h>
#include <Point.h>
#include <PropertyInfo.h> #include <PropertyInfo.h>
#include <Screen.h>
#include "AppGroupView.h" #include "AppGroupView.h"
#include "AppUsage.h" #include "AppUsage.h"
@ -50,6 +52,37 @@ property_info main_prop_list[] = {
}; };
/**
* Checks if notification position overlaps with
* deskbar position
*/
static bool
is_overlapping(deskbar_location deskbar,
uint32 notification) {
if (deskbar == B_DESKBAR_RIGHT_TOP
&& notification == (B_FOLLOW_RIGHT | B_FOLLOW_TOP))
return true;
if (deskbar == B_DESKBAR_RIGHT_BOTTOM
&& notification == (B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM))
return true;
if (deskbar == B_DESKBAR_LEFT_TOP
&& notification == (B_FOLLOW_LEFT | B_FOLLOW_TOP))
return true;
if (deskbar == B_DESKBAR_LEFT_BOTTOM
&& notification == (B_FOLLOW_LEFT | B_FOLLOW_BOTTOM))
return true;
if (deskbar == B_DESKBAR_TOP
&& (notification == (B_FOLLOW_LEFT | B_FOLLOW_TOP)
|| notification == (B_FOLLOW_RIGHT | B_FOLLOW_TOP)))
return true;
if (deskbar == B_DESKBAR_BOTTOM
&& (notification == (B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)
|| notification == (B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)))
return true;
return false;
}
NotificationWindow::NotificationWindow() NotificationWindow::NotificationWindow()
: :
BWindow(BRect(0, 0, -1, -1), B_TRANSLATE_MARK("Notification"), BWindow(BRect(0, 0, -1, -1), B_TRANSLATE_MARK("Notification"),
@ -63,7 +96,7 @@ NotificationWindow::NotificationWindow()
fCachePath.Append("Notifications"); fCachePath.Append("Notifications");
BDirectory cacheDir; BDirectory cacheDir;
result = cacheDir.SetTo(fCachePath.Path()); result = cacheDir.SetTo(fCachePath.Path());
if(result == B_ENTRY_NOT_FOUND) if (result == B_ENTRY_NOT_FOUND)
cacheDir.CreateDirectory(fCachePath.Path(), NULL); cacheDir.CreateDirectory(fCachePath.Path(), NULL);
SetLayout(new BGroupLayout(B_VERTICAL, 0)); SetLayout(new BGroupLayout(B_VERTICAL, 0));
@ -146,8 +179,8 @@ NotificationWindow::MessageReceived(BMessage* message)
BString sourceName(notification->SourceName()); BString sourceName(notification->SourceName());
bool allow = false; bool allow = false;
appfilter_t::iterator it = appfilter_t::iterator it = fAppFilters
fAppFilters.find(sourceSignature.String()); .find(sourceSignature.String());
AppUsage* appUsage = NULL; AppUsage* appUsage = NULL;
if (it == fAppFilters.end()) { if (it == fAppFilters.end()) {
@ -275,43 +308,70 @@ NotificationWindow::SetPosition()
float x = Frame().left; float x = Frame().left;
float y = Frame().top; float y = Frame().top;
// If we can't guess, don't move... // If we cant guess, don't move...
BPoint location(x, y);
BDeskbar deskbar; BDeskbar deskbar;
BRect frame = deskbar.Frame();
switch (deskbar.Location()) { // If notification and deskbar position are same
case B_DESKBAR_TOP: // then follow deskbar position
// Put it just under, top right corner uint32 position = (is_overlapping(deskbar.Location(), fPosition))
y = frame.bottom + topOffset; ? B_FOLLOW_DESKBAR
x = frame.right - width + rightOffset; : fPosition;
break;
case B_DESKBAR_BOTTOM:
// Put it just above, lower left corner if (position == B_FOLLOW_DESKBAR)
y = frame.top - height - bottomOffset; {
x = frame.right - width + rightOffset; BRect frame = deskbar.Frame();
break; switch (deskbar.Location()) {
case B_DESKBAR_RIGHT_TOP: case B_DESKBAR_TOP:
x = frame.left - width - rightOffset; // In case of overlapping here or for bottom
y = frame.top - topOffset + 1; // use user's notification position
break; y = frame.bottom + topOffset;
case B_DESKBAR_LEFT_TOP: x = (fPosition == B_FOLLOW_LEFT | B_FOLLOW_TOP)
x = frame.right + leftOffset; ? frame.left + rightOffset
y = frame.top - topOffset + 1; : frame.right - width + rightOffset;
break; break;
case B_DESKBAR_RIGHT_BOTTOM: case B_DESKBAR_BOTTOM:
y = frame.bottom - height + bottomOffset; y = frame.top - height - bottomOffset;
x = frame.left - width - rightOffset; x = (fPosition == B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)
break; ? frame.left + rightOffset
case B_DESKBAR_LEFT_BOTTOM: : frame.right - width + rightOffset;
y = frame.bottom - height + bottomOffset; break;
x = frame.right + leftOffset; case B_DESKBAR_RIGHT_TOP:
break; y = frame.top - topOffset + 1;
default: x = frame.left - width - rightOffset;
break; break;
case B_DESKBAR_LEFT_TOP:
y = frame.top - topOffset + 1;
x = frame.right + leftOffset;
break;
case B_DESKBAR_RIGHT_BOTTOM:
y = frame.bottom - height + bottomOffset;
x = frame.left - width - rightOffset;
break;
case B_DESKBAR_LEFT_BOTTOM:
y = frame.bottom - height + bottomOffset;
x = frame.right + leftOffset;
break;
default:
break;
}
location = BPoint(x, y);
} else if (position == (B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)) {
location = BScreen().Frame().RightBottom();
location -= BPoint(width, height);
} else if (position == (B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)) {
location = BScreen().Frame().LeftBottom();
location -= BPoint(0, height);
} else if (position == (B_FOLLOW_RIGHT | B_FOLLOW_TOP)) {
location = BScreen().Frame().RightTop();
location -= BPoint(width, 0);
} else if (position == (B_FOLLOW_LEFT | B_FOLLOW_TOP)) {
location = BScreen().Frame().LeftTop();
} }
MoveTo(x, y); MoveTo(location);
} }
@ -402,6 +462,12 @@ NotificationWindow::_LoadDisplaySettings(BMessage& settings)
else else
fIconSize = (icon_size)setting; fIconSize = (icon_size)setting;
int32 position;
if (settings.FindInt32(kNotificationPositionName, &position) != B_OK)
fPosition = kDefaultNotificationPosition;
else
fPosition = position;
// Notify the views about the change // Notify the views about the change
appview_t::iterator aIt; appview_t::iterator aIt;
for (aIt = fAppViews.begin(); aIt != fAppViews.end(); ++aIt) { for (aIt = fAppViews.begin(); aIt != fAppViews.end(); ++aIt) {

View File

@ -63,6 +63,7 @@ private:
float fWidth; float fWidth;
icon_size fIconSize; icon_size fIconSize;
int32 fTimeout; int32 fTimeout;
uint32 fPosition;
bool fShouldRun; bool fShouldRun;
BPath fCachePath; BPath fCachePath;
}; };

View File

@ -17,3 +17,4 @@ const char* kTimeoutName = "timeout";
// Display settings // Display settings
const char* kWidthName = "width"; const char* kWidthName = "width";
const char* kIconSizeName = "icon size"; const char* kIconSizeName = "icon size";
const char* kNotificationPositionName = "notification position";