X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2FScreen.cc;h=7e7ce5a4f5d68342e337ab958319431336d93095;hb=72a2e98738d87b89620bafd15141690aa4be8fab;hp=dac5d6f8938421579ec4b3b2bb86761f66257a3d;hpb=9aaf4f8de762a540780aaef54d15802762dc4130;p=chaz%2Fopenbox diff --git a/src/Screen.cc b/src/Screen.cc index dac5d6f8..7e7ce5a4 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -21,16 +21,18 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +#ifdef HAVE_CONFIG_H #include "../config.h" +#endif // HAVE_CONFIG_H extern "C" { #include #include -// for strcasestr() -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif // _GNU_SOURCE +#ifdef XINERAMA +# include +# include +#endif // XINERAMA #ifdef HAVE_STDLIB_H # include @@ -76,6 +78,7 @@ using std::string; #include "i18n.hh" #include "blackbox.hh" #include "Clientmenu.hh" +#include "Font.hh" #include "GCCache.hh" #include "Iconmenu.hh" #include "Image.hh" @@ -87,6 +90,7 @@ using std::string; #include "Window.hh" #include "Workspace.hh" #include "Workspacemenu.hh" +#include "Util.hh" #include "XAtom.hh" #ifndef FONT_ELEMENT_SIZE @@ -110,7 +114,7 @@ static int anotherWMRunning(Display *display, XErrorEvent *) { BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { blackbox = bb; - screenstr = (string)"session.screen" + itostring(scrn) + '.'; + screenstr = "session.screen" + itostring(scrn) + '.'; config = blackbox->getConfig(); xatom = blackbox->getXAtom(); @@ -133,10 +137,10 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { rootmenu = 0; - resource.mstyle.t_fontset = resource.mstyle.f_fontset = - resource.tstyle.fontset = resource.wstyle.fontset = (XFontSet) 0; resource.mstyle.t_font = resource.mstyle.f_font = resource.tstyle.font = - resource.wstyle.font = (XFontStruct *) 0; + resource.wstyle.font = (BFont *) 0; + + geom_pixmap = None; xatom->setSupported(this); // set-up netwm support #ifdef HAVE_GETPID @@ -155,8 +159,7 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { XDefineCursor(blackbox->getXDisplay(), getRootWindow(), blackbox->getSessionCursor()); - // start off full screen, top left. - usableArea.setSize(getWidth(), getHeight()); + updateAvailableArea(); image_control = new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(), @@ -168,9 +171,6 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { LoadStyle(); XGCValues gcv; - unsigned long gc_value_mask = GCForeground; - if (! i18n.multibyte()) gc_value_mask |= GCFont; - gcv.foreground = WhitePixel(blackbox->getXDisplay(), getScreenNumber()) ^ BlackPixel(blackbox->getXDisplay(), getScreenNumber()); gcv.function = GXxor; @@ -180,23 +180,8 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { const char *s = i18n(ScreenSet, ScreenPositionLength, "0: 0000 x 0: 0000"); - int l = strlen(s); - - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical); - geom_w = logical.width; - - geom_h = resource.wstyle.fontset_extents->max_ink_extent.height; - } else { - geom_h = resource.wstyle.font->ascent + - resource.wstyle.font->descent; - - geom_w = XTextWidth(resource.wstyle.font, s, l); - } - - geom_w += (resource.bevel_width * 2); - geom_h += (resource.bevel_width * 2); + geom_w = resource.wstyle.font->measureString(s) + resource.bevel_width * 2; + geom_h = resource.wstyle.font->height() + resource.bevel_width * 2; XSetWindowAttributes attrib; unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder; @@ -227,17 +212,19 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { iconmenu = new Iconmenu(this); configmenu = new Configmenu(this); - Workspace *wkspc = (Workspace *) 0; - if (resource.workspaces != 0) { + if (resource.workspaces > 0) { for (unsigned int i = 0; i < resource.workspaces; ++i) { - wkspc = new Workspace(this, workspacesList.size()); + Workspace *wkspc = new Workspace(this, workspacesList.size()); workspacesList.push_back(wkspc); - workspacemenu->insert(wkspc->getName(), wkspc->getMenu()); + workspacemenu->insertWorkspace(wkspc); + workspacemenu->update(); + } } else { - wkspc = new Workspace(this, workspacesList.size()); + Workspace *wkspc = new Workspace(this, workspacesList.size()); workspacesList.push_back(wkspc); - workspacemenu->insert(wkspc->getName(), wkspc->getMenu()); + workspacemenu->insertWorkspace(wkspc); + workspacemenu->update(); } saveWorkspaceNames(); @@ -262,7 +249,7 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { raiseWindows(0, 0); // this also initializes the empty stacking list rootmenu->update(); - updateClientList(); // initialize the client list, which will be empty + updateClientList(); // initialize the client lists, which will be empty updateAvailableArea(); changeWorkspaceID(0); @@ -296,7 +283,7 @@ BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { // manage shown windows for (i = 0; i < nchild; ++i) { - if (children[i] == None || (! blackbox->validateWindow(children[i]))) + if (children[i] == None || ! blackbox->validateWindow(children[i])) continue; XWindowAttributes attrib; @@ -332,6 +319,9 @@ BScreen::~BScreen(void) { std::for_each(netizenList.begin(), netizenList.end(), PointerAssassin()); + while (! systrayWindowList.empty()) + removeSystrayWindow(systrayWindowList[0]); + delete rootmenu; delete workspacemenu; delete iconmenu; @@ -340,24 +330,42 @@ BScreen::~BScreen(void) { delete toolbar; delete image_control; - if (resource.wstyle.fontset) - XFreeFontSet(blackbox->getXDisplay(), resource.wstyle.fontset); - if (resource.mstyle.t_fontset) - XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.t_fontset); - if (resource.mstyle.f_fontset) - XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.f_fontset); - if (resource.tstyle.fontset) - XFreeFontSet(blackbox->getXDisplay(), resource.tstyle.fontset); - if (resource.wstyle.font) - XFreeFont(blackbox->getXDisplay(), resource.wstyle.font); + delete resource.wstyle.font; if (resource.mstyle.t_font) - XFreeFont(blackbox->getXDisplay(), resource.mstyle.t_font); + delete resource.mstyle.t_font; if (resource.mstyle.f_font) - XFreeFont(blackbox->getXDisplay(), resource.mstyle.f_font); + delete resource.mstyle.f_font; if (resource.tstyle.font) - XFreeFont(blackbox->getXDisplay(), resource.tstyle.font); - + delete resource.tstyle.font; + +#ifdef BITMAPBUTTONS + if (resource.wstyle.close_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask); + if (resource.wstyle.max_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask); + if (resource.wstyle.icon_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask); + if (resource.wstyle.stick_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask); + + if (resource.tstyle.left_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.tstyle.left_button.mask); + if (resource.tstyle.right_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.tstyle.right_button.mask); + + if (resource.mstyle.bullet_image.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.mstyle.bullet_image.mask); + if (resource.mstyle.tick_image.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.mstyle.tick_image.mask); + + resource.wstyle.max_button.mask = resource.wstyle.close_button.mask = + resource.wstyle.icon_button.mask = + resource.wstyle.stick_button.mask = None; + resource.tstyle.left_button.mask = resource.tstyle.right_button.mask = None; + resource.mstyle.bullet_image.mask = resource.mstyle.tick_image.mask = None; +#endif // BITMAPBUTTONS + XFreeGC(blackbox->getXDisplay(), opGC); } @@ -419,6 +427,20 @@ void BScreen::saveFocusLast(bool f) { } +void BScreen::saveAAFonts(bool f) { + resource.aa_fonts = f; + config->setValue(screenstr + "antialiasFonts", resource.aa_fonts); + reconfigure(); +} + + +void BScreen::saveShadowFonts(bool f) { + resource.shadow_fonts = f; + config->setValue(screenstr + "dropShadowFonts", resource.shadow_fonts); + reconfigure(); +} + + void BScreen::saveHideToolbar(bool h) { resource.hide_toolbar = h; if (resource.hide_toolbar) @@ -429,10 +451,35 @@ 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::saveWindowToEdgeSnap(int s) { + resource.snap_to_edges = s; + + const char *snap; + switch (resource.snap_to_edges) { + case WindowNoSnap: snap = "NoSnap"; break; + case WindowResistance: snap = "Resistance"; break; + case WindowSnap: default: snap = "Snap"; break; + } + config->setValue(screenstr + "windowToEdgeSnap", snap); +} + + +void BScreen::saveWindowToWindowSnap(int s) { + resource.snap_to_windows = s; + + const char *snap; + switch (resource.snap_to_windows) { + case WindowNoSnap: snap = "NoSnap"; break; + case WindowResistance: snap = "Resistance"; break; + case WindowSnap: default: snap = "Snap"; break; + } + config->setValue(screenstr + "windowToWindowSnap", snap); +} + + +void BScreen::saveResizeZones(unsigned int z) { + resource.resize_zones = z; + config->setValue(screenstr + "resizeZones", resource.resize_zones); } @@ -454,6 +501,8 @@ void BScreen::savePlacementPolicy(int p) { const char *placement; switch (resource.placement_policy) { case CascadePlacement: placement = "CascadePlacement"; break; + case UnderMousePlacement: placement = "UnderMousePlacement"; break; + case ClickMousePlacement: placement = "ClickMousePlacement"; break; case ColSmartPlacement: placement = "ColSmartPlacement"; break; case RowSmartPlacement: default: placement = "RowSmartPlacement"; break; } @@ -461,10 +510,24 @@ void BScreen::savePlacementPolicy(int p) { } -void BScreen::saveEdgeSnapThreshold(int t) { - resource.edge_snap_threshold = t; +void BScreen::saveResistanceSize(int s) { + resource.resistance_size = s; + config->setValue(screenstr + "resistanceSize", + resource.resistance_size); +} + + +void BScreen::saveSnapThreshold(int t) { + resource.snap_threshold = t; config->setValue(screenstr + "edgeSnapThreshold", - resource.edge_snap_threshold); + resource.snap_threshold); +} + + +void BScreen::saveSnapOffset(int t) { + resource.snap_offset = t; + config->setValue(screenstr + "edgeSnapOffset", + resource.snap_offset); } @@ -500,7 +563,7 @@ void BScreen::saveDateFormat(int f) { } -void BScreen::saveClock24Hour(Bool c) { +void BScreen::saveClock24Hour(bool c) { resource.clock24hour = c; config->setValue(screenstr + "clockFormat", resource.clock24hour ? 24 : 12); } @@ -508,36 +571,104 @@ void BScreen::saveClock24Hour(Bool c) { void BScreen::saveWorkspaceNames() { - XAtom::StringVect nameList; - unsigned long numnames = (unsigned) -1; string names; - if (numnames > 0 && - xatom->getValue(getRootWindow(), XAtom::net_desktop_names, XAtom::utf8, - numnames, nameList)) { - for (unsigned int i = 0; i < nameList.size(); ++i) { - if (i > 0) names += ","; - names += nameList[i]; - } + for (unsigned int i = 0; i < workspacesList.size(); ++i) { + names += workspacesList[i]->getName(); + if (i < workspacesList.size() - 1) + names += ','; } + config->setValue(screenstr + "workspaceNames", names); } +void BScreen::savePlaceIgnoreShaded(bool i) { + resource.ignore_shaded = i; + config->setValue(screenstr + "placementIgnoreShaded", + resource.ignore_shaded); +} + + +void BScreen::savePlaceIgnoreMaximized(bool i) { + resource.ignore_maximized = i; + config->setValue(screenstr + "placementIgnoreMaximized", + resource.ignore_maximized); +} + + +void BScreen::saveAllowScrollLock(bool a) { + resource.allow_scroll_lock = a; + config->setValue(screenstr + "disableBindingsWithScrollLock", + resource.allow_scroll_lock); +} + + +void BScreen::saveWorkspaceWarping(bool w) { + resource.workspace_warping = w; + config->setValue(screenstr + "workspaceWarping", + resource.workspace_warping); +} + + +void BScreen::saveRootScrollDirection(int d) { + resource.root_scroll = d; + const char *dir; + switch (resource.root_scroll) { + case NoScroll: dir = "None"; break; + case ReverseScroll: dir = "Reverse"; break; + case NormalScroll: default: dir = "Normal"; break; + } + config->setValue(screenstr + "rootScrollDirection", dir); +} + + +void BScreen::saveRootMenuButton(unsigned int b) { + resource.root_menu_button = b; + const char *but; + switch (resource.root_menu_button) { + case 0: but = "None"; break; + case 1: but = "Left"; break; + case 2: but = "Middle"; break; + case 3: default: but = "Right"; break; + } + config->setValue(screenstr + "rootMenuButton", but); +} + + +void BScreen::saveWorkspaceMenuButton(unsigned int b) { + resource.workspace_menu_button = b; + const char *but; + switch (resource.workspace_menu_button) { + case 0: but = "None"; break; + case 1: but = "Left"; break; + case 2: default: but = "Middle"; break; + case 3: but = "Right"; break; + } + config->setValue(screenstr + "workspaceMenuButton", but); +} + + void BScreen::save_rc(void) { saveSloppyFocus(resource.sloppy_focus); saveAutoRaise(resource.auto_raise); saveImageDither(doImageDither()); + saveShadowFonts(resource.shadow_fonts); + saveAAFonts(resource.aa_fonts); + saveResizeZones(resource.resize_zones); saveOpaqueMove(resource.opaque_move); saveFullMax(resource.full_max); saveFocusNew(resource.focus_new); saveFocusLast(resource.focus_last); saveHideToolbar(resource.hide_toolbar); - saveWindowToWindowSnap(resource.window_to_window_snap); + saveWindowToWindowSnap(resource.snap_to_windows); + saveWindowToEdgeSnap(resource.snap_to_edges); saveWindowCornerSnap(resource.window_corner_snap); saveWorkspaces(resource.workspaces); savePlacementPolicy(resource.placement_policy); - saveEdgeSnapThreshold(resource.edge_snap_threshold); + saveSnapThreshold(resource.snap_threshold); + saveSnapOffset(resource.snap_offset); + saveResistanceSize(resource.resistance_size); saveRowPlacementDirection(resource.row_direction); saveColPlacementDirection(resource.col_direction); #ifdef HAVE_STRFTIME @@ -546,6 +677,13 @@ void BScreen::save_rc(void) { saveDateFormat(resource.date_format); savwClock24Hour(resource.clock24hour); #endif // HAVE_STRFTIME + savePlaceIgnoreShaded(resource.ignore_shaded); + savePlaceIgnoreMaximized(resource.ignore_maximized); + saveAllowScrollLock(resource.allow_scroll_lock); + saveWorkspaceWarping(resource.workspace_warping); + saveRootScrollDirection(resource.root_scroll); + saveRootMenuButton(resource.root_menu_button); + saveWorkspaceMenuButton(resource.workspace_menu_button); toolbar->save_rc(); slit->save_rc(); @@ -571,12 +709,36 @@ void BScreen::load_rc(void) { if (! config->getValue(screenstr + "opaqueMove", resource.opaque_move)) resource.opaque_move = false; + if (! config->getValue(screenstr + "antialiasFonts", resource.aa_fonts)) + resource.aa_fonts = true; + + if (! resource.aa_fonts || + ! config->getValue(screenstr + "dropShadowFonts", resource.shadow_fonts)) + resource.shadow_fonts = false; + + if (! config->getValue(screenstr + "resizeZones", resource.resize_zones) || + (resource.resize_zones != 1 && resource.resize_zones != 2 && + resource.resize_zones != 4)) + resource.resize_zones = 4; + 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; + resource.snap_to_windows = WindowResistance; + if (config->getValue(screenstr + "windowToWindowSnap", s)) { + if (s == "NoSnap") + resource.snap_to_windows = WindowNoSnap; + else if (s == "Snap") + resource.snap_to_windows = WindowSnap; + } + + resource.snap_to_edges = WindowResistance; + if (config->getValue(screenstr + "windowToEdgeSnap", s)) { + if (s == "NoSnap") + resource.snap_to_edges = WindowNoSnap; + else if (s == "Snap") + resource.snap_to_edges = WindowSnap; + } if (! config->getValue(screenstr + "windowCornerSnap", resource.window_corner_snap)) @@ -586,9 +748,19 @@ void BScreen::load_rc(void) { b = true; image_control->setDither(b); + if (! config->getValue(screenstr + "edgeSnapOffset", + resource.snap_offset)) + resource.snap_offset = 0; + if (resource.snap_offset > 50) // sanity check, setting this huge would + resource.snap_offset = 50; // seriously suck. + if (! config->getValue(screenstr + "edgeSnapThreshold", - resource.edge_snap_threshold)) - resource.edge_snap_threshold = 4; + resource.snap_threshold)) + resource.snap_threshold = 4; + + if (! config->getValue(screenstr + "resistanceSize", + resource.resistance_size)) + resource.resistance_size = 18; if (config->getValue(screenstr + "rowPlacementDirection", s) && s == "RightToLeft") @@ -602,8 +774,9 @@ void BScreen::load_rc(void) { else resource.col_direction = TopBottom; - XAtom::StringVect workspaceNames; if (config->getValue(screenstr + "workspaceNames", s)) { + XAtom::StringVect workspaceNames; + string::const_iterator it = s.begin(), end = s.end(); while(1) { string::const_iterator tmp = it; // current string.begin() @@ -613,9 +786,10 @@ void BScreen::load_rc(void) { break; ++it; } + + xatom->setValue(getRootWindow(), XAtom::net_desktop_names, XAtom::utf8, + workspaceNames); } - xatom->setValue(getRootWindow(), XAtom::net_desktop_names, XAtom::utf8, - workspaceNames); resource.sloppy_focus = true; resource.auto_raise = false; @@ -635,6 +809,10 @@ void BScreen::load_rc(void) { if (config->getValue(screenstr + "windowPlacement", s)) { if (s == "CascadePlacement") resource.placement_policy = CascadePlacement; + else if (s == "UnderMousePlacement") + resource.placement_policy = UnderMousePlacement; + else if (s == "ClickMousePlacement") + resource.placement_policy = ClickMousePlacement; else if (s == "ColSmartPlacement") resource.placement_policy = ColSmartPlacement; else //if (s == "RowSmartPlacement") @@ -643,9 +821,8 @@ void BScreen::load_rc(void) { resource.placement_policy = RowSmartPlacement; #ifdef HAVE_STRFTIME - if (config->getValue(screenstr + "strftimeFormat", s)) - resource.strftime_format = s; - else + if (! config->getValue(screenstr + "strftimeFormat", + resource.strftime_format)) resource.strftime_format = "%I:%M %p"; #else // !HAVE_STRFTIME long l; @@ -659,19 +836,88 @@ void BScreen::load_rc(void) { l = 12; resource.clock24hour = l == 24; #endif // HAVE_STRFTIME + + if (! config->getValue(screenstr + "placementIgnoreShaded", + resource.ignore_shaded)) + resource.ignore_shaded = true; + + if (! config->getValue(screenstr + "placementIgnoreMaximized", + resource.ignore_maximized)) + resource.ignore_maximized = true; + + if (! config->getValue(screenstr + "disableBindingsWithScrollLock", + resource.allow_scroll_lock)) + resource.allow_scroll_lock = false; + + if (! config->getValue(screenstr + "workspaceWarping", + resource.workspace_warping)) + resource.workspace_warping = false; + + resource.root_scroll = NormalScroll; + if (config->getValue(screenstr + "rootScrollDirection", s)) { + if (s == "None") + resource.root_scroll = NoScroll; + else if (s == "Reverse") + resource.root_scroll = ReverseScroll; + } + + resource.root_menu_button = 3; + if (config->getValue(screenstr + "rootMenuButton", s)) { + if (s == "None") + resource.root_menu_button = 0; + else if (s == "Left") + resource.root_menu_button = 1; + else if (s == "Middle") + resource.root_menu_button = 2; + } + + resource.workspace_menu_button = 2; + if (config->getValue(screenstr + "workspaceMenuButton", s)) { + if (s == "None") + resource.workspace_menu_button = 0; + else if (s == "Left") + resource.workspace_menu_button = 1; + else if (s == "Right") + resource.workspace_menu_button = 3; + } + // cant both be the same + if (resource.workspace_menu_button == resource.root_menu_button) + resource.workspace_menu_button = 0; +} + + +void BScreen::changeWorkspaceCount(unsigned int new_count) { + assert(new_count > 0); + + if (new_count < workspacesList.size()) { + // shrink + for (unsigned int i = workspacesList.size(); i > new_count; --i) + removeLastWorkspace(); + // removeLast already sets the current workspace to the + // last available one. + } else if (new_count > workspacesList.size()) { + // grow + for(unsigned int i = workspacesList.size(); i < new_count; ++i) + addWorkspace(); + } } void BScreen::reconfigure(void) { + // don't reconfigure while saving the initial rc file, it's a waste and it + // breaks somethings (workspace names) + if (blackbox->isStartup()) return; + load_rc(); toolbar->load_rc(); slit->load_rc(); LoadStyle(); - XGCValues gcv; - unsigned long gc_value_mask = GCForeground; - if (! i18n.multibyte()) gc_value_mask |= GCFont; + // we need to do this explicitly, because just loading this value from the rc + // does nothing + changeWorkspaceCount(resource.workspaces); + XGCValues gcv; gcv.foreground = WhitePixel(blackbox->getXDisplay(), getScreenNumber()); gcv.function = GXinvert; @@ -681,22 +927,9 @@ void BScreen::reconfigure(void) { const char *s = i18n(ScreenSet, ScreenPositionLength, "0: 0000 x 0: 0000"); - int l = strlen(s); - - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical); - geom_w = logical.width; - - geom_h = resource.wstyle.fontset_extents->max_ink_extent.height; - } else { - geom_w = XTextWidth(resource.wstyle.font, s, l); - - geom_h = resource.wstyle.font->ascent + resource.wstyle.font->descent; - } - geom_w += (resource.bevel_width * 2); - geom_h += (resource.bevel_width * 2); + geom_w = resource.wstyle.font->measureString(s) + resource.bevel_width * 2; + geom_h = resource.wstyle.font->height() + resource.bevel_width * 2; BTexture* texture = &(resource.wstyle.l_focus); geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap); @@ -774,7 +1007,7 @@ void BScreen::rereadMenu(void) { void BScreen::LoadStyle(void) { - Configuration style; + Configuration style(False); const char *sfile = blackbox->getStyleFilename(); if (sfile != NULL) { @@ -786,54 +1019,27 @@ void BScreen::LoadStyle(void) { } } + // merge in the rc file + style.merge(config->file(), True); + string s; // load fonts/fontsets - if (resource.wstyle.fontset) - XFreeFontSet(blackbox->getXDisplay(), resource.wstyle.fontset); - if (resource.tstyle.fontset) - XFreeFontSet(blackbox->getXDisplay(), resource.tstyle.fontset); - if (resource.mstyle.f_fontset) - XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.f_fontset); - if (resource.mstyle.t_fontset) - XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.t_fontset); - resource.wstyle.fontset = 0; - resource.tstyle.fontset = 0; - resource.mstyle.f_fontset = 0; - resource.mstyle.t_fontset = 0; if (resource.wstyle.font) - XFreeFont(blackbox->getXDisplay(), resource.wstyle.font); + delete resource.wstyle.font; if (resource.tstyle.font) - XFreeFont(blackbox->getXDisplay(), resource.tstyle.font); + delete resource.tstyle.font; if (resource.mstyle.f_font) - XFreeFont(blackbox->getXDisplay(), resource.mstyle.f_font); + delete resource.mstyle.f_font; if (resource.mstyle.t_font) - XFreeFont(blackbox->getXDisplay(), resource.mstyle.t_font); - resource.wstyle.font = 0; - resource.tstyle.font = 0; - resource.mstyle.f_font = 0; - resource.mstyle.t_font = 0; - - if (i18n.multibyte()) { - resource.wstyle.fontset = readDatabaseFontSet("window.font", style); - resource.tstyle.fontset = readDatabaseFontSet("toolbar.font", style); - resource.mstyle.t_fontset = readDatabaseFontSet("menu.title.font", style); - resource.mstyle.f_fontset = readDatabaseFontSet("menu.frame.font", style); - - resource.mstyle.t_fontset_extents = - XExtentsOfFontSet(resource.mstyle.t_fontset); - resource.mstyle.f_fontset_extents = - XExtentsOfFontSet(resource.mstyle.f_fontset); - resource.tstyle.fontset_extents = - XExtentsOfFontSet(resource.tstyle.fontset); - resource.wstyle.fontset_extents = - XExtentsOfFontSet(resource.wstyle.fontset); - } else { - resource.wstyle.font = readDatabaseFont("window.font", style); - resource.tstyle.font = readDatabaseFont("toolbar.font", style); - resource.mstyle.t_font = readDatabaseFont("menu.title.font", style); - resource.mstyle.f_font = readDatabaseFont("menu.frame.font", style); - } + delete resource.mstyle.t_font; + resource.wstyle.font = resource.tstyle.font = resource.mstyle.f_font = + resource.mstyle.t_font = (BFont *) 0; + + resource.wstyle.font = readDatabaseFont("window.", style); + resource.tstyle.font = readDatabaseFont("toolbar.", style); + resource.mstyle.t_font = readDatabaseFont("menu.title.", style); + resource.mstyle.f_font = readDatabaseFont("menu.frame.", style); // load window config resource.wstyle.t_focus = @@ -858,10 +1064,43 @@ void BScreen::LoadStyle(void) { readDatabaseTexture("window.button.unfocus", "black", style); resource.wstyle.b_pressed = readDatabaseTexture("window.button.pressed", "black", style); - resource.wstyle.f_focus = - readDatabaseColor("window.frame.focusColor", "white", style); - resource.wstyle.f_unfocus = - readDatabaseColor("window.frame.unfocusColor", "black", style); + +#ifdef BITMAPBUTTONS + if (resource.wstyle.close_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.wstyle.close_button.mask); + if (resource.wstyle.max_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.wstyle.max_button.mask); + if (resource.wstyle.icon_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.wstyle.icon_button.mask); + if (resource.wstyle.stick_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.wstyle.stick_button.mask); + + resource.wstyle.close_button.mask = resource.wstyle.max_button.mask = + resource.wstyle.icon_button.mask = + resource.wstyle.icon_button.mask = None; + + readDatabaseMask("window.button.close.mask", resource.wstyle.close_button, + style); + readDatabaseMask("window.button.max.mask", resource.wstyle.max_button, + style); + readDatabaseMask("window.button.icon.mask", resource.wstyle.icon_button, + style); + readDatabaseMask("window.button.stick.mask", resource.wstyle.stick_button, + style); +#endif // BITMAPBUTTONS + + // we create the window.frame texture by hand because it exists only to + // make the code cleaner and is not actually used for display + BColor color = readDatabaseColor("window.frame.focusColor", "white", style); + resource.wstyle.f_focus = BTexture("solid flat", getBaseDisplay(), + getScreenNumber(), image_control); + resource.wstyle.f_focus.setColor(color); + + color = readDatabaseColor("window.frame.unfocusColor", "white", style); + resource.wstyle.f_unfocus = BTexture("solid flat", getBaseDisplay(), + getScreenNumber(), image_control); + resource.wstyle.f_unfocus.setColor(color); + resource.wstyle.l_text_focus = readDatabaseColor("window.label.focus.textColor", "black", style); resource.wstyle.l_text_unfocus = @@ -879,7 +1118,24 @@ void BScreen::LoadStyle(void) { resource.wstyle.justify = CenterJustify; } + // sanity checks + if (resource.wstyle.t_focus.texture() == BTexture::Parent_Relative) + resource.wstyle.t_focus = resource.wstyle.f_focus; + if (resource.wstyle.t_unfocus.texture() == BTexture::Parent_Relative) + resource.wstyle.t_unfocus = resource.wstyle.f_unfocus; + if (resource.wstyle.h_focus.texture() == BTexture::Parent_Relative) + resource.wstyle.h_focus = resource.wstyle.f_focus; + if (resource.wstyle.h_unfocus.texture() == BTexture::Parent_Relative) + resource.wstyle.h_unfocus = resource.wstyle.f_unfocus; + // load toolbar config +#ifdef BITMAPBUTTONS + if (resource.tstyle.left_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.tstyle.left_button.mask); + if (resource.tstyle.right_button.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.tstyle.right_button.mask); +#endif // BITMAPBUTTONS + resource.tstyle.toolbar = readDatabaseTexture("toolbar", "black", style); resource.tstyle.label = @@ -901,6 +1157,13 @@ void BScreen::LoadStyle(void) { resource.tstyle.b_pic = readDatabaseColor("toolbar.button.picColor", "black", style); +#ifdef BITMAPBUTTONS + readDatabaseMask("toolbar.button.left.mask", resource.tstyle.left_button, + style); + readDatabaseMask("toolbar.button.right.mask", resource.tstyle.right_button, + style); +#endif // BITMAPBUTTONS + resource.tstyle.justify = LeftJustify; if (style.getValue("toolbar.justify", s)) { if (s == "right" || s == "Right") @@ -909,7 +1172,22 @@ void BScreen::LoadStyle(void) { resource.tstyle.justify = CenterJustify; } + // sanity checks + if (resource.tstyle.toolbar.texture() == BTexture::Parent_Relative) { + resource.tstyle.toolbar = BTexture("solid flat", getBaseDisplay(), + getScreenNumber(), image_control); + resource.tstyle.toolbar.setColor(BColor("black", getBaseDisplay(), + getScreenNumber())); + } + // load menu config +#ifdef BITMAPBUTTONS + if (resource.mstyle.bullet_image.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.mstyle.bullet_image.mask); + if (resource.mstyle.tick_image.mask != None) + XFreePixmap(blackbox->getXDisplay(), resource.mstyle.tick_image.mask); +#endif // BITMAPBUTTONS + resource.mstyle.title = readDatabaseTexture("menu.title", "white", style); resource.mstyle.frame = @@ -925,6 +1203,11 @@ void BScreen::LoadStyle(void) { resource.mstyle.h_text = readDatabaseColor("menu.hilite.textColor", "black", style); +#ifdef BITMAPBUTTONS + readDatabaseMask("menu.arrow.mask", resource.mstyle.bullet_image, style); + readDatabaseMask("menu.selected.mask", resource.mstyle.tick_image, style); +#endif // BITMAPBUTTONS + resource.mstyle.t_justify = LeftJustify; if (style.getValue("menu.title.justify", s)) { if (s == "right" || s == "Right") @@ -957,6 +1240,14 @@ void BScreen::LoadStyle(void) { resource.mstyle.bullet_pos = Basemenu::Right; } + // sanity checks + if (resource.mstyle.frame.texture() == BTexture::Parent_Relative) { + resource.mstyle.frame = BTexture("solid flat", getBaseDisplay(), + getScreenNumber(), image_control); + resource.mstyle.frame.setColor(BColor("black", getBaseDisplay(), + getScreenNumber())); + } + resource.border_color = readDatabaseColor("borderColor", "black", style); @@ -1013,7 +1304,8 @@ void BScreen::removeIcon(BlackboxWindow *w) { BlackboxWindow *BScreen::getIcon(unsigned int index) { if (index < iconList.size()) { BlackboxWindowList::iterator it = iconList.begin(); - for (; index > 0; --index, ++it) ; /* increment to index */ + while (index-- > 0) // increment to index + ++it; return *it; } @@ -1025,9 +1317,9 @@ unsigned int BScreen::addWorkspace(void) { Workspace *wkspc = new Workspace(this, workspacesList.size()); workspacesList.push_back(wkspc); saveWorkspaces(getWorkspaceCount()); + saveWorkspaceNames(); - workspacemenu->insert(wkspc->getName(), wkspc->getMenu(), - wkspc->getID() + 2); + workspacemenu->insertWorkspace(wkspc); workspacemenu->update(); toolbar->reconfigure(); @@ -1049,13 +1341,14 @@ unsigned int BScreen::removeLastWorkspace(void) { wkspc->removeAll(); - workspacemenu->remove(wkspc->getID() + 2); + workspacemenu->removeWorkspace(wkspc); workspacemenu->update(); workspacesList.pop_back(); delete wkspc; saveWorkspaces(getWorkspaceCount()); + saveWorkspaceNames(); toolbar->reconfigure(); @@ -1066,43 +1359,74 @@ unsigned int BScreen::removeLastWorkspace(void) { 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 + if (! current_workspace || id == current_workspace->getID()) return; + + BlackboxWindow *focused = blackbox->getFocusedWindow(); + if (focused && focused->getScreen() == this) { + assert(focused->isStuck() || + focused->getWorkspaceNumber() == current_workspace->getID()); + + 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 if it is going + // to be unmapped + if (focused && ! focused->isStuck()) blackbox->setFocusedWindow((BlackboxWindow *) 0); - - current_workspace->hideAll(); - workspacemenu->setItemSelected(current_workspace->getID() + 2, False); - current_workspace = getWorkspace(id); + current_workspace->hideAll(); + workspacemenu->setItemSelected(current_workspace->getID() + 2, False); - xatom->setValue(getRootWindow(), XAtom::net_current_desktop, - XAtom::cardinal, id); + current_workspace = getWorkspace(id); - workspacemenu->setItemSelected(current_workspace->getID() + 2, True); - toolbar->redrawWorkspaceLabel(True); + xatom->setValue(getRootWindow(), XAtom::net_current_desktop, + XAtom::cardinal, id); - current_workspace->showAll(); + workspacemenu->setItemSelected(current_workspace->getID() + 2, True); + toolbar->redrawWorkspaceLabel(True); - if (resource.focus_last && current_workspace->getLastFocusedWindow()) { - XSync(blackbox->getXDisplay(), False); - current_workspace->getLastFocusedWindow()->setInputFocus(); - } + current_workspace->showAll(); + + int x, y, rx, ry; + Window c, r; + unsigned int m; + BlackboxWindow *win = (BlackboxWindow *) 0; + bool f = False; + + XSync(blackbox->getXDisplay(), False); + + // If sloppy focus and we can find the client window under the pointer, + // try to focus it. + if (resource.sloppy_focus && + XQueryPointer(blackbox->getXDisplay(), getRootWindow(), &r, &c, + &rx, &ry, &x, &y, &m) && + c != None) { + if ( (win = blackbox->searchWindow(c)) ) + f = win->setInputFocus(); } + // If that fails, and we're doing focus_last, try to focus the last window. + if (! f && resource.focus_last && + (win = current_workspace->getLastFocusedWindow())) + f = win->setInputFocus(); + + /* + if we found a focus target, then we set the focused window explicitly + because it is possible to switch off this workspace before the x server + generates the FocusIn event for the window. if that happens, openbox would + lose track of what window was the 'LastFocused' window on the workspace. + + if we did not find a focus target, then set the current focused window to + nothing. + */ + if (f) + blackbox->setFocusedWindow(win); + else + blackbox->setFocusedWindow((BlackboxWindow *) 0); + updateNetizenCurrentWorkspace(); } @@ -1124,6 +1448,8 @@ void BScreen::updateClientList(void) { } else xatom->setValue(getRootWindow(), XAtom::net_client_list, XAtom::window, 0, 0); + + updateStackingList(); } @@ -1135,7 +1461,7 @@ void BScreen::updateStackingList(void) { BlackboxWindowList stack_order; /* - * Get the atacking order from all of the workspaces. + * Get the stacking 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? @@ -1144,13 +1470,13 @@ void BScreen::updateStackingList(void) { 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(); + BlackboxWindowList::iterator it = stack_order.begin(), + end = stack_order.end(); for (; it != end; ++it, ++win_it) *win_it = (*it)->getClientWindow(); xatom->setValue(getRootWindow(), XAtom::net_client_list_stacking, @@ -1163,15 +1489,22 @@ void BScreen::updateStackingList(void) { void BScreen::addSystrayWindow(Window window) { + XGrabServer(blackbox->getXDisplay()); + + XSelectInput(blackbox->getXDisplay(), window, StructureNotifyMask); systrayWindowList.push_back(window); xatom->setValue(getRootWindow(), XAtom::kde_net_system_tray_windows, XAtom::window, &systrayWindowList[0], systrayWindowList.size()); blackbox->saveSystrayWindowSearch(window, this); + + XUngrabServer(blackbox->getXDisplay()); } void BScreen::removeSystrayWindow(Window window) { + XGrabServer(blackbox->getXDisplay()); + WindowList::iterator it = systrayWindowList.begin(); const WindowList::iterator end = systrayWindowList.end(); for (; it != end; ++it) @@ -1181,69 +1514,108 @@ void BScreen::removeSystrayWindow(Window window) { XAtom::window, &systrayWindowList[0], systrayWindowList.size()); blackbox->removeSystrayWindowSearch(window); + XSelectInput(blackbox->getXDisplay(), window, NoEventMask); break; } -} + assert(it != end); // not a systray window -void BScreen::addDesktopWindow(Window window) { - desktopWindowList.push_back(window); - XLowerWindow(blackbox->getXDisplay(), window); - XSelectInput(blackbox->getXDisplay(), window, StructureNotifyMask); - blackbox->saveDesktopWindowSearch(window, this); + XUngrabServer(blackbox->getXDisplay()); } -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) { + // is the window a KDE systray window? + Window systray; + if (xatom->getValue(w, XAtom::kde_net_wm_system_tray_window_for, + XAtom::window, systray) && systray != None) { + addSystrayWindow(w); + return; + } + // is the window a docking app + XWMHints *wmhint = XGetWMHints(blackbox->getXDisplay(), w); + if (wmhint && (wmhint->flags & StateHint) && + wmhint->initial_state == WithdrawnState) { + slit->addClient(w); + return; + } -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 - win->restore(True); - addDesktopWindow(win->getClientWindow()); - delete win; - return; + desktopWindowList.push_back(win->getFrameWindow()); + } else { // if (win->isNormal()) { + // don't list desktop windows as managed windows + windowList.push_back(win); + updateClientList(); + + if (win->isTopmost()) + specialWindowList.push_back(win->getFrameWindow()); } - - windowList.push_back(win); - updateClientList(); - + XMapRequestEvent mre; mre.window = w; - if (blackbox->isStartup()) win->restoreAttributes(); + if (blackbox->isStartup() && win->isNormal()) win->restoreAttributes(); win->mapRequestEvent(&mre); } void BScreen::unmanageWindow(BlackboxWindow *w, bool remap) { + // is the window a KDE systray window? + Window systray; + if (xatom->getValue(w->getClientWindow(), + XAtom::kde_net_wm_system_tray_window_for, + XAtom::window, systray) && systray != None) { + removeSystrayWindow(w->getClientWindow()); + return; + } + w->restore(remap); + // Remove the modality so that its parent won't try to re-focus the window + if (w->isModal()) w->setModal(False); + if (w->getWorkspaceNumber() != BSENTINEL && - w->getWindowNumber() != BSENTINEL) + w->getWindowNumber() != BSENTINEL) { getWorkspace(w->getWorkspaceNumber())->removeWindow(w); - else if (w->isIconic()) + if (w->isStuck()) { + for (unsigned int i = 0; i < getNumberOfWorkspaces(); ++i) + if (i != w->getWorkspaceNumber()) + getWorkspace(i)->removeWindow(w, True); + } + } else if (w->isIconic()) removeIcon(w); - windowList.remove(w); - updateClientList(); + if (w->isDesktop()) { + WindowList::iterator it = desktopWindowList.begin(); + const WindowList::iterator end = desktopWindowList.end(); + for (; it != end; ++it) + if (*it == w->getFrameWindow()) { + desktopWindowList.erase(it); + break; + } + assert(it != end); // the window wasnt a desktop window? + } else { // if (w->isNormal()) { + // we don't list desktop windows as managed windows + windowList.remove(w); + updateClientList(); + + if (w->isTopmost()) { + WindowList::iterator it = specialWindowList.begin(); + const WindowList::iterator end = specialWindowList.end(); + for (; it != end; ++it) + if (*it == w->getFrameWindow()) { + specialWindowList.erase(it); + break; + } + assert(it != end); // the window wasnt a special window? + } + } if (blackbox->getFocusedWindow() == w) blackbox->setFocusedWindow((BlackboxWindow *) 0); @@ -1378,8 +1750,17 @@ void BScreen::updateNetizenConfigNotify(XEvent *e) { void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) { // the 13 represents the number of blackbox windows such as menus + int bbwins = 15; +#ifdef XINERAMA + ++bbwins; +#endif // XINERAMA +#ifdef XFT + ++bbwins; +#endif // XFT + Window *session_stack = new - Window[(num + workspacesList.size() + rootmenuList.size() + 13)]; + Window[(num + workspacesList.size() + rootmenuList.size() + + specialWindowList.size() + bbwins)]; unsigned int i = 0, k = num; XRaiseWindow(blackbox->getXDisplay(), iconmenu->getWindowID()); @@ -1394,6 +1775,14 @@ void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) { *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID(); *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID(); + *(session_stack + i++) = configmenu->getWindowSnapmenu()->getWindowID(); + *(session_stack + i++) = configmenu->getEdgeSnapmenu()->getWindowID(); +#ifdef XINERAMA + *(session_stack + i++) = configmenu->getXineramamenu()->getWindowID(); +#endif // XINERAMA +#ifdef XFT + *(session_stack + i++) = configmenu->getXftmenu()->getWindowID(); +#endif // XFT *(session_stack + i++) = configmenu->getWindowID(); *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID(); @@ -1415,6 +1804,10 @@ void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) { if (slit->isOnTop()) *(session_stack + i++) = slit->getWindowID(); + WindowList::iterator sit, send = specialWindowList.end(); + for (sit = specialWindowList.begin(); sit != send; ++sit) + *(session_stack + i++) = *sit; + while (k--) *(session_stack + i++) = *(workspace_stack + k); @@ -1426,13 +1819,27 @@ void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) { } -void BScreen::lowerDesktops(void) { - if (desktopWindowList.empty()) return; +void BScreen::lowerWindows(Window *workspace_stack, unsigned int num) { + assert(num > 0); // this would cause trouble in the XRaiseWindow call + + Window *session_stack = new Window[(num + desktopWindowList.size())]; + unsigned int i = 0, k = num; + + XLowerWindow(blackbox->getXDisplay(), workspace_stack[0]); + + while (k--) + *(session_stack + i++) = *(workspace_stack + k); + + WindowList::iterator dit = desktopWindowList.begin(); + const WindowList::iterator d_end = desktopWindowList.end(); + for (; dit != d_end; ++dit) + *(session_stack + i++) = *dit; + + XRestackWindows(blackbox->getXDisplay(), session_stack, i); - XLowerWindow(blackbox->getXDisplay(), desktopWindowList[0]); - if (desktopWindowList.size() > 1) - XRestackWindows(blackbox->getXDisplay(), &desktopWindowList[0], - desktopWindowList.size()); + delete [] session_stack; + + updateStackingList(); } @@ -1449,10 +1856,17 @@ void BScreen::reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id, if (w->isIconic()) { removeIcon(w); getWorkspace(wkspc_id)->addWindow(w); + if (w->isStuck()) + for (unsigned int i = 0; i < getNumberOfWorkspaces(); ++i) + if (i != w->getWorkspaceNumber()) + getWorkspace(i)->addWindow(w, True); } else if (ignore_sticky || ! w->isStuck()) { + if (w->isStuck()) + w->stick(); getWorkspace(w->getWorkspaceNumber())->removeWindow(w); getWorkspace(wkspc_id)->addWindow(w); } + updateStackingList(); } @@ -1460,8 +1874,7 @@ void BScreen::propagateWindowName(const BlackboxWindow *bw) { if (bw->isIconic()) { iconmenu->changeItemLabel(bw->getWindowNumber(), bw->getIconTitle()); iconmenu->update(); - } - else { + } else { Clientmenu *clientmenu = getWorkspace(bw->getWorkspaceNumber())->getMenu(); clientmenu->changeItemLabel(bw->getWindowNumber(), bw->getTitle()); clientmenu->update(); @@ -1472,36 +1885,28 @@ void BScreen::propagateWindowName(const BlackboxWindow *bw) { } -void BScreen::nextFocus(void) { +void BScreen::nextFocus(void) const { BlackboxWindow *focused = blackbox->getFocusedWindow(), *next = focused; - if (focused) { - // if window is not on this screen, ignore it - if (focused->getScreen()->getScreenNumber() != getScreenNumber()) - focused = (BlackboxWindow*) 0; - } - - if (focused && current_workspace->getCount() > 1) { - // next is the next window to recieve focus, current is a place holder - BlackboxWindow *current; + if (focused && + focused->getScreen()->getScreenNumber() == getScreenNumber() && + current_workspace->getCount() > 1) { do { - current = next; - next = current_workspace->getNextWindowInList(current); - } while(! next->setInputFocus() && next != focused); + next = current_workspace->getNextWindowInList(next); + } while (next != focused && ! next->setInputFocus()); if (next != focused) current_workspace->raiseWindow(next); - } else if (current_workspace->getCount() >= 1) { + } else if (current_workspace->getCount() > 0) { next = current_workspace->getTopWindowOnStack(); - - current_workspace->raiseWindow(next); next->setInputFocus(); + current_workspace->raiseWindow(next); } } -void BScreen::prevFocus(void) { +void BScreen::prevFocus(void) const { BlackboxWindow *focused = blackbox->getFocusedWindow(), *next = focused; @@ -1510,27 +1915,26 @@ void BScreen::prevFocus(void) { if (focused->getScreen()->getScreenNumber() != getScreenNumber()) focused = (BlackboxWindow*) 0; } - - if (focused && current_workspace->getCount() > 1) { - // next is the next window to recieve focus, current is a place holder - BlackboxWindow *current; + + if (focused && + focused->getScreen()->getScreenNumber() == getScreenNumber() && + current_workspace->getCount() > 1) { + // next is the next window to receive focus, current is a place holder do { - current = next; - next = current_workspace->getPrevWindowInList(current); - } while(! next->setInputFocus() && next != focused); + next = current_workspace->getPrevWindowInList(next); + } while (next != focused && ! next->setInputFocus()); if (next != focused) current_workspace->raiseWindow(next); - } else if (current_workspace->getCount() >= 1) { + } else if (current_workspace->getCount() > 0) { next = current_workspace->getTopWindowOnStack(); - - current_workspace->raiseWindow(next); next->setInputFocus(); + current_workspace->raiseWindow(next); } } -void BScreen::raiseFocus(void) { +void BScreen::raiseFocus(void) const { BlackboxWindow *focused = blackbox->getFocusedWindow(); if (! focused) return; @@ -1577,37 +1981,38 @@ void BScreen::InitMenu(void) { memset(label, 0, 1024); while (fgets(line, 1024, menu_file) && ! feof(menu_file)) { - if (line[0] != '#') { - int i, key = 0, index = -1, len = strlen(line); - - for (i = 0; i < len; i++) { - if (line[i] == '[') index = 0; - else if (line[i] == ']') break; - else if (line[i] != ' ') - if (index++ >= 0) - key += tolower(line[i]); - } + if (line[0] == '#') + continue; - if (key == 517) { // [begin] - index = -1; - for (i = index; i < len; i++) { - if (line[i] == '(') index = 0; - else if (line[i] == ')') break; - else if (index++ >= 0) { - if (line[i] == '\\' && i < len - 1) i++; - label[index - 1] = line[i]; - } - } + int i, key = 0, index = -1, len = strlen(line); - if (index == -1) index = 0; - label[index] = '\0'; + for (i = 0; i < len; i++) { + if (line[i] == '[') index = 0; + else if (line[i] == ']') break; + else if (line[i] != ' ') + if (index++ >= 0) + key += tolower(line[i]); + } - rootmenu->setLabel(label); - defaultMenu = parseMenuFile(menu_file, rootmenu); - if (! defaultMenu) - blackbox->addMenuTimestamp(menu_filename); - break; + if (key == 517) { // [begin] + index = -1; + for (i = index; i < len; i++) { + if (line[i] == '(') index = 0; + else if (line[i] == ')') break; + else if (index++ >= 0) { + if (line[i] == '\\' && i < len - 1) i++; + label[index - 1] = line[i]; + } } + + if (index == -1) index = 0; + label[index] = '\0'; + + rootmenu->setLabel(label); + defaultMenu = parseMenuFile(menu_file, rootmenu); + if (! defaultMenu) + blackbox->addMenuTimestamp(menu_filename); + break; } } } @@ -1629,322 +2034,315 @@ void BScreen::InitMenu(void) { } +static +size_t string_within(char begin, char end, + const char *input, size_t start_at, size_t length, + char *output) { + bool parse = False; + size_t index = 0; + size_t i = start_at; + for (; i < length; ++i) { + if (input[i] == begin) { + parse = True; + } else if (input[i] == end) { + break; + } else if (parse) { + if (input[i] == '\\' && i < length - 1) i++; + output[index++] = input[i]; + } + } + + if (parse) + output[index] = '\0'; + else + output[0] = '\0'; + + return i; +} + + bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) { - char line[1024], label[1024], command[1024]; + char line[1024], keyword[1024], label[1024], command[1024]; + bool done = False; - while (! feof(file)) { + while (! (done || feof(file))) { memset(line, 0, 1024); memset(label, 0, 1024); memset(command, 0, 1024); - if (fgets(line, 1024, file)) { - if (line[0] != '#') { - int i, key = 0, parse = 0, index = -1, line_length = strlen(line); + if (! fgets(line, 1024, file)) + continue; - // determine the keyword - for (i = 0; i < line_length; i++) { - if (line[i] == '[') parse = 1; - else if (line[i] == ']') break; - else if (line[i] != ' ') - if (parse) - key += tolower(line[i]); - } + if (line[0] == '#') // comment, skip it + continue; - // get the label enclosed in ()'s - parse = 0; - - for (i = 0; i < line_length; i++) { - if (line[i] == '(') { - index = 0; - parse = 1; - } else if (line[i] == ')') break; - else if (index++ >= 0) { - if (line[i] == '\\' && i < line_length - 1) i++; - label[index - 1] = line[i]; - } - } + size_t line_length = strlen(line); + unsigned int key = 0; - if (parse) { - label[index] = '\0'; - } else { - label[0] = '\0'; - } + // get the keyword enclosed in []'s + size_t pos = string_within('[', ']', line, 0, line_length, keyword); - // get the command enclosed in {}'s - parse = 0; - index = -1; - for (i = 0; i < line_length; i++) { - if (line[i] == '{') { - index = 0; - parse = 1; - } else if (line[i] == '}') break; - else if (index++ >= 0) { - if (line[i] == '\\' && i < line_length - 1) i++; - command[index - 1] = line[i]; - } - } + if (keyword[0] == '\0') { // no keyword, no menu entry + continue; + } else { + size_t len = strlen(keyword); + for (size_t i = 0; i < len; ++i) { + if (keyword[i] != ' ') + key += tolower(keyword[i]); + } + } - if (parse) { - command[index] = '\0'; - } else { - command[0] = '\0'; - } + // get the label enclosed in ()'s + pos = string_within('(', ')', line, pos, line_length, label); - switch (key) { - case 311: // end - return ((menu->getCount() == 0) ? True : False); + // get the command enclosed in {}'s + pos = string_within('{', '}', line, pos, line_length, command); - break; + switch (key) { + case 311: // end + done = True; - case 333: // nop - if (! *label) - label[0] = '\0'; - menu->insert(label); + break; - break; + case 333: // nop + if (! *label) + label[0] = '\0'; + menu->insert(label); - case 421: // exec - if ((! *label) && (! *command)) { - fprintf(stderr, i18n(ScreenSet, ScreenEXECError, - "BScreen::parseMenuFile: [exec] error, " - "no menu label and/or command defined\n")); - continue; - } + break; - menu->insert(label, BScreen::Execute, command); + case 421: // exec + if (! (*label && *command)) { + fprintf(stderr, i18n(ScreenSet, ScreenEXECError, + "BScreen::parseMenuFile: [exec] error, " + "no menu label and/or command defined\n")); + continue; + } - break; + menu->insert(label, BScreen::Execute, command); - case 442: // exit - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenEXITError, - "BScreen::parseMenuFile: [exit] error, " - "no menu label defined\n")); - continue; - } + break; - menu->insert(label, BScreen::Exit); + case 442: // exit + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenEXITError, + "BScreen::parseMenuFile: [exit] error, " + "no menu label defined\n")); + continue; + } - break; + menu->insert(label, BScreen::Exit); - case 561: // style - { - if ((! *label) || (! *command)) { - fprintf(stderr, - i18n(ScreenSet, ScreenSTYLEError, - "BScreen::parseMenuFile: [style] error, " - "no menu label and/or filename defined\n")); - continue; - } + break; - string style = expandTilde(command); + case 561: { // style + if (! (*label && *command)) { + fprintf(stderr, + i18n(ScreenSet, ScreenSTYLEError, + "BScreen::parseMenuFile: [style] error, " + "no menu label and/or filename defined\n")); + continue; + } - menu->insert(label, BScreen::SetStyle, style.c_str()); - } + string style = expandTilde(command); - break; + menu->insert(label, BScreen::SetStyle, style.c_str()); + } + break; - case 630: // config - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError, - "BScreen::parseMenufile: [config] error, " - "no label defined")); - continue; - } + case 630: // config + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError, + "BScreen::parseMenufile: [config] error, " + "no label defined")); + continue; + } - menu->insert(label, configmenu); + menu->insert(label, configmenu); - break; + break; - case 740: // include - { - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError, - "BScreen::parseMenuFile: [include] error, " - "no filename defined\n")); - continue; - } + case 740: { // include + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError, + "BScreen::parseMenuFile: [include] error, " + "no filename defined\n")); + continue; + } - string newfile = expandTilde(label); - FILE *submenufile = fopen(newfile.c_str(), "r"); - - if (submenufile) { - struct stat buf; - if (fstat(fileno(submenufile), &buf) || - (! S_ISREG(buf.st_mode))) { - fprintf(stderr, - i18n(ScreenSet, ScreenINCLUDEErrorReg, - "BScreen::parseMenuFile: [include] error: " - "'%s' is not a regular file\n"), newfile.c_str()); - break; - } - - if (! feof(submenufile)) { - if (! parseMenuFile(submenufile, menu)) - blackbox->addMenuTimestamp(newfile); - - fclose(submenufile); - } - } else { - perror(newfile.c_str()); - } - } + string newfile = expandTilde(label); + FILE *submenufile = fopen(newfile.c_str(), "r"); - break; + if (! submenufile) { + perror(newfile.c_str()); + continue; + } - case 767: // submenu - { - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError, - "BScreen::parseMenuFile: [submenu] error, " - "no menu label defined\n")); - continue; - } + struct stat buf; + if (fstat(fileno(submenufile), &buf) || + ! S_ISREG(buf.st_mode)) { + fprintf(stderr, + i18n(ScreenSet, ScreenINCLUDEErrorReg, + "BScreen::parseMenuFile: [include] error: " + "'%s' is not a regular file\n"), newfile.c_str()); + break; + } - Rootmenu *submenu = new Rootmenu(this); + if (! feof(submenufile)) { + if (! parseMenuFile(submenufile, menu)) + blackbox->addMenuTimestamp(newfile); - if (*command) - submenu->setLabel(command); - else - submenu->setLabel(label); + fclose(submenufile); + } + } - parseMenuFile(file, submenu); - submenu->update(); - menu->insert(label, submenu); - rootmenuList.push_back(submenu); - } + break; - break; + case 767: { // submenu + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError, + "BScreen::parseMenuFile: [submenu] error, " + "no menu label defined\n")); + continue; + } - case 773: // restart - { - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError, - "BScreen::parseMenuFile: [restart] error, " - "no menu label defined\n")); - continue; - } + Rootmenu *submenu = new Rootmenu(this); - if (*command) - menu->insert(label, BScreen::RestartOther, command); - else - menu->insert(label, BScreen::Restart); - } + if (*command) + submenu->setLabel(command); + else + submenu->setLabel(label); - break; + parseMenuFile(file, submenu); + submenu->update(); + menu->insert(label, submenu); + rootmenuList.push_back(submenu); + } - case 845: // reconfig - { - if (! *label) { - fprintf(stderr, - i18n(ScreenSet, ScreenRECONFIGError, - "BScreen::parseMenuFile: [reconfig] error, " - "no menu label defined\n")); - continue; - } + break; - menu->insert(label, BScreen::Reconfigure); - } + case 773: { // restart + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError, + "BScreen::parseMenuFile: [restart] error, " + "no menu label defined\n")); + continue; + } - break; + if (*command) + menu->insert(label, BScreen::RestartOther, command); + else + menu->insert(label, BScreen::Restart); + } - case 995: // stylesdir - case 1113: // stylesmenu - { - bool newmenu = ((key == 1113) ? True : False); - - if ((! *label) || ((! *command) && newmenu)) { - fprintf(stderr, - i18n(ScreenSet, ScreenSTYLESDIRError, - "BScreen::parseMenuFile: [stylesdir/stylesmenu]" - " error, no directory defined\n")); - continue; - } + break; - char *directory = ((newmenu) ? command : label); + case 845: { // reconfig + if (! *label) { + fprintf(stderr, + i18n(ScreenSet, ScreenRECONFIGError, + "BScreen::parseMenuFile: [reconfig] error, " + "no menu label defined\n")); + continue; + } - string stylesdir = expandTilde(directory); + menu->insert(label, BScreen::Reconfigure); + } - struct stat statbuf; + break; - if (! stat(stylesdir.c_str(), &statbuf)) { - if (S_ISDIR(statbuf.st_mode)) { - Rootmenu *stylesmenu; + case 995: // stylesdir + case 1113: { // stylesmenu + bool newmenu = ((key == 1113) ? True : False); - if (newmenu) - stylesmenu = new Rootmenu(this); - else - stylesmenu = menu; + if (! *label || (! *command && newmenu)) { + fprintf(stderr, + i18n(ScreenSet, ScreenSTYLESDIRError, + "BScreen::parseMenuFile: [stylesdir/stylesmenu]" + " error, no directory defined\n")); + continue; + } - DIR *d = opendir(stylesdir.c_str()); - struct dirent *p; - std::vector ls; + char *directory = ((newmenu) ? command : label); - while((p = readdir(d))) - ls.push_back(p->d_name); + string stylesdir = expandTilde(directory); - closedir(d); + struct stat statbuf; - std::sort(ls.begin(), ls.end()); + if (stat(stylesdir.c_str(), &statbuf) == -1) { + fprintf(stderr, + i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist, + "BScreen::parseMenuFile: [stylesdir/stylesmenu]" + " error, %s does not exist\n"), stylesdir.c_str()); + continue; + } + if (! S_ISDIR(statbuf.st_mode)) { + fprintf(stderr, + i18n(ScreenSet, ScreenSTYLESDIRErrorNotDir, + "BScreen::parseMenuFile:" + " [stylesdir/stylesmenu] error, %s is not a" + " directory\n"), stylesdir.c_str()); + continue; + } - std::vector::iterator it = ls.begin(), - end = ls.end(); - for (; it != end; ++it) { - const string& fname = *it; + Rootmenu *stylesmenu; - if (fname[fname.size()-1] == '~') - continue; + if (newmenu) + stylesmenu = new Rootmenu(this); + else + stylesmenu = menu; - string style = stylesdir; - style += '/'; - style += fname; + DIR *d = opendir(stylesdir.c_str()); + struct dirent *p; + std::vector ls; - if ((! stat(style.c_str(), &statbuf)) && - S_ISREG(statbuf.st_mode)) - stylesmenu->insert(fname, BScreen::SetStyle, style); - } + while((p = readdir(d))) + ls.push_back(p->d_name); - stylesmenu->update(); + closedir(d); - if (newmenu) { - stylesmenu->setLabel(label); - menu->insert(label, stylesmenu); - rootmenuList.push_back(stylesmenu); - } + std::sort(ls.begin(), ls.end()); - blackbox->addMenuTimestamp(stylesdir); - } else { - fprintf(stderr, - i18n(ScreenSet, ScreenSTYLESDIRErrorNotDir, - "BScreen::parseMenuFile:" - " [stylesdir/stylesmenu] error, %s is not a" - " directory\n"), stylesdir.c_str()); - } - } else { - fprintf(stderr, - i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist, - "BScreen::parseMenuFile: [stylesdir/stylesmenu]" - " error, %s does not exist\n"), stylesdir.c_str()); - } - break; - } + std::vector::iterator it = ls.begin(), + end = ls.end(); + for (; it != end; ++it) { + const string& fname = *it; - case 1090: // workspaces - { - if (! *label) { - fprintf(stderr, - i18n(ScreenSet, ScreenWORKSPACESError, - "BScreen:parseMenuFile: [workspaces] error, " - "no menu label defined\n")); - continue; - } + if (fname[fname.size()-1] == '~') + continue; - menu->insert(label, workspacemenu); + string style = stylesdir; + style += '/'; + style += fname; - break; - } - } + if (! stat(style.c_str(), &statbuf) && S_ISREG(statbuf.st_mode)) + stylesmenu->insert(fname, BScreen::SetStyle, style); } + + stylesmenu->update(); + + if (newmenu) { + stylesmenu->setLabel(label); + menu->insert(label, stylesmenu); + rootmenuList.push_back(stylesmenu); + } + + blackbox->addMenuTimestamp(stylesdir); + } + break; + + case 1090: { // workspaces + if (! *label) { + fprintf(stderr, + i18n(ScreenSet, ScreenWORKSPACESError, + "BScreen:parseMenuFile: [workspaces] error, " + "no menu label defined\n")); + continue; + } + + menu->insert(label, workspacemenu); + } + break; } } @@ -1959,6 +2357,12 @@ void BScreen::shutdown(void) { while(! windowList.empty()) unmanageWindow(windowList.front(), True); + while(! desktopWindowList.empty()) { + BlackboxWindow *win = blackbox->searchWindow(desktopWindowList.front()); + assert(win); + unmanageWindow(win, True); + } + slit->shutdown(); } @@ -1981,19 +2385,10 @@ void BScreen::showPosition(int x, int y) { XClearWindow(blackbox->getXDisplay(), geom_window); - BPen pen(resource.wstyle.l_text_focus, resource.wstyle.font); - if (i18n.multibyte()) { - XmbDrawString(blackbox->getXDisplay(), geom_window, - resource.wstyle.fontset, pen.gc(), - resource.bevel_width, resource.bevel_width - - resource.wstyle.fontset_extents->max_ink_extent.y, - label, strlen(label)); - } else { - XDrawString(blackbox->getXDisplay(), geom_window, - pen.gc(), resource.bevel_width, - resource.wstyle.font->ascent + resource.bevel_width, - label, strlen(label)); - } + resource.wstyle.font->drawString(geom_window, + resource.bevel_width, resource.bevel_width, + resource.wstyle.l_text_focus, + label); } @@ -2015,19 +2410,10 @@ void BScreen::showGeometry(unsigned int gx, unsigned int gy) { XClearWindow(blackbox->getXDisplay(), geom_window); - BPen pen(resource.wstyle.l_text_focus, resource.wstyle.font); - if (i18n.multibyte()) { - XmbDrawString(blackbox->getXDisplay(), geom_window, - resource.wstyle.fontset, pen.gc(), - resource.bevel_width, resource.bevel_width - - resource.wstyle.fontset_extents->max_ink_extent.y, - label, strlen(label)); - } else { - XDrawString(blackbox->getXDisplay(), geom_window, - pen.gc(), resource.bevel_width, - resource.wstyle.font->ascent + - resource.bevel_width, label, strlen(label)); - } + resource.wstyle.font->drawString(geom_window, + resource.bevel_width, resource.bevel_width, + resource.wstyle.l_text_focus, + label); } @@ -2056,10 +2442,28 @@ const Rect& BScreen::availableArea(void) const { } +#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 @@ -2086,6 +2490,27 @@ void BScreen::updateAvailableArea(void) { 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(); @@ -2097,13 +2522,13 @@ void BScreen::updateAvailableArea(void) { } -Workspace* BScreen::getWorkspace(unsigned int index) { +Workspace* BScreen::getWorkspace(unsigned int index) const { assert(index < workspacesList.size()); return workspacesList[index]; } -void BScreen::buttonPressEvent(XButtonEvent *xbutton) { +void BScreen::buttonPressEvent(const XButtonEvent *xbutton) { if (xbutton->button == 1) { if (! isRootColormapInstalled()) image_control->installRootColormap(); @@ -2113,61 +2538,95 @@ void BScreen::buttonPressEvent(XButtonEvent *xbutton) { 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); + // 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); + } - if (mx < 0) mx = 0; - if (my < 0) my = 0; + if (resource.root_menu_button > 0 && + xbutton->button == resource.root_menu_button) + showRootMenu(xbutton->x_root, xbutton->y_root); + else if (resource.workspace_menu_button > 0 && + xbutton->button == resource.workspace_menu_button) + showWorkspaceMenu(xbutton->x_root, xbutton->y_root); +} - if (mx + workspacemenu->getWidth() > getWidth()) - mx = getWidth() - workspacemenu->getWidth() - getBorderWidth(); - if (my + workspacemenu->getHeight() > getHeight()) - my = getHeight() - workspacemenu->getHeight() - getBorderWidth(); +void BScreen::showWorkspaceMenu(int x, int y) { + int mx = x - (workspacemenu->getWidth() / 2); + int my = y - (workspacemenu->getTitleHeight() / 2); - workspacemenu->move(mx, my); + if (mx < 0) mx = 0; + if (my < 0) my = 0; - 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 + workspacemenu->getWidth() > getWidth()) + mx = getWidth() - workspacemenu->getWidth() - getBorderWidth(); - if (mx < 0) mx = 0; - if (my < 0) my = 0; + if (my + workspacemenu->getHeight() > getHeight()) + my = getHeight() - workspacemenu->getHeight() - getBorderWidth(); - if (mx + rootmenu->getWidth() > getWidth()) - mx = getWidth() - rootmenu->getWidth() - getBorderWidth(); + workspacemenu->move(mx, my); - if (my + rootmenu->getHeight() > getHeight()) - my = getHeight() - rootmenu->getHeight() - getBorderWidth(); + if (! workspacemenu->isVisible()) { + workspacemenu->removeParent(); + workspacemenu->show(); + } +} + + +void BScreen::showRootMenu(int x, int y) { + int mx = x - (rootmenu->getWidth() / 2); + int my = y - (rootmenu->getTitleHeight() / 2); + + if (mx < 0) mx = 0; + if (my < 0) my = 0; - rootmenu->move(mx, my); + if (mx + rootmenu->getWidth() > getWidth()) + mx = getWidth() - rootmenu->getWidth() - getBorderWidth(); - if (! rootmenu->isVisible()) { - blackbox->checkMenu(); - rootmenu->show(); + if (my + rootmenu->getHeight() > getHeight()) + my = getHeight() - rootmenu->getHeight() - getBorderWidth(); + + rootmenu->move(mx, my); + + if (! rootmenu->isVisible()) { + blackbox->checkMenu(); + rootmenu->show(); + } +} + + +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()); } - // mouse wheel up - } else if (xbutton->button == 4) { - if (getCurrentWorkspaceID() >= getWorkspaceCount() - 1) - changeWorkspaceID(0); - else - changeWorkspaceID(getCurrentWorkspaceID() + 1); - // mouse wheel down - } else if (xbutton->button == 5) { - if (getCurrentWorkspaceID() == 0) - changeWorkspaceID(getWorkspaceCount() - 1); - else - changeWorkspaceID(getCurrentWorkspaceID() - 1); + 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 { @@ -2177,20 +2636,42 @@ void BScreen::toggleFocusModel(FocusModel model) { saveSloppyFocus(False); } - updateFocusModel(); + std::for_each(windowList.begin(), windowList.end(), + std::mem_fun(&BlackboxWindow::grabButtons)); } +#ifdef BITMAPBUTTONS +void BScreen::readDatabaseMask(const string &rname, PixmapMask &pixmapMask, + const Configuration &style) { + string s; + int hx, hy; //ignored + int ret = BitmapOpenFailed; //default to failure. + + if (style.getValue(rname, s)) + { + if (s[0] != '/' && s[0] != '~') + { + std::string xbmFile = std::string("~/.openbox/buttons/") + s; + ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(), + expandTilde(xbmFile).c_str(), &pixmapMask.w, + &pixmapMask.h, &pixmapMask.mask, &hx, &hy); + } else + ret = XReadBitmapFile(blackbox->getXDisplay(), getRootWindow(), + expandTilde(s).c_str(), &pixmapMask.w, + &pixmapMask.h, &pixmapMask.mask, &hx, &hy); + + if (ret == BitmapSuccess) + return; + } -void BScreen::updateFocusModel() -{ - std::for_each(workspacesList.begin(), workspacesList.end(), - std::mem_fun(&Workspace::updateFocusModel)); + pixmapMask.mask = None; + pixmapMask.w = pixmapMask.h = 0; } - +#endif // BITMAPSUCCESS BTexture BScreen::readDatabaseTexture(const string &rname, const string &default_color, - Configuration &style) { + const Configuration &style) { BTexture texture; string s; @@ -2203,25 +2684,19 @@ BTexture BScreen::readDatabaseTexture(const string &rname, 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)); - } - + texture.setColor(readDatabaseColor(rname + ".color", default_color, style)); + texture.setColorTo(readDatabaseColor(rname + ".colorTo", default_color, + style)); + texture.setBorderColor(readDatabaseColor(rname + ".borderColor", + default_color, style)); + return texture; } BColor BScreen::readDatabaseColor(const string &rname, - const string &default_color, - Configuration &style) { + const string &default_color, + const Configuration &style) { BColor color; string s; if (style.getValue(rname, s)) @@ -2232,195 +2707,41 @@ BColor BScreen::readDatabaseColor(const string &rname, } -XFontSet BScreen::readDatabaseFontSet(const string &rname, - Configuration &style) { - char *defaultFont = "fixed"; +BFont *BScreen::readDatabaseFont(const string &rbasename, + const Configuration &style) { + string fontname; - bool load_default = True; string s; - XFontSet fontset = 0; - if (style.getValue(rname, s) && (fontset = createFontSet(s))) - load_default = False; - - if (load_default) { - fontset = createFontSet(defaultFont); - - if (! fontset) { - fprintf(stderr, - i18n(ScreenSet, ScreenDefaultFontLoadFail, - "BScreen::setCurrentStyle(): couldn't load default font.\n")); - exit(2); - } - } - return fontset; -} - - -XFontStruct *BScreen::readDatabaseFont(const string &rname, - Configuration &style) { - char *defaultFont = "fixed"; - - bool load_default = False; - string s; - XFontStruct *font = 0; - if (style.getValue(rname, s)) { - if ((font = XLoadQueryFont(blackbox->getXDisplay(), s.c_str())) == NULL) { - fprintf(stderr, - i18n(ScreenSet, ScreenFontLoadFail, - "BScreen::setCurrentStyle(): couldn't load font '%s'\n"), - s.c_str()); - - load_default = True; +#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; } - } else { - load_default = True; - } - - if (load_default) { - font = XLoadQueryFont(blackbox->getXDisplay(), defaultFont); - if (font == NULL) { - fprintf(stderr, - i18n(ScreenSet, ScreenDefaultFontLoadFail, - "BScreen::setCurrentStyle(): couldn't load default font.\n")); - exit(2); - } - } - - return font; -} - - -#ifndef HAVE_STRCASESTR -static const char * strcasestr(const char *str, const char *ptn) { - const char *s2, *p2; - for(; *str; str++) { - for(s2=str,p2=ptn; ; s2++,p2++) { - if (! *p2) return str; - if (toupper(*s2) != toupper(*p2)) break; - } - } - return NULL; -} -#endif // HAVE_STRCASESTR - - -static const char *getFontElement(const char *pattern, char *buf, - int bufsiz, ...) { - const char *p, *v; - char *p2; - va_list va; - - va_start(va, bufsiz); - buf[bufsiz-1] = 0; - buf[bufsiz-2] = '*'; - while((v = va_arg(va, char *)) != NULL) { - p = strcasestr(pattern, v); - if (p) { - strncpy(buf, p+1, bufsiz-2); - p2 = strchr(buf, '-'); - if (p2) *p2=0; - va_end(va); - return p; - } - } - va_end(va); - strncpy(buf, "*", bufsiz); - return NULL; -} - - -static const char *getFontSize(const char *pattern, int *size) { - const char *p; - const char *p2=NULL; - int n=0; - - for (p=pattern; 1; p++) { - if (! *p) { - if (p2!=NULL && n>1 && n<72) { - *size = n; return p2+1; - } else { - *size = 16; return NULL; - } - } else if (*p=='-') { - if (n>1 && n<72 && p2!=NULL) { - *size = n; - return p2+1; - } - p2=p; n=0; - } else if (*p>='0' && *p<='9' && p2!=NULL) { - n *= 10; - n += *p-'0'; - } else { - p2=NULL; n=0; - } - } -} - - -XFontSet BScreen::createFontSet(const string &fontname) { - XFontSet fs; - char **missing, *def = "-"; - int nmissing, pixel_size = 0, buf_size = 0; - char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE]; - - fs = XCreateFontSet(blackbox->getXDisplay(), - fontname.c_str(), &missing, &nmissing, &def); - if (fs && (! nmissing)) - return fs; - - const char *nfontname = fontname.c_str(); -#ifdef HAVE_SETLOCALE - if (! fs) { - if (nmissing) XFreeStringList(missing); - - setlocale(LC_CTYPE, "C"); - fs = XCreateFontSet(blackbox->getXDisplay(), fontname.c_str(), - &missing, &nmissing, &def); - setlocale(LC_CTYPE, ""); - } -#endif // HAVE_SETLOCALE - - if (fs) { - XFontStruct **fontstructs; - char **fontnames; - XFontsOfFontSet(fs, &fontstructs, &fontnames); - nfontname = fontnames[0]; + + BFont *b = new BFont(blackbox->getXDisplay(), this, family, i, bold, + italic, resource.shadow_fonts, resource.aa_fonts); + if (b->valid()) + return b; + else + delete b; // fall back to the normal X font stuff } +#endif // XFT - getFontElement(nfontname, weight, FONT_ELEMENT_SIZE, - "-medium-", "-bold-", "-demibold-", "-regular-", NULL); - getFontElement(nfontname, slant, FONT_ELEMENT_SIZE, - "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL); - getFontSize(nfontname, &pixel_size); - - if (! strcmp(weight, "*")) - strncpy(weight, "medium", FONT_ELEMENT_SIZE); - if (! strcmp(slant, "*")) - strncpy(slant, "r", FONT_ELEMENT_SIZE); - if (pixel_size < 3) - pixel_size = 3; - else if (pixel_size > 97) - pixel_size = 97; - - buf_size = strlen(nfontname) + (FONT_ELEMENT_SIZE * 2) + 64; - char *pattern2 = new char[buf_size]; - sprintf(pattern2, - "%s," - "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*," - "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*", - nfontname, weight, slant, pixel_size, pixel_size); - nfontname = pattern2; - - if (nmissing) - XFreeStringList(missing); - if (fs) - XFreeFontSet(blackbox->getXDisplay(), fs); - - fs = XCreateFontSet(blackbox->getXDisplay(), nfontname, &missing, - &nmissing, &def); - - delete [] pattern2; + style.getValue(rbasename + "font", s); + // if this fails, a blank string will be used, which will cause the fallback + // font to load. - return fs; + BFont *b = new BFont(blackbox->getXDisplay(), this, s); + if (! b->valid()) + exit(2); // can't continue without a font + return b; }