src/window.cpp
branchgamebalance
changeset 9895 7bd07f43b0e3
parent 6443 b8f06d8eb7be
child 9908 0fa543611bbe
equal deleted inserted replaced
9894:70d78ac95d6c 9895:7bd07f43b0e3
   497  * - Main window (gamefield), Toolbar, Statusbar (always on)
   497  * - Main window (gamefield), Toolbar, Statusbar (always on)
   498  * - News window, Chatbar (when on)
   498  * - News window, Chatbar (when on)
   499  * - Any sticked windows since we wanted to keep these
   499  * - Any sticked windows since we wanted to keep these
   500  * @return w pointer to the window that is going to be deleted
   500  * @return w pointer to the window that is going to be deleted
   501  */
   501  */
   502 static Window *FindDeletableWindow(void)
   502 static Window *FindDeletableWindow()
   503 {
   503 {
   504 	Window* const *wz;
   504 	Window* const *wz;
   505 
   505 
   506 	FOR_ALL_WINDOWS(wz) {
   506 	FOR_ALL_WINDOWS(wz) {
   507 		Window *w = *wz;
   507 		Window *w = *wz;
   517  * windows intact (Main window, Toolbar, Statusbar, News Window, Chatbar)
   517  * windows intact (Main window, Toolbar, Statusbar, News Window, Chatbar)
   518  * Start finding an appropiate candidate from the lowest z-values (bottom)
   518  * Start finding an appropiate candidate from the lowest z-values (bottom)
   519  * @see FindDeletableWindow()
   519  * @see FindDeletableWindow()
   520  * @return w Pointer to the window that is being deleted
   520  * @return w Pointer to the window that is being deleted
   521  */
   521  */
   522 static Window *ForceFindDeletableWindow(void)
   522 static Window *ForceFindDeletableWindow()
   523 {
   523 {
   524 	Window* const *wz;
   524 	Window* const *wz;
   525 
   525 
   526 	for (wz = _z_windows;; wz++) {
   526 	for (wz = _z_windows;; wz++) {
   527 		Window *w = *wz;
   527 		Window *w = *wz;
   553 		w->widget = NULL;
   553 		w->widget = NULL;
   554 		w->widget_count = 0;
   554 		w->widget_count = 0;
   555 	}
   555 	}
   556 }
   556 }
   557 
   557 
   558 static Window *FindFreeWindow(void)
   558 static Window *FindFreeWindow()
   559 {
   559 {
   560 	Window *w;
   560 	Window *w;
   561 
   561 
   562 	for (w = _windows; w < endof(_windows); w++) {
   562 	for (w = _windows; w < endof(_windows); w++) {
   563 		Window* const *wz;
   563 		Window* const *wz;
   663 							WindowProc *proc, WindowClass cls, const Widget *widget)
   663 							WindowProc *proc, WindowClass cls, const Widget *widget)
   664 {
   664 {
   665 	return LocalAllocateWindow(x, y, width, height, proc, cls, widget, 0);
   665 	return LocalAllocateWindow(x, y, width, height, proc, cls, widget, 0);
   666 }
   666 }
   667 
   667 
   668 typedef struct SizeRect {
   668 struct SizeRect {
   669 	int left,top,width,height;
   669 	int left,top,width,height;
   670 } SizeRect;
   670 };
   671 
   671 
   672 
   672 
   673 static SizeRect _awap_r;
   673 static SizeRect _awap_r;
   674 
   674 
   675 static bool IsGoodAutoPlace1(int left, int top)
   675 static bool IsGoodAutoPlace1(int left, int top)
   889 	}
   889 	}
   890 
   890 
   891 	return NULL;
   891 	return NULL;
   892 }
   892 }
   893 
   893 
   894 void InitWindowSystem(void)
   894 void InitWindowSystem()
   895 {
   895 {
   896 	IConsoleClose();
   896 	IConsoleClose();
   897 
   897 
   898 	memset(&_windows, 0, sizeof(_windows));
   898 	memset(&_windows, 0, sizeof(_windows));
   899 	_last_z_window = _z_windows;
   899 	_last_z_window = _z_windows;
   900 	InitViewports();
   900 	InitViewports();
   901 	_no_scroll = 0;
   901 	_no_scroll = 0;
   902 }
   902 }
   903 
   903 
   904 void UnInitWindowSystem(void)
   904 void UnInitWindowSystem()
   905 {
   905 {
   906 	Window **wz;
   906 	Window **wz;
   907 
   907 
   908 restart_search:
   908 restart_search:
   909 	/* Delete all windows, reset z-array.
   909 	/* Delete all windows, reset z-array.
   917 	}
   917 	}
   918 
   918 
   919 	assert(_last_z_window == _z_windows);
   919 	assert(_last_z_window == _z_windows);
   920 }
   920 }
   921 
   921 
   922 void ResetWindowSystem(void)
   922 void ResetWindowSystem()
   923 {
   923 {
   924 	UnInitWindowSystem();
   924 	UnInitWindowSystem();
   925 	InitWindowSystem();
   925 	InitWindowSystem();
   926 	_thd.pos.x = 0;
   926 	_thd.pos.x = 0;
   927 	_thd.pos.y = 0;
   927 	_thd.pos.y = 0;
   928 	_thd.new_pos.x = 0;
   928 	_thd.new_pos.x = 0;
   929 	_thd.new_pos.y = 0;
   929 	_thd.new_pos.y = 0;
   930 }
   930 }
   931 
   931 
   932 static void DecreaseWindowCounters(void)
   932 static void DecreaseWindowCounters()
   933 {
   933 {
   934 	Window *w;
   934 	Window *w;
   935 	Window* const *wz;
   935 	Window* const *wz;
   936 
   936 
   937 	for (wz = _last_z_window; wz != _z_windows;) {
   937 	for (wz = _last_z_window; wz != _z_windows;) {
   952 			if (w->desc_flags & WDF_UNCLICK_BUTTONS) RaiseWindowButtons(w);
   952 			if (w->desc_flags & WDF_UNCLICK_BUTTONS) RaiseWindowButtons(w);
   953 		}
   953 		}
   954 	}
   954 	}
   955 }
   955 }
   956 
   956 
   957 Window *GetCallbackWnd(void)
   957 Window *GetCallbackWnd()
   958 {
   958 {
   959 	return FindWindowById(_thd.window_class, _thd.window_number);
   959 	return FindWindowById(_thd.window_class, _thd.window_number);
   960 }
   960 }
   961 
   961 
   962 static void HandlePlacePresize(void)
   962 static void HandlePlacePresize()
   963 {
   963 {
   964 	Window *w;
   964 	Window *w;
   965 	WindowEvent e;
   965 	WindowEvent e;
   966 
   966 
   967 	if (_special_mouse_mode != WSM_PRESIZE) return;
   967 	if (_special_mouse_mode != WSM_PRESIZE) return;
   977 	e.we.place.tile = TileVirtXY(e.we.place.pt.x, e.we.place.pt.y);
   977 	e.we.place.tile = TileVirtXY(e.we.place.pt.x, e.we.place.pt.y);
   978 	e.event = WE_PLACE_PRESIZE;
   978 	e.event = WE_PLACE_PRESIZE;
   979 	w->wndproc(w, &e);
   979 	w->wndproc(w, &e);
   980 }
   980 }
   981 
   981 
   982 static bool HandleDragDrop(void)
   982 static bool HandleDragDrop()
   983 {
   983 {
   984 	Window *w;
   984 	Window *w;
   985 	WindowEvent e;
   985 	WindowEvent e;
   986 
   986 
   987 	if (_special_mouse_mode != WSM_DRAGDROP) return true;
   987 	if (_special_mouse_mode != WSM_DRAGDROP) return true;
  1001 		w->wndproc(w, &e);
  1001 		w->wndproc(w, &e);
  1002 	}
  1002 	}
  1003 	return false;
  1003 	return false;
  1004 }
  1004 }
  1005 
  1005 
  1006 static bool HandlePopupMenu(void)
  1006 static bool HandlePopupMenu()
  1007 {
  1007 {
  1008 	Window *w;
  1008 	Window *w;
  1009 	WindowEvent e;
  1009 	WindowEvent e;
  1010 
  1010 
  1011 	if (!_popup_menu_active) return true;
  1011 	if (!_popup_menu_active) return true;
  1028 	w->wndproc(w, &e);
  1028 	w->wndproc(w, &e);
  1029 
  1029 
  1030 	return false;
  1030 	return false;
  1031 }
  1031 }
  1032 
  1032 
  1033 static bool HandleMouseOver(void)
  1033 static bool HandleMouseOver()
  1034 {
  1034 {
  1035 	Window *w;
  1035 	Window *w;
  1036 	WindowEvent e;
  1036 	WindowEvent e;
  1037 	static Window *last_w = NULL;
  1037 	static Window *last_w = NULL;
  1038 
  1038 
  1112 	SetWindowDirty(w);
  1112 	SetWindowDirty(w);
  1113 }
  1113 }
  1114 
  1114 
  1115 static bool _dragging_window;
  1115 static bool _dragging_window;
  1116 
  1116 
  1117 static bool HandleWindowDragging(void)
  1117 static bool HandleWindowDragging()
  1118 {
  1118 {
  1119 	Window* const *wz;
  1119 	Window* const *wz;
  1120 	// Get out immediately if no window is being dragged at all.
  1120 	// Get out immediately if no window is being dragged at all.
  1121 	if (!_dragging_window) return true;
  1121 	if (!_dragging_window) return true;
  1122 
  1122 
  1336 	BringWindowToFront(w);
  1336 	BringWindowToFront(w);
  1337 	DeleteWindowById(WC_DROPDOWN_MENU, 0);
  1337 	DeleteWindowById(WC_DROPDOWN_MENU, 0);
  1338 }
  1338 }
  1339 
  1339 
  1340 
  1340 
  1341 static bool HandleScrollbarScrolling(void)
  1341 static bool HandleScrollbarScrolling()
  1342 {
  1342 {
  1343 	Window* const *wz;
  1343 	Window* const *wz;
  1344 	int i;
  1344 	int i;
  1345 	int pos;
  1345 	int pos;
  1346 	Scrollbar *sb;
  1346 	Scrollbar *sb;
  1383 
  1383 
  1384 	_scrolling_scrollbar = false;
  1384 	_scrolling_scrollbar = false;
  1385 	return false;
  1385 	return false;
  1386 }
  1386 }
  1387 
  1387 
  1388 static bool HandleViewportScroll(void)
  1388 static bool HandleViewportScroll()
  1389 {
  1389 {
  1390 	WindowEvent e;
  1390 	WindowEvent e;
  1391 	Window *w;
  1391 	Window *w;
  1392 
  1392 
       
  1393 	bool scrollwheel_scrolling = _patches.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
       
  1394 
  1393 	if (!_scrolling_viewport) return true;
  1395 	if (!_scrolling_viewport) return true;
  1394 
  1396 
  1395 	w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
  1397 	w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
  1396 
  1398 
  1397 	if (!_right_button_down || w == NULL) {
  1399 	if (!(_right_button_down || scrollwheel_scrolling) || w == NULL) {
  1398 		_cursor.fix_at = false;
  1400 		_cursor.fix_at = false;
  1399 		_scrolling_viewport = false;
  1401 		_scrolling_viewport = false;
  1400 		return true;
  1402 		return true;
  1401 	}
  1403 	}
  1402 
  1404 
  1404 		e.we.scroll.delta.x = -_cursor.delta.x;
  1406 		e.we.scroll.delta.x = -_cursor.delta.x;
  1405 		e.we.scroll.delta.y = -_cursor.delta.y;
  1407 		e.we.scroll.delta.y = -_cursor.delta.y;
  1406 	} else {
  1408 	} else {
  1407 		e.we.scroll.delta.x = _cursor.delta.x;
  1409 		e.we.scroll.delta.x = _cursor.delta.x;
  1408 		e.we.scroll.delta.y = _cursor.delta.y;
  1410 		e.we.scroll.delta.y = _cursor.delta.y;
       
  1411 	}
       
  1412 
       
  1413 	if (scrollwheel_scrolling) {
       
  1414 		/* We are using scrollwheels for scrolling */
       
  1415 		e.we.scroll.delta.x = _cursor.h_wheel;
       
  1416 		e.we.scroll.delta.y = _cursor.v_wheel;
       
  1417 		_cursor.v_wheel = 0;
       
  1418 		_cursor.h_wheel = 0;
  1409 	}
  1419 	}
  1410 
  1420 
  1411 	/* Create a scroll-event and send it to the window */
  1421 	/* Create a scroll-event and send it to the window */
  1412 	e.event = WE_SCROLL;
  1422 	e.event = WE_SCROLL;
  1413 	w->wndproc(w, &e);
  1423 	w->wndproc(w, &e);
  1578 		// When there is no toolbar w is null, check for that
  1588 		// When there is no toolbar w is null, check for that
  1579 		if (w != NULL) w->wndproc(w, &e);
  1589 		if (w != NULL) w->wndproc(w, &e);
  1580 	}
  1590 	}
  1581 }
  1591 }
  1582 
  1592 
  1583 extern void UpdateTileSelection(void);
  1593 extern void UpdateTileSelection();
  1584 extern bool VpHandlePlaceSizingDrag(void);
  1594 extern bool VpHandlePlaceSizingDrag();
  1585 
  1595 
  1586 static int _input_events_this_tick = 0;
  1596 static int _input_events_this_tick = 0;
  1587 
  1597 
  1588 static void HandleAutoscroll(void)
  1598 static void HandleAutoscroll()
  1589 {
  1599 {
  1590 	Window *w;
  1600 	Window *w;
  1591 	ViewPort *vp;
  1601 	ViewPort *vp;
  1592 	int x = _cursor.pos.x;
  1602 	int x = _cursor.pos.x;
  1593 	int y = _cursor.pos.y;
  1603 	int y = _cursor.pos.y;
  1626 void MouseLoop(int click, int mousewheel)
  1636 void MouseLoop(int click, int mousewheel)
  1627 {
  1637 {
  1628 	int x,y;
  1638 	int x,y;
  1629 	Window *w;
  1639 	Window *w;
  1630 	ViewPort *vp;
  1640 	ViewPort *vp;
       
  1641 	bool scrollwheel_scrolling = _patches.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
  1631 
  1642 
  1632 	DecreaseWindowCounters();
  1643 	DecreaseWindowCounters();
  1633 	HandlePlacePresize();
  1644 	HandlePlacePresize();
  1634 	UpdateTileSelection();
  1645 	UpdateTileSelection();
  1635 	if (!VpHandlePlaceSizingDrag())  return;
  1646 	if (!VpHandlePlaceSizingDrag())  return;
  1641 	if (!HandleMouseOver())          return;
  1652 	if (!HandleMouseOver())          return;
  1642 
  1653 
  1643 	x = _cursor.pos.x;
  1654 	x = _cursor.pos.x;
  1644 	y = _cursor.pos.y;
  1655 	y = _cursor.pos.y;
  1645 
  1656 
  1646 	if (click == 0 && mousewheel == 0) return;
  1657 	if (click == 0 && mousewheel == 0 && !scrollwheel_scrolling) return;
  1647 
  1658 
  1648 	w = FindWindowFromPt(x, y);
  1659 	w = FindWindowFromPt(x, y);
  1649 	if (w == NULL) return;
  1660 	if (w == NULL) return;
  1650 	if (!MaybeBringWindowToFront(w)) return;
  1661 	if (!MaybeBringWindowToFront(w)) return;
  1651 	vp = IsPtInWindowViewport(w, x, y);
  1662 	vp = IsPtInWindowViewport(w, x, y);
  1652 
  1663 
  1653 	/* Don't allow any action in a viewport if either in menu of in generating world */
  1664 	/* Don't allow any action in a viewport if either in menu of in generating world */
  1654 	if (vp != NULL && (_game_mode == GM_MENU || IsGeneratingWorld())) return;
  1665 	if (vp != NULL && (_game_mode == GM_MENU || IsGeneratingWorld())) return;
  1655 
  1666 
  1656 	if (mousewheel != 0) {
  1667 	if (mousewheel != 0) {
  1657 		WindowEvent e;
  1668 		if (_patches.scrollwheel_scrolling == 0) {
  1658 
  1669 			/* Scrollwheel is in zoom mode. Make the zoom event. */
  1659 		/* Send WE_MOUSEWHEEL event to window */
  1670 			WindowEvent e;
  1660 		e.event = WE_MOUSEWHEEL;
  1671 
  1661 		e.we.wheel.wheel = mousewheel;
  1672 			/* Send WE_MOUSEWHEEL event to window */
  1662 		w->wndproc(w, &e);
  1673 			e.event = WE_MOUSEWHEEL;
       
  1674 			e.we.wheel.wheel = mousewheel;
       
  1675 			w->wndproc(w, &e);
       
  1676 		}
  1663 
  1677 
  1664 		/* Dispatch a MouseWheelEvent for widgets if it is not a viewport */
  1678 		/* Dispatch a MouseWheelEvent for widgets if it is not a viewport */
  1665 		if (vp == NULL) DispatchMouseWheelEvent(w, GetWidgetFromPos(w, x - w->left, y - w->top), mousewheel);
  1679 		if (vp == NULL) DispatchMouseWheelEvent(w, GetWidgetFromPos(w, x - w->left, y - w->top), mousewheel);
  1666 	}
  1680 	}
  1667 
  1681 
  1668 	if (vp != NULL) {
  1682 	if (vp != NULL) {
       
  1683 		if (scrollwheel_scrolling) click = 2; // we are using the scrollwheel in a viewport, so we emulate right mouse button
  1669 		switch (click) {
  1684 		switch (click) {
  1670 			case 1:
  1685 			case 1:
  1671 				DEBUG(misc, 2, "Cursor: 0x%X (%d)", _cursor.sprite, _cursor.sprite);
  1686 				DEBUG(misc, 2, "Cursor: 0x%X (%d)", _cursor.sprite, _cursor.sprite);
  1672 				if (_thd.place_mode != 0 &&
  1687 				if (_thd.place_mode != 0 &&
  1673 						// query button and place sign button work in pause mode
  1688 						// query button and place sign button work in pause mode
  1674 						_cursor.sprite != SPR_CURSOR_QUERY &&
  1689 						_cursor.sprite != SPR_CURSOR_QUERY &&
  1675 						_cursor.sprite != SPR_CURSOR_SIGN &&
  1690 						_cursor.sprite != SPR_CURSOR_SIGN &&
  1676 						_pause != 0 &&
  1691 						_pause_game != 0 &&
  1677 						!_cheats.build_in_pause.value) {
  1692 						!_cheats.build_in_pause.value) {
  1678 					return;
  1693 					return;
  1679 				}
  1694 				}
  1680 
  1695 
  1681 				if (_thd.place_mode == 0) {
  1696 				if (_thd.place_mode == 0) {
  1693 				break;
  1708 				break;
  1694 		}
  1709 		}
  1695 	} else {
  1710 	} else {
  1696 		switch (click) {
  1711 		switch (click) {
  1697 			case 1: DispatchLeftClickEvent(w, x - w->left, y - w->top);  break;
  1712 			case 1: DispatchLeftClickEvent(w, x - w->left, y - w->top);  break;
       
  1713 			default:
       
  1714 				if (!scrollwheel_scrolling || w == NULL || w->window_class != WC_SMALLMAP) break;
       
  1715 				/* We try to use the scrollwheel to scroll since we didn't touch any of the buttons.
       
  1716 				* Simulate a right button click so we can get started. */
       
  1717 				/* fallthough */
  1698 			case 2: DispatchRightClickEvent(w, x - w->left, y - w->top); break;
  1718 			case 2: DispatchRightClickEvent(w, x - w->left, y - w->top); break;
  1699 		}
  1719 		}
  1700 	}
  1720 	}
  1701 }
  1721 }
  1702 
  1722 
  1703 void HandleMouseEvents(void)
  1723 void HandleMouseEvents()
  1704 {
  1724 {
  1705 	int click;
  1725 	int click;
  1706 	int mousewheel;
  1726 	int mousewheel;
  1707 
  1727 
  1708 	/*
  1728 	/*
  1736 	}
  1756 	}
  1737 
  1757 
  1738 	MouseLoop(click, mousewheel);
  1758 	MouseLoop(click, mousewheel);
  1739 }
  1759 }
  1740 
  1760 
  1741 void InputLoop(void)
  1761 void InputLoop()
  1742 {
  1762 {
  1743 	HandleMouseEvents();
  1763 	HandleMouseEvents();
  1744 	HandleAutoscroll();
  1764 	HandleAutoscroll();
  1745 }
  1765 }
  1746 
  1766 
  1747 void UpdateWindows(void)
  1767 void UpdateWindows()
  1748 {
  1768 {
  1749 	Window* const *wz;
  1769 	Window* const *wz;
  1750 	static int we4_timer = 0;
  1770 	static int we4_timer = 0;
  1751 	int t = we4_timer + 1;
  1771 	int t = we4_timer + 1;
  1752 
  1772 
  1855 	FOR_ALL_WINDOWS(wz) {
  1875 	FOR_ALL_WINDOWS(wz) {
  1856 		if ((*wz)->window_class == cls) InvalidateThisWindowData(*wz);
  1876 		if ((*wz)->window_class == cls) InvalidateThisWindowData(*wz);
  1857 	}
  1877 	}
  1858 }
  1878 }
  1859 
  1879 
  1860 void CallWindowTickEvent(void)
  1880 void CallWindowTickEvent()
  1861 {
  1881 {
  1862 	Window* const *wz;
  1882 	Window* const *wz;
  1863 
  1883 
  1864 	for (wz = _last_z_window; wz != _z_windows;) {
  1884 	for (wz = _last_z_window; wz != _z_windows;) {
  1865 		CallWindowEventNP(*--wz, WE_TICK);
  1885 		CallWindowEventNP(*--wz, WE_TICK);
  1866 	}
  1886 	}
  1867 }
  1887 }
  1868 
  1888 
  1869 void DeleteNonVitalWindows(void)
  1889 void DeleteNonVitalWindows()
  1870 {
  1890 {
  1871 	Window* const *wz;
  1891 	Window* const *wz;
  1872 
  1892 
  1873 restart_search:
  1893 restart_search:
  1874 	/* When we find the window to delete, we need to restart the search
  1894 	/* When we find the window to delete, we need to restart the search
  1893 /* It is possible that a stickied window gets to a position where the
  1913 /* It is possible that a stickied window gets to a position where the
  1894  * 'close' button is outside the gaming area. You cannot close it then; except
  1914  * 'close' button is outside the gaming area. You cannot close it then; except
  1895  * with this function. It closes all windows calling the standard function,
  1915  * with this function. It closes all windows calling the standard function,
  1896  * then, does a little hacked loop of closing all stickied windows. Note
  1916  * then, does a little hacked loop of closing all stickied windows. Note
  1897  * that standard windows (status bar, etc.) are not stickied, so these aren't affected */
  1917  * that standard windows (status bar, etc.) are not stickied, so these aren't affected */
  1898 void DeleteAllNonVitalWindows(void)
  1918 void DeleteAllNonVitalWindows()
  1899 {
  1919 {
  1900 	Window* const *wz;
  1920 	Window* const *wz;
  1901 
  1921 
  1902 	/* Delete every window except for stickied ones, then sticky ones as well */
  1922 	/* Delete every window except for stickied ones, then sticky ones as well */
  1903 	DeleteNonVitalWindows();
  1923 	DeleteNonVitalWindows();
  1913 		}
  1933 		}
  1914 	}
  1934 	}
  1915 }
  1935 }
  1916 
  1936 
  1917 /* Delete all always on-top windows to get an empty screen */
  1937 /* Delete all always on-top windows to get an empty screen */
  1918 void HideVitalWindows(void)
  1938 void HideVitalWindows()
  1919 {
  1939 {
  1920 	DeleteWindowById(WC_TOOLBAR_MENU, 0);
  1940 	DeleteWindowById(WC_TOOLBAR_MENU, 0);
  1921 	DeleteWindowById(WC_MAIN_TOOLBAR, 0);
  1941 	DeleteWindowById(WC_MAIN_TOOLBAR, 0);
  1922 	DeleteWindowById(WC_STATUS_BAR, 0);
  1942 	DeleteWindowById(WC_STATUS_BAR, 0);
  1923 }
  1943 }