X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2FScreen.cc;h=1bea9bae9999b4ebd3edd6c3b32723dcc850c89b;hb=f4c0547b7a90c9647a2c39c3d1a737142eab088e;hp=159e2ae3ee5974d4c9f2995602cf1047f2e5cfb4;hpb=b8ee3dbc4565efb19338c5cf1948f0f4e2f24fd6;p=chaz%2Fopenbox diff --git a/src/Screen.cc b/src/Screen.cc index 159e2ae3..1bea9bae 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -66,8 +66,11 @@ extern "C" { #endif // HAVE_STDARG_H } +#include + #include #include +#include using std::string; #include "i18n.hh" @@ -137,9 +140,17 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { xatom->setSupported(this); // set-up netwm support #ifdef HAVE_GETPID - xatom->setValue(getRootWindow(), XAtom::blackbox_pid, XAtom::Type_Cardinal, + xatom->setValue(getRootWindow(), XAtom::blackbox_pid, XAtom::cardinal, (unsigned long) getpid()); #endif // HAVE_GETPID + unsigned long geometry[] = { getWidth(), + getHeight()}; + xatom->setValue(getRootWindow(), XAtom::net_desktop_geometry, + XAtom::cardinal, geometry, 2); + unsigned long viewport[] = {0,0}; + xatom->setValue(getRootWindow(), XAtom::net_desktop_viewport, + XAtom::cardinal, viewport, 2); + XDefineCursor(blackbox->getXDisplay(), getRootWindow(), blackbox->getSessionCursor()); @@ -230,21 +241,31 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { } saveWorkspaceNames(); + updateDesktopNames(); + updateNetizenWorkspaceCount(); + workspacemenu->insert(i18n(IconSet, IconIcons, "Icons"), iconmenu); workspacemenu->update(); current_workspace = workspacesList.front(); + + xatom->setValue(getRootWindow(), XAtom::net_current_desktop, + XAtom::cardinal, 0); //first workspace + workspacemenu->setItemSelected(2, True); + removeWorkspaceNames(); // do not need them any longer + toolbar = new Toolbar(this); slit = new Slit(this); InitMenu(); - raiseWindows(0, 0); + raiseWindows(0, 0); // this also initializes the empty stacking list rootmenu->update(); + updateClientList(); // initialize the client list, which will be empty updateAvailableArea(); changeWorkspaceID(0); @@ -415,6 +436,20 @@ void BScreen::saveHideToolbar(bool h) { } +void BScreen::saveWindowToWindowSnap(bool s) { + resource.window_to_window_snap = s; + config->setValue(screenstr + "windowToWindowSnap", + resource.window_to_window_snap); +} + + +void BScreen::saveWindowCornerSnap(bool s) { + resource.window_corner_snap = s; + config->setValue(screenstr + "windowCornerSnap", + resource.window_corner_snap); +} + + void BScreen::saveWorkspaces(unsigned int w) { resource.workspaces = w; config->setValue(screenstr + "workspaces", resource.workspaces); @@ -481,9 +516,10 @@ void BScreen::saveClock24Hour(Bool c) { void BScreen::saveWorkspaceNames() { string names; - WorkspaceList::iterator it; - WorkspaceList::iterator last = workspacesList.end() - 1; - for (it = workspacesList.begin(); it != workspacesList.end(); ++it) { + WorkspaceList::iterator it = workspacesList.begin(); + const WorkspaceList::iterator last = workspacesList.end() - 1; + const WorkspaceList::iterator end = workspacesList.end(); + for (; it != end; ++it) { names += (*it)->getName(); if (it != last) names += ','; @@ -501,6 +537,8 @@ void BScreen::save_rc(void) { saveFocusNew(resource.focus_new); saveFocusLast(resource.focus_last); saveHideToolbar(resource.hide_toolbar); + saveWindowToWindowSnap(resource.window_to_window_snap); + saveWindowCornerSnap(resource.window_corner_snap); saveWorkspaces(resource.workspaces); savePlacementPolicy(resource.placement_policy); saveEdgeSnapThreshold(resource.edge_snap_threshold); @@ -540,6 +578,14 @@ void BScreen::load_rc(void) { if (! config->getValue(screenstr + "hideToolbar", resource.hide_toolbar)) resource.hide_toolbar = false; + if (! config->getValue(screenstr + "windowToWindowSnap", + resource.window_to_window_snap)) + resource.window_to_window_snap = true; + + if (! config->getValue(screenstr + "windowCornerSnap", + resource.window_corner_snap)) + resource.window_corner_snap = true; + if (! config->getValue(screenstr + "imageDither", b)) b = true; image_control->setDither(b); @@ -560,7 +606,6 @@ void BScreen::load_rc(void) { else resource.col_direction = TopBottom; - removeWorkspaceNames(); if (config->getValue(screenstr + "workspaceNames", s)) { string::const_iterator it = s.begin(), end = s.end(); while(1) { @@ -675,11 +720,31 @@ void BScreen::reconfigure(void) { workspacemenu->reconfigure(); iconmenu->reconfigure(); - int remember_sub = rootmenu->getCurrentSubmenu(); + typedef std::vector SubList; + SubList remember_subs; + + // save the current open menus + Basemenu *menu = rootmenu; + int submenu; + while ((submenu = menu->getCurrentSubmenu()) >= 0) { + remember_subs.push_back(submenu); + menu = menu->find(submenu)->submenu(); + assert(menu); + } + InitMenu(); raiseWindows(0, 0); rootmenu->reconfigure(); - rootmenu->drawSubmenu(remember_sub); + + // reopen the saved menus + menu = rootmenu; + const SubList::iterator subs_end = remember_subs.end(); + for (SubList::iterator it = remember_subs.begin(); it != subs_end; ++it) { + menu->drawSubmenu(*it); + menu = menu->find(*it)->submenu(); + if (! menu) + break; + } configmenu->reconfigure(); @@ -960,7 +1025,7 @@ BlackboxWindow *BScreen::getIcon(unsigned int index) { unsigned int BScreen::addWorkspace(void) { Workspace *wkspc = new Workspace(this, workspacesList.size()); workspacesList.push_back(wkspc); - saveWorkspaces(getWorkspaceCount() + 1); + saveWorkspaces(getWorkspaceCount()); saveWorkspaceNames(); workspacemenu->insert(wkspc->getName(), wkspc->getMenu(), @@ -969,6 +1034,7 @@ unsigned int BScreen::addWorkspace(void) { toolbar->reconfigure(); + updateDesktopNames(); updateNetizenWorkspaceCount(); return workspacesList.size(); @@ -992,8 +1058,9 @@ unsigned int BScreen::removeLastWorkspace(void) { workspacesList.pop_back(); delete wkspc; - saveWorkspaces(getWorkspaceCount() - 1); + saveWorkspaces(getWorkspaceCount()); saveWorkspaceNames(); + updateDesktopNames(); toolbar->reconfigure(); @@ -1007,19 +1074,29 @@ void BScreen::changeWorkspaceID(unsigned int id) { if (! current_workspace) return; if (id != current_workspace->getID()) { + BlackboxWindow *focused = blackbox->getFocusedWindow(); + if (focused && focused->getScreen() == this && ! focused->isStuck()) { + if (focused->getWorkspaceNumber() != current_workspace->getID()) { + fprintf(stderr, "%s is on the wrong workspace, aborting\n", + focused->getTitle()); + abort(); + } + current_workspace->setLastFocusedWindow(focused); + } else { + // if no window had focus, no need to store a last focus + current_workspace->setLastFocusedWindow((BlackboxWindow *) 0); + } + // when we switch workspaces, unfocus whatever was focused + blackbox->setFocusedWindow((BlackboxWindow *) 0); + current_workspace->hideAll(); - workspacemenu->setItemSelected(current_workspace->getID() + 2, False); - if (blackbox->getFocusedWindow() && - blackbox->getFocusedWindow()->getScreen() == this && - (! blackbox->getFocusedWindow()->isStuck())) { - current_workspace->setLastFocusedWindow(blackbox->getFocusedWindow()); - blackbox->setFocusedWindow((BlackboxWindow *) 0); - } - current_workspace = getWorkspace(id); + xatom->setValue(getRootWindow(), XAtom::net_current_desktop, + XAtom::cardinal, id); + workspacemenu->setItemSelected(current_workspace->getID() + 2, True); toolbar->redrawWorkspaceLabel(True); @@ -1035,18 +1112,128 @@ void BScreen::changeWorkspaceID(unsigned int id) { } +/* + * Set the _NET_CLIENT_LIST root window property. + */ +void BScreen::updateClientList(void) { + if (windowList.size() > 0) { + Window *windows = new Window[windowList.size()]; + Window *win_it = windows; + BlackboxWindowList::iterator it = windowList.begin(); + const BlackboxWindowList::iterator end = windowList.end(); + for (; it != end; ++it, ++win_it) + *win_it = (*it)->getClientWindow(); + xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window, + windows, windowList.size()); + delete [] windows; + } else + xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window, + 0, 0); +} + + +/* + * Set the _NET_CLIENT_LIST_STACKING root window property. + */ +void BScreen::updateStackingList(void) { + + BlackboxWindowList stack_order; + + /* + * Get the atacking order from all of the workspaces. + * We start with the current workspace so that the sticky windows will be + * in the right order on the current workspace. + * XXX: Do we need to have sticky windows in the list once for each workspace? + */ + getCurrentWorkspace()->appendStackOrder(stack_order); + for (unsigned int i = 0; i < getWorkspaceCount(); ++i) + if (i != getCurrentWorkspaceID()) + getWorkspace(i)->appendStackOrder(stack_order); + + if (stack_order.size() > 0) { + // set the client list atoms + Window *windows = new Window[stack_order.size()]; + Window *win_it = windows; + BlackboxWindowList::iterator it = stack_order.begin(); + const BlackboxWindowList::iterator end = stack_order.end(); + for (; it != end; ++it, ++win_it) + *win_it = (*it)->getClientWindow(); + xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking, + XAtom::window, windows, stack_order.size()); + delete [] windows; + } else + xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking, + XAtom::window, 0, 0); +} + + +void BScreen::addSystrayWindow(Window window) { + systrayWindowList.push_back(window); + xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows, + XAtom::window, + &systrayWindowList[0], systrayWindowList.size()); + blackbox->saveSystrayWindowSearch(window, this); +} + + +void BScreen::removeSystrayWindow(Window window) { + WindowList::iterator it = systrayWindowList.begin(); + const WindowList::iterator end = systrayWindowList.end(); + for (; it != end; ++it) + if (*it == window) { + systrayWindowList.erase(it); + xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows, + XAtom::window, + &systrayWindowList[0], systrayWindowList.size()); + blackbox->removeSystrayWindowSearch(window); + break; + } +} + + +void BScreen::addDesktopWindow(Window window) { + desktopWindowList.push_back(window); + XLowerWindow(blackbox->getXDisplay(), window); + XSelectInput(blackbox->getXDisplay(), window, StructureNotifyMask); + blackbox->saveDesktopWindowSearch(window, this); +} + + +void BScreen::removeDesktopWindow(Window window) { + WindowList::iterator it = desktopWindowList.begin(); + const WindowList::iterator end = desktopWindowList.end(); + for (; it != end; ++it) + if (*it == window) { + desktopWindowList.erase(it); + XSelectInput(blackbox->getXDisplay(), window, None); + blackbox->removeDesktopWindowSearch(window); + break; + } +} + + void BScreen::manageWindow(Window w) { new BlackboxWindow(blackbox, w, this); BlackboxWindow *win = blackbox->searchWindow(w); if (! win) return; + if (win->isDesktop()) { + // desktop windows cant do anything, so we remove all the normal window + // stuff from them, they are only kept around so that we can keep them on + // the bottom of the z-order + addDesktopWindow(win->getClientWindow()); + win->restore(True); + delete win; + return; + } windowList.push_back(win); + updateClientList(); XMapRequestEvent mre; mre.window = w; - win->restoreAttributes(); + if (blackbox->isStartup()) win->restoreAttributes(); win->mapRequestEvent(&mre); } @@ -1061,6 +1248,7 @@ void BScreen::unmanageWindow(BlackboxWindow *w, bool remap) { removeIcon(w); windowList.remove(w); + updateClientList(); if (blackbox->getFocusedWindow() == w) blackbox->setFocusedWindow((BlackboxWindow *) 0); @@ -1107,6 +1295,25 @@ void BScreen::removeNetizen(Window w) { } +void BScreen::updateWorkArea(void) { + if (workspacesList.size() > 0) { + unsigned long *dims = new unsigned long[4 * workspacesList.size()]; + for (unsigned int i = 0, m = workspacesList.size(); i < m; ++i) { + // XXX: this could be different for each workspace + const Rect &area = availableArea(); + dims[(i * 4) + 0] = area.x(); + dims[(i * 4) + 1] = area.y(); + dims[(i * 4) + 2] = area.width(); + dims[(i * 4) + 3] = area.height(); + } + xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal, + dims, 4 * workspacesList.size()); + } else + xatom->setValue(getRootWindow(), XAtom::net_workarea, XAtom::cardinal, + 0, 0); +} + + void BScreen::updateNetizenCurrentWorkspace(void) { std::for_each(netizenList.begin(), netizenList.end(), std::mem_fun(&Netizen::sendCurrentWorkspace)); @@ -1114,6 +1321,11 @@ void BScreen::updateNetizenCurrentWorkspace(void) { void BScreen::updateNetizenWorkspaceCount(void) { + xatom->setValue(getRootWindow(), XAtom::net_number_of_desktops, + XAtom::cardinal, workspacesList.size()); + + updateWorkArea(); + std::for_each(netizenList.begin(), netizenList.end(), std::mem_fun(&Netizen::sendWorkspaceCount)); } @@ -1122,6 +1334,10 @@ void BScreen::updateNetizenWorkspaceCount(void) { void BScreen::updateNetizenWindowFocus(void) { Window f = ((blackbox->getFocusedWindow()) ? blackbox->getFocusedWindow()->getClientWindow() : None); + + xatom->setValue(getRootWindow(), XAtom::net_active_window, + XAtom::window, f); + NetizenList::iterator it = netizenList.begin(); for (; it != netizenList.end(); ++it) (*it)->sendWindowFocus(f); @@ -1165,7 +1381,7 @@ void BScreen::updateNetizenConfigNotify(XEvent *e) { void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) { - // XXX: why 13?? + // the 13 represents the number of blackbox windows such as menus Window *session_stack = new Window[(num + workspacesList.size() + rootmenuList.size() + 13)]; unsigned int i = 0, k = num; @@ -1209,11 +1425,35 @@ void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) { XRestackWindows(blackbox->getXDisplay(), session_stack, i); delete [] session_stack; + + updateStackingList(); +} + + +void BScreen::lowerDesktops(void) { + XLowerWindow(blackbox->getXDisplay(), desktopWindowList[0]); + if (desktopWindowList.size() > 1) + XRestackWindows(blackbox->getXDisplay(), &desktopWindowList[0], + desktopWindowList.size()); } void BScreen::addWorkspaceName(const string& name) { workspaceNames.push_back(name); + updateDesktopNames(); +} + + +void BScreen::updateDesktopNames(){ + XAtom::StringVect names; + + WorkspaceList::iterator it = workspacesList.begin(); + const WorkspaceList::iterator end = workspacesList.end(); + for (; it != end; ++it) + names.push_back((*it)->getName()); + + xatom->setValue(getRootWindow(), XAtom::net_desktop_names, + XAtom::utf8, names); } @@ -1888,6 +2128,8 @@ void BScreen::updateAvailableArea(void) { for (; it != end; ++it) if ((*it)->isMaximized()) (*it)->remaximize(); } + + updateWorkArea(); }