00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #define GETTEXT_DOMAIN "wesnoth-lib"
00017
00018
00019
00020
00021
00022
00023 #include "global.hpp"
00024 #include "preferences_display.hpp"
00025
00026 #include "construct_dialog.hpp"
00027 #include "display.hpp"
00028 #include "foreach.hpp"
00029 #include "formatter.hpp"
00030 #include "game_preferences.hpp"
00031 #include "gettext.hpp"
00032 #include "gui/dialogs/message.hpp"
00033 #include "gui/dialogs/simple_item_selector.hpp"
00034 #include "gui/dialogs/transient_message.hpp"
00035 #include "gui/widgets/window.hpp"
00036 #include "hotkeys.hpp"
00037 #include "log.hpp"
00038 #include "marked-up_text.hpp"
00039 #include "wml_separators.hpp"
00040
00041 namespace preferences {
00042
00043 display* disp = NULL;
00044
00045 display_manager::display_manager(display* d)
00046 {
00047 disp = d;
00048
00049 load_hotkeys();
00050
00051 set_grid(grid());
00052 set_turbo(turbo());
00053 set_turbo_speed(turbo_speed());
00054 set_fullscreen(fullscreen());
00055 set_scroll_to_action(scroll_to_action());
00056 set_color_cursors(preferences::get("color_cursors", false));
00057 }
00058
00059 display_manager::~display_manager()
00060 {
00061 disp = NULL;
00062 }
00063
00064 bool detect_video_settings(CVideo& video, std::pair<int,int>& resolution, int& bpp, int& video_flags)
00065 {
00066 video_flags = fullscreen() ? FULL_SCREEN : 0;
00067 resolution = preferences::resolution();
00068
00069 int DefaultBPP = 24;
00070 const SDL_VideoInfo* const video_info = SDL_GetVideoInfo();
00071 if(video_info != NULL && video_info->vfmt != NULL) {
00072 DefaultBPP = video_info->vfmt->BitsPerPixel;
00073 }
00074
00075 std::cerr << "Checking video mode: " << resolution.first << 'x'
00076 << resolution.second << 'x' << DefaultBPP << "...\n";
00077
00078 typedef std::pair<int, int> res_t;
00079 std::vector<res_t> res_list;
00080 res_list.push_back(res_t(1024, 768));
00081 res_list.push_back(res_t(1024, 600));
00082 res_list.push_back(res_t(800, 600));
00083 res_list.push_back(res_t(800, 480));
00084
00085 bpp = video.modePossible(resolution.first, resolution.second,
00086 DefaultBPP, video_flags, true);
00087
00088 foreach (const res_t &res, res_list)
00089 {
00090 if (bpp != 0) break;
00091 std::cerr << "Video mode " << resolution.first << 'x'
00092 << resolution.second << 'x' << DefaultBPP
00093 << " is not supported; attempting " << res.first
00094 << 'x' << res.second << 'x' << DefaultBPP << "...\n";
00095 resolution = res;
00096 bpp = video.modePossible(resolution.first, resolution.second,
00097 DefaultBPP, video_flags);
00098 }
00099
00100 return bpp != 0;
00101 }
00102
00103 void set_fullscreen(CVideo& video, const bool ison)
00104 {
00105 _set_fullscreen(ison);
00106
00107 const std::pair<int,int>& res = resolution();
00108 if(video.isFullScreen() != ison) {
00109 const int flags = ison ? FULL_SCREEN : 0;
00110 int bpp = video.bppForMode(res.first, res.second, flags);
00111
00112 if(bpp > 0) {
00113 video.setMode(res.first,res.second,bpp,flags);
00114 if(disp) {
00115 disp->redraw_everything();
00116 }
00117 } else {
00118 int tmp_flags = flags;
00119 std::pair<int,int> tmp_res;
00120 if(detect_video_settings(video, tmp_res, bpp, tmp_flags)) {
00121 set_resolution(video, tmp_res.first, tmp_res.second);
00122
00123 } else if(video.modePossible(1024,768,16,flags)) {
00124 set_resolution(video, 1024, 768);
00125 } else {
00126 gui2::show_transient_message(video,"",_("The video mode could not be changed. Your window manager must be set to 16 bits per pixel to run the game in windowed mode. Your display must support 1024x768x16 to run the game full screen."));
00127 }
00128
00129 set_color_cursors(preferences::get("color_cursors", false));
00130 }
00131 }
00132 }
00133
00134 void set_fullscreen(bool ison)
00135 {
00136 _set_fullscreen(ison);
00137
00138 if(disp != NULL) {
00139 set_fullscreen(disp->video(), ison);
00140 }
00141 }
00142
00143 void set_scroll_to_action(bool ison)
00144 {
00145 _set_scroll_to_action(ison);
00146 }
00147 void set_resolution(const std::pair<int,int>& resolution)
00148 {
00149 if(disp) {
00150 set_resolution(disp->video(), resolution.first, resolution.second);
00151 } else {
00152
00153 const std::string postfix = fullscreen() ? "resolution" : "windowsize";
00154 preferences::set(
00155 'x' + postfix, lexical_cast<std::string>(resolution.first));
00156 preferences::set(
00157 'y' + postfix, lexical_cast<std::string>(resolution.second));
00158 }
00159 }
00160
00161 bool set_resolution(CVideo& video
00162 , const unsigned width, const unsigned height)
00163 {
00164 SDL_Rect rect;
00165 SDL_GetClipRect(video.getSurface(), &rect);
00166 if(rect.w == width && rect.h == height) {
00167 return true;
00168 }
00169
00170 const int flags = fullscreen() ? FULL_SCREEN : 0;
00171 int bpp = video.bppForMode(width, height, flags);
00172
00173 if(bpp != 0) {
00174 video.setMode(width, height, bpp, flags);
00175
00176 if(disp) {
00177 disp->redraw_everything();
00178 }
00179
00180 } else {
00181
00182 gui2::show_transient_message(video,"",_("The video mode could not be changed. Your window manager must be set to 16 bits per pixel to run the game in windowed mode. Your display must support 1024x768x16 to run the game full screen."));
00183 return false;
00184 }
00185
00186 const std::string postfix = fullscreen() ? "resolution" : "windowsize";
00187 preferences::set('x' + postfix, lexical_cast<std::string>(width));
00188 preferences::set('y' + postfix, lexical_cast<std::string>(height));
00189
00190 return true;
00191 }
00192
00193 void set_turbo(bool ison)
00194 {
00195 _set_turbo(ison);
00196
00197 if(disp != NULL) {
00198 disp->set_turbo(ison);
00199 }
00200 }
00201
00202 void set_turbo_speed(double speed)
00203 {
00204 save_turbo_speed(speed);
00205
00206 if(disp != NULL) {
00207 disp->set_turbo_speed(speed);
00208 }
00209 }
00210
00211 void set_ellipses(bool ison)
00212 {
00213 _set_ellipses(ison);
00214 }
00215
00216 void set_grid(bool ison)
00217 {
00218 _set_grid(ison);
00219
00220 if(disp != NULL) {
00221 disp->set_grid(ison);
00222 }
00223 }
00224
00225 void set_color_cursors(bool value)
00226 {
00227 _set_color_cursors(value);
00228
00229 cursor::set();
00230 }
00231
00232 void set_idle_anim(bool ison) {
00233 _set_idle_anim(ison);
00234 if(disp != NULL) {
00235 disp->set_idle_anim(ison);
00236 }
00237 }
00238
00239 void set_idle_anim_rate(int rate) {
00240 _set_idle_anim_rate(rate);
00241 if(disp != NULL) {
00242 disp->set_idle_anim_rate(rate);
00243 }
00244 }
00245
00246 namespace {
00247 class escape_handler : public events::handler {
00248 public:
00249 escape_handler() : escape_pressed_(false) {}
00250 bool escape_pressed() const { return escape_pressed_; }
00251 void handle_event(const SDL_Event &event) { escape_pressed_ |= (event.type == SDL_KEYDOWN)
00252 && (reinterpret_cast<const SDL_KeyboardEvent&>(event).keysym.sym == SDLK_ESCAPE); }
00253 private:
00254 bool escape_pressed_;
00255 };
00256
00257 void repopulate_hotkeys_menu(std::vector<std::string>& menu_items)
00258 {
00259 menu_items.clear();;
00260
00261 std::vector<hotkey::hotkey_item>& hotkeys = hotkey::get_hotkeys();
00262
00263 foreach(const hotkey::hotkey_item& hi, hotkeys) {
00264 if(hi.hidden() || !hi.is_in_active_scope())
00265 continue;
00266
00267 menu_items.push_back((formatter() << hi.get_description() << COLUMN_SEPARATOR << font::NULL_MARKUP << hi.get_name()).str());
00268 }
00269
00270 menu_items.push_back((formatter() << HEADING_PREFIX << _("Action") << COLUMN_SEPARATOR << _("Binding")).str());
00271 }
00272
00273 }
00274
00275 #ifdef _MSC_VER
00276 #pragma warning (push)
00277 #pragma warning (disable:4701)
00278 #endif
00279 void show_hotkeys_dialog(display & disp)
00280 {
00281 log_scope ("show_hotkeys_dialog");
00282
00283 const events::event_context dialog_events_context;
00284
00285 const int centerx = disp.w()/2;
00286 const int centery = disp.h()/2;
00287 const int width = 700;
00288 const int height = disp.video().gety() < 600 ? 380 : 500;
00289 const int xpos = centerx - width/2;
00290 const int ypos = centery - height/2;
00291
00292 gui::button close_button (disp.video(), _("Close"));
00293 std::vector<gui::button*> buttons;
00294 buttons.push_back(&close_button);
00295
00296 gui::dialog_frame f(disp.video(),_("Hotkey Settings"),gui::dialog_frame::default_style,true,&buttons);
00297 f.layout(xpos,ypos,width,height);
00298 f.draw();
00299
00300 SDL_Rect clip_rect = create_rect(0, 0, disp.w (), disp.h ());
00301 SDL_Rect text_size = font::draw_text(NULL, clip_rect, font::SIZE_LARGE,
00302 font::NORMAL_COLOR,_("Press desired hotkey (Esc cancels)"),
00303 0, 0);
00304
00305 gui::menu::basic_sorter sorter;
00306 sorter.set_alpha_sort(0).set_alpha_sort(1);
00307
00308 std::vector<std::string> menu_items;
00309 repopulate_hotkeys_menu(menu_items);
00310
00311 gui::menu menu_(disp.video(), menu_items, false, height - font::relative_size(10), -1, &sorter, &gui::menu::bluebg_style);
00312 menu_.sort_by(0);
00313 menu_.reset_selection();
00314 menu_.set_width(font::relative_size(500));
00315 menu_.set_location(xpos + font::relative_size(10), ypos + font::relative_size(10));
00316
00317 gui::button change_button(disp.video(), _("Change Hotkey"));
00318 change_button.set_location(xpos + width - change_button.width () - font::relative_size(30), ypos + font::relative_size(30));
00319
00320 gui::button clear_button(disp.video(), _("Clear Hotkey"));
00321 clear_button.set_location(xpos + width - clear_button.width () - font::relative_size(30), ypos + font::relative_size(60));
00322
00323 gui::button reset_button(disp.video(), _("Reset All"));
00324 reset_button.set_location(xpos + width - reset_button.width() - font::relative_size(30), ypos + font::relative_size(90));
00325
00326 escape_handler esc_hand;
00327
00328 for(;;) {
00329
00330 if (close_button.pressed() || esc_hand.escape_pressed())
00331 {
00332 save_hotkeys();
00333 break;
00334 }
00335
00336 if (change_button.pressed () || menu_.double_clicked()) {
00337
00338 SDL_Rect dlgr = create_rect(centerx - text_size.w / 2 - 30
00339 , centery - text_size.h / 2 - 16
00340 , text_size.w + 60
00341 , text_size.h + 32);
00342
00343 surface_restorer restorer(&disp.video(),dlgr);
00344 gui::dialog_frame mini_frame(disp.video());
00345 mini_frame.layout(centerx-text_size.w/2 - 20,
00346 centery-text_size.h/2 - 6,
00347 text_size.w+40,
00348 text_size.h+12);
00349 mini_frame.draw_background();
00350 mini_frame.draw_border();
00351 font::draw_text (&disp.video(), clip_rect, font::SIZE_LARGE,font::NORMAL_COLOR,
00352 _("Press desired hotkey (Esc cancels)"),centerx-text_size.w/2,
00353 centery-text_size.h/2);
00354 disp.update_display();
00355 SDL_Event event;
00356 event.type = 0;
00357 int character = 0, keycode = 0, mod = 0;
00358 int joystick = 0, button = 0, hat = 0, value = 0;
00359 const int any_mod = KMOD_CTRL | KMOD_ALT | KMOD_LMETA;
00360
00361 while (event.type!=SDL_KEYDOWN && event.type!=SDL_JOYBUTTONDOWN && event.type!= SDL_JOYHATMOTION) SDL_PollEvent(&event);
00362 do {
00363 if (event.type==SDL_KEYDOWN)
00364 {
00365 keycode=event.key.keysym.sym;
00366 character=event.key.keysym.unicode;
00367 mod=event.key.keysym.mod;
00368 };
00369 if (event.type==SDL_JOYBUTTONDOWN) {
00370 joystick = event.jbutton.which;
00371 button = event.jbutton.button;
00372 }
00373 if (event.type==SDL_JOYHATMOTION) {
00374 joystick = event.jhat.which;
00375 hat = event.jhat.hat;
00376 value = event.jhat.value;
00377 }
00378 SDL_PollEvent(&event);
00379 disp.flip();
00380 disp.delay(10);
00381 } while (event.type!=SDL_KEYUP && event.type!=SDL_JOYBUTTONUP && event.type!=SDL_JOYHATMOTION);
00382 restorer.restore();
00383 disp.update_display();
00384 if (keycode == SDLK_ESCAPE && (mod & any_mod) == 0) {
00385
00386 } else {
00387 const hotkey::hotkey_item& oldhk = hotkey::get_hotkey(character, keycode, (mod & KMOD_SHIFT) != 0,
00388 (mod & KMOD_CTRL) != 0, (mod & KMOD_ALT) != 0, (mod & KMOD_LMETA) != 0);
00389
00390 hotkey::hotkey_item& newhk = hotkey::get_visible_hotkey(menu_.selection());
00391
00392 if(oldhk.get_id() != newhk.get_id() && !oldhk.null()) {
00393 std::stringstream msg;
00394 msg << " " << oldhk.get_description() << " : " << oldhk.get_name();
00395 gui2::show_transient_message(disp.video(),_("This hotkey is already in use."),msg.str());
00396 } else {
00397 if (event.type == SDL_JOYHATMOTION) {
00398 const hotkey::hotkey_item& oldhkhat = hotkey::get_hotkey(joystick, hat, value);
00399
00400 if(oldhkhat.get_id() != newhk.get_id() && !oldhkhat.null()) {
00401 std::stringstream msg;
00402 msg << " " << oldhkhat.get_description() << " : " << oldhkhat.get_name();
00403 gui2::show_transient_message(disp.video(),_("This hotkey is already in use."),msg.str());
00404 } else {
00405 newhk.set_hat(joystick, hat, value);
00406 menu_.change_item(menu_.selection(), 1, font::NULL_MARKUP + newhk.get_name());
00407 }
00408 } else
00409 if (event.type == SDL_JOYBUTTONUP) {
00410 const hotkey::hotkey_item& oldhkbtn = hotkey::get_hotkey(button, joystick);
00411
00412 if(oldhkbtn.get_id() != newhk.get_id() && !oldhkbtn.null()) {
00413 std::stringstream msg;
00414 msg << " " << oldhkbtn.get_description() << " : " << oldhkbtn.get_name();
00415 gui2::show_transient_message(disp.video(),_("This hotkey is already in use."),msg.str());
00416 } else {
00417 newhk.set_button(button, joystick);
00418 menu_.change_item(menu_.selection(), 1, font::NULL_MARKUP + newhk.get_name());
00419 }
00420 } else {
00421
00422 newhk.set_key(character, keycode, (mod & KMOD_SHIFT) != 0,
00423 (mod & KMOD_CTRL) != 0, (mod & KMOD_ALT) != 0, (mod & KMOD_LMETA) != 0);
00424
00425 menu_.change_item(menu_.selection(), 1, font::NULL_MARKUP + newhk.get_name());
00426
00427 if ((newhk.get_id() == hotkey::HOTKEY_SCREENSHOT
00428 || newhk.get_id() == hotkey::HOTKEY_MAP_SCREENSHOT)
00429 && (mod & any_mod) == 0) {
00430 gui2::show_transient_message(disp.video(), _("Warning"), _("Screenshot hotkeys should be combined with the Control, Alt or Meta modifiers to avoid problems."));
00431 }
00432 }
00433 }
00434 }
00435 }
00436
00437 if (clear_button.pressed()) {
00438
00439 hotkey::hotkey_item& newhk = hotkey::get_visible_hotkey(menu_.selection());
00440 newhk.clear_hotkey();
00441 menu_.change_item(menu_.selection(), 1, font::NULL_MARKUP + newhk.get_name());
00442 }
00443
00444 if (reset_button.pressed()) {
00445 const int res = gui2::show_message(
00446 disp.video(), _("Reset Hotkeys"),
00447 _("This will reset all hotkeys to their default values. Do you want to continue?"), gui2::tmessage::yes_no_buttons);
00448
00449 if(res != gui2::twindow::CANCEL) {
00450 clear_hotkeys();
00451 repopulate_hotkeys_menu(menu_items);
00452 menu_.set_items(menu_items);
00453
00454 gui2::show_transient_message(disp.video(), _("Hotkeys Reset"), _("All hotkeys have been reset to their default values."));
00455 }
00456 }
00457
00458 menu_.process();
00459
00460 events::pump();
00461 events::raise_process_event();
00462 events::raise_draw_event();
00463
00464 disp.update_display();
00465
00466 disp.delay(10);
00467 }
00468 }
00469 #ifdef _MSC_VER
00470 #pragma warning (pop)
00471 #endif
00472
00473 bool compare_resolutions(const std::pair<int,int>& lhs, const std::pair<int,int>& rhs)
00474 {
00475 return lhs.first*lhs.second < rhs.first*rhs.second;
00476 }
00477
00478 bool show_video_mode_dialog(display& disp)
00479 {
00480 const resize_lock prevent_resizing;
00481 const events::event_context dialog_events_context;
00482
00483 CVideo& video = disp.video();
00484
00485 SDL_PixelFormat format = *video.getSurface()->format;
00486 format.BitsPerPixel = video.getBpp();
00487
00488 const SDL_Rect* const * modes = SDL_ListModes(&format,FULL_SCREEN);
00489
00490
00491
00492 if(modes == reinterpret_cast<SDL_Rect**>(-1)) {
00493 std::cerr << "Can support any video mode\n";
00494
00495
00496
00497 static const SDL_Rect scr_modes[] = {
00498 { 0, 0, 320, 240 },
00499 { 0, 0, 640, 480 },
00500 { 0, 0, 800, 480 },
00501 { 0, 0, 800, 600 },
00502 { 0, 0, 1024, 600 },
00503 { 0, 0, 1024, 768 },
00504 { 0, 0, 1280, 960 },
00505 { 0, 0, 1280, 1024 },
00506 { 0, 0, 1366, 768 },
00507 { 0, 0, 1440, 900 },
00508 { 0, 0, 1440, 1200 },
00509 { 0, 0, 1600, 1200 },
00510 { 0, 0, 1680, 1050 },
00511 { 0, 0, 1920, 1080 },
00512 { 0, 0, 1920, 1200 },
00513 { 0, 0, 2560, 1600 }
00514 };
00515 static const SDL_Rect * const scr_modes_list[] = {
00516 &scr_modes[0],
00517 &scr_modes[1],
00518 &scr_modes[2],
00519 &scr_modes[3],
00520 &scr_modes[4],
00521 &scr_modes[5],
00522 &scr_modes[6],
00523 &scr_modes[7],
00524 &scr_modes[8],
00525 &scr_modes[9],
00526 &scr_modes[10],
00527 &scr_modes[11],
00528 &scr_modes[12],
00529 &scr_modes[13],
00530 &scr_modes[14],
00531 &scr_modes[15],
00532 NULL
00533 };
00534
00535 modes = scr_modes_list;
00536 } else if(modes == NULL) {
00537 std::cerr << "No modes supported\n";
00538 gui2::show_transient_message(disp.video(),"",_("There are no alternative video modes available"));
00539 return false;
00540 }
00541
00542 std::vector<std::pair<int,int> > resolutions;
00543
00544 for(int i = 0; modes[i] != NULL; ++i) {
00545 if(modes[i]->w >= min_allowed_width() && modes[i]->h >= min_allowed_height()) {
00546 resolutions.push_back(std::pair<int,int>(modes[i]->w,modes[i]->h));
00547 }
00548 }
00549
00550 const std::pair<int,int> current_res(video.getSurface()->w,video.getSurface()->h);
00551 resolutions.push_back(current_res);
00552
00553 std::sort(resolutions.begin(),resolutions.end(),compare_resolutions);
00554 resolutions.erase(std::unique(resolutions.begin(),resolutions.end()),resolutions.end());
00555
00556 std::vector<std::string> options;
00557 unsigned current_choice = 0;
00558
00559 for(size_t k = 0; k < resolutions.size(); ++k) {
00560 std::pair<int, int> const& res = resolutions[k];
00561 std::ostringstream option;
00562
00563 if (res == current_res)
00564 current_choice = static_cast<unsigned>(k);
00565
00566 option << res.first << utils::unicode_multiplication_sign << res.second;
00567
00568 if (static_cast<double>(res.first)/res.second >= 16.0/10.0)
00569 option << _(" (widescreen)");
00570 options.push_back(option.str());
00571 }
00572
00573 gui2::tsimple_item_selector dlg(_("Choose Resolution"), "", options);
00574 dlg.set_selected_index(current_choice);
00575 dlg.show(disp.video());
00576
00577 int choice = dlg.selected_index();
00578
00579 if(choice == -1 || resolutions[static_cast<size_t>(choice)] == current_res) {
00580 return false;
00581 }
00582
00583 set_resolution(resolutions[static_cast<size_t>(choice)]);
00584 return true;
00585 }
00586
00587 }
00588