Ticket #8188: workspacesdiff1.2.patch

File workspacesdiff1.2.patch, 13.9 KB (added by devine, 13 years ago)

Fixes the workspaces autoraise behavior and removes hardcoded decorator constants.

  • src/apps/workspaces/Workspaces.cpp

    diff --git src/apps/workspaces/Workspaces.cpp src/apps/workspaces/Workspaces.cpp
    index e7b99f9..f92b580 100644
     
    44 * This file is distributed under the terms of the MIT License.
    55 *
    66 * Authors:
    7  *      François Revol, revol@free.fr
    87 *      Axel Dörfler, axeld@pinc-software.de
    9  *      Oliver "Madison" Kohl,
     8 *      Daniel Devine, devine@ddevnet.net
     9 *      Oliver "Madison" Kohl
    1010 *      Matt Madia
     11 *      François Revol, revol@free.fr
    1112 */
    1213
    1314
     
    2122#include <FindDirectory.h>
    2223#include <Locale.h>
    2324#include <MenuItem.h>
     25#include <new.h>
    2426#include <Path.h>
    2527#include <PopUpMenu.h>
    2628#include <Roster.h>
    2729#include <Screen.h>
    2830#include <TextView.h>
    2931#include <Window.h>
    30 
    3132#include <ctype.h>
    3233#include <stdio.h>
    3334#include <stdlib.h>
    static const uint32 kMsgToggleAutoRaise = 'tgAR';  
    5556static const uint32 kMsgToggleAlwaysOnTop = 'tgAT';
    5657static const uint32 kMsgToggleLiveInDeskbar = 'tgDb';
    5758
    58 static const float kScreenBorderOffset = 10.0;
    5959
    6060extern "C" _EXPORT BView* instantiate_deskbar_item();
    6161
    class WorkspacesSettings {  
    7171        bool AlwaysOnTop() const { return fAlwaysOnTop; }
    7272        bool HasTitle() const { return fHasTitle; }
    7373        bool HasBorder() const { return fHasBorder; }
     74        bool SettingsLoaded() const { return fLoaded; }
    7475
    7576        void UpdateFramesForScreen(BRect screenFrame);
    7677        void UpdateScreenFrame();
    class WorkspacesSettings {  
    9091        bool    fAlwaysOnTop;
    9192        bool    fHasTitle;
    9293        bool    fHasBorder;
     94        bool    fLoaded;
    9395};
    9496
    9597class WorkspacesView : public BView {
    9698    public:
    97         WorkspacesView(BRect frame, bool showDragger);
     99        WorkspacesView(BRect frame, bool showDragger=true);
    98100        WorkspacesView(BMessage* archive);
    99101        ~WorkspacesView();
    100102
    class WorkspacesWindow : public BWindow {  
    134136        virtual void MessageReceived(BMessage *msg);
    135137        virtual bool QuitRequested();
    136138
    137         void SetAutoRaise(bool enable);
    138         bool IsAutoRaising() const { return fAutoRaising; }
     139        void SetAutoRaising(bool enable);
     140        bool IsAutoRaising() const { return fSettings->AutoRaising(); }
     141        bool HasTitle() const { return fSettings->HasTitle(); }
     142        float GetTabHeight() const { return fTabHeight; }
     143        float GetBorderWidth() const { return fBorderWidth; }
     144        float GetScreenBorderOffset() const { return 2.0 * fBorderWidth; }
    139145
    140146    private:
    141147        WorkspacesSettings *fSettings;
    142         bool    fAutoRaising;
     148        float   fTabHeight;
     149        float   fBorderWidth;
    143150};
    144151
    145152class WorkspacesApp : public BApplication {
    WorkspacesSettings::WorkspacesSettings()  
    167174{
    168175    UpdateScreenFrame();
    169176
    170     bool loaded = false;
    171177    BScreen screen;
    172 
     178    BPath path;
    173179    BFile file;
     180   
    174181    if (_Open(file, B_READ_ONLY) == B_OK) {
    175182        BMessage settings;
    176183        if (settings.Unflatten(&file) == B_OK) {
    177184            if (settings.FindRect("window", &fWindowFrame) == B_OK
    178                 && settings.FindRect("screen", &fScreenFrame) == B_OK)
    179                 loaded = true;
     185                && settings.FindRect("screen", &fScreenFrame) == B_OK){
     186                fLoaded = true;
     187            }
    180188
    181189            settings.FindBool("auto-raise", &fAutoRaising);
    182190            settings.FindBool("always on top", &fAlwaysOnTop);
    WorkspacesSettings::WorkspacesSettings()  
    187195                fHasBorder = true;
    188196        }
    189197    } else {
    190         // try reading BeOS compatible settings
    191         BPath path;
    192         if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
     198        if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK ) {
     199            // try reading BeOS compatible settings
    193200            path.Append(kOldSettingFile);
    194201            BFile file(path.Path(), B_READ_ONLY);
    195             if (file.InitCheck() == B_OK
     202            if (file.InitCheck() == B_OK 
    196203                && file.Read(&fWindowFrame, sizeof(BRect)) == sizeof(BRect)) {
    197204                // we now also store the frame of the screen to know
    198205                // in which context the window frame has been chosen
    WorkspacesSettings::WorkspacesSettings()  
    201208                    fScreenFrame = frame;
    202209                else
    203210                    fScreenFrame = screen.Frame();
    204 
    205                 loaded = true;
     211                fLoaded = true;
    206212            }
    207213        }
    208214    }
    209215
    210     if (loaded) {
    211         // if the current screen frame is different from the one
     216    if (fLoaded) {
     217        // If the current screen frame is different from the one
    212218        // just loaded, we need to alter the window frame accordingly
    213219        if (fScreenFrame != screen.Frame())
    214220            UpdateFramesForScreen(screen.Frame());
    215221    }
    216 
    217     if (!loaded
    218         || !(screen.Frame().right + 5 >= fWindowFrame.right
    219             && screen.Frame().bottom + 5 >= fWindowFrame.bottom
    220             && screen.Frame().left - 5 <= fWindowFrame.left
    221             && screen.Frame().top - 5 <= fWindowFrame.top)) {
    222         // set to some usable defaults
    223         float screenWidth = screen.Frame().Width();
    224         float screenHeight = screen.Frame().Height();
    225         float aspectRatio = screenWidth / screenHeight;
    226 
    227         uint32 columns, rows;
    228         BPrivate::get_workspaces_layout(&columns, &rows);
    229 
    230         // default size of ~1/10 of screen width
    231         float workspaceWidth = screenWidth / 10;
    232         float workspaceHeight = workspaceWidth / aspectRatio;
    233 
    234         float width = floor(workspaceWidth * columns);
    235         float height = floor(workspaceHeight * rows);
    236 
    237         float tabHeight = 20;
    238             // TODO: find tabHeight without being a window
    239 
    240         // shrink to fit more
    241         while (width + 2 * kScreenBorderOffset > screenWidth
    242             || height + 2 * kScreenBorderOffset + tabHeight > screenHeight) {
    243             width = floor(0.95 * width);
    244             height = floor(0.95 * height);
    245         }
    246 
    247         fWindowFrame = fScreenFrame;
    248         fWindowFrame.OffsetBy(-kScreenBorderOffset, -kScreenBorderOffset);
    249         fWindowFrame.left = fWindowFrame.right - width;
    250         fWindowFrame.top = fWindowFrame.bottom - height;
    251     }
    252222}
    253223
    254224
    WorkspacesSettings::~WorkspacesSettings()  
    260230        return;
    261231
    262232    BMessage settings('wksp');
    263 
     233   
    264234    if (settings.AddRect("window", fWindowFrame) == B_OK
    265235        && settings.AddRect("screen", fScreenFrame) == B_OK
    266236        && settings.AddBool("auto-raise", fAutoRaising) == B_OK
    WorkspacesSettings::~WorkspacesSettings()  
    268238        && settings.AddBool("has title", fHasTitle) == B_OK
    269239        && settings.AddBool("has border", fHasBorder) == B_OK)
    270240        settings.Flatten(&file);
     241    else
     242        fprintf(stderr,"An error occured while saving settings.\n");
    271243}
    272244
    273245
    WorkspacesSettings::_Open(BFile& file, int mode)  
    297269
    298270void
    299271WorkspacesSettings::UpdateFramesForScreen(BRect newScreenFrame)
    300 {
     272{   
    301273    // don't change the position if the screen frame hasn't changed
    302274    if (newScreenFrame == fScreenFrame)
    303275        return;
    WorkspacesSettings::UpdateFramesForScreen(BRect newScreenFrame)  
    313285        fWindowFrame.OffsetTo(fWindowFrame.left,
    314286            newScreenFrame.bottom - (fScreenFrame.bottom - fWindowFrame.top));
    315287    }
    316 
    317288    fScreenFrame = newScreenFrame;
    318289}
    319290
    WorkspacesSettings::SetWindowFrame(BRect frame)  
    336307//  #pragma mark -
    337308
    338309
    339 WorkspacesView::WorkspacesView(BRect frame, bool showDragger=true)
     310WorkspacesView::WorkspacesView(BRect frame, bool showDragger)
    340311    :
    341312    BView(frame, kDeskbarItemName, B_FOLLOW_ALL,
    342         kWorkspacesViewFlag | B_FRAME_EVENTS),
    343     fParentWhichDrawsOnChildren(NULL),
     313        kWorkspacesViewFlag | B_FRAME_EVENTS),    // kWorkspacesViewFlag is picked up by the app_server.
     314    fParentWhichDrawsOnChildren(NULL),            // ...That's how the desktop frames are done!
    344315    fCurrentFrame(frame)
    345316{
    346317    if(showDragger) {
    WorkspacesView::Instantiate(BMessage* archive)  
    380351    if (!validate_instantiation(archive, "WorkspacesView"))
    381352        return NULL;
    382353
    383     return new WorkspacesView(archive);
     354    return new(std::nothrow) WorkspacesView(archive);
    384355}
    385356
    386357
    status_t  
    388359WorkspacesView::Archive(BMessage* archive, bool deep) const
    389360{
    390361    status_t status = BView::Archive(archive, deep);
    391     if (status == B_OK)
    392         status = archive->AddString("add_on", kSignature);
    393     if (status == B_OK)
    394         status = archive->AddString("class", "WorkspacesView");
    395 
    396362    return status;
    397363}
    398364
    WorkspacesView::_AboutRequested()  
    420386    font.SetFace(B_BOLD_FACE);
    421387    view->SetFontAndColor(0, 10, &font);
    422388
    423     alert->Go();
     389    alert->Go(NULL);
    424390}
    425391
    426392
    WorkspacesView::MessageReceived(BMessage* message)  
    511477            // since HasItem() locks up we just remove directly.
    512478            BDeskbar deskbar;
    513479            // we shouldn't do this here actually, but it works for now...
    514             deskbar.RemoveItem (kDeskbarItemName);
     480            deskbar.RemoveItem(kDeskbarItemName);
    515481            break;
    516482        }
    517483
    WorkspacesView::MouseMoved(BPoint where, uint32 transit,  
    534500
    535501    where = ConvertToScreen(where);
    536502    BScreen screen(window);
    537     BRect frame = screen.Frame();
    538     if (where.x == frame.left || where.x == frame.right
    539         || where.y == frame.top || where.y == frame.bottom) {
    540         // cursor is on screen edge
    541         if (window->Frame().Contains(where))
     503    BRect screenFrame = screen.Frame();
     504    BRect windowFrame = window->Frame();
     505    float tabHeight = window->GetTabHeight();
     506    float borderWidth = window->GetBorderWidth();
     507   
     508    // cursor is on screen edge
     509    if (where.x == screenFrame.left || where.x == screenFrame.right
     510        || where.y == screenFrame.top || where.y == screenFrame.bottom) {
     511           
     512        if (!window->HasTitle())
     513            tabHeight = 0;
     514       
     515        // Stretch frame so that it may meet the edge of the screen.
     516        windowFrame.InsetBy(-borderWidth,-(tabHeight + borderWidth));
     517       
     518        if (windowFrame.Contains(where))
    542519            window->Activate();
    543520    }
    544521}
    WorkspacesWindow::WorkspacesWindow(WorkspacesSettings *settings)  
    642619    BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Workspaces"),
    643620        B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
    644621        B_AVOID_FRONT | B_WILL_ACCEPT_FIRST_CLICK, B_ALL_WORKSPACES),
    645     fSettings(settings),
    646     fAutoRaising(false)
     622    fSettings(settings)
    647623{
    648624    AddChild(new WorkspacesView(Bounds()));
     625   
     626    // Turn window decor on to grab decor widths.
     627    BMessage windowSettings;
     628    SetLook(B_TITLED_WINDOW_LOOK);
     629    if (GetDecoratorSettings(&windowSettings) == B_OK){
     630        BRect tabFrame = windowSettings.FindRect("tab frame");
     631        float borderWidth = windowSettings.FindFloat("border width");
     632        fTabHeight = tabFrame.Height();
     633        fBorderWidth = borderWidth;
     634       
     635        // NOTE: Below is based on old code from WorkspacesSettings::WorkspacesSettings().
     636        // Decorator dimensions are dynamically called and set instead of hardcoded here.
     637       
     638        // TODO: refresh tab height and border width variables if decor is changed.
     639       
     640        BScreen screen;
     641       
     642        float screenWidth = screen.Frame().Width();
     643        float screenHeight = screen.Frame().Height();
     644        float aspectRatio = screenWidth / screenHeight;
     645
     646        uint32 columns, rows;
     647        BPrivate::get_workspaces_layout(&columns, &rows);
     648
     649        // default size of ~1/10 of screen width
     650        float workspaceWidth = screenWidth / 10;
     651        float workspaceHeight = workspaceWidth / aspectRatio;
     652
     653        float width = floor(workspaceWidth * columns);
     654        float height = floor(workspaceHeight * rows);
     655       
     656        // If you have too many workspaces to fit on the screen, shrink until they fit.
     657        while (width + 2 * borderWidth > screenWidth
     658            || height + 2 * borderWidth + GetTabHeight() > screenHeight) {
     659            width = floor(0.95 * width);
     660            height = floor(0.95 * height);
     661        }
     662       
     663        BRect windowFrame = fSettings->WindowFrame();
     664        BRect frame;
     665       
     666        // If we don't have settings loaded or decorator/screen dimensions changed, load defaults.
     667        if (!fSettings->SettingsLoaded() || fSettings->ScreenFrame() != screen.Frame()) {
     668            frame = fSettings->ScreenFrame();
     669            frame.left = frame.right - width;
     670            frame.top = frame.bottom - height;
     671            ResizeTo(frame.Width(), frame.Height());
     672            // Put it in bottom corner by default.
     673            MoveTo(screenWidth - frame.Width() - borderWidth,
     674                    screenHeight - frame.Height() - borderWidth);
     675        } else {
     676            frame = windowFrame;   
     677        }
     678        fSettings->SetWindowFrame(frame);
     679    }
    649680
    650681    if (!fSettings->HasBorder())
    651682        SetLook(B_NO_BORDER_WINDOW_LOOK);
    WorkspacesWindow::WorkspacesWindow(WorkspacesSettings *settings)  
    655686    if (fSettings->AlwaysOnTop())
    656687        SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
    657688    else
    658         SetAutoRaise(fSettings->AutoRaising());
     689        SetAutoRaising(fSettings->AutoRaising());
    659690}
    660691
    661692
    WorkspacesWindow::FrameResized(float width, float height)  
    685716{
    686717    if (!modifiers() & B_SHIFT_KEY) {
    687718        BWindow::FrameResized(width, height);
     719        fSettings->SetWindowFrame(Frame());
    688720        return;
    689721    }
    690 
     722    // This is only run if you are trying to keep the aspect ratio.
    691723    uint32 columns, rows;
    692724    BPrivate::get_workspaces_layout(&columns, &rows);
    693725
    WorkspacesWindow::Zoom(BPoint origin, float width, float height)  
    724756    width = floor(workspaceWidth * columns);
    725757    height = floor(workspaceHeight * rows);
    726758
    727     float tabHeight = Frame().top - DecoratorFrame().top;
    728 
    729     while (width + 2 * kScreenBorderOffset > screenWidth
    730         || height + 2 * kScreenBorderOffset + tabHeight > screenHeight) {
     759    while (width + 2 * GetScreenBorderOffset() > screenWidth
     760        || height + 2 * GetScreenBorderOffset() + GetTabHeight() > screenHeight) {
    731761        width = floor(0.95 * width);
    732762        height = floor(0.95 * height);
    733763    }
    WorkspacesWindow::Zoom(BPoint origin, float width, float height)  
    735765    ResizeTo(width, height);
    736766
    737767    origin = screen.Frame().RightBottom();
    738     origin.x -= kScreenBorderOffset + width;
    739     origin.y -= kScreenBorderOffset + height;
     768    origin.x -= GetScreenBorderOffset() + width;
     769    origin.y -= GetScreenBorderOffset() + height;
    740770
    741771    MoveTo(origin);
    742772}
    WorkspacesWindow::MessageReceived(BMessage *message)  
    797827        }
    798828
    799829        case kMsgToggleAutoRaise:
    800             SetAutoRaise(!IsAutoRaising());
     830            SetAutoRaising(!IsAutoRaising());
    801831            SetFeel(B_NORMAL_WINDOW_FEEL);
    802832            break;
    803833
    WorkspacesWindow::QuitRequested()  
    845875
    846876
    847877void
    848 WorkspacesWindow::SetAutoRaise(bool enable)
     878WorkspacesWindow::SetAutoRaising(bool enable)
    849879{
    850     if (enable == fAutoRaising)
     880    if (enable == IsAutoRaising())
    851881        return;
    852882
    853     fAutoRaising = enable;
    854883    fSettings->SetAutoRaising(enable);
    855884
    856885    if (enable)
    WorkspacesApp::ArgvReceived(int32 argc, char **argv)  
    923952            else if (!strcmp(argv[i], "--alwaysontop"))
    924953                fWindow->SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
    925954            else if (!strcmp(argv[i], "--autoraise"))
    926                 fWindow->SetAutoRaise(true);
     955                fWindow->SetAutoRaising(true);
    927956            else {
    928957                const char *programName = strrchr(argv[0], '/');
    929958                programName = programName ? programName + 1 : argv[0];