1a10cf76eSAxel Dörfler /* 2b72c4836SAlexandre Deckner * Copyright 2001-2008, Haiku. 3a10cf76eSAxel Dörfler * Distributed under the terms of the MIT License. 4a10cf76eSAxel Dörfler * 5a10cf76eSAxel Dörfler * Authors: 6a10cf76eSAxel Dörfler * Rafael Romo 7a10cf76eSAxel Dörfler * Stefano Ceccherini (burton666@libero.it) 8a10cf76eSAxel Dörfler * Andrew Bachmann 9a10cf76eSAxel Dörfler * Thomas Kurschel 10a10cf76eSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de 11df3f5bacSStephan Aßmus * Stephan Aßmus <superstippi@gmx.de> 12b72c4836SAlexandre Deckner * Alexandre Deckner, alex@zappotek.com 13a10cf76eSAxel Dörfler */ 14a10cf76eSAxel Dörfler 15a10cf76eSAxel Dörfler 16a10cf76eSAxel Dörfler #include "AlertWindow.h" 17a10cf76eSAxel Dörfler #include "Constants.h" 18a10cf76eSAxel Dörfler #include "RefreshWindow.h" 19a10cf76eSAxel Dörfler #include "MonitorView.h" 20a10cf76eSAxel Dörfler #include "ScreenSettings.h" 21a10cf76eSAxel Dörfler #include "ScreenWindow.h" 22a10cf76eSAxel Dörfler #include "Utility.h" 23a10cf76eSAxel Dörfler 24a10cf76eSAxel Dörfler /* Note, this headers defines a *private* interface to the Radeon accelerant. 25a10cf76eSAxel Dörfler * It's a solution that works with the current BeOS interface that Haiku 26a10cf76eSAxel Dörfler * adopted. 27a10cf76eSAxel Dörfler * However, it's not a nice and clean solution. Don't use this header in any 28a10cf76eSAxel Dörfler * application if you can avoid it. No other driver is using this, or should 29a10cf76eSAxel Dörfler * be using this. 30a10cf76eSAxel Dörfler * It will be replaced as soon as we introduce an updated accelerant interface 31a10cf76eSAxel Dörfler * which may even happen before R1 hits the streets. 32a10cf76eSAxel Dörfler */ 33a10cf76eSAxel Dörfler #include "multimon.h" // the usual: DANGER WILL, ROBINSON! 34a10cf76eSAxel Dörfler 3512580984SAxel Dörfler #include <Alert.h> 3612580984SAxel Dörfler #include <Application.h> 3712580984SAxel Dörfler #include <Box.h> 3812580984SAxel Dörfler #include <Button.h> 3912580984SAxel Dörfler #include <Directory.h> 4012580984SAxel Dörfler #include <File.h> 4112580984SAxel Dörfler #include <FindDirectory.h> 4212580984SAxel Dörfler #include <InterfaceDefs.h> 4312580984SAxel Dörfler #include <MenuBar.h> 4412580984SAxel Dörfler #include <MenuItem.h> 4512580984SAxel Dörfler #include <MenuField.h> 4612580984SAxel Dörfler #include <Messenger.h> 4712580984SAxel Dörfler #include <Path.h> 4812580984SAxel Dörfler #include <PopUpMenu.h> 4912580984SAxel Dörfler #include <Screen.h> 5012580984SAxel Dörfler #include <String.h> 5112580984SAxel Dörfler #include <Roster.h> 5212580984SAxel Dörfler #include <Window.h> 5312580984SAxel Dörfler 5412580984SAxel Dörfler #include <stdio.h> 5512580984SAxel Dörfler #include <stdlib.h> 5612580984SAxel Dörfler #include <string.h> 5712580984SAxel Dörfler 58a10cf76eSAxel Dörfler 59c5d80d47SAxel Dörfler const char* kBackgroundsSignature = "application/x-vnd.haiku-backgrounds"; 60c5d80d47SAxel Dörfler 61a10cf76eSAxel Dörfler // list of officially supported colour spaces 62a10cf76eSAxel Dörfler static const struct { 63a10cf76eSAxel Dörfler color_space space; 64a10cf76eSAxel Dörfler int32 bits_per_pixel; 65a10cf76eSAxel Dörfler const char* label; 66a10cf76eSAxel Dörfler } kColorSpaces[] = { 67a10cf76eSAxel Dörfler { B_CMAP8, 8, "8 Bits/Pixel, 256 Colors" }, 68a10cf76eSAxel Dörfler { B_RGB15, 15, "15 Bits/Pixel, 32768 Colors" }, 69a10cf76eSAxel Dörfler { B_RGB16, 16, "16 Bits/Pixel, 65536 Colors" }, 70a10cf76eSAxel Dörfler { B_RGB32, 32, "32 Bits/Pixel, 16 Million Colors" } 71a10cf76eSAxel Dörfler }; 72a10cf76eSAxel Dörfler static const int32 kColorSpaceCount = sizeof(kColorSpaces) / sizeof(kColorSpaces[0]); 73a10cf76eSAxel Dörfler 74a10cf76eSAxel Dörfler // list of standard refresh rates 75a796facfSAxel Dörfler static const int32 kRefreshRates[] = { 60, 70, 72, 75, 80, 85, 95, 100 }; 76a10cf76eSAxel Dörfler static const int32 kRefreshRateCount = sizeof(kRefreshRates) / sizeof(kRefreshRates[0]); 77a10cf76eSAxel Dörfler 78a10cf76eSAxel Dörfler // list of combine modes 79a10cf76eSAxel Dörfler static const struct { 80a10cf76eSAxel Dörfler combine_mode mode; 81a10cf76eSAxel Dörfler const char *name; 82a10cf76eSAxel Dörfler } kCombineModes[] = { 83a10cf76eSAxel Dörfler { kCombineDisable, "disable" }, 84a10cf76eSAxel Dörfler { kCombineHorizontally, "horizontally" }, 85a10cf76eSAxel Dörfler { kCombineVertically, "vertically" } 86a10cf76eSAxel Dörfler }; 87a10cf76eSAxel Dörfler static const int32 kCombineModeCount = sizeof(kCombineModes) / sizeof(kCombineModes[0]); 88a10cf76eSAxel Dörfler 8929e8a73aSAxel Dörfler enum { 9029e8a73aSAxel Dörfler SHOW_COMBINE_FIELD = 0x01, 9129e8a73aSAxel Dörfler SHOW_SWAP_FIELD = 0x02, 9229e8a73aSAxel Dörfler SHOW_LAPTOP_PANEL_FIELD = 0x04, 9329e8a73aSAxel Dörfler SHOW_TV_STANDARD_FIELD = 0x08, 9429e8a73aSAxel Dörfler }; 9529e8a73aSAxel Dörfler 96a10cf76eSAxel Dörfler 97a10cf76eSAxel Dörfler static BString 98a10cf76eSAxel Dörfler tv_standard_to_string(uint32 mode) 99a10cf76eSAxel Dörfler { 100a10cf76eSAxel Dörfler switch (mode) { 101a10cf76eSAxel Dörfler case 0: return "disabled"; 102a10cf76eSAxel Dörfler case 1: return "NTSC"; 103a10cf76eSAxel Dörfler case 2: return "NTSC Japan"; 104a10cf76eSAxel Dörfler case 3: return "PAL BDGHI"; 105a10cf76eSAxel Dörfler case 4: return "PAL M"; 106a10cf76eSAxel Dörfler case 5: return "PAL N"; 107a10cf76eSAxel Dörfler case 6: return "SECAM"; 108a10cf76eSAxel Dörfler case 101: return "NTSC 443"; 109a10cf76eSAxel Dörfler case 102: return "PAL 60"; 110a10cf76eSAxel Dörfler case 103: return "PAL NC"; 111a10cf76eSAxel Dörfler default: 112a10cf76eSAxel Dörfler { 113a10cf76eSAxel Dörfler BString name; 114a10cf76eSAxel Dörfler name << "??? (" << mode << ")"; 115a10cf76eSAxel Dörfler 116a10cf76eSAxel Dörfler return name; 117a10cf76eSAxel Dörfler } 118a10cf76eSAxel Dörfler } 119a10cf76eSAxel Dörfler } 120a10cf76eSAxel Dörfler 121a10cf76eSAxel Dörfler 122a10cf76eSAxel Dörfler static void 123a10cf76eSAxel Dörfler resolution_to_string(screen_mode& mode, BString &string) 124a10cf76eSAxel Dörfler { 125a10cf76eSAxel Dörfler string << mode.width << " x " << mode.height; 126a10cf76eSAxel Dörfler } 127a10cf76eSAxel Dörfler 128a10cf76eSAxel Dörfler 129a10cf76eSAxel Dörfler static void 130a10cf76eSAxel Dörfler refresh_rate_to_string(float refresh, BString &string, 131a10cf76eSAxel Dörfler bool appendUnit = true, bool alwaysWithFraction = false) 132a10cf76eSAxel Dörfler { 133a10cf76eSAxel Dörfler snprintf(string.LockBuffer(32), 32, "%.*g", refresh >= 100.0 ? 4 : 3, refresh); 134a10cf76eSAxel Dörfler string.UnlockBuffer(); 135a10cf76eSAxel Dörfler 136a10cf76eSAxel Dörfler if (appendUnit) 137a10cf76eSAxel Dörfler string << " Hz"; 138a10cf76eSAxel Dörfler } 139a10cf76eSAxel Dörfler 140a10cf76eSAxel Dörfler 14107184a9eSAxel Dörfler static const char* 14207184a9eSAxel Dörfler screen_errors(status_t status) 14307184a9eSAxel Dörfler { 14407184a9eSAxel Dörfler switch (status) { 14507184a9eSAxel Dörfler case B_ENTRY_NOT_FOUND: 14607184a9eSAxel Dörfler return "Unknown Mode"; 14707184a9eSAxel Dörfler // TODO: add more? 14807184a9eSAxel Dörfler 14907184a9eSAxel Dörfler default: 15007184a9eSAxel Dörfler return strerror(status); 15107184a9eSAxel Dörfler } 15207184a9eSAxel Dörfler } 15307184a9eSAxel Dörfler 15429e8a73aSAxel Dörfler 15529e8a73aSAxel Dörfler static float 15629e8a73aSAxel Dörfler max_label_width(BMenuField* control, float widestLabel) 15729e8a73aSAxel Dörfler { 15829e8a73aSAxel Dörfler float labelWidth = control->StringWidth(control->Label()); 15929e8a73aSAxel Dörfler if (widestLabel < labelWidth) 16029e8a73aSAxel Dörfler return labelWidth; 16129e8a73aSAxel Dörfler return widestLabel; 16229e8a73aSAxel Dörfler } 16329e8a73aSAxel Dörfler 16429e8a73aSAxel Dörfler 16529e8a73aSAxel Dörfler static BRect 16629e8a73aSAxel Dörfler stack_and_align_menu_fields(const BList& menuFields) 16729e8a73aSAxel Dörfler { 16829e8a73aSAxel Dörfler float widestLabel = 0.0; 16929e8a73aSAxel Dörfler int32 count = menuFields.CountItems(); 17029e8a73aSAxel Dörfler for (int32 i = 0; i < count; i++) { 17129e8a73aSAxel Dörfler BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); 17229e8a73aSAxel Dörfler widestLabel = max_label_width(menuField, widestLabel); 17329e8a73aSAxel Dörfler } 17429e8a73aSAxel Dörfler 17529e8a73aSAxel Dörfler // add some room (but only if there is text at all) 17629e8a73aSAxel Dörfler if (widestLabel > 0.0) 17729e8a73aSAxel Dörfler widestLabel += 5.0; 17829e8a73aSAxel Dörfler 17929e8a73aSAxel Dörfler // make all controls the same width 180d1516993SAxel Dörfler float widestField = 0.0f; 18129e8a73aSAxel Dörfler for (int32 i = 0; i < count; i++) { 18229e8a73aSAxel Dörfler BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); 183d1516993SAxel Dörfler if (widestField == 0.0f) { 184d1516993SAxel Dörfler widestField = menuField->StringWidth("9999 x 9999 WWW") 185d1516993SAxel Dörfler + widestLabel; 186d1516993SAxel Dörfler } 18729e8a73aSAxel Dörfler menuField->SetAlignment(B_ALIGN_RIGHT); 18829e8a73aSAxel Dörfler menuField->SetDivider(widestLabel); 18929e8a73aSAxel Dörfler menuField->ResizeToPreferred(); 19029e8a73aSAxel Dörfler widestField = max_c(menuField->Bounds().Width(), widestField); 19129e8a73aSAxel Dörfler } 19229e8a73aSAxel Dörfler 19329e8a73aSAxel Dörfler // layout controls under each other, resize all to size 19429e8a73aSAxel Dörfler // of largest of them (they could still have different 19529e8a73aSAxel Dörfler // heights though) 19629e8a73aSAxel Dörfler BMenuField* topMenuField = (BMenuField*)menuFields.FirstItem(); 19729e8a73aSAxel Dörfler BPoint leftTop = topMenuField->Frame().LeftTop(); 19829e8a73aSAxel Dörfler BRect frame = topMenuField->Frame(); 19929e8a73aSAxel Dörfler 20029e8a73aSAxel Dörfler for (int32 i = 0; i < count; i++) { 20129e8a73aSAxel Dörfler BMenuField* menuField = (BMenuField*)menuFields.ItemAtFast(i); 20229e8a73aSAxel Dörfler menuField->MoveTo(leftTop); 20329e8a73aSAxel Dörfler float height = menuField->Bounds().Height(); 20429e8a73aSAxel Dörfler menuField->ResizeTo(widestField, height); 20529e8a73aSAxel Dörfler frame = frame | menuField->Frame(); 20629e8a73aSAxel Dörfler leftTop.y += height + 5.0; 20729e8a73aSAxel Dörfler } 20829e8a73aSAxel Dörfler 20929e8a73aSAxel Dörfler return frame; 21029e8a73aSAxel Dörfler } 211df3f5bacSStephan Aßmus 212df3f5bacSStephan Aßmus 2133dfd20c0SStephan Aßmus // #pragma mark - 2143dfd20c0SStephan Aßmus 2153dfd20c0SStephan Aßmus 2165a78744bSAxel Dörfler ScreenWindow::ScreenWindow(ScreenSettings *settings) 2175a78744bSAxel Dörfler : BWindow(settings->WindowFrame(), "Screen", B_TITLED_WINDOW, 218a10cf76eSAxel Dörfler B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES), 219199893c3SAxel Dörfler fBootWorkspaceApplied(false), 220a10cf76eSAxel Dörfler fScreenMode(this), 221abc649b8SWaldemar Kornewald fTempScreenMode(this), 222abc649b8SWaldemar Kornewald fModified(false) 223a10cf76eSAxel Dörfler { 224a10cf76eSAxel Dörfler BScreen screen(this); 225a10cf76eSAxel Dörfler 22612580984SAxel Dörfler accelerant_device_info info; 227d1516993SAxel Dörfler if (screen.GetDeviceInfo(&info) == B_OK 228d1516993SAxel Dörfler && !strcasecmp(info.chipset, "VESA")) 22912580984SAxel Dörfler fIsVesa = true; 23012580984SAxel Dörfler 2315de171daSAxel Dörfler _UpdateOriginal(); 232a10cf76eSAxel Dörfler fActive = fSelected = fOriginal; 233a10cf76eSAxel Dörfler 234df3f5bacSStephan Aßmus BView *view = new BView(Bounds(), "ScreenView", B_FOLLOW_ALL, B_WILL_DRAW); 235a10cf76eSAxel Dörfler view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 236a10cf76eSAxel Dörfler AddChild(view); 237a10cf76eSAxel Dörfler 2385a78744bSAxel Dörfler fSettings = settings; 2395a78744bSAxel Dörfler 2405a78744bSAxel Dörfler // we need the "Current Workspace" first to get its height 2415a78744bSAxel Dörfler 2425a78744bSAxel Dörfler BPopUpMenu *popUpMenu = new BPopUpMenu("Current Workspace", true, true); 243d1516993SAxel Dörfler fAllWorkspacesItem = new BMenuItem("All Workspaces", 244d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 2455a78744bSAxel Dörfler popUpMenu->AddItem(fAllWorkspacesItem); 246d1516993SAxel Dörfler BMenuItem *item = new BMenuItem("Current Workspace", 247d1516993SAxel Dörfler new BMessage(WORKSPACE_CHECK_MSG)); 248b72c4836SAlexandre Deckner 2495a78744bSAxel Dörfler popUpMenu->AddItem(item); 250*27c43a2dSRene Gollent fAllWorkspacesItem->SetMarked(true); 2515a78744bSAxel Dörfler 252df3f5bacSStephan Aßmus BMenuField* workspaceMenuField = new BMenuField(BRect(0, 0, 100, 15), 2535a78744bSAxel Dörfler "WorkspaceMenu", NULL, popUpMenu, true); 2545a78744bSAxel Dörfler workspaceMenuField->ResizeToPreferred(); 255a10cf76eSAxel Dörfler 256a10cf76eSAxel Dörfler // box on the left with workspace count and monitor view 257a10cf76eSAxel Dörfler 2585a78744bSAxel Dörfler popUpMenu = new BPopUpMenu("", true, true); 259df3f5bacSStephan Aßmus fWorkspaceCountField = new BMenuField(BRect(0.0, 0.0, 50.0, 15.0), 260df3f5bacSStephan Aßmus "WorkspaceCountMenu", "Workspace count:", popUpMenu, true); 261d1516993SAxel Dörfler float labelWidth = fWorkspaceCountField->StringWidth( 262d1516993SAxel Dörfler fWorkspaceCountField->Label()) + 5.0; 263df3f5bacSStephan Aßmus fWorkspaceCountField->SetDivider(labelWidth); 264df3f5bacSStephan Aßmus 265df3f5bacSStephan Aßmus fScreenBox = new BBox(BRect(0.0, 0.0, 100.0, 100.0), "left box"); 266df3f5bacSStephan Aßmus fScreenBox->AddChild(fWorkspaceCountField); 267a10cf76eSAxel Dörfler 268a10cf76eSAxel Dörfler for (int32 count = 1; count <= 32; count++) { 269a10cf76eSAxel Dörfler BString workspaceCount; 270a10cf76eSAxel Dörfler workspaceCount << count; 271a10cf76eSAxel Dörfler 272a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_WORKSPACE_CHANGED_MSG); 273a10cf76eSAxel Dörfler message->AddInt32("workspace count", count); 274a10cf76eSAxel Dörfler 275a10cf76eSAxel Dörfler popUpMenu->AddItem(new BMenuItem(workspaceCount.String(), 276a10cf76eSAxel Dörfler message)); 277a10cf76eSAxel Dörfler } 278a10cf76eSAxel Dörfler 2795a78744bSAxel Dörfler item = popUpMenu->ItemAt(count_workspaces() - 1); 280a10cf76eSAxel Dörfler if (item != NULL) 281a10cf76eSAxel Dörfler item->SetMarked(true); 282a10cf76eSAxel Dörfler 283df3f5bacSStephan Aßmus fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), "monitor", 2846bda235aSStefano Ceccherini screen.Frame().IntegerWidth() + 1, screen.Frame().IntegerHeight() + 1); 285df3f5bacSStephan Aßmus fScreenBox->AddChild(fMonitorView); 2865a78744bSAxel Dörfler 287df3f5bacSStephan Aßmus view->AddChild(fScreenBox); 288a10cf76eSAxel Dörfler 289a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 290a10cf76eSAxel Dörfler 291df3f5bacSStephan Aßmus fControlsBox = new BBox(BRect(0.0, 0.0, 100.0, 100.0)); 292df3f5bacSStephan Aßmus fControlsBox->SetLabel(workspaceMenuField); 293a10cf76eSAxel Dörfler 294a10cf76eSAxel Dörfler fResolutionMenu = new BPopUpMenu("resolution", true, true); 295a10cf76eSAxel Dörfler 296a10cf76eSAxel Dörfler uint16 previousWidth = 0, previousHeight = 0; 297a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 298a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 299a10cf76eSAxel Dörfler 300a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 301a10cf76eSAxel Dörfler continue; 302a10cf76eSAxel Dörfler 303a10cf76eSAxel Dörfler previousWidth = mode.width; 304a10cf76eSAxel Dörfler previousHeight = mode.height; 305a10cf76eSAxel Dörfler 306a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_RESOLUTION_MSG); 307a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 308a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 309a10cf76eSAxel Dörfler 310a10cf76eSAxel Dörfler BString name; 311a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 312a10cf76eSAxel Dörfler 313a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 314a10cf76eSAxel Dörfler } 315a10cf76eSAxel Dörfler 31629e8a73aSAxel Dörfler BRect rect(0.0, 0.0, 200.0, 15.0); 317df3f5bacSStephan Aßmus // fResolutionField needs to be at the correct 318df3f5bacSStephan Aßmus // left-top offset, because all other menu fields 319df3f5bacSStephan Aßmus // will be layouted relative to it 320df3f5bacSStephan Aßmus fResolutionField = new BMenuField(rect.OffsetToCopy(10.0, 30.0), 321d1516993SAxel Dörfler "ResolutionMenu", "Resolution:", fResolutionMenu, false); 322df3f5bacSStephan Aßmus fControlsBox->AddChild(fResolutionField); 323a10cf76eSAxel Dörfler 324a10cf76eSAxel Dörfler fColorsMenu = new BPopUpMenu("colors", true, true); 325a10cf76eSAxel Dörfler 326a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 327a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_COLORS_MSG); 328a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 329a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 330a10cf76eSAxel Dörfler 331a10cf76eSAxel Dörfler fColorsMenu->AddItem(new BMenuItem(kColorSpaces[i].label, message)); 332a10cf76eSAxel Dörfler } 333a10cf76eSAxel Dörfler 334df3f5bacSStephan Aßmus rect.OffsetTo(B_ORIGIN); 335df3f5bacSStephan Aßmus 336d1516993SAxel Dörfler fColorsField = new BMenuField(rect, "ColorsMenu", "Colors:", fColorsMenu, 337d1516993SAxel Dörfler false); 338df3f5bacSStephan Aßmus fControlsBox->AddChild(fColorsField); 339a10cf76eSAxel Dörfler 340a10cf76eSAxel Dörfler fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 341a10cf76eSAxel Dörfler 34229e8a73aSAxel Dörfler BMessage *message; 34329e8a73aSAxel Dörfler 34429e8a73aSAxel Dörfler float min, max; 34529e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fActive, min, max) && min == max) { 34629e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 34729e8a73aSAxel Dörfler // frequency, like the VESA driver 34829e8a73aSAxel Dörfler BString name; 34929e8a73aSAxel Dörfler name << min << " Hz"; 35029e8a73aSAxel Dörfler 35129e8a73aSAxel Dörfler message = new BMessage(POP_REFRESH_MSG); 35229e8a73aSAxel Dörfler message->AddFloat("refresh", min); 35329e8a73aSAxel Dörfler 35429e8a73aSAxel Dörfler fRefreshMenu->AddItem(item = new BMenuItem(name.String(), message)); 35529e8a73aSAxel Dörfler item->SetEnabled(false); 35629e8a73aSAxel Dörfler } else { 357a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 358a10cf76eSAxel Dörfler BString name; 359a10cf76eSAxel Dörfler name << kRefreshRates[i] << " Hz"; 360a10cf76eSAxel Dörfler 36129e8a73aSAxel Dörfler message = new BMessage(POP_REFRESH_MSG); 362a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 363a10cf76eSAxel Dörfler 364a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 365a10cf76eSAxel Dörfler } 366a10cf76eSAxel Dörfler 36729e8a73aSAxel Dörfler message = new BMessage(POP_OTHER_REFRESH_MSG); 368a10cf76eSAxel Dörfler 369a10cf76eSAxel Dörfler fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message); 370a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 37129e8a73aSAxel Dörfler } 372a10cf76eSAxel Dörfler 373d1516993SAxel Dörfler fRefreshField = new BMenuField(rect, "RefreshMenu", "Refresh Rate:", 374d1516993SAxel Dörfler fRefreshMenu, false); 37512580984SAxel Dörfler if (_IsVesa()) 37612580984SAxel Dörfler fRefreshField->Hide(); 377df3f5bacSStephan Aßmus fControlsBox->AddChild(fRefreshField); 378a10cf76eSAxel Dörfler 379df3f5bacSStephan Aßmus view->AddChild(fControlsBox); 380df3f5bacSStephan Aßmus 381df3f5bacSStephan Aßmus uint32 controlsFlags = 0; 382a10cf76eSAxel Dörfler 383a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 384a10cf76eSAxel Dörfler { 385a10cf76eSAxel Dörfler bool dummy; 386a10cf76eSAxel Dörfler uint32 dummy32; 387a10cf76eSAxel Dörfler bool multiMonSupport; 388a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 389a10cf76eSAxel Dörfler bool tvStandardSupport; 390a10cf76eSAxel Dörfler 391a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 392a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 393a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 394df3f5bacSStephan Aßmus if (multiMonSupport) { 395df3f5bacSStephan Aßmus controlsFlags |= SHOW_COMBINE_FIELD; 396df3f5bacSStephan Aßmus controlsFlags |= SHOW_SWAP_FIELD; 397df3f5bacSStephan Aßmus } 398df3f5bacSStephan Aßmus if (useLaptopPanelSupport) 399df3f5bacSStephan Aßmus controlsFlags |= SHOW_LAPTOP_PANEL_FIELD; 400a10cf76eSAxel Dörfler 401a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 402a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 403a10cf76eSAxel Dörfler 404a10cf76eSAxel Dörfler fCombineMenu = new BPopUpMenu("CombineDisplays", true, true); 405a10cf76eSAxel Dörfler 406a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 407a10cf76eSAxel Dörfler message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 408a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 409a10cf76eSAxel Dörfler 410d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 411d1516993SAxel Dörfler message)); 412a10cf76eSAxel Dörfler } 413a10cf76eSAxel Dörfler 414df3f5bacSStephan Aßmus fCombineField = new BMenuField(rect, "CombineMenu", 415d1516993SAxel Dörfler "Combine Displays:", fCombineMenu, false); 416df3f5bacSStephan Aßmus fControlsBox->AddChild(fCombineField); 417a10cf76eSAxel Dörfler 418a10cf76eSAxel Dörfler if (!multiMonSupport) 419df3f5bacSStephan Aßmus fCombineField->Hide(); 420a10cf76eSAxel Dörfler 421a10cf76eSAxel Dörfler fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true); 422a10cf76eSAxel Dörfler 423a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 424a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 425a10cf76eSAxel Dörfler message->AddBool("swap", false); 426a10cf76eSAxel Dörfler fSwapDisplaysMenu->AddItem(new BMenuItem("no", message)); 427a10cf76eSAxel Dörfler 428a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 429a10cf76eSAxel Dörfler message->AddBool("swap", true); 430a10cf76eSAxel Dörfler fSwapDisplaysMenu->AddItem(new BMenuItem("yes", message)); 431a10cf76eSAxel Dörfler 432df3f5bacSStephan Aßmus fSwapDisplaysField = new BMenuField(rect, "SwapMenu", "Swap Displays:", 433d1516993SAxel Dörfler fSwapDisplaysMenu, false); 434a10cf76eSAxel Dörfler 435df3f5bacSStephan Aßmus fControlsBox->AddChild(fSwapDisplaysField); 436a10cf76eSAxel Dörfler if (!multiMonSupport) 437df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 438a10cf76eSAxel Dörfler 439a10cf76eSAxel Dörfler fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true); 440a10cf76eSAxel Dörfler 441a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 442a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 443a10cf76eSAxel Dörfler message->AddBool("use", false); 444a10cf76eSAxel Dörfler fUseLaptopPanelMenu->AddItem(new BMenuItem("if needed", message)); 445a10cf76eSAxel Dörfler 446a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 447a10cf76eSAxel Dörfler message->AddBool("use", true); 448a10cf76eSAxel Dörfler fUseLaptopPanelMenu->AddItem(new BMenuItem("always", message)); 449a10cf76eSAxel Dörfler 450d1516993SAxel Dörfler fUseLaptopPanelField = new BMenuField(rect, "UseLaptopPanel", 451d1516993SAxel Dörfler "Use Laptop Panel:", fUseLaptopPanelMenu, false); 452a10cf76eSAxel Dörfler 453df3f5bacSStephan Aßmus fControlsBox->AddChild(fUseLaptopPanelField); 454a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 455df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 456a10cf76eSAxel Dörfler 457a10cf76eSAxel Dörfler fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 458a10cf76eSAxel Dörfler 459a10cf76eSAxel Dörfler // arbitrary limit 460a10cf76eSAxel Dörfler uint32 i; 461a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 462a10cf76eSAxel Dörfler uint32 mode; 463a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 464a10cf76eSAxel Dörfler break; 465a10cf76eSAxel Dörfler 466a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 467a10cf76eSAxel Dörfler 468a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 469a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 470a10cf76eSAxel Dörfler 471a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 472a10cf76eSAxel Dörfler } 473a10cf76eSAxel Dörfler 474df3f5bacSStephan Aßmus fTVStandardField = new BMenuField(rect, "tv standard", "Video Format:", 475d1516993SAxel Dörfler fTVStandardMenu, false); 476df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 477a10cf76eSAxel Dörfler 478df3f5bacSStephan Aßmus if (!tvStandardSupport || i == 0) { 479df3f5bacSStephan Aßmus fTVStandardField->Hide(); 480df3f5bacSStephan Aßmus } else { 481df3f5bacSStephan Aßmus controlsFlags |= SHOW_TV_STANDARD_FIELD; 482a10cf76eSAxel Dörfler } 483a10cf76eSAxel Dörfler 484df3f5bacSStephan Aßmus fControlsBox->AddChild(fTVStandardField); 485df3f5bacSStephan Aßmus } 486df3f5bacSStephan Aßmus 487df3f5bacSStephan Aßmus BRect buttonRect(0.0, 0.0, 30.0, 10.0); 488df3f5bacSStephan Aßmus fBackgroundsButton = new BButton(buttonRect, "BackgroundsButton", 489d1516993SAxel Dörfler "Set Background"B_UTF8_ELLIPSIS, 490d1516993SAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 4913dfd20c0SStephan Aßmus fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 492df3f5bacSStephan Aßmus fScreenBox->AddChild(fBackgroundsButton); 493df3f5bacSStephan Aßmus 494abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 495abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 496a10cf76eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG)); 497abc649b8SWaldemar Kornewald view->AddChild(fDefaultsButton); */ 498a10cf76eSAxel Dörfler 499df3f5bacSStephan Aßmus fRevertButton = new BButton(buttonRect, "RevertButton", "Revert", 500a10cf76eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 501a10cf76eSAxel Dörfler fRevertButton->SetEnabled(false); 502a10cf76eSAxel Dörfler view->AddChild(fRevertButton); 503a10cf76eSAxel Dörfler 504df3f5bacSStephan Aßmus fApplyButton = new BButton(buttonRect, "ApplyButton", "Apply", 505df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 506df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 507abc649b8SWaldemar Kornewald fControlsBox->AddChild(fApplyButton); 5085a78744bSAxel Dörfler 5095de171daSAxel Dörfler _UpdateControls(); 510df3f5bacSStephan Aßmus 5115de171daSAxel Dörfler _LayoutControls(controlsFlags); 512a10cf76eSAxel Dörfler } 513a10cf76eSAxel Dörfler 514a10cf76eSAxel Dörfler 515a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 516a10cf76eSAxel Dörfler { 517a10cf76eSAxel Dörfler delete fSettings; 518a10cf76eSAxel Dörfler } 519a10cf76eSAxel Dörfler 520a10cf76eSAxel Dörfler 521a10cf76eSAxel Dörfler bool 522a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 523a10cf76eSAxel Dörfler { 524a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 525199893c3SAxel Dörfler 526199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 527199893c3SAxel Dörfler screen_mode vesaMode; 528199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 529199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 53012580984SAxel Dörfler if (status < B_OK) { 53112580984SAxel Dörfler BString warning = "Could not write VESA mode settings file:\n\t"; 53212580984SAxel Dörfler warning << strerror(status); 53312580984SAxel Dörfler (new BAlert("VesaAlert", warning.String(), "Okay", NULL, NULL, 53412580984SAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); 53512580984SAxel Dörfler } 53612580984SAxel Dörfler } 53712580984SAxel Dörfler 538a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 539a10cf76eSAxel Dörfler 540a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 541a10cf76eSAxel Dörfler } 542a10cf76eSAxel Dörfler 543a10cf76eSAxel Dörfler 5445de171daSAxel Dörfler /*! Update resolution list according to combine mode 5455de171daSAxel Dörfler (some resolution may not be combinable due to memory restrictions) 546a10cf76eSAxel Dörfler */ 547a10cf76eSAxel Dörfler void 5485de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 549a10cf76eSAxel Dörfler { 550a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 551a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 552a10cf76eSAxel Dörfler 553a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 554a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 555a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 556a10cf76eSAxel Dörfler continue; 557a10cf76eSAxel Dörfler 558a10cf76eSAxel Dörfler BString name; 559a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 560a10cf76eSAxel Dörfler 561a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 562a10cf76eSAxel Dörfler if (item != NULL) 563a10cf76eSAxel Dörfler item->SetEnabled(true); 564a10cf76eSAxel Dörfler } 565a10cf76eSAxel Dörfler } 566a10cf76eSAxel Dörfler 567a10cf76eSAxel Dörfler 5685de171daSAxel Dörfler /*! Update color and refresh options according to current mode 5695de171daSAxel Dörfler (a color space is made active if there is any mode with 5705de171daSAxel Dörfler given resolution and this colour space; same applies for 5715de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 572a10cf76eSAxel Dörfler */ 573a10cf76eSAxel Dörfler void 5745de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 575a10cf76eSAxel Dörfler { 576a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 577a10cf76eSAxel Dörfler bool supported = false; 578a10cf76eSAxel Dörfler 579a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 580a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 581a10cf76eSAxel Dörfler 582a10cf76eSAxel Dörfler if (fSelected.width == mode.width 583a10cf76eSAxel Dörfler && fSelected.height == mode.height 5845de171daSAxel Dörfler && (kColorSpaces[i].space == mode.space 5855de171daSAxel Dörfler // advertize 24 bit mode as 32 bit to avoid confusion 5865de171daSAxel Dörfler || (kColorSpaces[i].space == B_RGB32 5875de171daSAxel Dörfler && mode.space == B_RGB24)) 588a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 589a10cf76eSAxel Dörfler supported = true; 590a10cf76eSAxel Dörfler break; 591a10cf76eSAxel Dörfler } 592a10cf76eSAxel Dörfler } 593a10cf76eSAxel Dörfler 594a10cf76eSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(i); 595a10cf76eSAxel Dörfler if (item) 596a10cf76eSAxel Dörfler item->SetEnabled(supported); 597a10cf76eSAxel Dörfler } 598a10cf76eSAxel Dörfler } 599a10cf76eSAxel Dörfler 600a10cf76eSAxel Dörfler 6015de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 602a10cf76eSAxel Dörfler void 6035de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 604a10cf76eSAxel Dörfler { 60529e8a73aSAxel Dörfler float min, max; 60629e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 60729e8a73aSAxel Dörfler return; 608a10cf76eSAxel Dörfler 60929e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 61029e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 61129e8a73aSAxel Dörfler BMessage* message = item->Message(); 61229e8a73aSAxel Dörfler float refresh; 61329e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 61429e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 615a10cf76eSAxel Dörfler } 616a10cf76eSAxel Dörfler } 617a10cf76eSAxel Dörfler 618a10cf76eSAxel Dörfler 6195de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 620a10cf76eSAxel Dörfler void 6215de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 622a10cf76eSAxel Dörfler { 623a10cf76eSAxel Dörfler BString string; 624a10cf76eSAxel Dörfler refresh_rate_to_string(fSelected.refresh, string); 625a10cf76eSAxel Dörfler 626a10cf76eSAxel Dörfler BMenuItem* item = fRefreshMenu->FindItem(string.String()); 627a10cf76eSAxel Dörfler if (item) { 628a10cf76eSAxel Dörfler if (!item->IsMarked()) 629a10cf76eSAxel Dörfler item->SetMarked(true); 63029e8a73aSAxel Dörfler 631a10cf76eSAxel Dörfler // "Other…" items only contains a refresh rate when active 632e6b421a9SJérôme Duval fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS); 633a10cf76eSAxel Dörfler return; 634a10cf76eSAxel Dörfler } 635a10cf76eSAxel Dörfler 636a10cf76eSAxel Dörfler // this is a non-standard refresh rate 637a10cf76eSAxel Dörfler 638a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 639a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 640a10cf76eSAxel Dörfler 641a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 642a10cf76eSAxel Dörfler 643a10cf76eSAxel Dörfler string.Append("/Other" B_UTF8_ELLIPSIS); 644a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 645a10cf76eSAxel Dörfler } 646a10cf76eSAxel Dörfler 647a10cf76eSAxel Dörfler 648a10cf76eSAxel Dörfler void 6495de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 650a10cf76eSAxel Dörfler { 651a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 652a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 653a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 654a10cf76eSAxel Dörfler 655a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 656a10cf76eSAxel Dörfler } 657a10cf76eSAxel Dörfler 658a10cf76eSAxel Dörfler 659a10cf76eSAxel Dörfler void 6605de171daSAxel Dörfler ScreenWindow::_UpdateControls() 661a10cf76eSAxel Dörfler { 662a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 663a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 664a10cf76eSAxel Dörfler item->SetMarked(true); 665a10cf76eSAxel Dörfler 666a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 667a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 668a10cf76eSAxel Dörfler item->SetMarked(true); 669a10cf76eSAxel Dörfler 670a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 671a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 672a10cf76eSAxel Dörfler 673a10cf76eSAxel Dörfler uint32 tvStandard; 674a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 675a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 676a10cf76eSAxel Dörfler if (!item->IsMarked()) 677a10cf76eSAxel Dörfler item->SetMarked(true); 678a10cf76eSAxel Dörfler break; 679a10cf76eSAxel Dörfler } 680a10cf76eSAxel Dörfler } 681a10cf76eSAxel Dörfler 6825de171daSAxel Dörfler _CheckResolutionMenu(); 6835de171daSAxel Dörfler _CheckColorMenu(); 6845de171daSAxel Dörfler _CheckRefreshMenu(); 685a10cf76eSAxel Dörfler 686a10cf76eSAxel Dörfler BString string; 687a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 688a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 689a10cf76eSAxel Dörfler 690a10cf76eSAxel Dörfler if (item != NULL) { 691a10cf76eSAxel Dörfler if (!item->IsMarked()) 692a10cf76eSAxel Dörfler item->SetMarked(true); 693a10cf76eSAxel Dörfler } else { 694a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 695a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 696a10cf76eSAxel Dörfler // 1. add a new resolution to list 697a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 698a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 699a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 700a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 701a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 702a10cf76eSAxel Dörfler // 2. choose nearest resolution 703a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 704a10cf76eSAxel Dörfler // 3. choose lowest resolution 705a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 706a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 707a10cf76eSAxel Dörfler if (item) 708a10cf76eSAxel Dörfler item->SetMarked(true); 709a10cf76eSAxel Dörfler 710a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 711a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 712a10cf76eSAxel Dörfler } 713a10cf76eSAxel Dörfler 714a10cf76eSAxel Dörfler // mark active combine mode 715a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 716a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 717a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 718a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 719a10cf76eSAxel Dörfler item->SetMarked(true); 720a10cf76eSAxel Dörfler break; 721a10cf76eSAxel Dörfler } 722a10cf76eSAxel Dörfler } 723a10cf76eSAxel Dörfler 724a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 725a10cf76eSAxel Dörfler 726a10cf76eSAxel Dörfler for (int32 i = kColorSpaceCount; i-- > 0;) { 7275de171daSAxel Dörfler if (kColorSpaces[i].space == fSelected.space 7285de171daSAxel Dörfler || (kColorSpaces[i].space == B_RGB32 7295de171daSAxel Dörfler && fSelected.space == B_RGB24)) { 730a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(i); 731a10cf76eSAxel Dörfler break; 732a10cf76eSAxel Dörfler } 733a10cf76eSAxel Dörfler } 734a10cf76eSAxel Dörfler 735a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 736a10cf76eSAxel Dörfler item->SetMarked(true); 737a10cf76eSAxel Dörfler 738a10cf76eSAxel Dörfler string.Truncate(0); 7395de171daSAxel Dörfler uint32 bitsPerPixel = fSelected.BitsPerPixel(); 7405de171daSAxel Dörfler // advertize 24 bit mode as 32 bit to avoid confusion 7415de171daSAxel Dörfler if (bitsPerPixel == 24) 7425de171daSAxel Dörfler bitsPerPixel = 32; 7435de171daSAxel Dörfler 7445de171daSAxel Dörfler string << bitsPerPixel << " Bits/Pixel"; 745a10cf76eSAxel Dörfler if (string != fColorsMenu->Superitem()->Label()) 746a10cf76eSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 747a10cf76eSAxel Dörfler 7485de171daSAxel Dörfler _UpdateMonitorView(); 7495de171daSAxel Dörfler _UpdateRefreshControl(); 750a10cf76eSAxel Dörfler 7515de171daSAxel Dörfler _CheckApplyEnabled(); 752a10cf76eSAxel Dörfler } 753a10cf76eSAxel Dörfler 754a10cf76eSAxel Dörfler 75512580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 756a10cf76eSAxel Dörfler void 7575de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 758a10cf76eSAxel Dörfler { 75912580984SAxel Dörfler // Usually, this function gets called after a mode 760a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 761a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 762a10cf76eSAxel Dörfler // what kind of mode we actually got 763a10cf76eSAxel Dörfler fScreenMode.Get(fActive); 764a10cf76eSAxel Dörfler fSelected = fActive; 765a10cf76eSAxel Dörfler 7665de171daSAxel Dörfler _UpdateControls(); 767a10cf76eSAxel Dörfler } 768a10cf76eSAxel Dörfler 769a10cf76eSAxel Dörfler 770a10cf76eSAxel Dörfler void 771a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 772a10cf76eSAxel Dörfler { 773a10cf76eSAxel Dörfler // move window on screen, if necessary 774a10cf76eSAxel Dörfler if (frame.right <= Frame().right 775a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 776a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 777a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 778a10cf76eSAxel Dörfler } 779a10cf76eSAxel Dörfler } 780a10cf76eSAxel Dörfler 781a10cf76eSAxel Dörfler 782a10cf76eSAxel Dörfler void 783a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 784a10cf76eSAxel Dörfler { 785abc649b8SWaldemar Kornewald fScreenMode.GetOriginalMode(fOriginal, workspace); 7865de171daSAxel Dörfler _UpdateActiveMode(); 787a10cf76eSAxel Dörfler 7886edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 7896edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 790a10cf76eSAxel Dörfler } 791a10cf76eSAxel Dörfler 792a10cf76eSAxel Dörfler 793a10cf76eSAxel Dörfler void 794a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 795a10cf76eSAxel Dörfler { 796a10cf76eSAxel Dörfler switch (message->what) { 797a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 7985de171daSAxel Dörfler _CheckApplyEnabled(); 799a10cf76eSAxel Dörfler break; 800a10cf76eSAxel Dörfler 801a10cf76eSAxel Dörfler case POP_WORKSPACE_CHANGED_MSG: 802a10cf76eSAxel Dörfler { 803abc649b8SWaldemar Kornewald // update checkpoint state 804a10cf76eSAxel Dörfler int32 index; 805abc649b8SWaldemar Kornewald if (message->FindInt32("index", &index) == B_OK) { 806a10cf76eSAxel Dörfler set_workspace_count(index + 1); 8075de171daSAxel Dörfler _CheckApplyEnabled(); 808abc649b8SWaldemar Kornewald } 809a10cf76eSAxel Dörfler break; 810a10cf76eSAxel Dörfler } 811a10cf76eSAxel Dörfler 812a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 813a10cf76eSAxel Dörfler { 814a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 815a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 816a10cf76eSAxel Dörfler 8175de171daSAxel Dörfler _CheckColorMenu(); 8185de171daSAxel Dörfler _CheckRefreshMenu(); 819a10cf76eSAxel Dörfler 8205de171daSAxel Dörfler _UpdateMonitorView(); 8215de171daSAxel Dörfler _UpdateRefreshControl(); 822a10cf76eSAxel Dörfler 8235de171daSAxel Dörfler _CheckApplyEnabled(); 824a10cf76eSAxel Dörfler break; 825a10cf76eSAxel Dörfler } 826a10cf76eSAxel Dörfler 827a10cf76eSAxel Dörfler case POP_COLORS_MSG: 828a10cf76eSAxel Dörfler { 829a10cf76eSAxel Dörfler message->FindInt32("space", (int32 *)&fSelected.space); 830a10cf76eSAxel Dörfler 831a10cf76eSAxel Dörfler BString string; 832a10cf76eSAxel Dörfler string << fSelected.BitsPerPixel() << " Bits/Pixel"; 833a10cf76eSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 834a10cf76eSAxel Dörfler 8355de171daSAxel Dörfler _CheckApplyEnabled(); 836a10cf76eSAxel Dörfler break; 837a10cf76eSAxel Dörfler } 838a10cf76eSAxel Dörfler 839a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 840a40498e2SWaldemar Kornewald { 841a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 842a10cf76eSAxel Dörfler fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS); 843a10cf76eSAxel Dörfler // revert "Other…" label - it might have had a refresh rate prefix 844a10cf76eSAxel Dörfler 8455de171daSAxel Dörfler _CheckApplyEnabled(); 846a10cf76eSAxel Dörfler break; 847a40498e2SWaldemar Kornewald } 848a10cf76eSAxel Dörfler 849a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 850a10cf76eSAxel Dörfler { 85129e8a73aSAxel Dörfler // make sure menu shows something useful 8525de171daSAxel Dörfler _UpdateRefreshControl(); 853a10cf76eSAxel Dörfler 85429e8a73aSAxel Dörfler float min = 0, max = 999; 85529e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 85629e8a73aSAxel Dörfler if (min < gMinRefresh) 85729e8a73aSAxel Dörfler min = gMinRefresh; 85829e8a73aSAxel Dörfler if (max > gMaxRefresh) 85929e8a73aSAxel Dörfler max = gMaxRefresh; 86029e8a73aSAxel Dörfler 861c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 862c5d10f7aSAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, min, max); 863a10cf76eSAxel Dörfler fRefreshWindow->Show(); 864a10cf76eSAxel Dörfler break; 865a10cf76eSAxel Dörfler } 866a10cf76eSAxel Dörfler 867a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 868a10cf76eSAxel Dörfler { 869a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 870a10cf76eSAxel Dörfler // select the refresh rate chosen 871a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 872a10cf76eSAxel Dörfler 8735de171daSAxel Dörfler _UpdateRefreshControl(); 8745de171daSAxel Dörfler _CheckApplyEnabled(); 875a10cf76eSAxel Dörfler break; 876a10cf76eSAxel Dörfler } 877a10cf76eSAxel Dörfler 878a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 879a10cf76eSAxel Dörfler { 880a10cf76eSAxel Dörfler // new combine mode has bee chosen 881a10cf76eSAxel Dörfler int32 mode; 882a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 883a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 884a10cf76eSAxel Dörfler 8855de171daSAxel Dörfler _CheckResolutionMenu(); 8865de171daSAxel Dörfler _CheckApplyEnabled(); 887a10cf76eSAxel Dörfler break; 888a10cf76eSAxel Dörfler } 889a10cf76eSAxel Dörfler 890a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 891a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 8925de171daSAxel Dörfler _CheckApplyEnabled(); 893a10cf76eSAxel Dörfler break; 894a10cf76eSAxel Dörfler 895a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 896a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 8975de171daSAxel Dörfler _CheckApplyEnabled(); 898a10cf76eSAxel Dörfler break; 899a10cf76eSAxel Dörfler 900a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 901a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 9025de171daSAxel Dörfler _CheckApplyEnabled(); 903a10cf76eSAxel Dörfler break; 904a10cf76eSAxel Dörfler 905df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 9066f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 9076f095d6aSRyan Leavengood app_info info; 9086f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 9096f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 9106f095d6aSRyan Leavengood } 911df3f5bacSStephan Aßmus break; 912df3f5bacSStephan Aßmus 913a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 914a10cf76eSAxel Dörfler { 9154be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 916a10cf76eSAxel Dörfler fSelected.width = 640; 917a10cf76eSAxel Dörfler fSelected.height = 480; 918a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 919a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 920a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 921a10cf76eSAxel Dörfler fSelected.swap_displays = false; 922a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 923a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 924a10cf76eSAxel Dörfler 925abc649b8SWaldemar Kornewald BMenuItem *item; 926abc649b8SWaldemar Kornewald item = fWorkspaceCountField->Menu()->ItemAt(3); 927abc649b8SWaldemar Kornewald if (item != NULL) 928abc649b8SWaldemar Kornewald item->SetMarked(true); 929abc649b8SWaldemar Kornewald 9305de171daSAxel Dörfler _UpdateControls(); 931a10cf76eSAxel Dörfler break; 932a10cf76eSAxel Dörfler } 933a10cf76eSAxel Dörfler 93410e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 935abc649b8SWaldemar Kornewald fTempScreenMode.Revert(); 9365de171daSAxel Dörfler _UpdateActiveMode(); 937abc649b8SWaldemar Kornewald break; 938abc649b8SWaldemar Kornewald 939abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 940abc649b8SWaldemar Kornewald { 941abc649b8SWaldemar Kornewald fModified = false; 942199893c3SAxel Dörfler fBootWorkspaceApplied = false; 943abc649b8SWaldemar Kornewald BMenuItem *item; 944abc649b8SWaldemar Kornewald item = fWorkspaceCountField->Menu()->ItemAt(fOriginalWorkspaceCount - 1); 945abc649b8SWaldemar Kornewald if (item != NULL) 946abc649b8SWaldemar Kornewald item->SetMarked(true); 947abc649b8SWaldemar Kornewald 948abc649b8SWaldemar Kornewald // ScreenMode::Revert() assumes that we first set the correct number 949abc649b8SWaldemar Kornewald // of workspaces 950abc649b8SWaldemar Kornewald set_workspace_count(fOriginalWorkspaceCount); 951a10cf76eSAxel Dörfler fScreenMode.Revert(); 9525de171daSAxel Dörfler _UpdateActiveMode(); 953a10cf76eSAxel Dörfler break; 954abc649b8SWaldemar Kornewald } 955a10cf76eSAxel Dörfler 956a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 9575de171daSAxel Dörfler _Apply(); 958a10cf76eSAxel Dörfler break; 959a10cf76eSAxel Dörfler 960abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 961abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 962abc649b8SWaldemar Kornewald fModified = true; 9635de171daSAxel Dörfler _UpdateActiveMode(); 964a10cf76eSAxel Dörfler break; 965a10cf76eSAxel Dörfler 966a10cf76eSAxel Dörfler default: 967a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 968a10cf76eSAxel Dörfler break; 969a10cf76eSAxel Dörfler } 970a10cf76eSAxel Dörfler } 971a10cf76eSAxel Dörfler 972a10cf76eSAxel Dörfler 97312580984SAxel Dörfler status_t 97412580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 97512580984SAxel Dörfler { 97612580984SAxel Dörfler BPath path; 97712580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 97812580984SAxel Dörfler if (status < B_OK) 97912580984SAxel Dörfler return status; 98012580984SAxel Dörfler 98112580984SAxel Dörfler path.Append("kernel/drivers"); 98212580984SAxel Dörfler status = create_directory(path.Path(), 0755); 98312580984SAxel Dörfler if (status < B_OK) 98412580984SAxel Dörfler return status; 98512580984SAxel Dörfler 98612580984SAxel Dörfler path.Append("vesa"); 98712580984SAxel Dörfler BFile file; 98812580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 98912580984SAxel Dörfler if (status < B_OK) 99012580984SAxel Dörfler return status; 99112580984SAxel Dörfler 99212580984SAxel Dörfler char buffer[256]; 99312580984SAxel Dörfler snprintf(buffer, sizeof(buffer), "mode %ld %ld %ld\n", 99412580984SAxel Dörfler mode.width, mode.height, mode.BitsPerPixel()); 99512580984SAxel Dörfler 99612580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 99712580984SAxel Dörfler if (bytesWritten < B_OK) 99812580984SAxel Dörfler return bytesWritten; 99912580984SAxel Dörfler 100012580984SAxel Dörfler return B_OK; 100112580984SAxel Dörfler } 100212580984SAxel Dörfler 100312580984SAxel Dörfler 1004a10cf76eSAxel Dörfler void 10055de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1006a10cf76eSAxel Dörfler { 1007*27c43a2dSRene Gollent fApplyButton->SetEnabled(fSelected != fActive 1008*27c43a2dSRene Gollent || fAllWorkspacesItem->IsMarked()); 10095de171daSAxel Dörfler fRevertButton->SetEnabled(count_workspaces() != fOriginalWorkspaceCount 10105de171daSAxel Dörfler || fSelected != fOriginal); 1011a10cf76eSAxel Dörfler } 1012a10cf76eSAxel Dörfler 1013a10cf76eSAxel Dörfler 1014a10cf76eSAxel Dörfler void 10155de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1016abc649b8SWaldemar Kornewald { 1017abc649b8SWaldemar Kornewald fOriginalWorkspaceCount = count_workspaces(); 1018abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1019abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1020abc649b8SWaldemar Kornewald } 1021abc649b8SWaldemar Kornewald 1022abc649b8SWaldemar Kornewald 1023abc649b8SWaldemar Kornewald void 10245de171daSAxel Dörfler ScreenWindow::_Apply() 1025a10cf76eSAxel Dörfler { 1026abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 1027abc649b8SWaldemar Kornewald fTempScreenMode.UpdateOriginalModes(); 102807184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 102907184a9eSAxel Dörfler if (status == B_OK) { 1030abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1031abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1032abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1033abc649b8SWaldemar Kornewald display_mode newMode; 1034abc649b8SWaldemar Kornewald BScreen screen(this); 1035abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1036abc649b8SWaldemar Kornewald 1037abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1038abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 1039abc649b8SWaldemar Kornewald for (int32 i = 0; i < count_workspaces(); i++) { 1040abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1041abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1042abc649b8SWaldemar Kornewald } 1043199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1044199893c3SAxel Dörfler } else { 1045199893c3SAxel Dörfler if (current_workspace() == 0) 1046199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1047abc649b8SWaldemar Kornewald } 1048abc649b8SWaldemar Kornewald 1049a10cf76eSAxel Dörfler fActive = fSelected; 1050a10cf76eSAxel Dörfler 1051abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 1052a10cf76eSAxel Dörfler BWindow* window = new AlertWindow(this); 1053a10cf76eSAxel Dörfler window->Show(); 105407184a9eSAxel Dörfler } else { 105507184a9eSAxel Dörfler char message[256]; 105607184a9eSAxel Dörfler snprintf(message, sizeof(message), 105707184a9eSAxel Dörfler "The screen mode could not be set:\n\t%s\n", screen_errors(status)); 105807184a9eSAxel Dörfler BAlert* alert = new BAlert("Screen Alert", message, "Okay", NULL, NULL, 105907184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 106007184a9eSAxel Dörfler alert->Go(); 1061a10cf76eSAxel Dörfler } 106207184a9eSAxel Dörfler } 106307184a9eSAxel Dörfler 1064df3f5bacSStephan Aßmus 1065df3f5bacSStephan Aßmus void 10665de171daSAxel Dörfler ScreenWindow::_LayoutControls(uint32 flags) 1067df3f5bacSStephan Aßmus { 1068df3f5bacSStephan Aßmus // layout the screen box and its controls 1069df3f5bacSStephan Aßmus fWorkspaceCountField->ResizeToPreferred(); 1070df3f5bacSStephan Aßmus 1071df3f5bacSStephan Aßmus float monitorViewHeight = fMonitorView->Bounds().Height(); 1072df3f5bacSStephan Aßmus float workspaceFieldHeight = fWorkspaceCountField->Bounds().Height(); 1073df3f5bacSStephan Aßmus float backgroundsButtonHeight = fBackgroundsButton->Bounds().Height(); 1074df3f5bacSStephan Aßmus 1075df3f5bacSStephan Aßmus float screenBoxWidth = fWorkspaceCountField->Bounds().Width() + 20.0; 10765de171daSAxel Dörfler float screenBoxHeight = monitorViewHeight + 5.0 + workspaceFieldHeight + 5.0 10775de171daSAxel Dörfler + backgroundsButtonHeight + 20.0; 1078df3f5bacSStephan Aßmus 107929e8a73aSAxel Dörfler #ifdef __HAIKU__ 1080df3f5bacSStephan Aßmus fScreenBox->MoveTo(10.0, 10.0 + fControlsBox->TopBorderOffset()); 108129e8a73aSAxel Dörfler #else 108229e8a73aSAxel Dörfler fScreenBox->MoveTo(10.0, 10.0 + 3); 108329e8a73aSAxel Dörfler #endif 1084df3f5bacSStephan Aßmus fScreenBox->ResizeTo(screenBoxWidth, screenBoxHeight); 1085df3f5bacSStephan Aßmus 1086df3f5bacSStephan Aßmus float leftOffset = 10.0; 1087df3f5bacSStephan Aßmus float topOffset = 10.0; 1088df3f5bacSStephan Aßmus fMonitorView->MoveTo(leftOffset, topOffset); 1089df3f5bacSStephan Aßmus fMonitorView->ResizeTo(screenBoxWidth - 20.0, monitorViewHeight); 1090df3f5bacSStephan Aßmus fMonitorView->SetResizingMode(B_FOLLOW_ALL); 1091df3f5bacSStephan Aßmus topOffset += monitorViewHeight + 5.0; 1092df3f5bacSStephan Aßmus 1093df3f5bacSStephan Aßmus fWorkspaceCountField->MoveTo(leftOffset, topOffset); 1094df3f5bacSStephan Aßmus fWorkspaceCountField->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 1095df3f5bacSStephan Aßmus topOffset += workspaceFieldHeight + 5.0; 1096df3f5bacSStephan Aßmus 1097df3f5bacSStephan Aßmus fBackgroundsButton->MoveTo(leftOffset, topOffset); 1098df3f5bacSStephan Aßmus fBackgroundsButton->ResizeTo(screenBoxWidth - 20.0, backgroundsButtonHeight); 1099df3f5bacSStephan Aßmus fBackgroundsButton->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 1100df3f5bacSStephan Aßmus 1101df3f5bacSStephan Aßmus fControlsBox->MoveTo(fScreenBox->Frame().right + 10.0, 10.0); 1102df3f5bacSStephan Aßmus 1103df3f5bacSStephan Aßmus // layout the right side 11044008594dSWaldemar Kornewald fApplyButton->ResizeToPreferred(); 11055de171daSAxel Dörfler BRect controlsRect = _LayoutMenuFields(flags); 1106df3f5bacSStephan Aßmus controlsRect.InsetBy(-10.0, -10.0); 11074008594dSWaldemar Kornewald controlsRect.bottom += 8 + fApplyButton->Bounds().Height(); 1108df3f5bacSStephan Aßmus // adjust size of controls box and move aligned buttons along 1109df3f5bacSStephan Aßmus float xDiff = controlsRect.right - fControlsBox->Bounds().right; 1110df3f5bacSStephan Aßmus float yDiff = controlsRect.bottom - fControlsBox->Bounds().bottom; 1111df3f5bacSStephan Aßmus if (yDiff < 0.0) { 1112df3f5bacSStephan Aßmus // don't shrink vertically 1113df3f5bacSStephan Aßmus yDiff = 0.0; 1114df3f5bacSStephan Aßmus } 1115df3f5bacSStephan Aßmus 1116df3f5bacSStephan Aßmus fControlsBox->ResizeBy(xDiff, yDiff); 1117df3f5bacSStephan Aßmus 1118df3f5bacSStephan Aßmus // align bottom of boxen 1119df3f5bacSStephan Aßmus float boxBottomDiff = fControlsBox->Frame().bottom - fScreenBox->Frame().bottom; 1120df3f5bacSStephan Aßmus if (boxBottomDiff > 0) 1121df3f5bacSStephan Aßmus fScreenBox->ResizeBy(0.0, boxBottomDiff); 1122df3f5bacSStephan Aßmus else 1123df3f5bacSStephan Aßmus fControlsBox->ResizeBy(0.0, -boxBottomDiff); 1124df3f5bacSStephan Aßmus 1125df3f5bacSStephan Aßmus BRect boxFrame = fScreenBox->Frame() | fControlsBox->Frame(); 1126df3f5bacSStephan Aßmus 1127df3f5bacSStephan Aßmus // layout rest of buttons 1128abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 1129abc649b8SWaldemar Kornewald // fDefaultsButton->ResizeToPreferred(); 1130abc649b8SWaldemar Kornewald // fDefaultsButton->MoveTo(boxFrame.left, boxFrame.bottom + 8); 1131df3f5bacSStephan Aßmus 1132df3f5bacSStephan Aßmus fRevertButton->ResizeToPreferred(); 1133abc649b8SWaldemar Kornewald fRevertButton->MoveTo(boxFrame.left, boxFrame.bottom + 8); 1134abc649b8SWaldemar Kornewald // fRevertButton->MoveTo(fDefaultsButton->Frame().right + 10, 1135abc649b8SWaldemar Kornewald // fDefaultsButton->Frame().top); 1136df3f5bacSStephan Aßmus 11374008594dSWaldemar Kornewald // Apply button was already resized above 1138abc649b8SWaldemar Kornewald float resolutionFieldRight = fResolutionField->Frame().right; 1139abc649b8SWaldemar Kornewald fApplyButton->MoveTo(resolutionFieldRight - fApplyButton->Bounds().Width(), 11404008594dSWaldemar Kornewald fControlsBox->Bounds().bottom - fApplyButton->Bounds().Height() - 10); 1141df3f5bacSStephan Aßmus 1142abc649b8SWaldemar Kornewald ResizeTo(boxFrame.right + 10, fRevertButton->Frame().bottom + 10); 1143df3f5bacSStephan Aßmus } 1144df3f5bacSStephan Aßmus 1145df3f5bacSStephan Aßmus 1146df3f5bacSStephan Aßmus BRect 11475de171daSAxel Dörfler ScreenWindow::_LayoutMenuFields(uint32 flags, bool sideBySide) 1148df3f5bacSStephan Aßmus { 1149df3f5bacSStephan Aßmus BList menuFields; 1150df3f5bacSStephan Aßmus menuFields.AddItem((void*)fResolutionField); 1151df3f5bacSStephan Aßmus menuFields.AddItem((void*)fColorsField); 1152df3f5bacSStephan Aßmus menuFields.AddItem((void*)fRefreshField); 1153df3f5bacSStephan Aßmus 1154df3f5bacSStephan Aßmus BRect frame; 1155df3f5bacSStephan Aßmus 1156df3f5bacSStephan Aßmus if (sideBySide) 1157df3f5bacSStephan Aßmus frame = stack_and_align_menu_fields(menuFields); 1158df3f5bacSStephan Aßmus 1159df3f5bacSStephan Aßmus if (sideBySide) 1160df3f5bacSStephan Aßmus menuFields.MakeEmpty(); 1161df3f5bacSStephan Aßmus 1162df3f5bacSStephan Aßmus if (flags & SHOW_COMBINE_FIELD) 1163df3f5bacSStephan Aßmus menuFields.AddItem((void*)fCombineField); 1164df3f5bacSStephan Aßmus if (flags & SHOW_SWAP_FIELD) 1165df3f5bacSStephan Aßmus menuFields.AddItem((void*)fSwapDisplaysField); 1166df3f5bacSStephan Aßmus if (flags & SHOW_LAPTOP_PANEL_FIELD) 1167df3f5bacSStephan Aßmus menuFields.AddItem((void*)fUseLaptopPanelField); 1168df3f5bacSStephan Aßmus if (flags & SHOW_TV_STANDARD_FIELD) 1169df3f5bacSStephan Aßmus menuFields.AddItem((void*)fTVStandardField); 1170df3f5bacSStephan Aßmus 1171df3f5bacSStephan Aßmus if (sideBySide) { 1172df3f5bacSStephan Aßmus if (menuFields.CountItems() > 0) { 1173df3f5bacSStephan Aßmus ((BMenuField*)menuFields.FirstItem())->MoveTo(frame.right + 8.0, frame.top); 1174df3f5bacSStephan Aßmus frame = frame | stack_and_align_menu_fields(menuFields); 1175df3f5bacSStephan Aßmus } 1176df3f5bacSStephan Aßmus } else { 1177df3f5bacSStephan Aßmus frame = stack_and_align_menu_fields(menuFields); 1178df3f5bacSStephan Aßmus } 1179df3f5bacSStephan Aßmus 1180df3f5bacSStephan Aßmus return frame; 1181df3f5bacSStephan Aßmus } 1182df3f5bacSStephan Aßmus 1183