diff options
Diffstat (limited to 'src/Screen.cc')
-rw-r--r-- | src/Screen.cc | 139 |
1 files changed, 103 insertions, 36 deletions
diff --git a/src/Screen.cc b/src/Screen.cc index e3b08c6..bf5a625 100644 --- a/src/Screen.cc +++ b/src/Screen.cc | |||
@@ -360,6 +360,12 @@ BScreen::BScreen(FbTk::ResourceManager &rm, | |||
360 | Display *disp = m_root_window.display(); | 360 | Display *disp = m_root_window.display(); |
361 | Fluxbox *fluxbox = Fluxbox::instance(); | 361 | Fluxbox *fluxbox = Fluxbox::instance(); |
362 | 362 | ||
363 | // TODO fluxgen: check if this is the right place (it was not -lis) | ||
364 | // | ||
365 | // Create the first one, initXinerama will expand this if needed. | ||
366 | m_head_areas.resize(1); | ||
367 | m_head_areas[0] = new HeadArea(); | ||
368 | |||
363 | initXinerama(); | 369 | initXinerama(); |
364 | 370 | ||
365 | // setup error handler to catch "screen already managed by other wm" | 371 | // setup error handler to catch "screen already managed by other wm" |
@@ -402,9 +408,6 @@ BScreen::BScreen(FbTk::ResourceManager &rm, | |||
402 | XFree(ret_prop); | 408 | XFree(ret_prop); |
403 | } | 409 | } |
404 | 410 | ||
405 | // TODO fluxgen: check if this is the right place | ||
406 | m_head_areas = new HeadArea[numHeads() ? numHeads() : 1]; | ||
407 | |||
408 | #ifdef HAVE_RANDR | 411 | #ifdef HAVE_RANDR |
409 | // setup RANDR for this screens root window | 412 | // setup RANDR for this screens root window |
410 | // we need to determine if we should use old randr select input function or not | 413 | // we need to determine if we should use old randr select input function or not |
@@ -556,21 +559,32 @@ BScreen::~BScreen() { | |||
556 | // we need to destroy it before we destroy workspaces | 559 | // we need to destroy it before we destroy workspaces |
557 | m_workspacemenu.reset(0); | 560 | m_workspacemenu.reset(0); |
558 | 561 | ||
559 | ExtraMenus::iterator mit = m_extramenus.begin(); | 562 | if (m_extramenus.size()) { |
560 | ExtraMenus::iterator mit_end = m_extramenus.end(); | 563 | // check whether extramenus are included in windowmenu |
561 | for (; mit != mit_end; ++mit) { | 564 | // if not, we clean them ourselves |
562 | // we set them to NOT internal so that they will be deleted when the | 565 | bool extramenus_in_windowmenu = false; |
563 | // menu is cleaned up. We can't delete them here because they are | 566 | for (size_t i = 0, n = m_windowmenu->numberOfItems(); i < n; i++) |
564 | // still in the menu | 567 | if (m_windowmenu->find(i)->submenu() == m_extramenus.begin()->second) { |
565 | // (They need to be internal for most of the time so that if we | 568 | extramenus_in_windowmenu = true; |
566 | // rebuild the menu, then they won't be removed. | 569 | break; |
567 | if (mit->second->parent() == 0) { | 570 | } |
568 | // not attached to our windowmenu | 571 | |
569 | // so we clean it up | 572 | ExtraMenus::iterator mit = m_extramenus.begin(); |
570 | delete mit->second; | 573 | ExtraMenus::iterator mit_end = m_extramenus.end(); |
571 | } else { | 574 | for (; mit != mit_end; ++mit) { |
572 | // let the parent clean it up | 575 | // we set them to NOT internal so that they will be deleted when the |
573 | mit->second->setInternalMenu(false); | 576 | // menu is cleaned up. We can't delete them here because they are |
577 | // still in the menu | ||
578 | // (They need to be internal for most of the time so that if we | ||
579 | // rebuild the menu, then they won't be removed. | ||
580 | if (! extramenus_in_windowmenu) { | ||
581 | // not attached to our windowmenu | ||
582 | // so we clean it up | ||
583 | delete mit->second; | ||
584 | } else { | ||
585 | // let the parent clean it up | ||
586 | mit->second->setInternalMenu(false); | ||
587 | } | ||
574 | } | 588 | } |
575 | } | 589 | } |
576 | 590 | ||
@@ -600,7 +614,8 @@ BScreen::~BScreen() { | |||
600 | m_slit.reset(0); | 614 | m_slit.reset(0); |
601 | 615 | ||
602 | // TODO fluxgen: check if this is the right place | 616 | // TODO fluxgen: check if this is the right place |
603 | delete [] m_head_areas; | 617 | for (size_t i = 0; i < m_head_areas.size(); i++) |
618 | delete m_head_areas[i]; | ||
604 | 619 | ||
605 | delete m_focus_control; | 620 | delete m_focus_control; |
606 | delete m_placement_strategy; | 621 | delete m_placement_strategy; |
@@ -722,7 +737,12 @@ unsigned int BScreen::currentWorkspaceID() const { | |||
722 | } | 737 | } |
723 | 738 | ||
724 | const Strut* BScreen::availableWorkspaceArea(int head) const { | 739 | const Strut* BScreen::availableWorkspaceArea(int head) const { |
725 | return m_head_areas[head ? head-1 : 0].availableWorkspaceArea(); | 740 | if (head > numHeads()) { |
741 | /* May this ever happen? */ | ||
742 | static Strut whole(-1 /* should never be used */, 0, width(), 0, height()); | ||
743 | return &whole; | ||
744 | } | ||
745 | return m_head_areas[head ? head-1 : 0]->availableWorkspaceArea(); | ||
726 | } | 746 | } |
727 | 747 | ||
728 | unsigned int BScreen::maxLeft(int head) const { | 748 | unsigned int BScreen::maxLeft(int head) const { |
@@ -812,11 +832,8 @@ void BScreen::propertyNotify(Atom atom) { | |||
812 | } | 832 | } |
813 | 833 | ||
814 | void BScreen::keyPressEvent(XKeyEvent &ke) { | 834 | void BScreen::keyPressEvent(XKeyEvent &ke) { |
815 | WinClient *old = WindowCmd<void>::client(); | ||
816 | WindowCmd<void>::setWindow(FocusControl::focusedFbWindow()); | ||
817 | Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode, | 835 | Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode, |
818 | Keys::GLOBAL|Keys::ON_DESKTOP); | 836 | Keys::GLOBAL|Keys::ON_DESKTOP); |
819 | WindowCmd<void>::setClient(old); | ||
820 | } | 837 | } |
821 | 838 | ||
822 | void BScreen::keyReleaseEvent(XKeyEvent &ke) { | 839 | void BScreen::keyReleaseEvent(XKeyEvent &ke) { |
@@ -835,11 +852,8 @@ void BScreen::buttonPressEvent(XButtonEvent &be) { | |||
835 | imageControl().installRootColormap(); | 852 | imageControl().installRootColormap(); |
836 | 853 | ||
837 | Keys *keys = Fluxbox::instance()->keys(); | 854 | Keys *keys = Fluxbox::instance()->keys(); |
838 | WinClient *old = WindowCmd<void>::client(); | ||
839 | WindowCmd<void>::setWindow(FocusControl::focusedFbWindow()); | ||
840 | keys->doAction(be.type, be.state, be.button, Keys::GLOBAL|Keys::ON_DESKTOP, | 855 | keys->doAction(be.type, be.state, be.button, Keys::GLOBAL|Keys::ON_DESKTOP, |
841 | be.time); | 856 | 0, be.time); |
842 | WindowCmd<void>::setClient(old); | ||
843 | } | 857 | } |
844 | 858 | ||
845 | void BScreen::notifyUngrabKeyboard() { | 859 | void BScreen::notifyUngrabKeyboard() { |
@@ -1412,7 +1426,7 @@ Strut *BScreen::requestStrut(int head, int left, int right, int top, int bottom) | |||
1412 | 1426 | ||
1413 | Strut* next = 0; | 1427 | Strut* next = 0; |
1414 | for (int i = begin; i != end; i++) { | 1428 | for (int i = begin; i != end; i++) { |
1415 | next = m_head_areas[i].requestStrut(i+1, left, right, top, bottom, next); | 1429 | next = m_head_areas[i]->requestStrut(i+1, left, right, top, bottom, next); |
1416 | } | 1430 | } |
1417 | 1431 | ||
1418 | return next; | 1432 | return next; |
@@ -1422,7 +1436,9 @@ void BScreen::clearStrut(Strut *str) { | |||
1422 | if (str->next()) | 1436 | if (str->next()) |
1423 | clearStrut(str->next()); | 1437 | clearStrut(str->next()); |
1424 | int head = str->head() ? str->head() - 1 : 0; | 1438 | int head = str->head() ? str->head() - 1 : 0; |
1425 | m_head_areas[head].clearStrut(str); | 1439 | /* The number of heads may have changed, be careful. */ |
1440 | if (head < numHeads()) | ||
1441 | m_head_areas[head]->clearStrut(str); | ||
1426 | // str is invalid now | 1442 | // str is invalid now |
1427 | } | 1443 | } |
1428 | 1444 | ||
@@ -1431,7 +1447,7 @@ void BScreen::updateAvailableWorkspaceArea() { | |||
1431 | bool updated = false; | 1447 | bool updated = false; |
1432 | 1448 | ||
1433 | for (size_t i = 0; i < n; i++) { | 1449 | for (size_t i = 0; i < n; i++) { |
1434 | updated = m_head_areas[i].updateAvailableWorkspaceArea() || updated; | 1450 | updated = m_head_areas[i]->updateAvailableWorkspaceArea() || updated; |
1435 | } | 1451 | } |
1436 | 1452 | ||
1437 | if (updated) | 1453 | if (updated) |
@@ -1886,6 +1902,9 @@ void BScreen::renderPosWindow() { | |||
1886 | } | 1902 | } |
1887 | 1903 | ||
1888 | void BScreen::updateSize() { | 1904 | void BScreen::updateSize() { |
1905 | // update xinerama layout | ||
1906 | initXinerama(); | ||
1907 | |||
1889 | // force update geometry | 1908 | // force update geometry |
1890 | rootWindow().updateGeometry(); | 1909 | rootWindow().updateGeometry(); |
1891 | 1910 | ||
@@ -1895,6 +1914,9 @@ void BScreen::updateSize() { | |||
1895 | // send resize notify | 1914 | // send resize notify |
1896 | m_resize_sig.notify(); | 1915 | m_resize_sig.notify(); |
1897 | m_workspace_area_sig.notify(); | 1916 | m_workspace_area_sig.notify(); |
1917 | |||
1918 | // move windows out of inactive heads | ||
1919 | clearHeads(); | ||
1898 | } | 1920 | } |
1899 | 1921 | ||
1900 | 1922 | ||
@@ -1935,18 +1957,23 @@ WinClient *BScreen::findGroupRight(WinClient &winclient) { | |||
1935 | 1957 | ||
1936 | return other; | 1958 | return other; |
1937 | } | 1959 | } |
1960 | void BScreen::clearXinerama() { | ||
1961 | #ifdef DEBUG | ||
1962 | cerr<<"BScreen::initXinerama(): dont have Xinerama"<<endl; | ||
1963 | #endif // DEBUG | ||
1964 | m_xinerama_avail = false; | ||
1965 | if (m_xinerama_headinfo) | ||
1966 | delete [] m_xinerama_headinfo; | ||
1967 | m_xinerama_headinfo = 0; | ||
1968 | m_xinerama_num_heads = 0; | ||
1969 | } | ||
1938 | 1970 | ||
1939 | void BScreen::initXinerama() { | 1971 | void BScreen::initXinerama() { |
1940 | #ifdef XINERAMA | 1972 | #ifdef XINERAMA |
1941 | Display *display = FbTk::App::instance()->display(); | 1973 | Display *display = FbTk::App::instance()->display(); |
1942 | 1974 | ||
1943 | if (!XineramaIsActive(display)) { | 1975 | if (!XineramaIsActive(display)) { |
1944 | #ifdef DEBUG | 1976 | clearXinerama(); |
1945 | cerr<<"BScreen::initXinerama(): dont have Xinerama"<<endl; | ||
1946 | #endif // DEBUG | ||
1947 | m_xinerama_avail = false; | ||
1948 | m_xinerama_headinfo = 0; | ||
1949 | m_xinerama_num_heads = 0; | ||
1950 | return; | 1977 | return; |
1951 | } | 1978 | } |
1952 | #ifdef DEBUG | 1979 | #ifdef DEBUG |
@@ -1957,6 +1984,18 @@ void BScreen::initXinerama() { | |||
1957 | XineramaScreenInfo *screen_info; | 1984 | XineramaScreenInfo *screen_info; |
1958 | int number; | 1985 | int number; |
1959 | screen_info = XineramaQueryScreens(display, &number); | 1986 | screen_info = XineramaQueryScreens(display, &number); |
1987 | |||
1988 | /* The call may have actually failed. If this is the first time we init | ||
1989 | * Xinerama, fall back to turning it off. If not, pretend nothing | ||
1990 | * happened -- another event will tell us and it will work then. */ | ||
1991 | if (!screen_info) { | ||
1992 | if (!m_xinerama_headinfo) | ||
1993 | clearXinerama(); | ||
1994 | return; | ||
1995 | } | ||
1996 | |||
1997 | if (m_xinerama_headinfo) | ||
1998 | delete [] m_xinerama_headinfo; | ||
1960 | m_xinerama_headinfo = new XineramaHeadInfo[number]; | 1999 | m_xinerama_headinfo = new XineramaHeadInfo[number]; |
1961 | m_xinerama_num_heads = number; | 2000 | m_xinerama_num_heads = number; |
1962 | for (int i=0; i < number; i++) { | 2001 | for (int i=0; i < number; i++) { |
@@ -1970,6 +2009,18 @@ void BScreen::initXinerama() { | |||
1970 | cerr<<"BScreen::initXinerama(): number of heads ="<<number<<endl; | 2009 | cerr<<"BScreen::initXinerama(): number of heads ="<<number<<endl; |
1971 | #endif // DEBUG | 2010 | #endif // DEBUG |
1972 | 2011 | ||
2012 | /* Reallocate to the new number of heads. */ | ||
2013 | int ha_num = numHeads() ? numHeads() : 1, ha_oldnum = m_head_areas.size(); | ||
2014 | if (ha_num > ha_oldnum) { | ||
2015 | m_head_areas.resize(ha_num); | ||
2016 | for (int i = ha_oldnum; i < ha_num; i++) | ||
2017 | m_head_areas[i] = new HeadArea(); | ||
2018 | } else if (ha_num < ha_oldnum) { | ||
2019 | for (int i = ha_num; i < ha_oldnum; i++) | ||
2020 | delete m_head_areas[i]; | ||
2021 | m_head_areas.resize(ha_num); | ||
2022 | } | ||
2023 | |||
1973 | #else // XINERAMA | 2024 | #else // XINERAMA |
1974 | // no xinerama | 2025 | // no xinerama |
1975 | m_xinerama_avail = false; | 2026 | m_xinerama_avail = false; |
@@ -1978,6 +2029,22 @@ void BScreen::initXinerama() { | |||
1978 | 2029 | ||
1979 | } | 2030 | } |
1980 | 2031 | ||
2032 | /* Move windows out of inactive heads */ | ||
2033 | void BScreen::clearHeads() { | ||
2034 | if (!hasXinerama()) return; | ||
2035 | |||
2036 | for (Workspaces::iterator i = m_workspaces_list.begin(); | ||
2037 | i != m_workspaces_list.end(); i++) { | ||
2038 | for (Workspace::Windows::iterator win = (*i)->windowList().begin(); | ||
2039 | win != (*i)->windowList().end(); win++) { | ||
2040 | if (getHead((*win)->fbWindow()) == 0) { | ||
2041 | // first head is a safe bet here | ||
2042 | (*win)->placeWindow(1); | ||
2043 | } | ||
2044 | } | ||
2045 | } | ||
2046 | } | ||
2047 | |||
1981 | int BScreen::getHead(int x, int y) const { | 2048 | int BScreen::getHead(int x, int y) const { |
1982 | if (!hasXinerama()) return 0; | 2049 | if (!hasXinerama()) return 0; |
1983 | #ifdef XINERAMA | 2050 | #ifdef XINERAMA |