trunk/src/osd/sdl/window.c
| r243824 | r243825 | |
| 384 | 384 | |
| 385 | 385 | void sdl_window_info::blit_surface_size(int &blitwidth, int &blitheight) |
| 386 | 386 | { |
| 387 | | int window_width, window_height; |
| 388 | | get_size(window_width, window_height); |
| 387 | osd_dim window_dim = get_size(); |
| 389 | 388 | |
| 390 | | INT32 newwidth, newheight; |
| 389 | int newwidth, newheight; |
| 391 | 390 | int xscale = 1, yscale = 1; |
| 392 | 391 | float desired_aspect = 1.0f; |
| 393 | | INT32 target_width = window_width; |
| 394 | | INT32 target_height = window_height; |
| 392 | INT32 target_width = window_dim.width(); |
| 393 | INT32 target_height = window_dim.height(); |
| 395 | 394 | |
| 396 | 395 | // start with the minimum size |
| 397 | 396 | m_target->compute_minimum_size(newwidth, newheight); |
| r243824 | r243825 | |
| 415 | 414 | if (video_config.keepaspect) |
| 416 | 415 | { |
| 417 | 416 | // if we could stretch more in the X direction, and that makes a better fit, bump the xscale |
| 418 | | while (newwidth * (xscale + 1) <= window_width && |
| 417 | while (newwidth * (xscale + 1) <= window_dim.width() && |
| 419 | 418 | better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) |
| 420 | 419 | xscale++; |
| 421 | 420 | |
| 422 | 421 | // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale |
| 423 | | while (newheight * (yscale + 1) <= window_height && |
| 422 | while (newheight * (yscale + 1) <= window_dim.height() && |
| 424 | 423 | better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) |
| 425 | 424 | yscale++; |
| 426 | 425 | |
| 427 | 426 | // now that we've maxed out, see if backing off the maximally stretched one makes a better fit |
| 428 | | if (window_width - newwidth * xscale < window_height - newheight * yscale) |
| 427 | if (window_dim.width() - newwidth * xscale < window_dim.height() - newheight * yscale) |
| 429 | 428 | { |
| 430 | 429 | while (better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect) && (xscale >= 0)) |
| 431 | 430 | xscale--; |
| r243824 | r243825 | |
| 454 | 453 | //FIXME: really necessary to distinguish for yuv_modes ? |
| 455 | 454 | if (m_target->zoom_to_screen() |
| 456 | 455 | && (video_config.scale_mode == VIDEO_SCALE_MODE_NONE )) |
| 457 | | newwidth = window_width; |
| 456 | newwidth = window_dim.width(); |
| 458 | 457 | |
| 459 | | #if 0 |
| 460 | | // Fixme: notify_changed really necessary ? |
| 461 | | if ((blitwidth != newwidth) || (blitheight != newheight)) |
| 462 | | notify_changed(); |
| 463 | | #endif |
| 464 | 458 | blitwidth = newwidth; |
| 465 | 459 | blitheight = newheight; |
| 466 | 460 | } |
| r243824 | r243825 | |
| 498 | 492 | { |
| 499 | 493 | ASSERT_MAIN_THREAD(); |
| 500 | 494 | |
| 501 | | int cw=0; int ch=0; |
| 502 | | get_size(cw, ch); |
| 495 | osd_dim cd = get_size(); |
| 503 | 496 | |
| 504 | | if (width != cw || height != ch) |
| 497 | if (width != cd.width() || height != cd.height()) |
| 505 | 498 | execute_async_wait(&sdlwindow_resize_wt, worker_param(this, width, height)); |
| 506 | 499 | } |
| 507 | 500 | |
| r243824 | r243825 | |
| 555 | 548 | // If we are going fullscreen (leaving windowed) remember our windowed size |
| 556 | 549 | if (!window->fullscreen()) |
| 557 | 550 | { |
| 558 | | window->get_size(window->m_windowed_width, window->m_windowed_height); |
| 551 | window->m_windowed_dim = window->get_size(); |
| 559 | 552 | } |
| 560 | 553 | |
| 561 | 554 | window->renderer().destroy(); |
| r243824 | r243825 | |
| 853 | 846 | //============================================================ |
| 854 | 847 | |
| 855 | 848 | #if SDLMAME_SDL2 |
| 856 | | void sdl_window_info::pick_best_mode(int *fswidth, int *fsheight) |
| 849 | osd_dim sdl_window_info::pick_best_mode() |
| 857 | 850 | { |
| 858 | 851 | int minimum_width, minimum_height, target_width, target_height; |
| 859 | 852 | int i; |
| r243824 | r243825 | |
| 912 | 905 | if (size_score > best_score) |
| 913 | 906 | { |
| 914 | 907 | best_score = size_score; |
| 915 | | *fswidth = mode.w; |
| 916 | | *fsheight = mode.h; |
| 908 | return osd_dim(mode.w, mode.h); |
| 917 | 909 | } |
| 918 | 910 | |
| 919 | 911 | } |
| 920 | 912 | } |
| 913 | return osd_dim(0,0); // please compiler |
| 921 | 914 | } |
| 922 | 915 | #else |
| 923 | | void sdl_window_info::pick_best_mode(int *fswidth, int *fsheight) |
| 916 | osd_dim sdl_window_info::pick_best_mode() |
| 924 | 917 | { |
| 925 | 918 | int minimum_width, minimum_height, target_width, target_height; |
| 926 | 919 | int i; |
| r243824 | r243825 | |
| 958 | 951 | } |
| 959 | 952 | else if (modes == (SDL_Rect **)-1) // all modes are possible |
| 960 | 953 | { |
| 961 | | *fswidth = m_win_config.width; |
| 962 | | *fsheight = m_win_config.height; |
| 954 | return osd_dim(m_win_config.width, m_win_config.height); |
| 963 | 955 | } |
| 964 | 956 | else |
| 965 | 957 | { |
| r243824 | r243825 | |
| 986 | 978 | if (size_score > best_score) |
| 987 | 979 | { |
| 988 | 980 | best_score = size_score; |
| 989 | | *fswidth = modes[i]->w; |
| 990 | | *fsheight = modes[i]->h; |
| 981 | return osd_dim(modes[i]->w, modes[i]->h); |
| 991 | 982 | } |
| 992 | 983 | |
| 993 | 984 | } |
| 994 | 985 | } |
| 986 | return osd_dim(0,0); |
| 995 | 987 | } |
| 996 | 988 | #endif |
| 997 | 989 | |
| r243824 | r243825 | |
| 1029 | 1021 | } |
| 1030 | 1022 | else if (video_config.switchres) |
| 1031 | 1023 | { |
| 1032 | | this->pick_best_mode(&tempwidth, &tempheight); |
| 1033 | | resize(tempwidth, tempheight); |
| 1024 | osd_dim tmp = this->pick_best_mode(); |
| 1025 | resize(tmp.width(), tmp.height()); |
| 1034 | 1026 | } |
| 1035 | 1027 | } |
| 1036 | 1028 | |
| r243824 | r243825 | |
| 1086 | 1078 | worker_param * wp = (worker_param *) param; |
| 1087 | 1079 | sdl_window_info * window = wp->window(); |
| 1088 | 1080 | |
| 1089 | | int tempwidth, tempheight; |
| 1081 | osd_dim temp(0,0); |
| 1090 | 1082 | static int result[2] = {0,1}; |
| 1091 | 1083 | |
| 1092 | 1084 | ASSERT_WINDOW_THREAD(); |
| r243824 | r243825 | |
| 1095 | 1087 | if (window->fullscreen()) |
| 1096 | 1088 | { |
| 1097 | 1089 | // default to the current mode exactly |
| 1098 | | tempwidth = window->monitor()->position_size().w; |
| 1099 | | tempheight = window->monitor()->position_size().h; |
| 1090 | temp = window->monitor()->position_size().dim(); |
| 1100 | 1091 | |
| 1101 | 1092 | // if we're allowed to switch resolutions, override with something better |
| 1102 | 1093 | if (video_config.switchres) |
| 1103 | | window->pick_best_mode(&tempwidth, &tempheight); |
| 1094 | temp = window->pick_best_mode(); |
| 1104 | 1095 | } |
| 1105 | | else if (window->m_windowed_width) |
| 1096 | else if (window->m_windowed_dim.width() > 0) |
| 1106 | 1097 | { |
| 1107 | 1098 | // if we have a remembered size force the new window size to it |
| 1108 | | tempwidth = window->m_windowed_width; |
| 1109 | | tempheight = window->m_windowed_height; |
| 1099 | temp = window->m_windowed_dim; |
| 1110 | 1100 | } |
| 1111 | 1101 | else |
| 1112 | 1102 | { |
| 1113 | 1103 | if (window->m_startmaximized) |
| 1114 | 1104 | { |
| 1115 | | tempwidth = tempheight = 0; |
| 1116 | | window->get_max_bounds(&tempwidth, &tempheight, video_config.keepaspect ); |
| 1105 | temp = window->get_max_bounds(video_config.keepaspect ); |
| 1117 | 1106 | } |
| 1118 | 1107 | else |
| 1119 | 1108 | { |
| 1109 | #if 0 |
| 1110 | // Couriersud: This code never has worked with the last version of get_min_bounds |
| 1120 | 1111 | /* Create the window directly with the correct aspect |
| 1121 | 1112 | instead of letting sdlwindow_blit_surface_size() resize it |
| 1122 | 1113 | this stops the window from "flashing" from the wrong aspect |
| 1123 | 1114 | size to the right one at startup. */ |
| 1124 | 1115 | tempwidth = (window->m_win_config.width != 0) ? window->m_win_config.width : 640; |
| 1125 | 1116 | tempheight = (window->m_win_config.height != 0) ? window->m_win_config.height : 480; |
| 1126 | | |
| 1127 | | window->get_min_bounds(&tempwidth, &tempheight, video_config.keepaspect ); |
| 1117 | #endif |
| 1118 | temp = window->get_min_bounds(video_config.keepaspect ); |
| 1128 | 1119 | } |
| 1129 | 1120 | } |
| 1130 | 1121 | |
| r243824 | r243825 | |
| 1166 | 1157 | #endif |
| 1167 | 1158 | // create the SDL window |
| 1168 | 1159 | window->m_sdl_window = SDL_CreateWindow(window->m_title, |
| 1169 | | window->monitor()->position_size().x, window->monitor()->position_size().y, |
| 1170 | | tempwidth, tempheight, window->m_extra_flags); |
| 1160 | window->monitor()->position_size().left(), window->monitor()->position_size().top(), |
| 1161 | temp.width(), temp.height(), window->m_extra_flags); |
| 1171 | 1162 | //window().sdl_window() = SDL_CreateWindow(window().m_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, |
| 1172 | 1163 | // width, height, m_extra_flags); |
| 1173 | 1164 | |
| r243824 | r243825 | |
| 1186 | 1177 | //SDL_GetCurrentDisplayMode(window().monitor()->handle, &mode); |
| 1187 | 1178 | SDL_GetWindowDisplayMode(window->sdl_window(), &mode); |
| 1188 | 1179 | window->m_original_mode = mode; |
| 1189 | | mode.w = tempwidth; |
| 1190 | | mode.h = tempheight; |
| 1180 | mode.w = temp.width(); |
| 1181 | mode.h = temp.height(); |
| 1191 | 1182 | if (window->m_win_config.refresh) |
| 1192 | 1183 | mode.refresh_rate = window->m_win_config.refresh; |
| 1193 | 1184 | |
| r243824 | r243825 | |
| 1241 | 1232 | if (!window->m_sdlsurf) |
| 1242 | 1233 | printf("completely failed\n"); |
| 1243 | 1234 | #endif |
| 1244 | | window->m_sdlsurf = SDL_SetVideoMode(tempwidth, tempheight, |
| 1235 | window->m_sdlsurf = SDL_SetVideoMode(temp.width(), temp.height(), |
| 1245 | 1236 | 0, SDL_SWSURFACE | SDL_ANYFORMAT | window->m_extra_flags); |
| 1246 | 1237 | |
| 1247 | 1238 | if (!window->m_sdlsurf) |
| r243824 | r243825 | |
| 1377 | 1368 | return NULL; |
| 1378 | 1369 | } |
| 1379 | 1370 | |
| 1371 | int sdl_window_info::wnd_extra_width() |
| 1372 | { |
| 1373 | return m_fullscreen ? 0 : WINDOW_DECORATION_WIDTH; |
| 1374 | } |
| 1380 | 1375 | |
| 1376 | int sdl_window_info::wnd_extra_height() |
| 1377 | { |
| 1378 | return m_fullscreen ? 0 : WINDOW_DECORATION_HEIGHT; |
| 1379 | } |
| 1380 | |
| 1381 | |
| 1381 | 1382 | //============================================================ |
| 1382 | 1383 | // constrain_to_aspect_ratio |
| 1383 | 1384 | // (window thread) |
| 1384 | 1385 | //============================================================ |
| 1385 | 1386 | |
| 1386 | | void sdl_window_info::constrain_to_aspect_ratio(int *window_width, int *window_height, int adjustment) |
| 1387 | osd_rect sdl_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int adjustment) |
| 1387 | 1388 | { |
| 1388 | | INT32 extrawidth = 0; |
| 1389 | | INT32 extraheight = 0; |
| 1389 | INT32 extrawidth = wnd_extra_width(); |
| 1390 | INT32 extraheight = wnd_extra_height(); |
| 1390 | 1391 | INT32 propwidth, propheight; |
| 1391 | 1392 | INT32 minwidth, minheight; |
| 1392 | 1393 | INT32 maxwidth, maxheight; |
| 1393 | 1394 | INT32 viswidth, visheight; |
| 1395 | INT32 adjwidth, adjheight; |
| 1394 | 1396 | float pixel_aspect; |
| 1395 | 1397 | |
| 1396 | 1398 | // get the pixel aspect ratio for the target monitor |
| 1397 | 1399 | pixel_aspect = m_monitor->aspect(); |
| 1398 | 1400 | |
| 1399 | 1401 | // determine the proposed width/height |
| 1400 | | propwidth = *window_width - extrawidth; |
| 1401 | | propheight = *window_height - extraheight; |
| 1402 | propwidth = rect.width() - extrawidth; |
| 1403 | propheight = rect.height() - extraheight; |
| 1402 | 1404 | |
| 1403 | 1405 | // based on which edge we are adjusting, take either the width, height, or both as gospel |
| 1404 | 1406 | // and scale to fit using that as our parameter |
| r243824 | r243825 | |
| 1431 | 1433 | propheight = MAX(propheight, minheight); |
| 1432 | 1434 | |
| 1433 | 1435 | // clamp against the maximum (fit on one screen for full screen mode) |
| 1434 | | maxwidth = m_monitor->position_size().w - extrawidth; |
| 1435 | | maxheight = m_monitor->position_size().h - extraheight; |
| 1436 | | if (this->m_fullscreen) |
| 1436 | if (m_fullscreen) |
| 1437 | 1437 | { |
| 1438 | | // nothing |
| 1438 | maxwidth = m_monitor->position_size().width() - extrawidth; |
| 1439 | maxheight = m_monitor->position_size().height() - extraheight; |
| 1439 | 1440 | } |
| 1440 | 1441 | else |
| 1441 | 1442 | { |
| 1443 | maxwidth = m_monitor->position_size().width() - extrawidth; |
| 1444 | maxheight = m_monitor->position_size().height() - extraheight; |
| 1445 | |
| 1442 | 1446 | // further clamp to the maximum width/height in the window |
| 1443 | | if (this->m_win_config.width != 0) |
| 1444 | | maxwidth = MIN(maxwidth, this->m_win_config.width + extrawidth); |
| 1445 | | if (this->m_win_config.height != 0) |
| 1446 | | maxheight = MIN(maxheight, this->m_win_config.height + extraheight); |
| 1447 | if (m_win_config.width != 0) |
| 1448 | maxwidth = MIN(maxwidth, m_win_config.width + extrawidth); |
| 1449 | if (m_win_config.height != 0) |
| 1450 | maxheight = MIN(maxheight, m_win_config.height + extraheight); |
| 1447 | 1451 | } |
| 1448 | 1452 | |
| 1449 | 1453 | // clamp to the maximum |
| r243824 | r243825 | |
| 1453 | 1457 | // compute the visible area based on the proposed rectangle |
| 1454 | 1458 | m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), viswidth, visheight); |
| 1455 | 1459 | |
| 1456 | | *window_width = viswidth; |
| 1457 | | *window_height = visheight; |
| 1460 | // compute the adjustments we need to make |
| 1461 | adjwidth = (viswidth + extrawidth) - rect.width(); |
| 1462 | adjheight = (visheight + extraheight) - rect.height(); |
| 1463 | |
| 1464 | // based on which corner we're adjusting, constrain in different ways |
| 1465 | osd_rect ret(rect); |
| 1466 | |
| 1467 | switch (adjustment) |
| 1468 | { |
| 1469 | case WMSZ_BOTTOM: |
| 1470 | case WMSZ_BOTTOMRIGHT: |
| 1471 | case WMSZ_RIGHT: |
| 1472 | ret = rect.resize(rect.width() + adjwidth, rect.height() + adjheight); |
| 1473 | break; |
| 1474 | |
| 1475 | case WMSZ_BOTTOMLEFT: |
| 1476 | ret = rect.move_by(-adjwidth, 0).resize(rect.width(), rect.height() + adjheight); |
| 1477 | break; |
| 1478 | |
| 1479 | case WMSZ_LEFT: |
| 1480 | case WMSZ_TOPLEFT: |
| 1481 | case WMSZ_TOP: |
| 1482 | ret = rect.move_by(-adjwidth, -adjheight); |
| 1483 | break; |
| 1484 | |
| 1485 | case WMSZ_TOPRIGHT: |
| 1486 | ret = rect.move_by(0, -adjheight).resize(rect.width() + adjwidth, rect.height()); |
| 1487 | break; |
| 1458 | 1488 | } |
| 1489 | return ret; |
| 1490 | } |
| 1459 | 1491 | |
| 1460 | 1492 | |
| 1493 | |
| 1461 | 1494 | //============================================================ |
| 1462 | 1495 | // get_min_bounds |
| 1463 | 1496 | // (window thread) |
| 1464 | 1497 | //============================================================ |
| 1465 | 1498 | |
| 1466 | | void sdl_window_info::get_min_bounds(int *window_width, int *window_height, int constrain) |
| 1499 | osd_dim sdl_window_info::get_min_bounds(int constrain) |
| 1467 | 1500 | { |
| 1468 | 1501 | INT32 minwidth, minheight; |
| 1469 | 1502 | |
| 1470 | 1503 | // get the minimum target size |
| 1471 | | this->m_target->compute_minimum_size(minwidth, minheight); |
| 1504 | m_target->compute_minimum_size(minwidth, minheight); |
| 1472 | 1505 | |
| 1473 | 1506 | // expand to our minimum dimensions |
| 1474 | 1507 | if (minwidth < MIN_WINDOW_DIM) |
| r243824 | r243825 | |
| 1476 | 1509 | if (minheight < MIN_WINDOW_DIM) |
| 1477 | 1510 | minheight = MIN_WINDOW_DIM; |
| 1478 | 1511 | |
| 1512 | // account for extra window stuff |
| 1513 | minwidth += wnd_extra_width(); |
| 1514 | minheight += wnd_extra_height(); |
| 1515 | |
| 1479 | 1516 | // if we want it constrained, figure out which one is larger |
| 1480 | 1517 | if (constrain) |
| 1481 | 1518 | { |
| 1482 | | int test1w, test1h; |
| 1483 | | int test2w, test2h; |
| 1484 | | |
| 1485 | 1519 | // first constrain with no height limit |
| 1486 | | test1w = minwidth; test1h = 10000; |
| 1487 | | this->constrain_to_aspect_ratio(&test1w, &test1h, WMSZ_BOTTOMRIGHT); |
| 1520 | osd_rect test1(0,0,minwidth,10000); |
| 1521 | test1 = constrain_to_aspect_ratio(test1, WMSZ_BOTTOMRIGHT); |
| 1488 | 1522 | |
| 1489 | 1523 | // then constrain with no width limit |
| 1490 | | test2w = 10000; test2h = minheight; |
| 1491 | | this->constrain_to_aspect_ratio(&test2w, &test2h, WMSZ_BOTTOMRIGHT); |
| 1524 | osd_rect test2(0,0,10000,minheight); |
| 1525 | test2 = constrain_to_aspect_ratio(test2, WMSZ_BOTTOMRIGHT); |
| 1492 | 1526 | |
| 1493 | 1527 | // pick the larger |
| 1494 | | if ( test1w > test2w ) |
| 1528 | if (test1.width() > test2.width()) |
| 1495 | 1529 | { |
| 1496 | | minwidth = test1w; |
| 1497 | | minheight = test1h; |
| 1530 | minwidth = test1.width(); |
| 1531 | minheight = test1.height(); |
| 1498 | 1532 | } |
| 1499 | 1533 | else |
| 1500 | 1534 | { |
| 1501 | | minwidth = test2w; |
| 1502 | | minheight = test2h; |
| 1535 | minwidth = test2.width(); |
| 1536 | minheight = test2.height(); |
| 1503 | 1537 | } |
| 1504 | 1538 | } |
| 1505 | 1539 | |
| 1506 | | *window_width = minwidth; |
| 1507 | | *window_height = minheight; |
| 1540 | return osd_dim(minwidth, minheight); |
| 1508 | 1541 | } |
| 1509 | 1542 | |
| 1510 | 1543 | |
| 1544 | |
| 1511 | 1545 | //============================================================ |
| 1512 | 1546 | // get_max_bounds |
| 1513 | 1547 | // (window thread) |
| 1514 | 1548 | //============================================================ |
| 1515 | 1549 | |
| 1516 | | void sdl_window_info::get_max_bounds(int *window_width, int *window_height, int constrain) |
| 1550 | osd_dim sdl_window_info::get_max_bounds(int constrain) |
| 1517 | 1551 | { |
| 1518 | | INT32 maxwidth, maxheight; |
| 1519 | | |
| 1520 | 1552 | // compute the maximum client area |
| 1521 | | maxwidth = m_monitor->position_size().w; |
| 1522 | | maxheight = m_monitor->position_size().h; |
| 1523 | 1553 | |
| 1554 | osd_rect maximum = m_monitor->position_size(); |
| 1555 | |
| 1524 | 1556 | // clamp to the window's max |
| 1525 | | if (this->m_win_config.width != 0) |
| 1557 | int tempw = maximum.width(); |
| 1558 | int temph = maximum.height(); |
| 1559 | if (m_win_config.width != 0) |
| 1526 | 1560 | { |
| 1527 | | int temp = this->m_win_config.width + WINDOW_DECORATION_WIDTH; |
| 1528 | | if (temp < maxwidth) |
| 1529 | | maxwidth = temp; |
| 1561 | int temp = m_win_config.width + wnd_extra_width(); |
| 1562 | if (temp < maximum.width()) |
| 1563 | tempw = temp; |
| 1530 | 1564 | } |
| 1531 | | if (this->m_win_config.height != 0) |
| 1565 | if (m_win_config.height != 0) |
| 1532 | 1566 | { |
| 1533 | | int temp = this->m_win_config.height + WINDOW_DECORATION_HEIGHT; |
| 1534 | | if (temp < maxheight) |
| 1535 | | maxheight = temp; |
| 1567 | int temp = m_win_config.height + wnd_extra_height(); |
| 1568 | if (temp < maximum.height()) |
| 1569 | temph = temp; |
| 1536 | 1570 | } |
| 1537 | 1571 | |
| 1572 | maximum = maximum.resize(tempw, temph); |
| 1573 | |
| 1538 | 1574 | // constrain to fit |
| 1539 | 1575 | if (constrain) |
| 1540 | | this->constrain_to_aspect_ratio(&maxwidth, &maxheight, WMSZ_BOTTOMRIGHT); |
| 1541 | | //else |
| 1576 | maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT); |
| 1577 | else |
| 1542 | 1578 | { |
| 1543 | | maxwidth -= WINDOW_DECORATION_WIDTH; |
| 1544 | | maxheight -= WINDOW_DECORATION_HEIGHT; |
| 1545 | | *window_width = maxwidth; |
| 1546 | | *window_height = maxheight; |
| 1579 | maximum = maximum.resize(maximum.width() - wnd_extra_width(), maximum.height() - wnd_extra_height()); |
| 1547 | 1580 | } |
| 1581 | return maximum.dim(); |
| 1548 | 1582 | } |
trunk/src/osd/windows/window.c
| r243824 | r243825 | |
| 831 | 831 | // (window thread) |
| 832 | 832 | //============================================================ |
| 833 | 833 | |
| 834 | | win_monitor_info *win_window_info::winwindow_video_window_monitor(const RECT *proposed) |
| 834 | win_monitor_info *win_window_info::winwindow_video_window_monitor(const osd_rect *proposed) |
| 835 | 835 | { |
| 836 | 836 | win_monitor_info *monitor; |
| 837 | 837 | |
| r243824 | r243825 | |
| 839 | 839 | if (!m_fullscreen) |
| 840 | 840 | { |
| 841 | 841 | if (proposed != NULL) |
| 842 | | monitor = winvideo_monitor_from_handle(MonitorFromRect(proposed, MONITOR_DEFAULTTONEAREST)); |
| 842 | { |
| 843 | RECT p; |
| 844 | p.top = proposed->top(); |
| 845 | p.left = proposed->left(); |
| 846 | p.bottom = proposed->bottom(); |
| 847 | p.right = proposed->right(); |
| 848 | monitor = winvideo_monitor_from_handle(MonitorFromRect(&p, MONITOR_DEFAULTTONEAREST)); |
| 849 | } |
| 843 | 850 | else |
| 844 | 851 | monitor = winvideo_monitor_from_handle(MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST)); |
| 845 | 852 | } |
| r243824 | r243825 | |
| 1153 | 1160 | |
| 1154 | 1161 | int win_window_info::complete_create() |
| 1155 | 1162 | { |
| 1156 | | RECT monitorbounds, client; |
| 1163 | RECT client; |
| 1157 | 1164 | int tempwidth, tempheight; |
| 1158 | 1165 | HMENU menu = NULL; |
| 1159 | 1166 | HDC dc; |
| r243824 | r243825 | |
| 1161 | 1168 | assert(GetCurrentThreadId() == window_threadid); |
| 1162 | 1169 | |
| 1163 | 1170 | // get the monitor bounds |
| 1164 | | monitorbounds = m_monitor->position_size(); |
| 1171 | osd_rect monitorbounds = m_monitor->position_size(); |
| 1165 | 1172 | |
| 1166 | 1173 | // create the window menu if needed |
| 1167 | 1174 | if (downcast<windows_options &>(machine().options()).menu()) |
| r243824 | r243825 | |
| 1176 | 1183 | "MAME", |
| 1177 | 1184 | m_title, |
| 1178 | 1185 | m_fullscreen ? FULLSCREEN_STYLE : WINDOW_STYLE, |
| 1179 | | monitorbounds.left + 20, monitorbounds.top + 20, |
| 1180 | | monitorbounds.left + 100, monitorbounds.top + 100, |
| 1186 | monitorbounds.left() + 20, monitorbounds.top() + 20, |
| 1187 | monitorbounds.left() + 100, monitorbounds.top() + 100, |
| 1181 | 1188 | NULL,//(win_window_list != NULL) ? win_window_list->m_hwnd : NULL, |
| 1182 | 1189 | menu, |
| 1183 | 1190 | GetModuleHandle(NULL), |
| r243824 | r243825 | |
| 1198 | 1205 | // adjust the window position to the initial width/height |
| 1199 | 1206 | tempwidth = (m_win_config.width != 0) ? m_win_config.width : 640; |
| 1200 | 1207 | tempheight = (m_win_config.height != 0) ? m_win_config.height : 480; |
| 1201 | | SetWindowPos(m_hwnd, NULL, monitorbounds.left + 20, monitorbounds.top + 20, |
| 1202 | | monitorbounds.left + tempwidth + wnd_extra_width(), |
| 1203 | | monitorbounds.top + tempheight + wnd_extra_height(), |
| 1208 | SetWindowPos(m_hwnd, NULL, monitorbounds.left() + 20, monitorbounds.top() + 20, |
| 1209 | monitorbounds.left() + tempwidth + wnd_extra_width(), |
| 1210 | monitorbounds.top() + tempheight + wnd_extra_height(), |
| 1204 | 1211 | SWP_NOZORDER); |
| 1205 | 1212 | |
| 1206 | 1213 | // maximum or minimize as appropriate |
| r243824 | r243825 | |
| 1346 | 1353 | { |
| 1347 | 1354 | RECT *rect = (RECT *)lparam; |
| 1348 | 1355 | if (video_config.keepaspect && !(GetAsyncKeyState(VK_CONTROL) & 0x8000)) |
| 1349 | | window->constrain_to_aspect_ratio(rect, wparam); |
| 1356 | { |
| 1357 | osd_rect r = window->constrain_to_aspect_ratio(RECT_to_osd_rect(*rect), wparam); |
| 1358 | rect->top = r.top(); |
| 1359 | rect->left = r.left(); |
| 1360 | rect->bottom = r.bottom(); |
| 1361 | rect->right = r.right(); |
| 1362 | } |
| 1350 | 1363 | InvalidateRect(wnd, NULL, FALSE); |
| 1351 | 1364 | break; |
| 1352 | 1365 | } |
| r243824 | r243825 | |
| 1500 | 1513 | // (window thread) |
| 1501 | 1514 | //============================================================ |
| 1502 | 1515 | |
| 1503 | | void win_window_info::constrain_to_aspect_ratio(RECT *rect, int adjustment) |
| 1516 | osd_rect win_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int adjustment) |
| 1504 | 1517 | { |
| 1505 | | win_monitor_info *monitor = winwindow_video_window_monitor(rect); |
| 1518 | win_monitor_info *monitor = winwindow_video_window_monitor(&rect); |
| 1506 | 1519 | INT32 extrawidth = wnd_extra_width(); |
| 1507 | 1520 | INT32 extraheight = wnd_extra_height(); |
| 1508 | 1521 | INT32 propwidth, propheight; |
| r243824 | r243825 | |
| 1518 | 1531 | pixel_aspect = monitor->aspect(); |
| 1519 | 1532 | |
| 1520 | 1533 | // determine the proposed width/height |
| 1521 | | propwidth = rect_width(rect) - extrawidth; |
| 1522 | | propheight = rect_height(rect) - extraheight; |
| 1534 | propwidth = rect.width() - extrawidth; |
| 1535 | propheight = rect.height() - extraheight; |
| 1523 | 1536 | |
| 1524 | 1537 | // based on which edge we are adjusting, take either the width, height, or both as gospel |
| 1525 | 1538 | // and scale to fit using that as our parameter |
| r243824 | r243825 | |
| 1554 | 1567 | // clamp against the maximum (fit on one screen for full screen mode) |
| 1555 | 1568 | if (m_fullscreen) |
| 1556 | 1569 | { |
| 1557 | | maxwidth = rect_width(&monitor->position_size()) - extrawidth; |
| 1558 | | maxheight = rect_height(&monitor->position_size()) - extraheight; |
| 1570 | maxwidth = monitor->position_size().width() - extrawidth; |
| 1571 | maxheight = monitor->position_size().height() - extraheight; |
| 1559 | 1572 | } |
| 1560 | 1573 | else |
| 1561 | 1574 | { |
| 1562 | | maxwidth = rect_width(&monitor->usuable_position_size()) - extrawidth; |
| 1563 | | maxheight = rect_height(&monitor->usuable_position_size()) - extraheight; |
| 1575 | maxwidth = monitor->usuable_position_size().width() - extrawidth; |
| 1576 | maxheight = monitor->usuable_position_size().height() - extraheight; |
| 1564 | 1577 | |
| 1565 | 1578 | // further clamp to the maximum width/height in the window |
| 1566 | 1579 | if (m_win_config.width != 0) |
| r243824 | r243825 | |
| 1577 | 1590 | m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), viswidth, visheight); |
| 1578 | 1591 | |
| 1579 | 1592 | // compute the adjustments we need to make |
| 1580 | | adjwidth = (viswidth + extrawidth) - rect_width(rect); |
| 1581 | | adjheight = (visheight + extraheight) - rect_height(rect); |
| 1593 | adjwidth = (viswidth + extrawidth) - rect.width(); |
| 1594 | adjheight = (visheight + extraheight) - rect.height(); |
| 1582 | 1595 | |
| 1583 | 1596 | // based on which corner we're adjusting, constrain in different ways |
| 1597 | osd_rect ret(rect); |
| 1598 | |
| 1584 | 1599 | switch (adjustment) |
| 1585 | 1600 | { |
| 1586 | 1601 | case WMSZ_BOTTOM: |
| 1587 | 1602 | case WMSZ_BOTTOMRIGHT: |
| 1588 | 1603 | case WMSZ_RIGHT: |
| 1589 | | rect->right += adjwidth; |
| 1590 | | rect->bottom += adjheight; |
| 1604 | ret = rect.resize(rect.width() + adjwidth, rect.height() + adjheight); |
| 1591 | 1605 | break; |
| 1592 | 1606 | |
| 1593 | 1607 | case WMSZ_BOTTOMLEFT: |
| 1594 | | rect->left -= adjwidth; |
| 1595 | | rect->bottom += adjheight; |
| 1608 | ret = rect.move_by(-adjwidth, 0).resize(rect.width(), rect.height() + adjheight); |
| 1596 | 1609 | break; |
| 1597 | 1610 | |
| 1598 | 1611 | case WMSZ_LEFT: |
| 1599 | 1612 | case WMSZ_TOPLEFT: |
| 1600 | 1613 | case WMSZ_TOP: |
| 1601 | | rect->left -= adjwidth; |
| 1602 | | rect->top -= adjheight; |
| 1614 | ret = rect.move_by(-adjwidth, -adjheight); |
| 1603 | 1615 | break; |
| 1604 | 1616 | |
| 1605 | 1617 | case WMSZ_TOPRIGHT: |
| 1606 | | rect->right += adjwidth; |
| 1607 | | rect->top -= adjheight; |
| 1618 | ret = rect.move_by(0, -adjheight).resize(rect.width() + adjwidth, rect.height()); |
| 1608 | 1619 | break; |
| 1609 | 1620 | } |
| 1621 | return ret; |
| 1610 | 1622 | } |
| 1611 | 1623 | |
| 1612 | 1624 | |
| r243824 | r243825 | |
| 1616 | 1628 | // (window thread) |
| 1617 | 1629 | //============================================================ |
| 1618 | 1630 | |
| 1619 | | void win_window_info::get_min_bounds(RECT *bounds, int constrain) |
| 1631 | osd_dim win_window_info::get_min_bounds(int constrain) |
| 1620 | 1632 | { |
| 1621 | 1633 | INT32 minwidth, minheight; |
| 1622 | 1634 | |
| r243824 | r243825 | |
| 1638 | 1650 | // if we want it constrained, figure out which one is larger |
| 1639 | 1651 | if (constrain) |
| 1640 | 1652 | { |
| 1641 | | RECT test1, test2; |
| 1642 | | |
| 1643 | 1653 | // first constrain with no height limit |
| 1644 | | test1.top = test1.left = 0; |
| 1645 | | test1.right = minwidth; |
| 1646 | | test1.bottom = 10000; |
| 1647 | | constrain_to_aspect_ratio(&test1, WMSZ_BOTTOMRIGHT); |
| 1654 | osd_rect test1(0,0,minwidth,10000); |
| 1655 | test1 = constrain_to_aspect_ratio(test1, WMSZ_BOTTOMRIGHT); |
| 1648 | 1656 | |
| 1649 | 1657 | // then constrain with no width limit |
| 1650 | | test2.top = test2.left = 0; |
| 1651 | | test2.right = 10000; |
| 1652 | | test2.bottom = minheight; |
| 1653 | | constrain_to_aspect_ratio(&test2, WMSZ_BOTTOMRIGHT); |
| 1658 | osd_rect test2(0,0,10000,minheight); |
| 1659 | test2 = constrain_to_aspect_ratio(test2, WMSZ_BOTTOMRIGHT); |
| 1654 | 1660 | |
| 1655 | 1661 | // pick the larger |
| 1656 | | if (rect_width(&test1) > rect_width(&test2)) |
| 1662 | if (test1.width() > test2.width()) |
| 1657 | 1663 | { |
| 1658 | | minwidth = rect_width(&test1); |
| 1659 | | minheight = rect_height(&test1); |
| 1664 | minwidth = test1.width(); |
| 1665 | minheight = test1.height(); |
| 1660 | 1666 | } |
| 1661 | 1667 | else |
| 1662 | 1668 | { |
| 1663 | | minwidth = rect_width(&test2); |
| 1664 | | minheight = rect_height(&test2); |
| 1669 | minwidth = test2.width(); |
| 1670 | minheight = test2.height(); |
| 1665 | 1671 | } |
| 1666 | 1672 | } |
| 1667 | 1673 | |
| 1668 | | // get the window rect |
| 1669 | | GetWindowRect(m_hwnd, bounds); |
| 1670 | | |
| 1671 | | // now adjust |
| 1672 | | bounds->right = bounds->left + minwidth; |
| 1673 | | bounds->bottom = bounds->top + minheight; |
| 1674 | return osd_dim(minwidth, minheight); |
| 1674 | 1675 | } |
| 1675 | 1676 | |
| 1676 | 1677 | |
| r243824 | r243825 | |
| 1680 | 1681 | // (window thread) |
| 1681 | 1682 | //============================================================ |
| 1682 | 1683 | |
| 1683 | | void win_window_info::get_max_bounds(RECT *bounds, int constrain) |
| 1684 | osd_dim win_window_info::get_max_bounds(int constrain) |
| 1684 | 1685 | { |
| 1685 | | RECT maximum; |
| 1686 | | |
| 1687 | 1686 | assert(GetCurrentThreadId() == window_threadid); |
| 1688 | 1687 | |
| 1689 | 1688 | // compute the maximum client area |
| 1690 | 1689 | m_monitor->refresh(); |
| 1691 | | maximum = m_monitor->usuable_position_size(); |
| 1690 | osd_rect maximum = m_monitor->usuable_position_size(); |
| 1692 | 1691 | |
| 1693 | 1692 | // clamp to the window's max |
| 1693 | int tempw = maximum.width(); |
| 1694 | int temph = maximum.height(); |
| 1694 | 1695 | if (m_win_config.width != 0) |
| 1695 | 1696 | { |
| 1696 | 1697 | int temp = m_win_config.width + wnd_extra_width(); |
| 1697 | | if (temp < rect_width(&maximum)) |
| 1698 | | maximum.right = maximum.left + temp; |
| 1698 | if (temp < maximum.width()) |
| 1699 | tempw = temp; |
| 1699 | 1700 | } |
| 1700 | 1701 | if (m_win_config.height != 0) |
| 1701 | 1702 | { |
| 1702 | 1703 | int temp = m_win_config.height + wnd_extra_height(); |
| 1703 | | if (temp < rect_height(&maximum)) |
| 1704 | | maximum.bottom = maximum.top + temp; |
| 1704 | if (temp < maximum.height()) |
| 1705 | temph = temp; |
| 1705 | 1706 | } |
| 1706 | 1707 | |
| 1708 | maximum = maximum.resize(tempw, temph); |
| 1709 | |
| 1707 | 1710 | // constrain to fit |
| 1708 | 1711 | if (constrain) |
| 1709 | | constrain_to_aspect_ratio(&maximum, WMSZ_BOTTOMRIGHT); |
| 1712 | maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT); |
| 1710 | 1713 | else |
| 1711 | 1714 | { |
| 1712 | | maximum.right -= wnd_extra_width(); |
| 1713 | | maximum.bottom -= wnd_extra_height(); |
| 1715 | maximum = maximum.resize(maximum.width() - wnd_extra_width(), maximum.height() - wnd_extra_height()); |
| 1714 | 1716 | } |
| 1715 | | |
| 1716 | | // center within the work area |
| 1717 | | RECT work = m_monitor->usuable_position_size(); |
| 1718 | | bounds->left = work.left + (rect_width(&work) - rect_width(&maximum)) / 2; |
| 1719 | | bounds->top = work.top + (rect_height(&work) - rect_height(&maximum)) / 2; |
| 1720 | | bounds->right = bounds->left + rect_width(&maximum); |
| 1721 | | bounds->bottom = bounds->top + rect_height(&maximum); |
| 1717 | return maximum.dim(); |
| 1722 | 1718 | } |
| 1723 | 1719 | |
| 1724 | 1720 | |
| r243824 | r243825 | |
| 1734 | 1730 | |
| 1735 | 1731 | if (!m_fullscreen) |
| 1736 | 1732 | { |
| 1737 | | RECT bounds, minbounds, maxbounds; |
| 1733 | RECT bounds; |
| 1738 | 1734 | |
| 1739 | 1735 | // compare the maximum bounds versus the current bounds |
| 1740 | | get_min_bounds(&minbounds, video_config.keepaspect); |
| 1741 | | get_max_bounds(&maxbounds, video_config.keepaspect); |
| 1736 | osd_dim minbounds = get_min_bounds(video_config.keepaspect); |
| 1737 | osd_dim maxbounds = get_max_bounds(video_config.keepaspect); |
| 1742 | 1738 | GetWindowRect(m_hwnd, &bounds); |
| 1743 | 1739 | |
| 1744 | 1740 | // if either the width or height matches, we were maximized |
| 1745 | | m_isminimized = (rect_width(&bounds) == rect_width(&minbounds) || |
| 1746 | | rect_height(&bounds) == rect_height(&minbounds)); |
| 1747 | | m_ismaximized = (rect_width(&bounds) == rect_width(&maxbounds) || |
| 1748 | | rect_height(&bounds) == rect_height(&maxbounds)); |
| 1741 | m_isminimized = (rect_width(&bounds) == minbounds.width()) || |
| 1742 | (rect_height(&bounds) == minbounds.height()); |
| 1743 | m_ismaximized = (rect_width(&bounds) == maxbounds.width()) || |
| 1744 | (rect_height(&bounds) == maxbounds.height()); |
| 1749 | 1745 | } |
| 1750 | 1746 | else |
| 1751 | 1747 | { |
| r243824 | r243825 | |
| 1763 | 1759 | |
| 1764 | 1760 | void win_window_info::minimize_window() |
| 1765 | 1761 | { |
| 1766 | | RECT newsize; |
| 1767 | | |
| 1768 | 1762 | assert(GetCurrentThreadId() == window_threadid); |
| 1769 | 1763 | |
| 1770 | | get_min_bounds(&newsize, video_config.keepaspect); |
| 1771 | | SetWindowPos(m_hwnd, NULL, newsize.left, newsize.top, rect_width(&newsize), rect_height(&newsize), SWP_NOZORDER); |
| 1764 | osd_dim newsize = get_min_bounds(video_config.keepaspect); |
| 1765 | |
| 1766 | // get the window rect |
| 1767 | RECT bounds; |
| 1768 | GetWindowRect(m_hwnd, &bounds); |
| 1769 | |
| 1770 | osd_rect newrect(bounds.left, bounds.top, newsize ); |
| 1771 | |
| 1772 | |
| 1773 | SetWindowPos(m_hwnd, NULL, newrect.left(), newrect.top(), newrect.width(), newrect.height(), SWP_NOZORDER); |
| 1772 | 1774 | } |
| 1773 | 1775 | |
| 1774 | 1776 | |
| r243824 | r243825 | |
| 1780 | 1782 | |
| 1781 | 1783 | void win_window_info::maximize_window() |
| 1782 | 1784 | { |
| 1783 | | RECT newsize; |
| 1784 | | |
| 1785 | 1785 | assert(GetCurrentThreadId() == window_threadid); |
| 1786 | 1786 | |
| 1787 | | get_max_bounds(&newsize, video_config.keepaspect); |
| 1788 | | SetWindowPos(m_hwnd, NULL, newsize.left, newsize.top, rect_width(&newsize), rect_height(&newsize), SWP_NOZORDER); |
| 1787 | osd_dim newsize = get_max_bounds(video_config.keepaspect); |
| 1788 | |
| 1789 | // center within the work area |
| 1790 | osd_rect work = m_monitor->usuable_position_size(); |
| 1791 | osd_rect newrect = osd_rect(work.left() + (work.width() - newsize.width()) / 2, |
| 1792 | work.top() + (work.height() - newsize.height()) / 2, |
| 1793 | newsize); |
| 1794 | |
| 1795 | SetWindowPos(m_hwnd, NULL, newrect.left(), newrect.top(), newrect.width(), newrect.height(), SWP_NOZORDER); |
| 1789 | 1796 | } |
| 1790 | 1797 | |
| 1791 | 1798 | |
| r243824 | r243825 | |
| 1797 | 1804 | |
| 1798 | 1805 | void win_window_info::adjust_window_position_after_major_change() |
| 1799 | 1806 | { |
| 1800 | | RECT oldrect, newrect; |
| 1807 | RECT oldrect; |
| 1801 | 1808 | |
| 1802 | 1809 | assert(GetCurrentThreadId() == window_threadid); |
| 1803 | 1810 | |
| 1804 | 1811 | // get the current size |
| 1805 | 1812 | GetWindowRect(m_hwnd, &oldrect); |
| 1813 | osd_rect newrect = RECT_to_osd_rect(oldrect); |
| 1806 | 1814 | |
| 1807 | 1815 | // adjust the window size so the client area is what we want |
| 1808 | 1816 | if (!m_fullscreen) |
| 1809 | 1817 | { |
| 1810 | 1818 | // constrain the existing size to the aspect ratio |
| 1811 | | newrect = oldrect; |
| 1812 | 1819 | if (video_config.keepaspect) |
| 1813 | | constrain_to_aspect_ratio(&newrect, WMSZ_BOTTOMRIGHT); |
| 1820 | newrect = constrain_to_aspect_ratio(newrect, WMSZ_BOTTOMRIGHT); |
| 1814 | 1821 | } |
| 1815 | 1822 | |
| 1816 | 1823 | // in full screen, make sure it covers the primary display |
| r243824 | r243825 | |
| 1821 | 1828 | } |
| 1822 | 1829 | |
| 1823 | 1830 | // adjust the position if different |
| 1824 | | if (oldrect.left != newrect.left || oldrect.top != newrect.top || |
| 1825 | | oldrect.right != newrect.right || oldrect.bottom != newrect.bottom) |
| 1831 | if (oldrect.left != newrect.left() || oldrect.top != newrect.top() || |
| 1832 | oldrect.right != newrect.right() || oldrect.bottom != newrect.bottom()) |
| 1826 | 1833 | SetWindowPos(m_hwnd, m_fullscreen ? HWND_TOPMOST : HWND_TOP, |
| 1827 | | newrect.left, newrect.top, |
| 1828 | | rect_width(&newrect), rect_height(&newrect), 0); |
| 1834 | newrect.left(), newrect.top(), |
| 1835 | newrect.width(), newrect.height(), 0); |
| 1829 | 1836 | |
| 1830 | 1837 | // take note of physical window size (used for lightgun coordinate calculation) |
| 1831 | 1838 | if (this == win_window_list) |
| 1832 | 1839 | { |
| 1833 | | win_physical_width = rect_width(&newrect); |
| 1834 | | win_physical_height = rect_height(&newrect); |
| 1840 | win_physical_width = newrect.width(); |
| 1841 | win_physical_height = newrect.height(); |
| 1835 | 1842 | logerror("Physical width %d, height %d\n",win_physical_width,win_physical_height); |
| 1836 | 1843 | } |
| 1837 | 1844 | } |