diff --git a/src/apps/login/Jamfile b/src/apps/login/Jamfile index a5d8989137..5b4a014d58 100644 --- a/src/apps/login/Jamfile +++ b/src/apps/login/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src apps login ; SetSubDirSupportedPlatformsBeOSCompatible ; +UsePrivateHeaders app ; #UsePrivateHeaders shared ; #UsePrivateHeaders tracker ; #SubDirHdrs $(HAIKU_TOP) src kits tracker ; diff --git a/src/apps/login/LoginApp.cpp b/src/apps/login/LoginApp.cpp index 2b85d00ccb..fca7347c7c 100644 --- a/src/apps/login/LoginApp.cpp +++ b/src/apps/login/LoginApp.cpp @@ -1,6 +1,9 @@ +#include #include +#include #include +#include #include #include @@ -8,6 +11,7 @@ #include "LoginWindow.h" #ifdef __HAIKU__ +#include #include #include "multiuser_utils.h" #endif @@ -31,7 +35,7 @@ void LoginApp::ReadyToRun() { BScreen s; - BRect frame(0, 0, 300, 100); + BRect frame(0, 0, 400, 150); frame.OffsetBySelf(s.Frame().Width()/2 - frame.Width()/2, s.Frame().Height()/2 - frame.Height()/2); LoginWindow *w = new LoginWindow(frame); @@ -42,16 +46,39 @@ LoginApp::ReadyToRun() void LoginApp::MessageReceived(BMessage *message) { + bool reboot = false; + switch (message->what) { - case kAttemptLogin: - break; + case kAttemptLogin: + message->PrintToStream(); + TryLogin(message); + // TODO + break; +#ifdef __HAIKU__ + case kHaltAction: + reboot = false; + // FALLTHROUGH + case kRebootAction: + { + BRoster roster; + BRoster::Private rosterPrivate(roster); + status_t error = rosterPrivate.ShutDown(reboot, false, false); + if (error < B_OK) { + BString msg("Error: "); + msg << strerror(error); + (new BAlert("Error", msg.String(), "Ok"))->Go(); + } + break; + } + case kSuspendAction: + (new BAlert("Error", "Unimplemented", "Ok"))->Go(); + break; +#endif default: BApplication::MessageReceived(message); } } - void TryLogin(BMessage *message); - status_t ValidateLogin(const char *login, const char *password/*, bool force = false*/); void LoginApp::TryLogin(BMessage *message) @@ -59,13 +86,14 @@ LoginApp::TryLogin(BMessage *message) status_t err; const char *login; const char *password; - BMessage reply(B_REPLY); + BMessage reply(kLoginBad); if (message->FindString("login", &login) == B_OK) { if (message->FindString("password", &password) < B_OK) password = NULL; err = ValidateLogin(login, password); + printf("ValidateLogin: %s\n", strerror(err)); if (err == B_OK) { - reply.AddInt32("error", B_OK); + reply.what = kLoginOk; message->SendReply(&reply); if (password == NULL) @@ -109,11 +137,11 @@ LoginApp::ValidateLogin(const char *login, const char *password/*, bool force = return B_OK; #else // for testing - if (strcmp(crypt(password, pwd->pw_passwd), pwd->pw_passwd)) - return B_NOT_ALLOWED; + if (strcmp(crypt(password, pwd->pw_passwd), pwd->pw_passwd) == 0) + return B_OK; #endif - return B_NOT_ALLOWED; + return B_PERMISSION_DENIED; } diff --git a/src/apps/login/LoginApp.h b/src/apps/login/LoginApp.h index ecac850a0a..d5a0f40f4c 100644 --- a/src/apps/login/LoginApp.h +++ b/src/apps/login/LoginApp.h @@ -1,7 +1,15 @@ +#ifndef _LOGINAPP_H_ +#define _LOGINAPP_H_ + #include /* try loging in a user */ const uint32 kAttemptLogin = 'logi'; +const uint32 kHaltAction = 'halt'; +const uint32 kRebootAction = 'rebo'; +const uint32 kSuspendAction = 'susp'; +const uint32 kLoginBad = 'lgba'; +const uint32 kLoginOk = 'lgok'; class LoginApp : public BApplication { public: @@ -17,3 +25,5 @@ private: int getpty(char *pty, char *tty); }; + +#endif // _LOGINAPP_H_ diff --git a/src/apps/login/LoginView.cpp b/src/apps/login/LoginView.cpp index 90f2cbff8f..b6d1cbe107 100644 --- a/src/apps/login/LoginView.cpp +++ b/src/apps/login/LoginView.cpp @@ -1,30 +1,70 @@ #include +#include #include +#include "LoginApp.h" #include "LoginView.h" #define CSEP 15 +#define BH 20 +#define BW 60 LoginView::LoginView(BRect frame) : BView(frame, "LoginView", B_FOLLOW_ALL, 0) { + // TODO: when I don't need to test in BeOS anymore, + // rewrite to use layout engine. SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetLowColor(ViewColor()); BRect r; - r.Set(CSEP, CSEP, 80, Bounds().Height() - 2 * CSEP); + r.Set(CSEP, CSEP, 80, Bounds().Height() - 3 * CSEP - BH); fUserList = new BListView(r, "users"); - BScrollView *sv = new BScrollView("userssv", fUserList); + BScrollView *sv = new BScrollView("userssv", fUserList, + B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true); AddChild(sv); + fUserList->SetSelectionMessage(new BMessage(kUserSelected)); + fUserList->SetInvocationMessage(new BMessage(kUserInvoked)); - r.Set(100, Bounds().top + CSEP, Bounds().right - CSEP, Bounds().top + CSEP + CSEP); - fLoginControl = new BTextControl(r, "login", "login:", "", new BMessage(kLoginEdited)); + r.Set(140, Bounds().top + CSEP, + Bounds().right - CSEP, Bounds().top + CSEP + CSEP); + fLoginControl = new BTextControl(r, "login", "login:", "", + new BMessage(kLoginEdited)); AddChild(fLoginControl); + r.OffsetBySelf(0, CSEP + CSEP); - fPasswordControl = new BTextControl(r, "password", "password:", "", new BMessage(kPasswordEdited)); + fPasswordControl = new BTextControl(r, "password", "password:", "", + new BMessage(kPasswordEdited)); fPasswordControl->TextView()->HideTyping(true); AddChild(fPasswordControl); - + + r.OffsetBySelf(0, CSEP + CSEP); + fHidePasswordCheckBox = new BCheckBox(r, "hidepw", "Hide Password", + new BMessage(kHidePassword)); + fHidePasswordCheckBox->SetValue(1); + AddChild(fHidePasswordCheckBox); + + // buttons + float buttonWidth = BW; //(Bounds().Width() - 4 * CSEP) / 3; + BRect buttonRect(0, Bounds().bottom - BH, + buttonWidth, Bounds().bottom); + buttonRect.OffsetBySelf(CSEP, -CSEP); + + fHaltButton = new BButton(buttonRect, "halt", "Halt", + new BMessage(kHaltAction)); + AddChild(fHaltButton); + + buttonRect.OffsetBySelf(CSEP + buttonWidth, 0); + fRebootButton = new BButton(buttonRect, "reboot", "Reboot", + new BMessage(kRebootAction)); + AddChild(fRebootButton); + + buttonRect.OffsetToSelf(Bounds().Width() - CSEP - buttonWidth, + Bounds().Height() - CSEP - BH); + fLoginButton = new BButton(buttonRect, "ok", "Ok", + new BMessage(kAttemptLogin)); + AddChild(fLoginButton); + } @@ -35,7 +75,16 @@ LoginView::~LoginView() void LoginView::AttachedToWindow() { - fLoginControl->MakeFocus(); + fUserList->SetTarget(this); + fLoginControl->SetTarget(this); + fPasswordControl->SetTarget(this); + fHidePasswordCheckBox->SetTarget(this); + fHaltButton->SetTarget(be_app_messenger); + fRebootButton->SetTarget(be_app_messenger); + fLoginButton->SetTarget(this); + Window()->SetDefaultButton(fLoginButton); + //fLoginControl->MakeFocus(); + fUserList->MakeFocus(); // populate user list BMessenger(this).SendMessage(kAddNextUser); } @@ -45,13 +94,64 @@ void LoginView::MessageReceived(BMessage *message) { switch (message->what) { - case kSetProgress: - break; - case kAddNextUser: - AddNextUser(); - break; - default: - BView::MessageReceived(message); + case kSetProgress: + break; + case kAddNextUser: + AddNextUser(); + break; + case kUserSelected: + { + int32 selection = fUserList->CurrentSelection(); + if (selection > -1) { + BStringItem *item = dynamic_cast( + fUserList->ItemAt(selection)); + if (item) + fLoginControl->SetText(item->Text()); + } + break; + } + case kUserInvoked: + fPasswordControl->MakeFocus(); + break; + case kLoginEdited: + break; + case kHidePassword: + fPasswordControl->TextView()->HideTyping( + fHidePasswordCheckBox->Value() == 0); + break; + case kAttemptLogin: + { + BMessage *m = new BMessage(kAttemptLogin); + m->AddString("login", fLoginControl->Text()); + m->AddString("password", fPasswordControl->Text()); + be_app->PostMessage(m, NULL, this); + break; + } + case kLoginBad: + fPasswordControl->SetText(""); + EnableControls(false); + if (Window()) { + BPoint savedPos = Window()->Frame().LeftTop(); + for (int i = 0; i < 10; i++) { + BPoint p(savedPos); + p.x += (i%2) ? 10 : -10; + Window()->MoveTo(p); + Window()->UpdateIfNeeded(); + snooze(30000); + } + Window()->MoveTo(savedPos); + } + EnableControls(true); + break; + case kLoginOk: + // XXX: quit ? + if (Window()) { + Window()->Hide(); + } + break; + default: + message->PrintToStream(); + BView::MessageReceived(message); } } @@ -81,3 +181,14 @@ LoginView::AddNextUser() } +void +LoginView::EnableControls(bool enable) +{ + fLoginControl->SetEnabled(enable); + fPasswordControl->SetEnabled(enable); + fHidePasswordCheckBox->SetEnabled(enable); + fHaltButton->SetEnabled(enable); + fRebootButton->SetEnabled(enable); + fLoginButton->SetEnabled(enable); +} + diff --git a/src/apps/login/LoginView.h b/src/apps/login/LoginView.h index b27bf842aa..a42d9b7f5b 100644 --- a/src/apps/login/LoginView.h +++ b/src/apps/login/LoginView.h @@ -1,23 +1,35 @@ +#include +#include #include #include #include #include +const uint32 kUserSelected = 'usel'; +const uint32 kUserInvoked = 'uinv'; const uint32 kLoginEdited = 'logc'; const uint32 kPasswordEdited = 'pasc'; +const uint32 kHidePassword = 'hidp'; const uint32 kAddNextUser = 'adnu'; const uint32 kSetProgress = 'setp'; class LoginView : public BView { - public: - LoginView(BRect frame); - virtual ~LoginView(); - void AttachedToWindow(); - void MessageReceived(BMessage *message); - private: - void AddNextUser(); - BTextControl *fLoginControl; - BTextControl *fPasswordControl; - BListView *fUserList; +public: + LoginView(BRect frame); + virtual ~LoginView(); + void AttachedToWindow(); + void MessageReceived(BMessage *message); + +private: + void AddNextUser(); + void EnableControls(bool enable); + + BListView* fUserList; + BTextControl* fLoginControl; + BTextControl* fPasswordControl; + BCheckBox* fHidePasswordCheckBox; + BButton* fHaltButton; + BButton* fRebootButton; + BButton* fLoginButton; }; diff --git a/src/apps/login/LoginWindow.h b/src/apps/login/LoginWindow.h index 9a64513601..b2abfc9eed 100644 --- a/src/apps/login/LoginWindow.h +++ b/src/apps/login/LoginWindow.h @@ -1,3 +1,6 @@ +#ifndef _LOGINWINDOW_H_ +#define _LOGINWINDOW_H_ + #include class LoginWindow : public BWindow { @@ -6,3 +9,4 @@ public: virtual ~LoginWindow(); }; +#endif // _LOGINWINDOW_H_