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 249b72c4836SAlexandre Deckner // TODO: since per workspace settings is unimplemented (Ticket #693) 250b72c4836SAlexandre Deckner // we force the menu to "All Workspaces" for now 25112580984SAxel Dörfler fAllWorkspacesItem->SetMarked(true); 25212580984SAxel Dörfler item->SetEnabled(false); 253b72c4836SAlexandre Deckner 2545a78744bSAxel Dörfler popUpMenu->AddItem(item); 2555a78744bSAxel Dörfler 256df3f5bacSStephan Aßmus BMenuField* workspaceMenuField = new BMenuField(BRect(0, 0, 100, 15), 2575a78744bSAxel Dörfler "WorkspaceMenu", NULL, popUpMenu, true); 2585a78744bSAxel Dörfler workspaceMenuField->ResizeToPreferred(); 259a10cf76eSAxel Dörfler 260a10cf76eSAxel Dörfler // box on the left with workspace count and monitor view 261a10cf76eSAxel Dörfler 2625a78744bSAxel Dörfler popUpMenu = new BPopUpMenu("", true, true); 263df3f5bacSStephan Aßmus fWorkspaceCountField = new BMenuField(BRect(0.0, 0.0, 50.0, 15.0), 264df3f5bacSStephan Aßmus "WorkspaceCountMenu", "Workspace count:", popUpMenu, true); 265d1516993SAxel Dörfler float labelWidth = fWorkspaceCountField->StringWidth( 266d1516993SAxel Dörfler fWorkspaceCountField->Label()) + 5.0; 267df3f5bacSStephan Aßmus fWorkspaceCountField->SetDivider(labelWidth); 268df3f5bacSStephan Aßmus 269df3f5bacSStephan Aßmus fScreenBox = new BBox(BRect(0.0, 0.0, 100.0, 100.0), "left box"); 270df3f5bacSStephan Aßmus fScreenBox->AddChild(fWorkspaceCountField); 271a10cf76eSAxel Dörfler 272a10cf76eSAxel Dörfler for (int32 count = 1; count <= 32; count++) { 273a10cf76eSAxel Dörfler BString workspaceCount; 274a10cf76eSAxel Dörfler workspaceCount << count; 275a10cf76eSAxel Dörfler 276a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_WORKSPACE_CHANGED_MSG); 277a10cf76eSAxel Dörfler message->AddInt32("workspace count", count); 278a10cf76eSAxel Dörfler 279a10cf76eSAxel Dörfler popUpMenu->AddItem(new BMenuItem(workspaceCount.String(), 280a10cf76eSAxel Dörfler message)); 281a10cf76eSAxel Dörfler } 282a10cf76eSAxel Dörfler 2835a78744bSAxel Dörfler item = popUpMenu->ItemAt(count_workspaces() - 1); 284a10cf76eSAxel Dörfler if (item != NULL) 285a10cf76eSAxel Dörfler item->SetMarked(true); 286a10cf76eSAxel Dörfler 287df3f5bacSStephan Aßmus fMonitorView = new MonitorView(BRect(0.0, 0.0, 80.0, 80.0), "monitor", 288*6bda235aSStefano Ceccherini screen.Frame().IntegerWidth() + 1, screen.Frame().IntegerHeight() + 1); 289df3f5bacSStephan Aßmus fScreenBox->AddChild(fMonitorView); 2905a78744bSAxel Dörfler 291df3f5bacSStephan Aßmus view->AddChild(fScreenBox); 292a10cf76eSAxel Dörfler 293a10cf76eSAxel Dörfler // box on the right with screen resolution, etc. 294a10cf76eSAxel Dörfler 295df3f5bacSStephan Aßmus fControlsBox = new BBox(BRect(0.0, 0.0, 100.0, 100.0)); 296df3f5bacSStephan Aßmus fControlsBox->SetLabel(workspaceMenuField); 297a10cf76eSAxel Dörfler 298a10cf76eSAxel Dörfler fResolutionMenu = new BPopUpMenu("resolution", true, true); 299a10cf76eSAxel Dörfler 300a10cf76eSAxel Dörfler uint16 previousWidth = 0, previousHeight = 0; 301a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 302a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 303a10cf76eSAxel Dörfler 304a10cf76eSAxel Dörfler if (mode.width == previousWidth && mode.height == previousHeight) 305a10cf76eSAxel Dörfler continue; 306a10cf76eSAxel Dörfler 307a10cf76eSAxel Dörfler previousWidth = mode.width; 308a10cf76eSAxel Dörfler previousHeight = mode.height; 309a10cf76eSAxel Dörfler 310a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_RESOLUTION_MSG); 311a10cf76eSAxel Dörfler message->AddInt32("width", mode.width); 312a10cf76eSAxel Dörfler message->AddInt32("height", mode.height); 313a10cf76eSAxel Dörfler 314a10cf76eSAxel Dörfler BString name; 315a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 316a10cf76eSAxel Dörfler 317a10cf76eSAxel Dörfler fResolutionMenu->AddItem(new BMenuItem(name.String(), message)); 318a10cf76eSAxel Dörfler } 319a10cf76eSAxel Dörfler 32029e8a73aSAxel Dörfler BRect rect(0.0, 0.0, 200.0, 15.0); 321df3f5bacSStephan Aßmus // fResolutionField needs to be at the correct 322df3f5bacSStephan Aßmus // left-top offset, because all other menu fields 323df3f5bacSStephan Aßmus // will be layouted relative to it 324df3f5bacSStephan Aßmus fResolutionField = new BMenuField(rect.OffsetToCopy(10.0, 30.0), 325d1516993SAxel Dörfler "ResolutionMenu", "Resolution:", fResolutionMenu, false); 326df3f5bacSStephan Aßmus fControlsBox->AddChild(fResolutionField); 327a10cf76eSAxel Dörfler 328a10cf76eSAxel Dörfler fColorsMenu = new BPopUpMenu("colors", true, true); 329a10cf76eSAxel Dörfler 330a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 331a10cf76eSAxel Dörfler BMessage *message = new BMessage(POP_COLORS_MSG); 332a10cf76eSAxel Dörfler message->AddInt32("bits_per_pixel", kColorSpaces[i].bits_per_pixel); 333a10cf76eSAxel Dörfler message->AddInt32("space", kColorSpaces[i].space); 334a10cf76eSAxel Dörfler 335a10cf76eSAxel Dörfler fColorsMenu->AddItem(new BMenuItem(kColorSpaces[i].label, message)); 336a10cf76eSAxel Dörfler } 337a10cf76eSAxel Dörfler 338df3f5bacSStephan Aßmus rect.OffsetTo(B_ORIGIN); 339df3f5bacSStephan Aßmus 340d1516993SAxel Dörfler fColorsField = new BMenuField(rect, "ColorsMenu", "Colors:", fColorsMenu, 341d1516993SAxel Dörfler false); 342df3f5bacSStephan Aßmus fControlsBox->AddChild(fColorsField); 343a10cf76eSAxel Dörfler 344a10cf76eSAxel Dörfler fRefreshMenu = new BPopUpMenu("refresh rate", true, true); 345a10cf76eSAxel Dörfler 34629e8a73aSAxel Dörfler BMessage *message; 34729e8a73aSAxel Dörfler 34829e8a73aSAxel Dörfler float min, max; 34929e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fActive, min, max) && min == max) { 35029e8a73aSAxel Dörfler // This is a special case for drivers that only support a single 35129e8a73aSAxel Dörfler // frequency, like the VESA driver 35229e8a73aSAxel Dörfler BString name; 35329e8a73aSAxel Dörfler name << min << " Hz"; 35429e8a73aSAxel Dörfler 35529e8a73aSAxel Dörfler message = new BMessage(POP_REFRESH_MSG); 35629e8a73aSAxel Dörfler message->AddFloat("refresh", min); 35729e8a73aSAxel Dörfler 35829e8a73aSAxel Dörfler fRefreshMenu->AddItem(item = new BMenuItem(name.String(), message)); 35929e8a73aSAxel Dörfler item->SetEnabled(false); 36029e8a73aSAxel Dörfler } else { 361a10cf76eSAxel Dörfler for (int32 i = 0; i < kRefreshRateCount; ++i) { 362a10cf76eSAxel Dörfler BString name; 363a10cf76eSAxel Dörfler name << kRefreshRates[i] << " Hz"; 364a10cf76eSAxel Dörfler 36529e8a73aSAxel Dörfler message = new BMessage(POP_REFRESH_MSG); 366a10cf76eSAxel Dörfler message->AddFloat("refresh", kRefreshRates[i]); 367a10cf76eSAxel Dörfler 368a10cf76eSAxel Dörfler fRefreshMenu->AddItem(new BMenuItem(name.String(), message)); 369a10cf76eSAxel Dörfler } 370a10cf76eSAxel Dörfler 37129e8a73aSAxel Dörfler message = new BMessage(POP_OTHER_REFRESH_MSG); 372a10cf76eSAxel Dörfler 373a10cf76eSAxel Dörfler fOtherRefresh = new BMenuItem("Other" B_UTF8_ELLIPSIS, message); 374a10cf76eSAxel Dörfler fRefreshMenu->AddItem(fOtherRefresh); 37529e8a73aSAxel Dörfler } 376a10cf76eSAxel Dörfler 377d1516993SAxel Dörfler fRefreshField = new BMenuField(rect, "RefreshMenu", "Refresh Rate:", 378d1516993SAxel Dörfler fRefreshMenu, false); 37912580984SAxel Dörfler if (_IsVesa()) 38012580984SAxel Dörfler fRefreshField->Hide(); 381df3f5bacSStephan Aßmus fControlsBox->AddChild(fRefreshField); 382a10cf76eSAxel Dörfler 383df3f5bacSStephan Aßmus view->AddChild(fControlsBox); 384df3f5bacSStephan Aßmus 385df3f5bacSStephan Aßmus uint32 controlsFlags = 0; 386a10cf76eSAxel Dörfler 387a10cf76eSAxel Dörfler // enlarged area for multi-monitor settings 388a10cf76eSAxel Dörfler { 389a10cf76eSAxel Dörfler bool dummy; 390a10cf76eSAxel Dörfler uint32 dummy32; 391a10cf76eSAxel Dörfler bool multiMonSupport; 392a10cf76eSAxel Dörfler bool useLaptopPanelSupport; 393a10cf76eSAxel Dörfler bool tvStandardSupport; 394a10cf76eSAxel Dörfler 395a10cf76eSAxel Dörfler multiMonSupport = TestMultiMonSupport(&screen) == B_OK; 396a10cf76eSAxel Dörfler useLaptopPanelSupport = GetUseLaptopPanel(&screen, &dummy) == B_OK; 397a10cf76eSAxel Dörfler tvStandardSupport = GetTVStandard(&screen, &dummy32) == B_OK; 398df3f5bacSStephan Aßmus if (multiMonSupport) { 399df3f5bacSStephan Aßmus controlsFlags |= SHOW_COMBINE_FIELD; 400df3f5bacSStephan Aßmus controlsFlags |= SHOW_SWAP_FIELD; 401df3f5bacSStephan Aßmus } 402df3f5bacSStephan Aßmus if (useLaptopPanelSupport) 403df3f5bacSStephan Aßmus controlsFlags |= SHOW_LAPTOP_PANEL_FIELD; 404a10cf76eSAxel Dörfler 405a10cf76eSAxel Dörfler // even if there is no support, we still create all controls 406a10cf76eSAxel Dörfler // to make sure we don't access NULL pointers later on 407a10cf76eSAxel Dörfler 408a10cf76eSAxel Dörfler fCombineMenu = new BPopUpMenu("CombineDisplays", true, true); 409a10cf76eSAxel Dörfler 410a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 411a10cf76eSAxel Dörfler message = new BMessage(POP_COMBINE_DISPLAYS_MSG); 412a10cf76eSAxel Dörfler message->AddInt32("mode", kCombineModes[i].mode); 413a10cf76eSAxel Dörfler 414d1516993SAxel Dörfler fCombineMenu->AddItem(new BMenuItem(kCombineModes[i].name, 415d1516993SAxel Dörfler message)); 416a10cf76eSAxel Dörfler } 417a10cf76eSAxel Dörfler 418df3f5bacSStephan Aßmus fCombineField = new BMenuField(rect, "CombineMenu", 419d1516993SAxel Dörfler "Combine Displays:", fCombineMenu, false); 420df3f5bacSStephan Aßmus fControlsBox->AddChild(fCombineField); 421a10cf76eSAxel Dörfler 422a10cf76eSAxel Dörfler if (!multiMonSupport) 423df3f5bacSStephan Aßmus fCombineField->Hide(); 424a10cf76eSAxel Dörfler 425a10cf76eSAxel Dörfler fSwapDisplaysMenu = new BPopUpMenu("SwapDisplays", true, true); 426a10cf76eSAxel Dörfler 427a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 428a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 429a10cf76eSAxel Dörfler message->AddBool("swap", false); 430a10cf76eSAxel Dörfler fSwapDisplaysMenu->AddItem(new BMenuItem("no", message)); 431a10cf76eSAxel Dörfler 432a10cf76eSAxel Dörfler message = new BMessage(POP_SWAP_DISPLAYS_MSG); 433a10cf76eSAxel Dörfler message->AddBool("swap", true); 434a10cf76eSAxel Dörfler fSwapDisplaysMenu->AddItem(new BMenuItem("yes", message)); 435a10cf76eSAxel Dörfler 436df3f5bacSStephan Aßmus fSwapDisplaysField = new BMenuField(rect, "SwapMenu", "Swap Displays:", 437d1516993SAxel Dörfler fSwapDisplaysMenu, false); 438a10cf76eSAxel Dörfler 439df3f5bacSStephan Aßmus fControlsBox->AddChild(fSwapDisplaysField); 440a10cf76eSAxel Dörfler if (!multiMonSupport) 441df3f5bacSStephan Aßmus fSwapDisplaysField->Hide(); 442a10cf76eSAxel Dörfler 443a10cf76eSAxel Dörfler fUseLaptopPanelMenu = new BPopUpMenu("UseLaptopPanel", true, true); 444a10cf76eSAxel Dörfler 445a10cf76eSAxel Dörfler // !order is important - we rely that boolean value == idx 446a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 447a10cf76eSAxel Dörfler message->AddBool("use", false); 448a10cf76eSAxel Dörfler fUseLaptopPanelMenu->AddItem(new BMenuItem("if needed", message)); 449a10cf76eSAxel Dörfler 450a10cf76eSAxel Dörfler message = new BMessage(POP_USE_LAPTOP_PANEL_MSG); 451a10cf76eSAxel Dörfler message->AddBool("use", true); 452a10cf76eSAxel Dörfler fUseLaptopPanelMenu->AddItem(new BMenuItem("always", message)); 453a10cf76eSAxel Dörfler 454d1516993SAxel Dörfler fUseLaptopPanelField = new BMenuField(rect, "UseLaptopPanel", 455d1516993SAxel Dörfler "Use Laptop Panel:", fUseLaptopPanelMenu, false); 456a10cf76eSAxel Dörfler 457df3f5bacSStephan Aßmus fControlsBox->AddChild(fUseLaptopPanelField); 458a10cf76eSAxel Dörfler if (!useLaptopPanelSupport) 459df3f5bacSStephan Aßmus fUseLaptopPanelField->Hide(); 460a10cf76eSAxel Dörfler 461a10cf76eSAxel Dörfler fTVStandardMenu = new BPopUpMenu("TVStandard", true, true); 462a10cf76eSAxel Dörfler 463a10cf76eSAxel Dörfler // arbitrary limit 464a10cf76eSAxel Dörfler uint32 i; 465a10cf76eSAxel Dörfler for (i = 0; i < 100; ++i) { 466a10cf76eSAxel Dörfler uint32 mode; 467a10cf76eSAxel Dörfler if (GetNthSupportedTVStandard(&screen, i, &mode) != B_OK) 468a10cf76eSAxel Dörfler break; 469a10cf76eSAxel Dörfler 470a10cf76eSAxel Dörfler BString name = tv_standard_to_string(mode); 471a10cf76eSAxel Dörfler 472a10cf76eSAxel Dörfler message = new BMessage(POP_TV_STANDARD_MSG); 473a10cf76eSAxel Dörfler message->AddInt32("tv_standard", mode); 474a10cf76eSAxel Dörfler 475a10cf76eSAxel Dörfler fTVStandardMenu->AddItem(new BMenuItem(name.String(), message)); 476a10cf76eSAxel Dörfler } 477a10cf76eSAxel Dörfler 478df3f5bacSStephan Aßmus fTVStandardField = new BMenuField(rect, "tv standard", "Video Format:", 479d1516993SAxel Dörfler fTVStandardMenu, false); 480df3f5bacSStephan Aßmus fTVStandardField->SetAlignment(B_ALIGN_RIGHT); 481a10cf76eSAxel Dörfler 482df3f5bacSStephan Aßmus if (!tvStandardSupport || i == 0) { 483df3f5bacSStephan Aßmus fTVStandardField->Hide(); 484df3f5bacSStephan Aßmus } else { 485df3f5bacSStephan Aßmus controlsFlags |= SHOW_TV_STANDARD_FIELD; 486a10cf76eSAxel Dörfler } 487a10cf76eSAxel Dörfler 488df3f5bacSStephan Aßmus fControlsBox->AddChild(fTVStandardField); 489df3f5bacSStephan Aßmus } 490df3f5bacSStephan Aßmus 491df3f5bacSStephan Aßmus BRect buttonRect(0.0, 0.0, 30.0, 10.0); 492df3f5bacSStephan Aßmus fBackgroundsButton = new BButton(buttonRect, "BackgroundsButton", 493d1516993SAxel Dörfler "Set Background"B_UTF8_ELLIPSIS, 494d1516993SAxel Dörfler new BMessage(BUTTON_LAUNCH_BACKGROUNDS_MSG)); 4953dfd20c0SStephan Aßmus fBackgroundsButton->SetFontSize(be_plain_font->Size() * 0.9); 496df3f5bacSStephan Aßmus fScreenBox->AddChild(fBackgroundsButton); 497df3f5bacSStephan Aßmus 498abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 499abc649b8SWaldemar Kornewald /* fDefaultsButton = new BButton(buttonRect, "DefaultsButton", "Defaults", 500a10cf76eSAxel Dörfler new BMessage(BUTTON_DEFAULTS_MSG)); 501abc649b8SWaldemar Kornewald view->AddChild(fDefaultsButton); */ 502a10cf76eSAxel Dörfler 503df3f5bacSStephan Aßmus fRevertButton = new BButton(buttonRect, "RevertButton", "Revert", 504a10cf76eSAxel Dörfler new BMessage(BUTTON_REVERT_MSG)); 505a10cf76eSAxel Dörfler fRevertButton->SetEnabled(false); 506a10cf76eSAxel Dörfler view->AddChild(fRevertButton); 507a10cf76eSAxel Dörfler 508df3f5bacSStephan Aßmus fApplyButton = new BButton(buttonRect, "ApplyButton", "Apply", 509df3f5bacSStephan Aßmus new BMessage(BUTTON_APPLY_MSG)); 510df3f5bacSStephan Aßmus fApplyButton->SetEnabled(false); 511abc649b8SWaldemar Kornewald fControlsBox->AddChild(fApplyButton); 5125a78744bSAxel Dörfler 5135de171daSAxel Dörfler _UpdateControls(); 514df3f5bacSStephan Aßmus 5155de171daSAxel Dörfler _LayoutControls(controlsFlags); 516a10cf76eSAxel Dörfler } 517a10cf76eSAxel Dörfler 518a10cf76eSAxel Dörfler 519a10cf76eSAxel Dörfler ScreenWindow::~ScreenWindow() 520a10cf76eSAxel Dörfler { 521a10cf76eSAxel Dörfler delete fSettings; 522a10cf76eSAxel Dörfler } 523a10cf76eSAxel Dörfler 524a10cf76eSAxel Dörfler 525a10cf76eSAxel Dörfler bool 526a10cf76eSAxel Dörfler ScreenWindow::QuitRequested() 527a10cf76eSAxel Dörfler { 528a10cf76eSAxel Dörfler fSettings->SetWindowFrame(Frame()); 529199893c3SAxel Dörfler 530199893c3SAxel Dörfler // Write mode of workspace 0 (the boot workspace) to the vesa settings file 531199893c3SAxel Dörfler screen_mode vesaMode; 532199893c3SAxel Dörfler if (fBootWorkspaceApplied && fScreenMode.Get(vesaMode, 0) == B_OK) { 533199893c3SAxel Dörfler status_t status = _WriteVesaModeFile(vesaMode); 53412580984SAxel Dörfler if (status < B_OK) { 53512580984SAxel Dörfler BString warning = "Could not write VESA mode settings file:\n\t"; 53612580984SAxel Dörfler warning << strerror(status); 53712580984SAxel Dörfler (new BAlert("VesaAlert", warning.String(), "Okay", NULL, NULL, 53812580984SAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); 53912580984SAxel Dörfler } 54012580984SAxel Dörfler } 54112580984SAxel Dörfler 542a10cf76eSAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 543a10cf76eSAxel Dörfler 544a10cf76eSAxel Dörfler return BWindow::QuitRequested(); 545a10cf76eSAxel Dörfler } 546a10cf76eSAxel Dörfler 547a10cf76eSAxel Dörfler 5485de171daSAxel Dörfler /*! Update resolution list according to combine mode 5495de171daSAxel Dörfler (some resolution may not be combinable due to memory restrictions) 550a10cf76eSAxel Dörfler */ 551a10cf76eSAxel Dörfler void 5525de171daSAxel Dörfler ScreenWindow::_CheckResolutionMenu() 553a10cf76eSAxel Dörfler { 554a10cf76eSAxel Dörfler for (int32 i = 0; i < fResolutionMenu->CountItems(); i++) 555a10cf76eSAxel Dörfler fResolutionMenu->ItemAt(i)->SetEnabled(false); 556a10cf76eSAxel Dörfler 557a10cf76eSAxel Dörfler for (int32 i = 0; i < fScreenMode.CountModes(); i++) { 558a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(i); 559a10cf76eSAxel Dörfler if (mode.combine != fSelected.combine) 560a10cf76eSAxel Dörfler continue; 561a10cf76eSAxel Dörfler 562a10cf76eSAxel Dörfler BString name; 563a10cf76eSAxel Dörfler name << mode.width << " x " << mode.height; 564a10cf76eSAxel Dörfler 565a10cf76eSAxel Dörfler BMenuItem *item = fResolutionMenu->FindItem(name.String()); 566a10cf76eSAxel Dörfler if (item != NULL) 567a10cf76eSAxel Dörfler item->SetEnabled(true); 568a10cf76eSAxel Dörfler } 569a10cf76eSAxel Dörfler } 570a10cf76eSAxel Dörfler 571a10cf76eSAxel Dörfler 5725de171daSAxel Dörfler /*! Update color and refresh options according to current mode 5735de171daSAxel Dörfler (a color space is made active if there is any mode with 5745de171daSAxel Dörfler given resolution and this colour space; same applies for 5755de171daSAxel Dörfler refresh rate, though "Other…" is always possible) 576a10cf76eSAxel Dörfler */ 577a10cf76eSAxel Dörfler void 5785de171daSAxel Dörfler ScreenWindow::_CheckColorMenu() 579a10cf76eSAxel Dörfler { 580a10cf76eSAxel Dörfler for (int32 i = 0; i < kColorSpaceCount; i++) { 581a10cf76eSAxel Dörfler bool supported = false; 582a10cf76eSAxel Dörfler 583a10cf76eSAxel Dörfler for (int32 j = 0; j < fScreenMode.CountModes(); j++) { 584a10cf76eSAxel Dörfler screen_mode mode = fScreenMode.ModeAt(j); 585a10cf76eSAxel Dörfler 586a10cf76eSAxel Dörfler if (fSelected.width == mode.width 587a10cf76eSAxel Dörfler && fSelected.height == mode.height 5885de171daSAxel Dörfler && (kColorSpaces[i].space == mode.space 5895de171daSAxel Dörfler // advertize 24 bit mode as 32 bit to avoid confusion 5905de171daSAxel Dörfler || (kColorSpaces[i].space == B_RGB32 5915de171daSAxel Dörfler && mode.space == B_RGB24)) 592a10cf76eSAxel Dörfler && fSelected.combine == mode.combine) { 593a10cf76eSAxel Dörfler supported = true; 594a10cf76eSAxel Dörfler break; 595a10cf76eSAxel Dörfler } 596a10cf76eSAxel Dörfler } 597a10cf76eSAxel Dörfler 598a10cf76eSAxel Dörfler BMenuItem* item = fColorsMenu->ItemAt(i); 599a10cf76eSAxel Dörfler if (item) 600a10cf76eSAxel Dörfler item->SetEnabled(supported); 601a10cf76eSAxel Dörfler } 602a10cf76eSAxel Dörfler } 603a10cf76eSAxel Dörfler 604a10cf76eSAxel Dörfler 6055de171daSAxel Dörfler /*! Enable/disable refresh options according to current mode. */ 606a10cf76eSAxel Dörfler void 6075de171daSAxel Dörfler ScreenWindow::_CheckRefreshMenu() 608a10cf76eSAxel Dörfler { 60929e8a73aSAxel Dörfler float min, max; 61029e8a73aSAxel Dörfler if (fScreenMode.GetRefreshLimits(fSelected, min, max) != B_OK || min == max) 61129e8a73aSAxel Dörfler return; 612a10cf76eSAxel Dörfler 61329e8a73aSAxel Dörfler for (int32 i = fRefreshMenu->CountItems(); i-- > 0;) { 61429e8a73aSAxel Dörfler BMenuItem* item = fRefreshMenu->ItemAt(i); 61529e8a73aSAxel Dörfler BMessage* message = item->Message(); 61629e8a73aSAxel Dörfler float refresh; 61729e8a73aSAxel Dörfler if (message != NULL && message->FindFloat("refresh", &refresh) == B_OK) 61829e8a73aSAxel Dörfler item->SetEnabled(refresh >= min && refresh <= max); 619a10cf76eSAxel Dörfler } 620a10cf76eSAxel Dörfler } 621a10cf76eSAxel Dörfler 622a10cf76eSAxel Dörfler 6235de171daSAxel Dörfler /*! Activate appropriate menu item according to selected refresh rate */ 624a10cf76eSAxel Dörfler void 6255de171daSAxel Dörfler ScreenWindow::_UpdateRefreshControl() 626a10cf76eSAxel Dörfler { 627a10cf76eSAxel Dörfler BString string; 628a10cf76eSAxel Dörfler refresh_rate_to_string(fSelected.refresh, string); 629a10cf76eSAxel Dörfler 630a10cf76eSAxel Dörfler BMenuItem* item = fRefreshMenu->FindItem(string.String()); 631a10cf76eSAxel Dörfler if (item) { 632a10cf76eSAxel Dörfler if (!item->IsMarked()) 633a10cf76eSAxel Dörfler item->SetMarked(true); 63429e8a73aSAxel Dörfler 635a10cf76eSAxel Dörfler // "Other…" items only contains a refresh rate when active 636e6b421a9SJérôme Duval fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS); 637a10cf76eSAxel Dörfler return; 638a10cf76eSAxel Dörfler } 639a10cf76eSAxel Dörfler 640a10cf76eSAxel Dörfler // this is a non-standard refresh rate 641a10cf76eSAxel Dörfler 642a10cf76eSAxel Dörfler fOtherRefresh->Message()->ReplaceFloat("refresh", fSelected.refresh); 643a10cf76eSAxel Dörfler fOtherRefresh->SetMarked(true); 644a10cf76eSAxel Dörfler 645a10cf76eSAxel Dörfler fRefreshMenu->Superitem()->SetLabel(string.String()); 646a10cf76eSAxel Dörfler 647a10cf76eSAxel Dörfler string.Append("/Other" B_UTF8_ELLIPSIS); 648a10cf76eSAxel Dörfler fOtherRefresh->SetLabel(string.String()); 649a10cf76eSAxel Dörfler } 650a10cf76eSAxel Dörfler 651a10cf76eSAxel Dörfler 652a10cf76eSAxel Dörfler void 6535de171daSAxel Dörfler ScreenWindow::_UpdateMonitorView() 654a10cf76eSAxel Dörfler { 655a10cf76eSAxel Dörfler BMessage updateMessage(UPDATE_DESKTOP_MSG); 656a10cf76eSAxel Dörfler updateMessage.AddInt32("width", fSelected.width); 657a10cf76eSAxel Dörfler updateMessage.AddInt32("height", fSelected.height); 658a10cf76eSAxel Dörfler 659a10cf76eSAxel Dörfler PostMessage(&updateMessage, fMonitorView); 660a10cf76eSAxel Dörfler } 661a10cf76eSAxel Dörfler 662a10cf76eSAxel Dörfler 663a10cf76eSAxel Dörfler void 6645de171daSAxel Dörfler ScreenWindow::_UpdateControls() 665a10cf76eSAxel Dörfler { 666a10cf76eSAxel Dörfler BMenuItem* item = fSwapDisplaysMenu->ItemAt((int32)fSelected.swap_displays); 667a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 668a10cf76eSAxel Dörfler item->SetMarked(true); 669a10cf76eSAxel Dörfler 670a10cf76eSAxel Dörfler item = fUseLaptopPanelMenu->ItemAt((int32)fSelected.use_laptop_panel); 671a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 672a10cf76eSAxel Dörfler item->SetMarked(true); 673a10cf76eSAxel Dörfler 674a10cf76eSAxel Dörfler for (int32 i = 0; i < fTVStandardMenu->CountItems(); i++) { 675a10cf76eSAxel Dörfler item = fTVStandardMenu->ItemAt(i); 676a10cf76eSAxel Dörfler 677a10cf76eSAxel Dörfler uint32 tvStandard; 678a10cf76eSAxel Dörfler item->Message()->FindInt32("tv_standard", (int32 *)&tvStandard); 679a10cf76eSAxel Dörfler if (tvStandard == fSelected.tv_standard) { 680a10cf76eSAxel Dörfler if (!item->IsMarked()) 681a10cf76eSAxel Dörfler item->SetMarked(true); 682a10cf76eSAxel Dörfler break; 683a10cf76eSAxel Dörfler } 684a10cf76eSAxel Dörfler } 685a10cf76eSAxel Dörfler 6865de171daSAxel Dörfler _CheckResolutionMenu(); 6875de171daSAxel Dörfler _CheckColorMenu(); 6885de171daSAxel Dörfler _CheckRefreshMenu(); 689a10cf76eSAxel Dörfler 690a10cf76eSAxel Dörfler BString string; 691a10cf76eSAxel Dörfler resolution_to_string(fSelected, string); 692a10cf76eSAxel Dörfler item = fResolutionMenu->FindItem(string.String()); 693a10cf76eSAxel Dörfler 694a10cf76eSAxel Dörfler if (item != NULL) { 695a10cf76eSAxel Dörfler if (!item->IsMarked()) 696a10cf76eSAxel Dörfler item->SetMarked(true); 697a10cf76eSAxel Dörfler } else { 698a10cf76eSAxel Dörfler // this is bad luck - if mode has been set via screen references, 699a10cf76eSAxel Dörfler // this case cannot occur; there are three possible solutions: 700a10cf76eSAxel Dörfler // 1. add a new resolution to list 701a10cf76eSAxel Dörfler // - we had to remove it as soon as a "valid" one is selected 702a10cf76eSAxel Dörfler // - we don't know which frequencies/bit depths are supported 703a10cf76eSAxel Dörfler // - as long as we haven't the GMT formula to create 704a10cf76eSAxel Dörfler // parameters for any resolution given, we cannot 705a10cf76eSAxel Dörfler // really set current mode - it's just not in the list 706a10cf76eSAxel Dörfler // 2. choose nearest resolution 707a10cf76eSAxel Dörfler // - probably a good idea, but implies coding and testing 708a10cf76eSAxel Dörfler // 3. choose lowest resolution 709a10cf76eSAxel Dörfler // - do you really think we are so lazy? yes, we are 710a10cf76eSAxel Dörfler item = fResolutionMenu->ItemAt(0); 711a10cf76eSAxel Dörfler if (item) 712a10cf76eSAxel Dörfler item->SetMarked(true); 713a10cf76eSAxel Dörfler 714a10cf76eSAxel Dörfler // okay - at least we set menu label to active resolution 715a10cf76eSAxel Dörfler fResolutionMenu->Superitem()->SetLabel(string.String()); 716a10cf76eSAxel Dörfler } 717a10cf76eSAxel Dörfler 718a10cf76eSAxel Dörfler // mark active combine mode 719a10cf76eSAxel Dörfler for (int32 i = 0; i < kCombineModeCount; i++) { 720a10cf76eSAxel Dörfler if (kCombineModes[i].mode == fSelected.combine) { 721a10cf76eSAxel Dörfler item = fCombineMenu->ItemAt(i); 722a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 723a10cf76eSAxel Dörfler item->SetMarked(true); 724a10cf76eSAxel Dörfler break; 725a10cf76eSAxel Dörfler } 726a10cf76eSAxel Dörfler } 727a10cf76eSAxel Dörfler 728a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(0); 729a10cf76eSAxel Dörfler 730a10cf76eSAxel Dörfler for (int32 i = kColorSpaceCount; i-- > 0;) { 7315de171daSAxel Dörfler if (kColorSpaces[i].space == fSelected.space 7325de171daSAxel Dörfler || (kColorSpaces[i].space == B_RGB32 7335de171daSAxel Dörfler && fSelected.space == B_RGB24)) { 734a10cf76eSAxel Dörfler item = fColorsMenu->ItemAt(i); 735a10cf76eSAxel Dörfler break; 736a10cf76eSAxel Dörfler } 737a10cf76eSAxel Dörfler } 738a10cf76eSAxel Dörfler 739a10cf76eSAxel Dörfler if (item && !item->IsMarked()) 740a10cf76eSAxel Dörfler item->SetMarked(true); 741a10cf76eSAxel Dörfler 742a10cf76eSAxel Dörfler string.Truncate(0); 7435de171daSAxel Dörfler uint32 bitsPerPixel = fSelected.BitsPerPixel(); 7445de171daSAxel Dörfler // advertize 24 bit mode as 32 bit to avoid confusion 7455de171daSAxel Dörfler if (bitsPerPixel == 24) 7465de171daSAxel Dörfler bitsPerPixel = 32; 7475de171daSAxel Dörfler 7485de171daSAxel Dörfler string << bitsPerPixel << " Bits/Pixel"; 749a10cf76eSAxel Dörfler if (string != fColorsMenu->Superitem()->Label()) 750a10cf76eSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 751a10cf76eSAxel Dörfler 7525de171daSAxel Dörfler _UpdateMonitorView(); 7535de171daSAxel Dörfler _UpdateRefreshControl(); 754a10cf76eSAxel Dörfler 7555de171daSAxel Dörfler _CheckApplyEnabled(); 756a10cf76eSAxel Dörfler } 757a10cf76eSAxel Dörfler 758a10cf76eSAxel Dörfler 75912580984SAxel Dörfler /*! Reflect active mode in chosen settings */ 760a10cf76eSAxel Dörfler void 7615de171daSAxel Dörfler ScreenWindow::_UpdateActiveMode() 762a10cf76eSAxel Dörfler { 76312580984SAxel Dörfler // Usually, this function gets called after a mode 764a10cf76eSAxel Dörfler // has been set manually; still, as the graphics driver 765a10cf76eSAxel Dörfler // is free to fiddle with mode passed, we better ask 766a10cf76eSAxel Dörfler // what kind of mode we actually got 767a10cf76eSAxel Dörfler fScreenMode.Get(fActive); 768a10cf76eSAxel Dörfler fSelected = fActive; 769a10cf76eSAxel Dörfler 7705de171daSAxel Dörfler _UpdateControls(); 771a10cf76eSAxel Dörfler } 772a10cf76eSAxel Dörfler 773a10cf76eSAxel Dörfler 774a10cf76eSAxel Dörfler void 775a10cf76eSAxel Dörfler ScreenWindow::ScreenChanged(BRect frame, color_space mode) 776a10cf76eSAxel Dörfler { 777a10cf76eSAxel Dörfler // move window on screen, if necessary 778a10cf76eSAxel Dörfler if (frame.right <= Frame().right 779a10cf76eSAxel Dörfler && frame.bottom <= Frame().bottom) { 780a10cf76eSAxel Dörfler MoveTo((frame.Width() - Frame().Width()) / 2, 781a10cf76eSAxel Dörfler (frame.Height() - Frame().Height()) / 2); 782a10cf76eSAxel Dörfler } 783a10cf76eSAxel Dörfler } 784a10cf76eSAxel Dörfler 785a10cf76eSAxel Dörfler 786a10cf76eSAxel Dörfler void 787a10cf76eSAxel Dörfler ScreenWindow::WorkspaceActivated(int32 workspace, bool state) 788a10cf76eSAxel Dörfler { 789abc649b8SWaldemar Kornewald fScreenMode.GetOriginalMode(fOriginal, workspace); 7905de171daSAxel Dörfler _UpdateActiveMode(); 791a10cf76eSAxel Dörfler 7926edaa0f6SStefano Ceccherini BMessage message(UPDATE_DESKTOP_COLOR_MSG); 7936edaa0f6SStefano Ceccherini PostMessage(&message, fMonitorView); 794a10cf76eSAxel Dörfler } 795a10cf76eSAxel Dörfler 796a10cf76eSAxel Dörfler 797a10cf76eSAxel Dörfler void 798a10cf76eSAxel Dörfler ScreenWindow::MessageReceived(BMessage* message) 799a10cf76eSAxel Dörfler { 800a10cf76eSAxel Dörfler switch (message->what) { 801a10cf76eSAxel Dörfler case WORKSPACE_CHECK_MSG: 8025de171daSAxel Dörfler _CheckApplyEnabled(); 803a10cf76eSAxel Dörfler break; 804a10cf76eSAxel Dörfler 805a10cf76eSAxel Dörfler case POP_WORKSPACE_CHANGED_MSG: 806a10cf76eSAxel Dörfler { 807abc649b8SWaldemar Kornewald // update checkpoint state 808a10cf76eSAxel Dörfler int32 index; 809abc649b8SWaldemar Kornewald if (message->FindInt32("index", &index) == B_OK) { 810a10cf76eSAxel Dörfler set_workspace_count(index + 1); 8115de171daSAxel Dörfler _CheckApplyEnabled(); 812abc649b8SWaldemar Kornewald } 813a10cf76eSAxel Dörfler break; 814a10cf76eSAxel Dörfler } 815a10cf76eSAxel Dörfler 816a10cf76eSAxel Dörfler case POP_RESOLUTION_MSG: 817a10cf76eSAxel Dörfler { 818a10cf76eSAxel Dörfler message->FindInt32("width", &fSelected.width); 819a10cf76eSAxel Dörfler message->FindInt32("height", &fSelected.height); 820a10cf76eSAxel Dörfler 8215de171daSAxel Dörfler _CheckColorMenu(); 8225de171daSAxel Dörfler _CheckRefreshMenu(); 823a10cf76eSAxel Dörfler 8245de171daSAxel Dörfler _UpdateMonitorView(); 8255de171daSAxel Dörfler _UpdateRefreshControl(); 826a10cf76eSAxel Dörfler 8275de171daSAxel Dörfler _CheckApplyEnabled(); 828a10cf76eSAxel Dörfler break; 829a10cf76eSAxel Dörfler } 830a10cf76eSAxel Dörfler 831a10cf76eSAxel Dörfler case POP_COLORS_MSG: 832a10cf76eSAxel Dörfler { 833a10cf76eSAxel Dörfler message->FindInt32("space", (int32 *)&fSelected.space); 834a10cf76eSAxel Dörfler 835a10cf76eSAxel Dörfler BString string; 836a10cf76eSAxel Dörfler string << fSelected.BitsPerPixel() << " Bits/Pixel"; 837a10cf76eSAxel Dörfler fColorsMenu->Superitem()->SetLabel(string.String()); 838a10cf76eSAxel Dörfler 8395de171daSAxel Dörfler _CheckApplyEnabled(); 840a10cf76eSAxel Dörfler break; 841a10cf76eSAxel Dörfler } 842a10cf76eSAxel Dörfler 843a10cf76eSAxel Dörfler case POP_REFRESH_MSG: 844a40498e2SWaldemar Kornewald { 845a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 846a10cf76eSAxel Dörfler fOtherRefresh->SetLabel("Other" B_UTF8_ELLIPSIS); 847a10cf76eSAxel Dörfler // revert "Other…" label - it might have had a refresh rate prefix 848a10cf76eSAxel Dörfler 8495de171daSAxel Dörfler _CheckApplyEnabled(); 850a10cf76eSAxel Dörfler break; 851a40498e2SWaldemar Kornewald } 852a10cf76eSAxel Dörfler 853a10cf76eSAxel Dörfler case POP_OTHER_REFRESH_MSG: 854a10cf76eSAxel Dörfler { 85529e8a73aSAxel Dörfler // make sure menu shows something useful 8565de171daSAxel Dörfler _UpdateRefreshControl(); 857a10cf76eSAxel Dörfler 85829e8a73aSAxel Dörfler float min = 0, max = 999; 85929e8a73aSAxel Dörfler fScreenMode.GetRefreshLimits(fSelected, min, max); 86029e8a73aSAxel Dörfler if (min < gMinRefresh) 86129e8a73aSAxel Dörfler min = gMinRefresh; 86229e8a73aSAxel Dörfler if (max > gMaxRefresh) 86329e8a73aSAxel Dörfler max = gMaxRefresh; 86429e8a73aSAxel Dörfler 865c5d10f7aSAxel Dörfler RefreshWindow *fRefreshWindow = new RefreshWindow( 866c5d10f7aSAxel Dörfler fRefreshField->ConvertToScreen(B_ORIGIN), fSelected.refresh, min, max); 867a10cf76eSAxel Dörfler fRefreshWindow->Show(); 868a10cf76eSAxel Dörfler break; 869a10cf76eSAxel Dörfler } 870a10cf76eSAxel Dörfler 871a10cf76eSAxel Dörfler case SET_CUSTOM_REFRESH_MSG: 872a10cf76eSAxel Dörfler { 873a10cf76eSAxel Dörfler // user pressed "done" in "Other…" refresh dialog; 874a10cf76eSAxel Dörfler // select the refresh rate chosen 875a10cf76eSAxel Dörfler message->FindFloat("refresh", &fSelected.refresh); 876a10cf76eSAxel Dörfler 8775de171daSAxel Dörfler _UpdateRefreshControl(); 8785de171daSAxel Dörfler _CheckApplyEnabled(); 879a10cf76eSAxel Dörfler break; 880a10cf76eSAxel Dörfler } 881a10cf76eSAxel Dörfler 882a10cf76eSAxel Dörfler case POP_COMBINE_DISPLAYS_MSG: 883a10cf76eSAxel Dörfler { 884a10cf76eSAxel Dörfler // new combine mode has bee chosen 885a10cf76eSAxel Dörfler int32 mode; 886a10cf76eSAxel Dörfler if (message->FindInt32("mode", &mode) == B_OK) 887a10cf76eSAxel Dörfler fSelected.combine = (combine_mode)mode; 888a10cf76eSAxel Dörfler 8895de171daSAxel Dörfler _CheckResolutionMenu(); 8905de171daSAxel Dörfler _CheckApplyEnabled(); 891a10cf76eSAxel Dörfler break; 892a10cf76eSAxel Dörfler } 893a10cf76eSAxel Dörfler 894a10cf76eSAxel Dörfler case POP_SWAP_DISPLAYS_MSG: 895a10cf76eSAxel Dörfler message->FindBool("swap", &fSelected.swap_displays); 8965de171daSAxel Dörfler _CheckApplyEnabled(); 897a10cf76eSAxel Dörfler break; 898a10cf76eSAxel Dörfler 899a10cf76eSAxel Dörfler case POP_USE_LAPTOP_PANEL_MSG: 900a10cf76eSAxel Dörfler message->FindBool("use", &fSelected.use_laptop_panel); 9015de171daSAxel Dörfler _CheckApplyEnabled(); 902a10cf76eSAxel Dörfler break; 903a10cf76eSAxel Dörfler 904a10cf76eSAxel Dörfler case POP_TV_STANDARD_MSG: 905a10cf76eSAxel Dörfler message->FindInt32("tv_standard", (int32 *)&fSelected.tv_standard); 9065de171daSAxel Dörfler _CheckApplyEnabled(); 907a10cf76eSAxel Dörfler break; 908a10cf76eSAxel Dörfler 909df3f5bacSStephan Aßmus case BUTTON_LAUNCH_BACKGROUNDS_MSG: 9106f095d6aSRyan Leavengood if (be_roster->Launch(kBackgroundsSignature) == B_ALREADY_RUNNING) { 9116f095d6aSRyan Leavengood app_info info; 9126f095d6aSRyan Leavengood be_roster->GetAppInfo(kBackgroundsSignature, &info); 9136f095d6aSRyan Leavengood be_roster->ActivateApp(info.team); 9146f095d6aSRyan Leavengood } 915df3f5bacSStephan Aßmus break; 916df3f5bacSStephan Aßmus 917a10cf76eSAxel Dörfler case BUTTON_DEFAULTS_MSG: 918a10cf76eSAxel Dörfler { 9194be51fe3SWaldemar Kornewald // TODO: get preferred settings of screen 920a10cf76eSAxel Dörfler fSelected.width = 640; 921a10cf76eSAxel Dörfler fSelected.height = 480; 922a10cf76eSAxel Dörfler fSelected.space = B_CMAP8; 923a10cf76eSAxel Dörfler fSelected.refresh = 60.0; 924a10cf76eSAxel Dörfler fSelected.combine = kCombineDisable; 925a10cf76eSAxel Dörfler fSelected.swap_displays = false; 926a10cf76eSAxel Dörfler fSelected.use_laptop_panel = false; 927a10cf76eSAxel Dörfler fSelected.tv_standard = 0; 928a10cf76eSAxel Dörfler 929abc649b8SWaldemar Kornewald BMenuItem *item; 930abc649b8SWaldemar Kornewald item = fWorkspaceCountField->Menu()->ItemAt(3); 931abc649b8SWaldemar Kornewald if (item != NULL) 932abc649b8SWaldemar Kornewald item->SetMarked(true); 933abc649b8SWaldemar Kornewald 9345de171daSAxel Dörfler _UpdateControls(); 935a10cf76eSAxel Dörfler break; 936a10cf76eSAxel Dörfler } 937a10cf76eSAxel Dörfler 93810e9b12fSWaldemar Kornewald case BUTTON_UNDO_MSG: 939abc649b8SWaldemar Kornewald fTempScreenMode.Revert(); 9405de171daSAxel Dörfler _UpdateActiveMode(); 941abc649b8SWaldemar Kornewald break; 942abc649b8SWaldemar Kornewald 943abc649b8SWaldemar Kornewald case BUTTON_REVERT_MSG: 944abc649b8SWaldemar Kornewald { 945abc649b8SWaldemar Kornewald fModified = false; 946199893c3SAxel Dörfler fBootWorkspaceApplied = false; 947abc649b8SWaldemar Kornewald BMenuItem *item; 948abc649b8SWaldemar Kornewald item = fWorkspaceCountField->Menu()->ItemAt(fOriginalWorkspaceCount - 1); 949abc649b8SWaldemar Kornewald if (item != NULL) 950abc649b8SWaldemar Kornewald item->SetMarked(true); 951abc649b8SWaldemar Kornewald 952abc649b8SWaldemar Kornewald // ScreenMode::Revert() assumes that we first set the correct number 953abc649b8SWaldemar Kornewald // of workspaces 954abc649b8SWaldemar Kornewald set_workspace_count(fOriginalWorkspaceCount); 955a10cf76eSAxel Dörfler fScreenMode.Revert(); 9565de171daSAxel Dörfler _UpdateActiveMode(); 957a10cf76eSAxel Dörfler break; 958abc649b8SWaldemar Kornewald } 959a10cf76eSAxel Dörfler 960a10cf76eSAxel Dörfler case BUTTON_APPLY_MSG: 9615de171daSAxel Dörfler _Apply(); 962a10cf76eSAxel Dörfler break; 963a10cf76eSAxel Dörfler 964abc649b8SWaldemar Kornewald case MAKE_INITIAL_MSG: 965abc649b8SWaldemar Kornewald // user pressed "keep" in confirmation dialog 966abc649b8SWaldemar Kornewald fModified = true; 9675de171daSAxel Dörfler _UpdateActiveMode(); 968a10cf76eSAxel Dörfler break; 969a10cf76eSAxel Dörfler 970a10cf76eSAxel Dörfler default: 971a10cf76eSAxel Dörfler BWindow::MessageReceived(message); 972a10cf76eSAxel Dörfler break; 973a10cf76eSAxel Dörfler } 974a10cf76eSAxel Dörfler } 975a10cf76eSAxel Dörfler 976a10cf76eSAxel Dörfler 97712580984SAxel Dörfler status_t 97812580984SAxel Dörfler ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const 97912580984SAxel Dörfler { 98012580984SAxel Dörfler BPath path; 98112580984SAxel Dörfler status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true); 98212580984SAxel Dörfler if (status < B_OK) 98312580984SAxel Dörfler return status; 98412580984SAxel Dörfler 98512580984SAxel Dörfler path.Append("kernel/drivers"); 98612580984SAxel Dörfler status = create_directory(path.Path(), 0755); 98712580984SAxel Dörfler if (status < B_OK) 98812580984SAxel Dörfler return status; 98912580984SAxel Dörfler 99012580984SAxel Dörfler path.Append("vesa"); 99112580984SAxel Dörfler BFile file; 99212580984SAxel Dörfler status = file.SetTo(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE); 99312580984SAxel Dörfler if (status < B_OK) 99412580984SAxel Dörfler return status; 99512580984SAxel Dörfler 99612580984SAxel Dörfler char buffer[256]; 99712580984SAxel Dörfler snprintf(buffer, sizeof(buffer), "mode %ld %ld %ld\n", 99812580984SAxel Dörfler mode.width, mode.height, mode.BitsPerPixel()); 99912580984SAxel Dörfler 100012580984SAxel Dörfler ssize_t bytesWritten = file.Write(buffer, strlen(buffer)); 100112580984SAxel Dörfler if (bytesWritten < B_OK) 100212580984SAxel Dörfler return bytesWritten; 100312580984SAxel Dörfler 100412580984SAxel Dörfler return B_OK; 100512580984SAxel Dörfler } 100612580984SAxel Dörfler 100712580984SAxel Dörfler 1008a10cf76eSAxel Dörfler void 10095de171daSAxel Dörfler ScreenWindow::_CheckApplyEnabled() 1010a10cf76eSAxel Dörfler { 1011b72c4836SAlexandre Deckner fApplyButton->SetEnabled(fSelected != fActive); 10125de171daSAxel Dörfler fRevertButton->SetEnabled(count_workspaces() != fOriginalWorkspaceCount 10135de171daSAxel Dörfler || fSelected != fOriginal); 1014a10cf76eSAxel Dörfler } 1015a10cf76eSAxel Dörfler 1016a10cf76eSAxel Dörfler 1017a10cf76eSAxel Dörfler void 10185de171daSAxel Dörfler ScreenWindow::_UpdateOriginal() 1019abc649b8SWaldemar Kornewald { 1020abc649b8SWaldemar Kornewald fOriginalWorkspaceCount = count_workspaces(); 1021abc649b8SWaldemar Kornewald fScreenMode.Get(fOriginal); 1022abc649b8SWaldemar Kornewald fScreenMode.UpdateOriginalModes(); 1023abc649b8SWaldemar Kornewald } 1024abc649b8SWaldemar Kornewald 1025abc649b8SWaldemar Kornewald 1026abc649b8SWaldemar Kornewald void 10275de171daSAxel Dörfler ScreenWindow::_Apply() 1028a10cf76eSAxel Dörfler { 1029abc649b8SWaldemar Kornewald // make checkpoint, so we can undo these changes 1030abc649b8SWaldemar Kornewald fTempScreenMode.UpdateOriginalModes(); 103107184a9eSAxel Dörfler status_t status = fScreenMode.Set(fSelected); 103207184a9eSAxel Dörfler if (status == B_OK) { 1033abc649b8SWaldemar Kornewald // use the mode that has eventually been set and 1034abc649b8SWaldemar Kornewald // thus we know to be working; it can differ from 1035abc649b8SWaldemar Kornewald // the mode selected by user due to hardware limitation 1036abc649b8SWaldemar Kornewald display_mode newMode; 1037abc649b8SWaldemar Kornewald BScreen screen(this); 1038abc649b8SWaldemar Kornewald screen.GetMode(&newMode); 1039abc649b8SWaldemar Kornewald 1040abc649b8SWaldemar Kornewald if (fAllWorkspacesItem->IsMarked()) { 1041abc649b8SWaldemar Kornewald int32 originatingWorkspace = current_workspace(); 1042abc649b8SWaldemar Kornewald for (int32 i = 0; i < count_workspaces(); i++) { 1043abc649b8SWaldemar Kornewald if (i != originatingWorkspace) 1044abc649b8SWaldemar Kornewald screen.SetMode(i, &newMode, true); 1045abc649b8SWaldemar Kornewald } 1046199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1047199893c3SAxel Dörfler } else { 1048199893c3SAxel Dörfler if (current_workspace() == 0) 1049199893c3SAxel Dörfler fBootWorkspaceApplied = true; 1050abc649b8SWaldemar Kornewald } 1051abc649b8SWaldemar Kornewald 1052a10cf76eSAxel Dörfler fActive = fSelected; 1053a10cf76eSAxel Dörfler 1054abc649b8SWaldemar Kornewald // TODO: only show alert when this is an unknown mode 1055a10cf76eSAxel Dörfler BWindow* window = new AlertWindow(this); 1056a10cf76eSAxel Dörfler window->Show(); 105707184a9eSAxel Dörfler } else { 105807184a9eSAxel Dörfler char message[256]; 105907184a9eSAxel Dörfler snprintf(message, sizeof(message), 106007184a9eSAxel Dörfler "The screen mode could not be set:\n\t%s\n", screen_errors(status)); 106107184a9eSAxel Dörfler BAlert* alert = new BAlert("Screen Alert", message, "Okay", NULL, NULL, 106207184a9eSAxel Dörfler B_WIDTH_AS_USUAL, B_WARNING_ALERT); 106307184a9eSAxel Dörfler alert->Go(); 1064a10cf76eSAxel Dörfler } 106507184a9eSAxel Dörfler } 106607184a9eSAxel Dörfler 1067df3f5bacSStephan Aßmus 1068df3f5bacSStephan Aßmus void 10695de171daSAxel Dörfler ScreenWindow::_LayoutControls(uint32 flags) 1070df3f5bacSStephan Aßmus { 1071df3f5bacSStephan Aßmus // layout the screen box and its controls 1072df3f5bacSStephan Aßmus fWorkspaceCountField->ResizeToPreferred(); 1073df3f5bacSStephan Aßmus 1074df3f5bacSStephan Aßmus float monitorViewHeight = fMonitorView->Bounds().Height(); 1075df3f5bacSStephan Aßmus float workspaceFieldHeight = fWorkspaceCountField->Bounds().Height(); 1076df3f5bacSStephan Aßmus float backgroundsButtonHeight = fBackgroundsButton->Bounds().Height(); 1077df3f5bacSStephan Aßmus 1078df3f5bacSStephan Aßmus float screenBoxWidth = fWorkspaceCountField->Bounds().Width() + 20.0; 10795de171daSAxel Dörfler float screenBoxHeight = monitorViewHeight + 5.0 + workspaceFieldHeight + 5.0 10805de171daSAxel Dörfler + backgroundsButtonHeight + 20.0; 1081df3f5bacSStephan Aßmus 108229e8a73aSAxel Dörfler #ifdef __HAIKU__ 1083df3f5bacSStephan Aßmus fScreenBox->MoveTo(10.0, 10.0 + fControlsBox->TopBorderOffset()); 108429e8a73aSAxel Dörfler #else 108529e8a73aSAxel Dörfler fScreenBox->MoveTo(10.0, 10.0 + 3); 108629e8a73aSAxel Dörfler #endif 1087df3f5bacSStephan Aßmus fScreenBox->ResizeTo(screenBoxWidth, screenBoxHeight); 1088df3f5bacSStephan Aßmus 1089df3f5bacSStephan Aßmus float leftOffset = 10.0; 1090df3f5bacSStephan Aßmus float topOffset = 10.0; 1091df3f5bacSStephan Aßmus fMonitorView->MoveTo(leftOffset, topOffset); 1092df3f5bacSStephan Aßmus fMonitorView->ResizeTo(screenBoxWidth - 20.0, monitorViewHeight); 1093df3f5bacSStephan Aßmus fMonitorView->SetResizingMode(B_FOLLOW_ALL); 1094df3f5bacSStephan Aßmus topOffset += monitorViewHeight + 5.0; 1095df3f5bacSStephan Aßmus 1096df3f5bacSStephan Aßmus fWorkspaceCountField->MoveTo(leftOffset, topOffset); 1097df3f5bacSStephan Aßmus fWorkspaceCountField->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 1098df3f5bacSStephan Aßmus topOffset += workspaceFieldHeight + 5.0; 1099df3f5bacSStephan Aßmus 1100df3f5bacSStephan Aßmus fBackgroundsButton->MoveTo(leftOffset, topOffset); 1101df3f5bacSStephan Aßmus fBackgroundsButton->ResizeTo(screenBoxWidth - 20.0, backgroundsButtonHeight); 1102df3f5bacSStephan Aßmus fBackgroundsButton->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 1103df3f5bacSStephan Aßmus 1104df3f5bacSStephan Aßmus fControlsBox->MoveTo(fScreenBox->Frame().right + 10.0, 10.0); 1105df3f5bacSStephan Aßmus 1106df3f5bacSStephan Aßmus // layout the right side 11074008594dSWaldemar Kornewald fApplyButton->ResizeToPreferred(); 11085de171daSAxel Dörfler BRect controlsRect = _LayoutMenuFields(flags); 1109df3f5bacSStephan Aßmus controlsRect.InsetBy(-10.0, -10.0); 11104008594dSWaldemar Kornewald controlsRect.bottom += 8 + fApplyButton->Bounds().Height(); 1111df3f5bacSStephan Aßmus // adjust size of controls box and move aligned buttons along 1112df3f5bacSStephan Aßmus float xDiff = controlsRect.right - fControlsBox->Bounds().right; 1113df3f5bacSStephan Aßmus float yDiff = controlsRect.bottom - fControlsBox->Bounds().bottom; 1114df3f5bacSStephan Aßmus if (yDiff < 0.0) { 1115df3f5bacSStephan Aßmus // don't shrink vertically 1116df3f5bacSStephan Aßmus yDiff = 0.0; 1117df3f5bacSStephan Aßmus } 1118df3f5bacSStephan Aßmus 1119df3f5bacSStephan Aßmus fControlsBox->ResizeBy(xDiff, yDiff); 1120df3f5bacSStephan Aßmus 1121df3f5bacSStephan Aßmus // align bottom of boxen 1122df3f5bacSStephan Aßmus float boxBottomDiff = fControlsBox->Frame().bottom - fScreenBox->Frame().bottom; 1123df3f5bacSStephan Aßmus if (boxBottomDiff > 0) 1124df3f5bacSStephan Aßmus fScreenBox->ResizeBy(0.0, boxBottomDiff); 1125df3f5bacSStephan Aßmus else 1126df3f5bacSStephan Aßmus fControlsBox->ResizeBy(0.0, -boxBottomDiff); 1127df3f5bacSStephan Aßmus 1128df3f5bacSStephan Aßmus BRect boxFrame = fScreenBox->Frame() | fControlsBox->Frame(); 1129df3f5bacSStephan Aßmus 1130df3f5bacSStephan Aßmus // layout rest of buttons 1131abc649b8SWaldemar Kornewald // TODO: we don't support getting the screen's preferred settings 1132abc649b8SWaldemar Kornewald // fDefaultsButton->ResizeToPreferred(); 1133abc649b8SWaldemar Kornewald // fDefaultsButton->MoveTo(boxFrame.left, boxFrame.bottom + 8); 1134df3f5bacSStephan Aßmus 1135df3f5bacSStephan Aßmus fRevertButton->ResizeToPreferred(); 1136abc649b8SWaldemar Kornewald fRevertButton->MoveTo(boxFrame.left, boxFrame.bottom + 8); 1137abc649b8SWaldemar Kornewald // fRevertButton->MoveTo(fDefaultsButton->Frame().right + 10, 1138abc649b8SWaldemar Kornewald // fDefaultsButton->Frame().top); 1139df3f5bacSStephan Aßmus 11404008594dSWaldemar Kornewald // Apply button was already resized above 1141abc649b8SWaldemar Kornewald float resolutionFieldRight = fResolutionField->Frame().right; 1142abc649b8SWaldemar Kornewald fApplyButton->MoveTo(resolutionFieldRight - fApplyButton->Bounds().Width(), 11434008594dSWaldemar Kornewald fControlsBox->Bounds().bottom - fApplyButton->Bounds().Height() - 10); 1144df3f5bacSStephan Aßmus 1145abc649b8SWaldemar Kornewald ResizeTo(boxFrame.right + 10, fRevertButton->Frame().bottom + 10); 1146df3f5bacSStephan Aßmus } 1147df3f5bacSStephan Aßmus 1148df3f5bacSStephan Aßmus 1149df3f5bacSStephan Aßmus BRect 11505de171daSAxel Dörfler ScreenWindow::_LayoutMenuFields(uint32 flags, bool sideBySide) 1151df3f5bacSStephan Aßmus { 1152df3f5bacSStephan Aßmus BList menuFields; 1153df3f5bacSStephan Aßmus menuFields.AddItem((void*)fResolutionField); 1154df3f5bacSStephan Aßmus menuFields.AddItem((void*)fColorsField); 1155df3f5bacSStephan Aßmus menuFields.AddItem((void*)fRefreshField); 1156df3f5bacSStephan Aßmus 1157df3f5bacSStephan Aßmus BRect frame; 1158df3f5bacSStephan Aßmus 1159df3f5bacSStephan Aßmus if (sideBySide) 1160df3f5bacSStephan Aßmus frame = stack_and_align_menu_fields(menuFields); 1161df3f5bacSStephan Aßmus 1162df3f5bacSStephan Aßmus if (sideBySide) 1163df3f5bacSStephan Aßmus menuFields.MakeEmpty(); 1164df3f5bacSStephan Aßmus 1165df3f5bacSStephan Aßmus if (flags & SHOW_COMBINE_FIELD) 1166df3f5bacSStephan Aßmus menuFields.AddItem((void*)fCombineField); 1167df3f5bacSStephan Aßmus if (flags & SHOW_SWAP_FIELD) 1168df3f5bacSStephan Aßmus menuFields.AddItem((void*)fSwapDisplaysField); 1169df3f5bacSStephan Aßmus if (flags & SHOW_LAPTOP_PANEL_FIELD) 1170df3f5bacSStephan Aßmus menuFields.AddItem((void*)fUseLaptopPanelField); 1171df3f5bacSStephan Aßmus if (flags & SHOW_TV_STANDARD_FIELD) 1172df3f5bacSStephan Aßmus menuFields.AddItem((void*)fTVStandardField); 1173df3f5bacSStephan Aßmus 1174df3f5bacSStephan Aßmus if (sideBySide) { 1175df3f5bacSStephan Aßmus if (menuFields.CountItems() > 0) { 1176df3f5bacSStephan Aßmus ((BMenuField*)menuFields.FirstItem())->MoveTo(frame.right + 8.0, frame.top); 1177df3f5bacSStephan Aßmus frame = frame | stack_and_align_menu_fields(menuFields); 1178df3f5bacSStephan Aßmus } 1179df3f5bacSStephan Aßmus } else { 1180df3f5bacSStephan Aßmus frame = stack_and_align_menu_fields(menuFields); 1181df3f5bacSStephan Aßmus } 1182df3f5bacSStephan Aßmus 1183df3f5bacSStephan Aßmus return frame; 1184df3f5bacSStephan Aßmus } 1185df3f5bacSStephan Aßmus 1186