+
+
+void BScreen::addStrut(Strut *strut) {
+ strutList.push_back(strut);
+}
+
+
+void BScreen::removeStrut(Strut *strut) {
+ strutList.remove(strut);
+}
+
+
+const Rect& BScreen::availableArea(void) const {
+ if (doFullMax())
+ return getRect(); // return the full screen
+ return usableArea;
+}
+
+
+#ifdef XINERAMA
+const RectList& BScreen::allAvailableAreas(void) const {
+ assert(isXineramaActive());
+ assert(xineramaUsableArea.size() > 0);
+ fprintf(stderr, "1found x %d y %d w %d h %d\n",
+ xineramaUsableArea[0].x(), xineramaUsableArea[0].y(),
+ xineramaUsableArea[0].width(), xineramaUsableArea[0].height());
+ return xineramaUsableArea;
+}
+#endif // XINERAMA
+
+
+void BScreen::updateAvailableArea(void) {
+ Rect old_area = usableArea;
+ usableArea = getRect(); // reset to full screen
+
+#ifdef XINERAMA
+ // reset to the full areas
+ if (isXineramaActive())
+ xineramaUsableArea = getXineramaAreas();
+#endif // XINERAMA
+
+ /* these values represent offsets from the screen edge
+ * we look for the biggest offset on each edge and then apply them
+ * all at once
+ * do not be confused by the similarity to the names of Rect's members
+ */
+ unsigned int current_left = 0, current_right = 0, current_top = 0,
+ current_bottom = 0;
+
+ StrutList::const_iterator it = strutList.begin(), end = strutList.end();
+
+ for(; it != end; ++it) {
+ Strut *strut = *it;
+ if (strut->left > current_left)
+ current_left = strut->left;
+ if (strut->top > current_top)
+ current_top = strut->top;
+ if (strut->right > current_right)
+ current_right = strut->right;
+ if (strut->bottom > current_bottom)
+ current_bottom = strut->bottom;
+ }
+
+ usableArea.setPos(current_left, current_top);
+ usableArea.setSize(usableArea.width() - (current_left + current_right),
+ usableArea.height() - (current_top + current_bottom));
+
+#ifdef XINERAMA
+ if (isXineramaActive()) {
+ // keep each of the ximerama-defined areas inside the strut
+ RectList::iterator xit, xend = xineramaUsableArea.end();
+ for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) {
+ if (xit->x() < usableArea.x()) {
+ xit->setX(usableArea.x());
+ xit->setWidth(xit->width() - usableArea.x());
+ }
+ if (xit->y() < usableArea.y()) {
+ xit->setY(usableArea.y());
+ xit->setHeight(xit->height() - usableArea.y());
+ }
+ if (xit->x() + xit->width() > usableArea.width())
+ xit->setWidth(usableArea.width() - xit->x());
+ if (xit->y() + xit->height() > usableArea.height())
+ xit->setHeight(usableArea.height() - xit->y());
+ }
+ }
+#endif // XINERAMA
+
+ if (old_area != usableArea) {
+ BlackboxWindowList::iterator it = windowList.begin(),
+ end = windowList.end();
+ for (; it != end; ++it)
+ if ((*it)->isMaximized()) (*it)->remaximize();
+ }
+
+ updateWorkArea();
+}
+
+
+Workspace* BScreen::getWorkspace(unsigned int index) {
+ assert(index < workspacesList.size());
+ return workspacesList[index];
+}
+
+
+void BScreen::buttonPressEvent(const XButtonEvent *xbutton) {
+ if (xbutton->button == 1) {
+ if (! isRootColormapInstalled())
+ image_control->installRootColormap();
+
+ if (workspacemenu->isVisible())
+ workspacemenu->hide();
+
+ if (rootmenu->isVisible())
+ rootmenu->hide();
+ } else if (xbutton->button == 2) {
+ int mx = xbutton->x_root - (workspacemenu->getWidth() / 2);
+ int my = xbutton->y_root - (workspacemenu->getTitleHeight() / 2);
+
+ if (mx < 0) mx = 0;
+ if (my < 0) my = 0;
+
+ if (mx + workspacemenu->getWidth() > getWidth())
+ mx = getWidth() - workspacemenu->getWidth() - getBorderWidth();
+
+ if (my + workspacemenu->getHeight() > getHeight())
+ my = getHeight() - workspacemenu->getHeight() - getBorderWidth();
+
+ workspacemenu->move(mx, my);
+
+ if (! workspacemenu->isVisible()) {
+ workspacemenu->removeParent();
+ workspacemenu->show();
+ }
+ } else if (xbutton->button == 3) {
+ int mx = xbutton->x_root - (rootmenu->getWidth() / 2);
+ int my = xbutton->y_root - (rootmenu->getTitleHeight() / 2);
+
+ if (mx < 0) mx = 0;
+ if (my < 0) my = 0;
+
+ if (mx + rootmenu->getWidth() > getWidth())
+ mx = getWidth() - rootmenu->getWidth() - getBorderWidth();
+
+ if (my + rootmenu->getHeight() > getHeight())
+ my = getHeight() - rootmenu->getHeight() - getBorderWidth();
+
+ rootmenu->move(mx, my);
+
+ if (! rootmenu->isVisible()) {
+ blackbox->checkMenu();
+ rootmenu->show();
+ }
+ // mouse wheel up
+ } else if ((xbutton->button == 4 && resource.root_scroll == NormalScroll) ||
+ (xbutton->button == 5 && resource.root_scroll == ReverseScroll)) {
+ if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1)
+ changeWorkspaceID(0);
+ else
+ changeWorkspaceID(getCurrentWorkspaceID() + 1);
+ // mouse wheel down
+ } else if ((xbutton->button == 5 && resource.root_scroll == NormalScroll) ||
+ (xbutton->button == 4 && resource.root_scroll == ReverseScroll)) {
+ if (getCurrentWorkspaceID() == 0)
+ changeWorkspaceID(getWorkspaceCount() - 1);
+ else
+ changeWorkspaceID(getCurrentWorkspaceID() - 1);
+ }
+}
+
+
+void BScreen::propertyNotifyEvent(const XPropertyEvent *pe) {
+ if (pe->atom == xatom->getAtom(XAtom::net_desktop_names)) {
+ // _NET_WM_DESKTOP_NAMES
+ WorkspaceList::iterator it = workspacesList.begin();
+ const WorkspaceList::iterator end = workspacesList.end();
+ for (; it != end; ++it) {
+ (*it)->readName(); // re-read its name from the window property
+ workspacemenu->changeWorkspaceLabel((*it)->getID(), (*it)->getName());
+ }
+ workspacemenu->update();
+ toolbar->reconfigure();
+ saveWorkspaceNames();
+ }
+}
+
+
+void BScreen::toggleFocusModel(FocusModel model) {
+ std::for_each(windowList.begin(), windowList.end(),
+ std::mem_fun(&BlackboxWindow::ungrabButtons));
+
+ if (model == SloppyFocus) {
+ saveSloppyFocus(True);
+ } else {
+ // we're cheating here to save writing the config file 3 times
+ resource.auto_raise = False;
+ resource.click_raise = False;
+ saveSloppyFocus(False);
+ }
+
+ std::for_each(windowList.begin(), windowList.end(),
+ std::mem_fun(&BlackboxWindow::grabButtons));
+}
+
+
+BTexture BScreen::readDatabaseTexture(const string &rname,
+ const string &default_color,
+ const Configuration &style) {
+ BTexture texture;
+ string s;
+
+ if (style.getValue(rname, s))
+ texture = BTexture(s);
+ else
+ texture.setTexture(BTexture::Solid | BTexture::Flat);
+
+ // associate this texture with this screen
+ texture.setDisplay(getBaseDisplay(), getScreenNumber());
+ texture.setImageControl(image_control);
+
+ if (texture.texture() & BTexture::Solid) {
+ texture.setColor(readDatabaseColor(rname + ".color",
+ default_color, style));
+ texture.setColorTo(readDatabaseColor(rname + ".colorTo",
+ default_color, style));
+ } else if (texture.texture() & BTexture::Gradient) {
+ texture.setColor(readDatabaseColor(rname + ".color",
+ default_color, style));
+ texture.setColorTo(readDatabaseColor(rname + ".colorTo",
+ default_color, style));
+ }
+
+ return texture;
+}
+
+
+BColor BScreen::readDatabaseColor(const string &rname,
+ const string &default_color,
+ const Configuration &style) {
+ BColor color;
+ string s;
+ if (style.getValue(rname, s))
+ color = BColor(s, getBaseDisplay(), getScreenNumber());
+ else
+ color = BColor(default_color, getBaseDisplay(), getScreenNumber());
+ return color;
+}
+
+
+BFont *BScreen::readDatabaseFont(const string &rbasename,
+ const Configuration &style) {
+ string fontname;
+
+ string s;
+
+#ifdef XFT
+ int i;
+ if (style.getValue(rbasename + "xft.font", s) &&
+ style.getValue(rbasename + "xft.size", i)) {
+ string family = s;
+ bool bold = False;
+ bool italic = False;
+ if (style.getValue(rbasename + "xft.flags", s)) {
+ if (s.find("bold") != string::npos)
+ bold = True;
+ if (s.find("italic") != string::npos)
+ italic = True;
+ }
+
+ BFont *b = new BFont(blackbox->getXDisplay(), this, family, i, bold,
+ italic, resource.aa_fonts);
+ if (b->valid())
+ return b;
+ else
+ delete b; // fall back to the normal X font stuff
+ }
+#endif // XFT
+
+ style.getValue(rbasename + "font", s);
+ // if this fails, a blank string will be used, which will cause the fallback
+ // font to load.
+
+ BFont *b = new BFont(blackbox->getXDisplay(), this, s);
+ if (! b->valid())
+ exit(2); // can't continue without a font
+ return b;
+}