aboutsummaryrefslogtreecommitdiff
path: root/src/Screen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Screen.cc')
-rw-r--r--src/Screen.cc139
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
724const Strut* BScreen::availableWorkspaceArea(int head) const { 739const 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
728unsigned int BScreen::maxLeft(int head) const { 748unsigned int BScreen::maxLeft(int head) const {
@@ -812,11 +832,8 @@ void BScreen::propertyNotify(Atom atom) {
812} 832}
813 833
814void BScreen::keyPressEvent(XKeyEvent &ke) { 834void 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
822void BScreen::keyReleaseEvent(XKeyEvent &ke) { 839void 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
845void BScreen::notifyUngrabKeyboard() { 859void 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
1888void BScreen::updateSize() { 1904void 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}
1960void 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
1939void BScreen::initXinerama() { 1971void 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 */
2033void 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
1981int BScreen::getHead(int x, int y) const { 2048int BScreen::getHead(int x, int y) const {
1982 if (!hasXinerama()) return 0; 2049 if (!hasXinerama()) return 0;
1983#ifdef XINERAMA 2050#ifdef XINERAMA