From a5cf354a27420b4ccc72eaafeccdae450b0abac9 Mon Sep 17 00:00:00 2001 From: Clemens Zeidler Date: Wed, 17 Nov 2010 04:38:48 +0000 Subject: [PATCH] Add protected RestoreState, SaveState functions to BApplication. HasBeenRestored can be used to check in ReadyToRun if the RestoreState function has been called. The default implementation just store the window geometry and the decorator settings. Subclass implementations can use the global restore_window_geometry, save_window_geometry function for convenience. Please review. Will commit a simple session manager tomorrow. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39462 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/app/Application.h | 13 ++- headers/private/app/ApplicationPrivate.h | 4 + src/kits/app/Application.cpp | 108 +++++++++++++++++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) diff --git a/headers/os/app/Application.h b/headers/os/app/Application.h index a9263efd7d..105073e6c0 100644 --- a/headers/os/app/Application.h +++ b/headers/os/app/Application.h @@ -29,6 +29,10 @@ namespace BPrivate { } +void restore_window_geometry(BWindow* window, const BMessage* windowGeometry); +void save_window_geometry(const BWindow* window, BMessage* windowGeometry); + + class BApplication : public BLooper { public: BApplication(const char* signature); @@ -91,6 +95,12 @@ public: class Private; +protected: + // Session Manager + bool HasBeenRestored(); + virtual status_t RestoreState(const BMessage* state); + virtual status_t SaveState(BMessage* state) const; + private: typedef BLooper _inherited; @@ -145,8 +155,9 @@ private: BMessageRunner* fPulseRunner; status_t fInitError; void* fServerReadOnlyMemory; - uint32 _reserved[12]; + uint32 _reserved[11]; + uint32 fHasBeenRestored; bool fReadyToRunCalled; }; diff --git a/headers/private/app/ApplicationPrivate.h b/headers/private/app/ApplicationPrivate.h index bfd6a56d95..bea2498ae8 100644 --- a/headers/private/app/ApplicationPrivate.h +++ b/headers/private/app/ApplicationPrivate.h @@ -14,6 +14,10 @@ struct server_read_only_memory; +const uint32 kRestoreStateMsg = '_RSM'; +const uint32 kSaveStateMsg = '_SSM'; + + class BApplication::Private { public: static inline BPrivate::PortLink *ServerLink() diff --git a/src/kits/app/Application.cpp b/src/kits/app/Application.cpp index dc40511c97..350b82d902 100644 --- a/src/kits/app/Application.cpp +++ b/src/kits/app/Application.cpp @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,46 @@ using namespace BPrivate; +void +restore_window_geometry(BWindow* window, const BMessage* windowGeometry) +{ + BRect frame; + status_t status = windowGeometry->FindRect("frame", &frame); + if (status == B_OK) { + // make sure window is on the screen + BScreen screen; + BRect screenFrame = screen.Frame(); + if (screenFrame.right < frame.left || screenFrame.bottom < frame.top) + frame.OffsetBy(-frame.top, -frame.left); + + window->MoveTo(frame.LeftTop()); + window->ResizeTo(frame.Width(), frame.Height()); + } + + uint32 workspaces; + status = windowGeometry->FindInt32("workspaces", (int32*)&workspaces); + if (status == B_OK) + window->SetWorkspaces(workspaces); + + BMessage decoratroSettings; + status = windowGeometry->FindMessage("decorator_settings", + &decoratroSettings); + if (status == B_OK) + window->SetDecoratorSettings(decoratroSettings); +} + + +void +save_window_geometry(const BWindow* window, BMessage* windowGeometry) +{ + windowGeometry->AddRect("frame", window->Frame()); + windowGeometry->AddInt32("workspaces", window->Workspaces()); + BMessage decoratroSettings; + if (window->GetDecoratorSettings(&decoratroSettings) == B_OK) + windowGeometry->AddMessage("decorator_settings", &decoratroSettings); +} + + BApplication *be_app = NULL; BMessenger be_app_messenger; @@ -274,6 +316,7 @@ BApplication::_InitData(const char *signature, bool initGUI, status_t *_error) fServerAllocator = NULL; fInitialWorkspace = 0; //fDraggedMessage = NULL; + fHasBeenRestored = 0; fReadyToRunCalled = false; // initially, there is no pulse @@ -572,6 +615,8 @@ BApplication::ReadyToRun() // supposed to be implemented by subclasses } +#include "ApplicationPrivate.h" + void BApplication::MessageReceived(BMessage *message) @@ -597,6 +642,19 @@ BApplication::MessageReceived(BMessage *message) be_roster->ActivateApp(Team()); break; + case kRestoreStateMsg: + if (RestoreState(message) == B_OK) + fHasBeenRestored = 1; + break; + + case kSaveStateMsg: + { + BMessage state; + if (SaveState(&state) == B_OK) + message->SendReply(&state); + break; + } + default: BLooper::MessageReceived(message); break; @@ -1028,6 +1086,56 @@ BApplication::Perform(perform_code d, void *arg) } +bool +BApplication::HasBeenRestored() +{ + return fHasBeenRestored != 0; +} + + +status_t +BApplication::RestoreState(const BMessage* state) +{ + int32 i = 0; + while (true) { + BMessage windowState; + if (state->FindMessage("window", i, &windowState) != B_OK) + break; + i++; + + BString title; + if (windowState.FindString("title", &title) != B_OK) + continue; + + for (int i = 0; i < CountWindows(); i++) { + BWindow* window = WindowAt(i); + if (title != window->Title()) + continue; + restore_window_geometry(window, &windowState); + } + } + + return B_OK; +} + + +status_t +BApplication::SaveState(BMessage* state) const +{ + // just store all window positions + for (int i = 0; i < CountWindows(); i++) { + BWindow* window = WindowAt(i); + + BMessage windowState; + save_window_geometry(window, &windowState); + windowState.AddString("title", window->Title()); + state->AddMessage("window", &windowState); + } + + return B_OK; +} + + void BApplication::_ReservedApplication1() {} void BApplication::_ReservedApplication2() {} void BApplication::_ReservedApplication3() {}