From f8ea576460470ecc2e395cf43e31a67752adbbb5 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 3 Jan 2003 19:36:41 +0000 Subject: [PATCH] rm the old bb src --- src/bbscreen.cc | 1554 ----------------- src/bbscreen.hh | 268 --- src/bbwindow.cc | 4208 ----------------------------------------------- src/bbwindow.hh | 416 ----- src/bindings.cc | 73 +- src/bindings.hh | 3 + src/openbox.cc | 6 + src/screen.cc | 5 + 8 files changed, 60 insertions(+), 6473 deletions(-) delete mode 100644 src/bbscreen.cc delete mode 100644 src/bbscreen.hh delete mode 100644 src/bbwindow.cc delete mode 100644 src/bbwindow.hh diff --git a/src/bbscreen.cc b/src/bbscreen.cc deleted file mode 100644 index fb930317..00000000 --- a/src/bbscreen.cc +++ /dev/null @@ -1,1554 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#ifdef HAVE_CONFIG_H -#include "../config.h" -#endif // HAVE_CONFIG_H - -extern "C" { -#include -#include - -#ifdef XINERAMA -# include -# include -#endif // XINERAMA - -#ifdef HAVE_STDLIB_H -# include -#endif // HAVE_STDLIB_H - -#ifdef HAVE_STRING_H -# include -#endif // HAVE_STRING_H - -#ifdef HAVE_CTYPE_H -# include -#endif // HAVE_CTYPE_H - -#ifdef HAVE_UNISTD_H -# include -# include -#endif // HAVE_UNISTD_H - -#ifdef HAVE_DIRENT_H -# include -#endif // HAVE_DIRENT_H - -#ifdef HAVE_LOCALE_H -# include -#endif // HAVE_LOCALE_H - -#ifdef HAVE_SYS_STAT_H -# include -#endif // HAVE_SYS_STAT_H - -#ifdef HAVE_STDARG_H -# include -#endif // HAVE_STDARG_H -} - -#include - -#include -#include -#include -using std::string; - -#include "bbscreen.hh" -#include "otk/font.hh" -#include "otk/gccache.hh" -#include "otk/image.hh" -#include "otk/assassin.hh" -#include "otk/util.hh" -#include "openbox.hh" -#include "bbwindow.hh" -#include "workspace.hh" - -#ifndef FONT_ELEMENT_SIZE -#define FONT_ELEMENT_SIZE 50 -#endif // FONT_ELEMENT_SIZE - -namespace ob { - -static bool running = True; - -static int anotherWMRunning(Display *display, XErrorEvent *) { - fprintf(stderr, - "BScreen::BScreen: an error occured while querying the X server.\n" - " another window manager already running on display %s.\n", - DisplayString(display)); - - running = False; - - return(-1); -} - - -BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(scrn) { - blackbox = bb; - screenstr = "session.screen" + otk::itostring(scrn) + '.'; - config = blackbox->getConfig(); - xatom = blackbox->getXAtom(); - - event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask | - SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask; - - XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning); - XSelectInput(otk::OBDisplay::display, getRootWindow(), event_mask); - XSync(otk::OBDisplay::display, False); - XSetErrorHandler((XErrorHandler) old); - - managed = running; - if (! managed) return; - - fprintf(stderr, "BScreen::BScreen: managing screen %d " - "using visual 0x%lx, depth %d\n", - getScreenNumber(), XVisualIDFromVisual(getVisual()), - getDepth()); - - resource.wstyle.font = (otk::BFont *) 0; - - geom_pixmap = None; - -// xatom->setSupported(this); // set-up netwm support -#ifdef HAVE_GETPID - xatom->setValue(getRootWindow(), otk::OBProperty::blackbox_pid, - otk::OBProperty::Atom_Cardinal, - (unsigned long) getpid()); -#endif // HAVE_GETPID - unsigned long geometry[] = { getWidth(), - getHeight()}; - xatom->set(getRootWindow(), otk::OBProperty::net_desktop_geometry, - otk::OBProperty::Atom_Cardinal, geometry, 2); - unsigned long viewport[] = {0,0}; - xatom->set(getRootWindow(), otk::OBProperty::net_desktop_viewport, - otk::OBProperty::Atom_Cardinal, viewport, 2); - - - XDefineCursor(otk::OBDisplay::display, getRootWindow(), - blackbox->getSessionCursor()); - - updateAvailableArea(); - - image_control = - new otk::BImageControl(Openbox::instance->timerManager(), - this, True, blackbox->getColorsPerChannel(), - blackbox->getCacheLife(), blackbox->getCacheMax()); - image_control->installRootColormap(); - root_colormap_installed = True; - - load_rc(); - - // XXX: ugh - resource.wstyle.setImageControl(image_control); - LoadStyle(); - - XGCValues gcv; - gcv.foreground = WhitePixel(otk::OBDisplay::display, getScreenNumber()) - ^ BlackPixel(otk::OBDisplay::display, getScreenNumber()); - gcv.function = GXxor; - gcv.subwindow_mode = IncludeInferiors; - opGC = XCreateGC(otk::OBDisplay::display, getRootWindow(), - GCForeground | GCFunction | GCSubwindowMode, &gcv); - - const char *s = "0: 0000 x 0: 0000"; - geom_w = resource.wstyle.font->measureString(s) + resource.wstyle.bevel_width * 2; - geom_h = resource.wstyle.font->height() + resource.wstyle.bevel_width * 2; - - XSetWindowAttributes attrib; - unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder; - attrib.border_pixel = getBorderColor()->pixel(); - attrib.colormap = getColormap(); - attrib.save_under = True; - - // XXX -- move this geom_* crap out of here - - geom_window = XCreateWindow(otk::OBDisplay::display, getRootWindow(), - 0, 0, geom_w, geom_h, resource.wstyle.border_width, - getDepth(), InputOutput, getVisual(), - mask, &attrib); - geom_visible = False; - - otk::BTexture* texture = &(resource.wstyle.l_focus); - geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap); - if (geom_pixmap == ParentRelative) { - texture = &(resource.wstyle.t_focus); - geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap); - } - if (! geom_pixmap) - XSetWindowBackground(otk::OBDisplay::display, geom_window, - texture->color().pixel()); - else - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - geom_window, geom_pixmap); - - if (resource.workspaces > 0) { - for (unsigned int i = 0; i < resource.workspaces; ++i) { - Workspace *wkspc = new Workspace(this, workspacesList.size()); - workspacesList.push_back(wkspc); - - } - } else { - Workspace *wkspc = new Workspace(this, workspacesList.size()); - workspacesList.push_back(wkspc); - } - - // /GEOM_PIXMAP - - saveWorkspaceNames(); - - updateNetizenWorkspaceCount(); - - current_workspace = workspacesList.front(); - - xatom->set(getRootWindow(), otk::OBProperty::net_current_desktop, - otk::OBProperty::Atom_Cardinal, 0); //first workspace - - raiseWindows(0, 0); // this also initializes the empty stacking list - - updateClientList(); // initialize the client lists, which will be empty - updateAvailableArea(); - - changeWorkspaceID(0); - - unsigned int i, j, nchild; - Window r, p, *children; - XQueryTree(otk::OBDisplay::display, getRootWindow(), &r, &p, - &children, &nchild); - - // preen the window list of all icon windows... for better dockapp support - for (i = 0; i < nchild; i++) { - if (children[i] == None) continue; - - XWMHints *wmhints = XGetWMHints(otk::OBDisplay::display, - children[i]); - - if (wmhints) { - if ((wmhints->flags & IconWindowHint) && - (wmhints->icon_window != children[i])) { - for (j = 0; j < nchild; j++) { - if (children[j] == wmhints->icon_window) { - children[j] = None; - break; - } - } - } - - XFree(wmhints); - } - } - - // manage shown windows - for (i = 0; i < nchild; ++i) { - if (children[i] == None || ! blackbox->validateWindow(children[i])) - continue; - - XWindowAttributes attrib; - if (XGetWindowAttributes(otk::OBDisplay::display, children[i], &attrib)) { - if (attrib.override_redirect) continue; - - if (attrib.map_state != IsUnmapped) { - manageWindow(children[i]); - } - } - } - - XFree(children); - - // call this again just in case a window we found updates the Strut list - updateAvailableArea(); -} - - -BScreen::~BScreen(void) { - if (! managed) return; - - if (geom_pixmap != None) - image_control->removeImage(geom_pixmap); - - if (geom_window != None) - XDestroyWindow(otk::OBDisplay::display, geom_window); - - std::for_each(workspacesList.begin(), workspacesList.end(), - otk::PointerAssassin()); - - std::for_each(iconList.begin(), iconList.end(), otk::PointerAssassin()); - - while (! systrayWindowList.empty()) - removeSystrayWindow(systrayWindowList[0]); - - delete image_control; - - // delete style - - XFreeGC(otk::OBDisplay::display, opGC); -} - - -void BScreen::LoadStyle(void) { - otk::Configuration style_conf(False); - - const char *sfile = blackbox->getStyleFilename(); - if (sfile != NULL) { - style_conf.setFile(sfile); - if (! style_conf.load()) { - style_conf.setFile(DEFAULTSTYLE); - if (! style_conf.load()) - style_conf.create(); // hardcoded default values will be used. - } - } - - // merge in the rc file - style_conf.merge(config->file(), True); - - resource.wstyle.load(style_conf); -} - -void BScreen::saveSloppyFocus(bool s) { - resource.sloppy_focus = s; - - string fmodel; - if (resource.sloppy_focus) { - fmodel = "SloppyFocus"; - if (resource.auto_raise) fmodel += " AutoRaise"; - if (resource.click_raise) fmodel += " ClickRaise"; - } else { - fmodel = "ClickToFocus"; - } - config->setValue(screenstr + "focusModel", fmodel); -} - - -void BScreen::saveAutoRaise(bool a) { - resource.auto_raise = a; - saveSloppyFocus(resource.sloppy_focus); -} - - -void BScreen::saveClickRaise(bool c) { - resource.click_raise = c; - saveSloppyFocus(resource.sloppy_focus); -} - - -void BScreen::saveImageDither(bool d) { - image_control->setDither(d); - config->setValue(screenstr + "imageDither", doImageDither()); -} - - -void BScreen::saveOpaqueMove(bool o) { - resource.opaque_move = o; - config->setValue(screenstr + "opaqueMove", resource.opaque_move); -} - - -void BScreen::saveFullMax(bool f) { - resource.full_max = f; - config->setValue(screenstr + "fullMaximization", resource.full_max); -} - - -void BScreen::saveFocusNew(bool f) { - resource.focus_new = f; - config->setValue(screenstr + "focusNewWindows", resource.focus_new); -} - - -void BScreen::saveFocusLast(bool f) { - resource.focus_last = f; - config->setValue(screenstr + "focusLastWindow", resource.focus_last); -} - - -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::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); -} - - -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); -} - - -void BScreen::savePlacementPolicy(int p) { - resource.placement_policy = 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; - } - config->setValue(screenstr + "windowPlacement", placement); -} - - -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.snap_threshold); -} - - -void BScreen::saveSnapOffset(int t) { - resource.snap_offset = t; - config->setValue(screenstr + "edgeSnapOffset", - resource.snap_offset); -} - - -void BScreen::saveRowPlacementDirection(int d) { - resource.row_direction = d; - config->setValue(screenstr + "rowPlacementDirection", - resource.row_direction == LeftRight ? - "LeftToRight" : "RightToLeft"); -} - - -void BScreen::saveColPlacementDirection(int d) { - resource.col_direction = d; - config->setValue(screenstr + "colPlacementDirection", - resource.col_direction == TopBottom ? - "TopToBottom" : "BottomToTop"); -} - - -void BScreen::saveStrftimeFormat(const std::string& format) { - resource.strftime_format = format; - config->setValue(screenstr + "strftimeFormat", resource.strftime_format); -} - - -void BScreen::saveWorkspaceNames() { - string names; - - 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::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); - saveWindowToWindowSnap(resource.snap_to_windows); - saveWindowToEdgeSnap(resource.snap_to_edges); - saveWindowCornerSnap(resource.window_corner_snap); - saveWorkspaces(resource.workspaces); - savePlacementPolicy(resource.placement_policy); - saveSnapThreshold(resource.snap_threshold); - saveSnapOffset(resource.snap_offset); - saveResistanceSize(resource.resistance_size); - saveRowPlacementDirection(resource.row_direction); - saveColPlacementDirection(resource.col_direction); - saveStrftimeFormat(resource.strftime_format); - savePlaceIgnoreShaded(resource.ignore_shaded); - savePlaceIgnoreMaximized(resource.ignore_maximized); - saveAllowScrollLock(resource.allow_scroll_lock); - saveWorkspaceWarping(resource.workspace_warping); - saveRootScrollDirection(resource.root_scroll); -} - - -void BScreen::load_rc(void) { - std::string s; - bool b; - - if (! config->getValue(screenstr + "fullMaximization", resource.full_max)) - resource.full_max = false; - - if (! config->getValue(screenstr + "focusNewWindows", resource.focus_new)) - resource.focus_new = false; - - if (! config->getValue(screenstr + "focusLastWindow", resource.focus_last)) - resource.focus_last = false; - - if (! config->getValue(screenstr + "workspaces", resource.workspaces)) - resource.workspaces = 1; - - 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; - - 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)) - resource.window_corner_snap = true; - - if (! config->getValue(screenstr + "imageDither", b)) - 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.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") - resource.row_direction = RightLeft; - else - resource.row_direction = LeftRight; - - if (config->getValue(screenstr + "colPlacementDirection", s) && - s == "BottomToTop") - resource.col_direction = BottomTop; - else - resource.col_direction = TopBottom; - - if (config->getValue(screenstr + "workspaceNames", s)) { - otk::OBProperty::StringVect workspaceNames; - - string::const_iterator it = s.begin(), end = s.end(); - while(1) { - string::const_iterator tmp = it; // current string.begin() - it = std::find(tmp, end, ','); // look for comma between tmp and end - workspaceNames.push_back(string(tmp, it)); // s[tmp:it] - if (it == end) - break; - ++it; - } - - xatom->set(getRootWindow(), otk::OBProperty::net_desktop_names, - otk::OBProperty::utf8, workspaceNames); - } - - resource.sloppy_focus = true; - resource.auto_raise = false; - resource.click_raise = false; - if (config->getValue(screenstr + "focusModel", s)) { - if (s.find("ClickToFocus") != string::npos) { - resource.sloppy_focus = false; - } else { - // must be sloppy - if (s.find("AutoRaise") != string::npos) - resource.auto_raise = true; - if (s.find("ClickRaise") != string::npos) - resource.click_raise = true; - } - } - - 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") - resource.placement_policy = RowSmartPlacement; - } else - resource.placement_policy = RowSmartPlacement; - - if (! config->getValue(screenstr + "strftimeFormat", - resource.strftime_format)) - resource.strftime_format = "%I:%M %p"; - - 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; - } -} - - -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->state() == Openbox::State_Starting) return; - - load_rc(); - LoadStyle(); - - // we need to do this explicitly, because just loading this value from the rc - // does nothing - changeWorkspaceCount(resource.workspaces); - - XGCValues gcv; - gcv.foreground = WhitePixel(otk::OBDisplay::display, - getScreenNumber()); - gcv.function = GXinvert; - gcv.subwindow_mode = IncludeInferiors; - XChangeGC(otk::OBDisplay::display, opGC, - GCForeground | GCFunction | GCSubwindowMode, &gcv); - - const char *s = "0: 0000 x 0: 0000"; - - geom_w = resource.wstyle.font->measureString(s) + resource.wstyle.bevel_width * 2; - geom_h = resource.wstyle.font->height() + resource.wstyle.bevel_width * 2; - - otk::BTexture* texture = &(resource.wstyle.l_focus); - geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap); - if (geom_pixmap == ParentRelative) { - texture = &(resource.wstyle.t_focus); - geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap); - } - if (! geom_pixmap) - XSetWindowBackground(otk::OBDisplay::display, geom_window, - texture->color().pixel()); - else - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - geom_window, geom_pixmap); - - XSetWindowBorderWidth(otk::OBDisplay::display, geom_window, - resource.wstyle.border_width); - XSetWindowBorder(otk::OBDisplay::display, geom_window, - resource.wstyle.border_color.pixel()); - - typedef std::vector SubList; - SubList remember_subs; - - raiseWindows(0, 0); - - std::for_each(workspacesList.begin(), workspacesList.end(), - std::mem_fun(&Workspace::reconfigure)); - - BlackboxWindowList::iterator iit = iconList.begin(); - for (; iit != iconList.end(); ++iit) { - BlackboxWindow *bw = *iit; - if (bw->validateClient()) - bw->reconfigure(); - } - - otk::BImageControl::timeout(image_control); -} - - - -void BScreen::addIcon(BlackboxWindow *w) { - if (! w) return; - - w->setWorkspace(otk::BSENTINEL); - w->setWindowNumber(iconList.size()); - - iconList.push_back(w); -} - - -void BScreen::removeIcon(BlackboxWindow *w) { - if (! w) return; - - iconList.remove(w); - - BlackboxWindowList::iterator it = iconList.begin(), - end = iconList.end(); - for (int i = 0; it != end; ++it) - (*it)->setWindowNumber(i++); -} - - -BlackboxWindow *BScreen::getIcon(unsigned int index) { - if (index < iconList.size()) { - BlackboxWindowList::iterator it = iconList.begin(); - while (index-- > 0) // increment to index - ++it; - return *it; - } - - return (BlackboxWindow *) 0; -} - - -unsigned int BScreen::addWorkspace(void) { - Workspace *wkspc = new Workspace(this, workspacesList.size()); - workspacesList.push_back(wkspc); - saveWorkspaces(getWorkspaceCount()); - saveWorkspaceNames(); - - return workspacesList.size(); -} - - -unsigned int BScreen::removeLastWorkspace(void) { - if (workspacesList.size() == 1) - return 1; - - Workspace *wkspc = workspacesList.back(); - - if (current_workspace->getID() == wkspc->getID()) - changeWorkspaceID(current_workspace->getID() - 1); - - wkspc->removeAll(); - - workspacesList.pop_back(); - delete wkspc; - - saveWorkspaces(getWorkspaceCount()); - saveWorkspaceNames(); - - updateNetizenWorkspaceCount(); - - return workspacesList.size(); -} - - -void BScreen::changeWorkspaceID(unsigned int id) { - 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(); - - current_workspace = getWorkspace(id); - - xatom->set(getRootWindow(), otk::OBProperty::net_current_desktop, - otk::OBProperty::Atom_Cardinal, id); - - current_workspace->showAll(); - - int x, y, rx, ry; - Window c, r; - unsigned int m; - BlackboxWindow *win = (BlackboxWindow *) 0; - bool f = False; - - XSync(otk::OBDisplay::display, False); - - // If sloppy focus and we can find the client window under the pointer, - // try to focus it. - if (resource.sloppy_focus && - XQueryPointer(otk::OBDisplay::display, 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); -} - - -/* - * 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->set(getRootWindow(), otk::OBProperty::net_client_list, - otk::OBProperty::Atom_Window, windows, windowList.size()); - delete [] windows; - } else - xatom->set(getRootWindow(), otk::OBProperty::net_client_list, - otk::OBProperty::Atom_Window, 0, 0); - - updateStackingList(); -} - - -/* - * Set the _NET_CLIENT_LIST_STACKING root window property. - */ -void BScreen::updateStackingList(void) { - - BlackboxWindowList stack_order; - - /* - * 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? - */ - 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(), - end = stack_order.end(); - for (; it != end; ++it, ++win_it) - *win_it = (*it)->getClientWindow(); - xatom->set(getRootWindow(), otk::OBProperty::net_client_list_stacking, - otk::OBProperty::Atom_Window, windows, stack_order.size()); - delete [] windows; - } else - xatom->set(getRootWindow(), otk::OBProperty::net_client_list_stacking, - otk::OBProperty::Atom_Window, 0, 0); -} - - -void BScreen::addSystrayWindow(Window window) { - XGrabServer(otk::OBDisplay::display); - - XSelectInput(otk::OBDisplay::display, window, StructureNotifyMask); - systrayWindowList.push_back(window); - xatom->set(getRootWindow(), otk::OBProperty::kde_net_system_tray_windows, - otk::OBProperty::Atom_Window, - &systrayWindowList[0], systrayWindowList.size()); - blackbox->saveSystrayWindowSearch(window, this); - - XUngrabServer(otk::OBDisplay::display); -} - - -void BScreen::removeSystrayWindow(Window window) { - XGrabServer(otk::OBDisplay::display); - - WindowList::iterator it = systrayWindowList.begin(); - const WindowList::iterator end = systrayWindowList.end(); - for (; it != end; ++it) - if (*it == window) { - systrayWindowList.erase(it); - xatom->set(getRootWindow(), - otk::OBProperty::kde_net_system_tray_windows, - otk::OBProperty::Atom_Window, - &systrayWindowList[0], systrayWindowList.size()); - blackbox->removeSystrayWindowSearch(window); - XSelectInput(otk::OBDisplay::display, window, NoEventMask); - break; - } - - assert(it != end); // not a systray window - - XUngrabServer(otk::OBDisplay::display); -} - - -void BScreen::manageWindow(Window w) { - // is the window a KDE systray window? - Window systray; - if (xatom->get(w, otk::OBProperty::kde_net_wm_system_tray_window_for, - otk::OBProperty::Atom_Window, &systray) && - systray != None) - { - addSystrayWindow(w); - return; - } - - // is the window a docking app - XWMHints *wmhint = XGetWMHints(otk::OBDisplay::display, w); - if (wmhint && (wmhint->flags & StateHint) && - wmhint->initial_state == WithdrawnState) { - //slit->addClient(w); - return; - } - - new BlackboxWindow(blackbox, w, this); - - BlackboxWindow *win = blackbox->searchWindow(w); - if (! win) - return; - - if (win->isDesktop()) { - 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()); - } - - XMapRequestEvent mre; - mre.window = w; - if (blackbox->state() == Openbox::State_Starting && - 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->get(w->getClientWindow(), - otk::OBProperty::kde_net_wm_system_tray_window_for, - otk::OBProperty::Atom_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() != otk::BSENTINEL && - w->getWindowNumber() != otk::BSENTINEL) { - getWorkspace(w->getWorkspaceNumber())->removeWindow(w); - 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); - - 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); - - /* - some managed windows can also be window group controllers. when - unmanaging such windows, we should also delete the window group. - */ - BWindowGroup *group = blackbox->searchGroup(w->getClientWindow()); - delete group; - - delete 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 otk::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->set(getRootWindow(), otk::OBProperty::net_workarea, - otk::OBProperty::Atom_Cardinal, - dims, 4 * workspacesList.size()); - delete [] dims; - } else - xatom->set(getRootWindow(), otk::OBProperty::net_workarea, - otk::OBProperty::Atom_Cardinal, 0, 0); -} - - -void BScreen::updateNetizenWorkspaceCount(void) { - xatom->set(getRootWindow(), otk::OBProperty::net_number_of_desktops, - otk::OBProperty::Atom_Cardinal, workspacesList.size()); - - updateWorkArea(); -} - - -void BScreen::updateNetizenWindowFocus(void) { - Window f = ((blackbox->getFocusedWindow()) ? - blackbox->getFocusedWindow()->getClientWindow() : None); - - xatom->set(getRootWindow(), otk::OBProperty::net_active_window, - otk::OBProperty::Atom_Window, f); -} - - -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 - - Window *session_stack = new - Window[(num + specialWindowList.size() + bbwins)]; - unsigned int i = 0, k = num; - - 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); - - XRestackWindows(otk::OBDisplay::display, session_stack, i); - - delete [] session_stack; - - updateStackingList(); -} - - -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(otk::OBDisplay::display, 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(otk::OBDisplay::display, session_stack, i); - - delete [] session_stack; - - updateStackingList(); -} - - -void BScreen::reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id, - bool ignore_sticky) { - if (! w) return; - - if (wkspc_id == otk::BSENTINEL) - wkspc_id = current_workspace->getID(); - - if (w->getWorkspaceNumber() == wkspc_id) - return; - - 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(); -} - - -void BScreen::propagateWindowName(const BlackboxWindow *bw) { - if (bw->isIconic()) { - } else { - } -} - - -void BScreen::nextFocus(void) const { - BlackboxWindow *focused = blackbox->getFocusedWindow(), - *next = focused; - - if (focused && - focused->getScreen()->getScreenNumber() == getScreenNumber() && - current_workspace->getCount() > 1) { - do { - next = current_workspace->getNextWindowInList(next); - } while (next != focused && ! next->setInputFocus()); - - if (next != focused) - current_workspace->raiseWindow(next); - } else if (current_workspace->getCount() > 0) { - next = current_workspace->getTopWindowOnStack(); - next->setInputFocus(); - current_workspace->raiseWindow(next); - } -} - - -void BScreen::prevFocus(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 && - focused->getScreen()->getScreenNumber() == getScreenNumber() && - current_workspace->getCount() > 1) { - // next is the next window to receive focus, current is a place holder - do { - next = current_workspace->getPrevWindowInList(next); - } while (next != focused && ! next->setInputFocus()); - - if (next != focused) - current_workspace->raiseWindow(next); - } else if (current_workspace->getCount() > 0) { - next = current_workspace->getTopWindowOnStack(); - next->setInputFocus(); - current_workspace->raiseWindow(next); - } -} - - -void BScreen::raiseFocus(void) const { - BlackboxWindow *focused = blackbox->getFocusedWindow(); - if (! focused) - return; - - // if on this Screen, raise it - if (focused->getScreen()->getScreenNumber() == getScreenNumber()) { - Workspace *workspace = getWorkspace(focused->getWorkspaceNumber()); - workspace->raiseWindow(focused); - } -} - - -void BScreen::shutdown(void) { - XSelectInput(otk::OBDisplay::display, getRootWindow(), NoEventMask); - XSync(otk::OBDisplay::display, False); - - while(! windowList.empty()) - unmanageWindow(windowList.front(), True); - - while(! desktopWindowList.empty()) { - BlackboxWindow *win = blackbox->searchWindow(desktopWindowList.front()); - assert(win); - unmanageWindow(win, True); - } -} - - -void BScreen::showPosition(int x, int y) { - if (! geom_visible) { - XMoveResizeWindow(otk::OBDisplay::display, geom_window, - (getWidth() - geom_w) / 2, - (getHeight() - geom_h) / 2, geom_w, geom_h); - XMapWindow(otk::OBDisplay::display, geom_window); - XRaiseWindow(otk::OBDisplay::display, geom_window); - - geom_visible = True; - } - - char label[1024]; - - sprintf(label, "X: %4d x Y: %4d", x, y); - - XClearWindow(otk::OBDisplay::display, geom_window); - - resource.wstyle.font->drawString(geom_window, - resource.wstyle.bevel_width, resource.wstyle.bevel_width, - resource.wstyle.l_text_focus, - label); -} - - -void BScreen::showGeometry(unsigned int gx, unsigned int gy) { - if (! geom_visible) { - XMoveResizeWindow(otk::OBDisplay::display, geom_window, - (getWidth() - geom_w) / 2, - (getHeight() - geom_h) / 2, geom_w, geom_h); - XMapWindow(otk::OBDisplay::display, geom_window); - XRaiseWindow(otk::OBDisplay::display, geom_window); - - geom_visible = True; - } - - char label[1024]; - - sprintf(label, "W: %4d x H: %4d", gx, gy); - - XClearWindow(otk::OBDisplay::display, geom_window); - - resource.wstyle.font->drawString(geom_window, - resource.wstyle.bevel_width, resource.wstyle.bevel_width, - resource.wstyle.l_text_focus, - label); -} - - -void BScreen::hideGeometry(void) { - if (geom_visible) { - XUnmapWindow(otk::OBDisplay::display, geom_window); - geom_visible = False; - } -} - - -void BScreen::addStrut(otk::Strut *strut) { - strutList.push_back(strut); -} - - -void BScreen::removeStrut(otk::Strut *strut) { - strutList.remove(strut); -} - - -const otk::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) { - otk::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) { - otk::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) const { - assert(index < workspacesList.size()); - return workspacesList[index]; -} - - -void BScreen::buttonPressEvent(const XButtonEvent *xbutton) { - if (xbutton->button == 1) { - if (! isRootColormapInstalled()) - image_control->installRootColormap(); - - // 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->atom(otk::OBProperty::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(); - 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)); -} - -} diff --git a/src/bbscreen.hh b/src/bbscreen.hh deleted file mode 100644 index f0bc33d5..00000000 --- a/src/bbscreen.hh +++ /dev/null @@ -1,268 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __Screen_hh -#define __Screen_hh - -extern "C" { -#include - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else // !TIME_WITH_SYS_TIME -# ifdef HAVE_SYS_TIME_H -# include -# else // !HAVE_SYS_TIME_H -# include -# endif // HAVE_SYS_TIME_H -#endif // TIME_WITH_SYS_TIME -} - -#include -#include - -#include "otk/color.hh" -#include "otk/font.hh" -#include "otk/texture.hh" -#include "otk/image.hh" -#include "otk/strut.hh" -#include "otk/property.hh" -#include "otk/configuration.hh" -#include "otk/style.hh" -#include "timer.hh" -#include "workspace.hh" -#include "blackbox.hh" - -namespace ob { - -class BScreen : public otk::ScreenInfo { -private: - bool root_colormap_installed, managed, geom_visible; - GC opGC; - Pixmap geom_pixmap; - Window geom_window; - - Blackbox *blackbox; - otk::BImageControl *image_control; - otk::Configuration *config; - otk::OBProperty *xatom; - - BlackboxWindowList iconList, windowList; - - typedef std::vector WindowList; - WindowList specialWindowList, desktopWindowList, systrayWindowList; - - Workspace *current_workspace; - - unsigned int geom_w, geom_h; - unsigned long event_mask; - - otk::Rect usableArea; -#ifdef XINERAMA - RectList xineramaUsableArea; -#endif // XINERAMA - - typedef std::list StrutList; - StrutList strutList; - typedef std::vector WorkspaceList; - WorkspaceList workspacesList; - - struct screen_resource { - otk::Style wstyle; - - bool sloppy_focus, auto_raise, auto_edge_balance, ordered_dither, - opaque_move, full_max, focus_new, focus_last, click_raise, - allow_scroll_lock, window_corner_snap, aa_fonts, - ignore_shaded, ignore_maximized, workspace_warping, shadow_fonts; - - int snap_to_windows, snap_to_edges; - unsigned int snap_offset; - - unsigned int workspaces; - int placement_policy, - snap_threshold, row_direction, col_direction, root_scroll, - resistance_size; - - unsigned int resize_zones; - - std::string strftime_format; - - } resource; - std::string screenstr; - - BScreen(const BScreen&); - BScreen& operator=(const BScreen&); - - void updateWorkArea(void); - -public: - // XXX: temporary - void updateNetizenWorkspaceCount(); - void updateNetizenWindowFocus(); - - - enum { WindowNoSnap = 0, WindowSnap, WindowResistance }; - enum { RowSmartPlacement = 1, ColSmartPlacement, CascadePlacement, - UnderMousePlacement, ClickMousePlacement, LeftRight, RightLeft, - TopBottom, BottomTop, IgnoreShaded, IgnoreMaximized }; - enum { Restart = 1, RestartOther, Exit, Shutdown, Execute, Reconfigure, - WindowShade, WindowIconify, WindowMaximize, WindowClose, WindowRaise, - WindowLower, WindowStick, WindowKill, SetStyle }; - enum FocusModel { SloppyFocus, ClickToFocus }; - enum RootScrollDirection { NoScroll = 0, NormalScroll, ReverseScroll }; - - BScreen(Blackbox *bb, unsigned int scrn); - ~BScreen(void); - - void LoadStyle(void); - - inline bool isSloppyFocus(void) const { return resource.sloppy_focus; } - inline bool isRootColormapInstalled(void) const - { return root_colormap_installed; } - inline bool doAutoRaise(void) const { return resource.auto_raise; } - inline bool doClickRaise(void) const { return resource.click_raise; } - inline bool isScreenManaged(void) const { return managed; } - inline bool doShadowFonts(void) const { return resource.shadow_fonts; } - inline bool doAAFonts(void) const { return resource.aa_fonts; } - inline bool doImageDither(void) const { return image_control->doDither(); } - inline bool doOrderedDither(void) const { return resource.ordered_dither; } - inline bool doOpaqueMove(void) const { return resource.opaque_move; } - inline bool doFullMax(void) const { return resource.full_max; } - inline bool doFocusNew(void) const { return resource.focus_new; } - inline bool doFocusLast(void) const { return resource.focus_last; } - inline int getWindowToWindowSnap(void) const - { return resource.snap_to_windows; } - inline int getWindowToEdgeSnap(void) const - { return resource.snap_to_edges; } - inline bool getWindowCornerSnap(void) const - { return resource.window_corner_snap; } - inline bool allowScrollLock(void) const { return resource.allow_scroll_lock; } - inline bool doWorkspaceWarping(void) const - { return resource.workspace_warping; } - inline int rootScrollDirection(void) const { return resource.root_scroll; } - - inline const GC &getOpGC(void) const { return opGC; } - - inline Blackbox *getBlackbox(void) { return blackbox; } - inline otk::BColor *getBorderColor(void) { - return &resource.wstyle.border_color; - } - inline otk::BImageControl *getImageControl(void) { return image_control; } - - Workspace *getWorkspace(unsigned int index) const; - - inline Workspace *getCurrentWorkspace(void) { return current_workspace; } - - inline unsigned int getResizeZones(void) const - { return resource.resize_zones; } - inline bool getPlaceIgnoreShaded(void) const - { return resource.ignore_shaded; } - inline bool getPlaceIgnoreMaximized(void) const - { return resource.ignore_maximized; } - - inline unsigned int getCurrentWorkspaceID(void) const - { return current_workspace->getID(); } - inline unsigned int getWorkspaceCount(void) const - { return workspacesList.size(); } - inline unsigned int getIconCount(void) const { return iconList.size(); } - inline unsigned int getNumberOfWorkspaces(void) const - { return resource.workspaces; } - inline int getPlacementPolicy(void) const - { return resource.placement_policy; } - inline int getSnapOffset(void) const - { return resource.snap_offset; } - inline int getSnapThreshold(void) const - { return resource.snap_threshold; } - inline int getResistanceSize(void) const - { return resource.resistance_size; } - inline int getRowPlacementDirection(void) const - { return resource.row_direction; } - inline int getColPlacementDirection(void) const - { return resource.col_direction; } - - void changeWorkspaceCount(unsigned int new_count); - - inline void setRootColormapInstalled(bool r) { root_colormap_installed = r; } - void saveSloppyFocus(bool s); - void saveAutoRaise(bool a); - void saveClickRaise(bool c); - void saveWorkspaces(unsigned int w); - void savePlacementPolicy(int p); - void saveRowPlacementDirection(int d); - void saveColPlacementDirection(int d); - void saveSnapThreshold(int t); - void saveSnapOffset(int o); - void saveResistanceSize(int s); - void saveImageDither(bool d); - void saveShadowFonts(bool f); - void saveAAFonts(bool f); - void saveOpaqueMove(bool o); - void saveFullMax(bool f); - void saveFocusNew(bool f); - void saveFocusLast(bool f); - void saveWindowToEdgeSnap(int s); - void saveWindowToWindowSnap(int s); - void saveWindowCornerSnap(bool s); - void saveResizeZones(unsigned int z); - void savePlaceIgnoreShaded(bool i); - void savePlaceIgnoreMaximized(bool i); - void saveAllowScrollLock(bool a); - void saveWorkspaceWarping(bool w); - void saveRootScrollDirection(int d); - - inline const char *getStrftimeFormat(void) - { return resource.strftime_format.c_str(); } - void saveStrftimeFormat(const std::string& format); - - inline otk::Style *getWindowStyle(void) { return &resource.wstyle; } - - BlackboxWindow *getIcon(unsigned int index); - - // allAvailableAreas should be used whenever possible instead of this function - // as then Xinerama will work correctly. - const otk::Rect& availableArea(void) const; -#ifdef XINERAMA - const RectList& allAvailableAreas(void) const; -#endif // XINERAMA - void updateAvailableArea(void); - void addStrut(otk::Strut *strut); - void removeStrut(otk::Strut *strut); - - unsigned int addWorkspace(void); - unsigned int removeLastWorkspace(void); - void changeWorkspaceID(unsigned int id); - void saveWorkspaceNames(void); - - void addSystrayWindow(Window window); - void removeSystrayWindow(Window window); - - void addIcon(BlackboxWindow *w); - void removeIcon(BlackboxWindow *w); - - void updateClientList(void); - void updateStackingList(void); - void manageWindow(Window w); - void unmanageWindow(BlackboxWindow *w, bool remap); - void raiseWindows(Window *workspace_stack, unsigned int num); - void lowerWindows(Window *workspace_stack, unsigned int num); - void reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id, - bool ignore_sticky); - void propagateWindowName(const BlackboxWindow *bw); - void prevFocus(void) const; - void nextFocus(void) const; - void raiseFocus(void) const; - void load_rc(void); - void save_rc(void); - void reconfigure(void); - void toggleFocusModel(FocusModel model); - void shutdown(void); - void showPosition(int x, int y); - void showGeometry(unsigned int gx, unsigned int gy); - void hideGeometry(void); - - void buttonPressEvent(const XButtonEvent *xbutton); - void propertyNotifyEvent(const XPropertyEvent *pe); -}; - -} - -#endif // __Screen_hh diff --git a/src/bbwindow.cc b/src/bbwindow.cc deleted file mode 100644 index e9616099..00000000 --- a/src/bbwindow.cc +++ /dev/null @@ -1,4208 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif // HAVE_CONFIG_H - -extern "C" { -#include -#include - -#ifdef HAVE_STRING_H -# include -#endif // HAVE_STRING_H - -#ifdef DEBUG -# ifdef HAVE_STDIO_H -# include -# endif // HAVE_STDIO_H -#endif // DEBUG - -#ifdef HAVE_STDLIB_H -# include -#endif // HAVE_STDLIB_H -} - -#include "blackbox.hh" -#include "font.hh" -#include "gccache.hh" -#include "image.hh" -#include "bbscreen.hh" -#include "bbwindow.hh" -#include "workspace.hh" - -#include "otk/util.hh" -#include "otk/style.hh" - -using std::string; -using std::abs; - -namespace ob { - -/* - * Initializes the class with default values/the window's set initial values. - */ -BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { - // fprintf(stderr, "BlackboxWindow size: %d bytes\n", - // sizeof(BlackboxWindow)); - -#ifdef DEBUG - fprintf(stderr, "BlackboxWindow::BlackboxWindow(): creating 0x%lx\n", w); -#endif // DEBUG - - /* - set timer to zero... it is initialized properly later, so we check - if timer is zero in the destructor, and assume that the window is not - fully constructed if timer is zero... - */ - timer = 0; - blackbox = b; - client.window = w; - screen = s; - xatom = blackbox->getXAtom(); - - if (! validateClient()) { - delete this; - return; - } - - // fetch client size and placement - XWindowAttributes wattrib; - if (! XGetWindowAttributes(otk::OBDisplay::display, - client.window, &wattrib) || - ! wattrib.screen || wattrib.override_redirect) { -#ifdef DEBUG - fprintf(stderr, - "BlackboxWindow::BlackboxWindow(): XGetWindowAttributes failed\n"); -#endif // DEBUG - - delete this; - return; - } - - // set the eventmask early in the game so that we make sure we get - // all the events we are interested in - XSetWindowAttributes attrib_set; - attrib_set.event_mask = PropertyChangeMask | FocusChangeMask | - StructureNotifyMask; - attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask; - XChangeWindowAttributes(otk::OBDisplay::display, client.window, - CWEventMask|CWDontPropagate, &attrib_set); - - flags.moving = flags.resizing = flags.shaded = flags.visible = - flags.iconic = flags.focused = flags.stuck = flags.modal = - flags.send_focus_message = flags.shaped = flags.skip_taskbar = - flags.skip_pager = flags.fullscreen = False; - flags.maximized = 0; - - blackbox_attrib.workspace = window_number = otk::BSENTINEL; - - blackbox_attrib.flags = blackbox_attrib.attrib = blackbox_attrib.stack = 0l; - blackbox_attrib.decoration = DecorNormal; - blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0; - blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0; - - frame.border_w = 1; - frame.window = frame.plate = frame.title = frame.handle = None; - frame.close_button = frame.iconify_button = frame.maximize_button = - frame.stick_button = None; - frame.right_grip = frame.left_grip = None; - - frame.ulabel_pixel = frame.flabel_pixel = frame.utitle_pixel = - frame.ftitle_pixel = frame.uhandle_pixel = frame.fhandle_pixel = - frame.ubutton_pixel = frame.fbutton_pixel = frame.uborder_pixel = - frame.fborder_pixel = frame.ugrip_pixel = frame.fgrip_pixel = 0; - frame.utitle = frame.ftitle = frame.uhandle = frame.fhandle = None; - frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None; - frame.ugrip = frame.fgrip = None; - - functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize; - mwm_decorations = Decor_Titlebar | Decor_Handle | Decor_Border | - Decor_Iconify | Decor_Maximize; - - client.normal_hint_flags = 0; - client.window_group = None; - client.transient_for = 0; - - current_state = NormalState; - - /* - set the initial size and location of client window (relative to the - _root window_). This position is the reference point used with the - window's gravity to find the window's initial position. - */ - client.rect.setRect(wattrib.x, wattrib.y, wattrib.width, wattrib.height); - client.old_bw = wattrib.border_width; - - lastButtonPressTime = 0; - - timer = new otk::OBTimer(Openbox::instance->timerManager(), - (otk::OBTimeoutHandler)timeout, - this); - timer->setTimeout(blackbox->getAutoRaiseDelay()); - - // get size, aspect, minimum/maximum size and other hints set by the - // client - - if (! getBlackboxHints()) - getNetWMHints(); - - getWMProtocols(); - getWMHints(); - getWMNormalHints(); - - frame.window = createToplevelWindow(); - - blackbox->saveWindowSearch(frame.window, this); - - frame.plate = createChildWindow(frame.window, ExposureMask); - blackbox->saveWindowSearch(frame.plate, this); - - // determine if this is a transient window - getTransientInfo(); - - // determine the window's type, so we can decide its decorations and - // functionality, or if we should not manage it at all - if (getWindowType()) { - // adjust the window decorations/behavior based on the window type - switch (window_type) { - case Type_Desktop: - case Type_Dock: - case Type_Menu: - blackbox_attrib.workspace = 0; // we do need to belong to a workspace - flags.stuck = True; // we show up on all workspaces - case Type_Splash: - // none of these windows are manipulated by the window manager - functions = 0; - break; - - case Type_Toolbar: - case Type_Utility: - // these windows get less functionality - functions &= ~(Func_Maximize | Func_Resize | Func_Iconify); - break; - - case Type_Dialog: - // dialogs cannot be maximized - functions &= ~Func_Maximize; - break; - - case Type_Normal: - // normal windows retain all of the possible decorations and - // functionality - break; - } - } else { - getMWMHints(); - } - - // further adjeust the window's decorations/behavior based on window sizes - if ((client.normal_hint_flags & PMinSize) && - (client.normal_hint_flags & PMaxSize) && - client.max_width <= client.min_width && - client.max_height <= client.min_height) { - functions &= ~(Func_Resize | Func_Maximize); - } - - setAllowedActions(); - - setupDecor(); - - if (decorations & Decor_Titlebar) - createTitlebar(); - - if (decorations & Decor_Handle) - createHandle(); - - // apply the size and gravity hint to the frame - - upsize(); - - bool place_window = True; - if (blackbox->state() == Openbox::State_Starting || isTransient() || - client.normal_hint_flags & (PPosition|USPosition)) { - applyGravity(frame.rect); - - if (blackbox->state() == Openbox::State_Starting || - client.rect.intersects(screen->getRect())) - place_window = False; - } - - // add the window's strut. note this is done *after* placing the window. - screen->addStrut(&client.strut); - updateStrut(); - - /* - the server needs to be grabbed here to prevent client's from sending - events while we are in the process of configuring their window. - We hold the grab until after we are done moving the window around. - */ - - XGrabServer(otk::OBDisplay::display); - - associateClientWindow(); - - blackbox->saveWindowSearch(client.window, this); - - if (blackbox_attrib.workspace >= screen->getWorkspaceCount()) - screen->getCurrentWorkspace()->addWindow(this, place_window); - else - screen->getWorkspace(blackbox_attrib.workspace)-> - addWindow(this, place_window); - - if (! place_window) { - // don't need to call configure if we are letting the workspace - // place the window - configure(frame.rect.x(), frame.rect.y(), - frame.rect.width(), frame.rect.height()); - - } - - positionWindows(); - - XUngrabServer(otk::OBDisplay::display); - -#ifdef SHAPE - if (otk::OBDisplay::shape() && flags.shaped) - configureShape(); -#endif // SHAPE - - // now that we know where to put the window and what it should look like - // we apply the decorations - decorate(); - - grabButtons(); - - XMapSubwindows(otk::OBDisplay::display, frame.window); - - // this ensures the title, buttons, and other decor are properly displayed - redrawWindowFrame(); - - // preserve the window's initial state on first map, and its current state - // across a restart - unsigned long initial_state = current_state; - if (! getState()) - current_state = initial_state; - - // get sticky state from our parent window if we've got one - if (isTransient() && client.transient_for != (BlackboxWindow *) ~0ul && - client.transient_for->isStuck() != flags.stuck) - flags.stuck = True; - - if (flags.shaded) { - flags.shaded = False; - initial_state = current_state; - shade(); - - /* - At this point in the life of a window, current_state should only be set - to IconicState if the window was an *icon*, not if it was shaded. - */ - if (initial_state != IconicState) - current_state = NormalState; - } - - if (flags.stuck) { - flags.stuck = False; - stick(); - } - - if (flags.maximized && (functions & Func_Maximize)) - remaximize(); -} - - -BlackboxWindow::~BlackboxWindow(void) { -#ifdef DEBUG - fprintf(stderr, "BlackboxWindow::~BlackboxWindow: destroying 0x%lx\n", - client.window); -#endif // DEBUG - - if (! timer) // window not managed... - return; - - if (flags.moving) - endMove(); - - screen->removeStrut(&client.strut); - screen->updateAvailableArea(); - - // We don't need to worry about resizing because resizing always grabs the X - // server. This should only ever happen if using opaque moving. - if (flags.moving) - endMove(); - - delete timer; - - if (client.window_group) { - BWindowGroup *group = blackbox->searchGroup(client.window_group); - if (group) group->removeWindow(this); - } - - // remove ourselves from our transient_for - if (isTransient()) { - if (client.transient_for != (BlackboxWindow *) ~0ul) - client.transient_for->client.transientList.remove(this); - client.transient_for = (BlackboxWindow*) 0; - } - - if (client.transientList.size() > 0) { - // reset transient_for for all transients - BlackboxWindowList::iterator it, end = client.transientList.end(); - for (it = client.transientList.begin(); it != end; ++it) - (*it)->client.transient_for = (BlackboxWindow*) 0; - } - - if (frame.title) - destroyTitlebar(); - - if (frame.handle) - destroyHandle(); - - if (frame.plate) { - blackbox->removeWindowSearch(frame.plate); - XDestroyWindow(otk::OBDisplay::display, frame.plate); - } - - if (frame.window) { - blackbox->removeWindowSearch(frame.window); - XDestroyWindow(otk::OBDisplay::display, frame.window); - } - - blackbox->removeWindowSearch(client.window); -} - - -void BlackboxWindow::enableDecor(bool enable) { - blackbox_attrib.flags |= AttribDecoration; - blackbox_attrib.decoration = enable ? DecorNormal : DecorNone; - setupDecor(); - - // we can not be shaded if we lack a titlebar - if (! (decorations & Decor_Titlebar) && flags.shaded) - shade(); - - if (flags.visible && frame.window) { - XMapSubwindows(otk::OBDisplay::display, frame.window); - XMapWindow(otk::OBDisplay::display, frame.window); - } - - reconfigure(); - setState(current_state); -} - - -void BlackboxWindow::setupDecor() { - if (blackbox_attrib.decoration != DecorNone) { - // start with everything on - decorations = Decor_Close | - (mwm_decorations & Decor_Titlebar ? Decor_Titlebar : 0) | - (mwm_decorations & Decor_Border ? Decor_Border : 0) | - (mwm_decorations & Decor_Handle ? Decor_Handle : 0) | - (mwm_decorations & Decor_Iconify ? Decor_Iconify : 0) | - (mwm_decorations & Decor_Maximize ? Decor_Maximize : 0); - - if (! (functions & Func_Close)) decorations &= ~Decor_Close; - if (! (functions & Func_Maximize)) decorations &= ~Decor_Maximize; - if (! (functions & Func_Iconify)) decorations &= ~Decor_Iconify; - if (! (functions & Func_Resize)) decorations &= ~Decor_Handle; - - switch (window_type) { - case Type_Desktop: - case Type_Dock: - case Type_Menu: - case Type_Splash: - // none of these windows are decorated by the window manager at all - decorations = 0; - break; - - case Type_Toolbar: - case Type_Utility: - decorations &= ~(Decor_Border); - break; - - case Type_Dialog: - decorations &= ~Decor_Handle; - break; - - case Type_Normal: - break; - } - } else { - decorations = 0; - } -} - -/* - * Creates a new top level window, with a given location, size, and border - * width. - * Returns: the newly created window - */ -Window BlackboxWindow::createToplevelWindow(void) { - XSetWindowAttributes attrib_create; - unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap | - CWOverrideRedirect | CWEventMask; - - attrib_create.background_pixmap = None; - attrib_create.colormap = screen->getColormap(); - attrib_create.override_redirect = True; - attrib_create.event_mask = EnterWindowMask | LeaveWindowMask | - ButtonPress; - /* - We catch button presses because other wise they get passed down to the - root window, which will then cause root menus to show when you click the - window's frame. - */ - - return XCreateWindow(otk::OBDisplay::display, screen->getRootWindow(), - 0, 0, 1, 1, frame.border_w, screen->getDepth(), - InputOutput, screen->getVisual(), create_mask, - &attrib_create); -} - - -/* - * Creates a child window, and optionally associates a given cursor with - * the new window. - */ -Window BlackboxWindow::createChildWindow(Window parent, - unsigned long event_mask, - Cursor cursor) { - XSetWindowAttributes attrib_create; - unsigned long create_mask = CWBackPixmap | CWBorderPixel | - CWEventMask; - - attrib_create.background_pixmap = None; - attrib_create.event_mask = event_mask; - - if (cursor) { - create_mask |= CWCursor; - attrib_create.cursor = cursor; - } - - return XCreateWindow(otk::OBDisplay::display, parent, 0, 0, 1, 1, 0, - screen->getDepth(), InputOutput, screen->getVisual(), - create_mask, &attrib_create); -} - - -void BlackboxWindow::associateClientWindow(void) { - XSetWindowBorderWidth(otk::OBDisplay::display, client.window, 0); - getWMName(); - getWMIconName(); - - XChangeSaveSet(otk::OBDisplay::display, client.window, SetModeInsert); - - XSelectInput(otk::OBDisplay::display, frame.plate, SubstructureRedirectMask); - - /* - note we used to grab around this call to XReparentWindow however the - server is now grabbed before this method is called - */ - unsigned long event_mask = PropertyChangeMask | FocusChangeMask | - StructureNotifyMask; - XSelectInput(otk::OBDisplay::display, client.window, - event_mask & ~StructureNotifyMask); - XReparentWindow(otk::OBDisplay::display, client.window, frame.plate, 0, 0); - XSelectInput(otk::OBDisplay::display, client.window, event_mask); - - XRaiseWindow(otk::OBDisplay::display, frame.plate); - XMapSubwindows(otk::OBDisplay::display, frame.plate); - -#ifdef SHAPE - if (otk::OBDisplay::shape()) { - XShapeSelectInput(otk::OBDisplay::display, client.window, - ShapeNotifyMask); - - Bool shaped = False; - int foo; - unsigned int ufoo; - - XShapeQueryExtents(otk::OBDisplay::display, client.window, &shaped, - &foo, &foo, &ufoo, &ufoo, &foo, &foo, &foo, - &ufoo, &ufoo); - flags.shaped = shaped; - } -#endif // SHAPE -} - - -void BlackboxWindow::decorate(void) { - otk::BTexture* texture; - - texture = &(screen->getWindowStyle()->b_focus); - frame.fbutton = texture->render(frame.button_w, frame.button_w, - frame.fbutton); - if (! frame.fbutton) - frame.fbutton_pixel = texture->color().pixel(); - - texture = &(screen->getWindowStyle()->b_unfocus); - frame.ubutton = texture->render(frame.button_w, frame.button_w, - frame.ubutton); - if (! frame.ubutton) - frame.ubutton_pixel = texture->color().pixel(); - - unsigned char needsPressed = 0; - - texture = &(screen->getWindowStyle()->b_pressed_focus); - - if (texture->texture() != otk::BTexture::NoTexture) { - frame.pfbutton = texture->render(frame.button_w, frame.button_w, - frame.pfbutton); - if (! frame.pfbutton) - frame.pfbutton_pixel = texture->color().pixel(); - } else { - needsPressed = 0x1; - } - - texture = &(screen->getWindowStyle()->b_pressed_unfocus); - - if (texture->texture() != otk::BTexture::NoTexture) { - frame.pubutton = texture->render(frame.button_w, frame.button_w, - frame.pubutton); - if (! frame.pubutton) - frame.pubutton = texture->color().pixel(); - } else { - needsPressed |= 0x2; - } - - // if we either pressed unfocused, or pressed focused were undefined, - // make them inherit from the old resource. It's a hack for sure, but - // it allows for some backwards and forwards compatibility. - if (needsPressed) { - texture = &(screen->getWindowStyle()->b_pressed); - - if (needsPressed & 0x1) { - frame.pfbutton = texture->render(frame.button_w, frame.button_w, - frame.pfbutton); - if (! frame.pfbutton) - frame.pfbutton_pixel = texture->color().pixel(); - } - if (needsPressed & 0x2) { - frame.pubutton = texture->render(frame.button_w, frame.button_w, - frame.pubutton); - if (! frame.pubutton) - frame.pubutton = texture->color().pixel(); - } - - } - - if (decorations & Decor_Titlebar) { - texture = &(screen->getWindowStyle()->t_focus); - frame.ftitle = texture->render(frame.inside_w, frame.title_h, - frame.ftitle); - if (! frame.ftitle) - frame.ftitle_pixel = texture->color().pixel(); - - texture = &(screen->getWindowStyle()->t_unfocus); - frame.utitle = texture->render(frame.inside_w, frame.title_h, - frame.utitle); - if (! frame.utitle) - frame.utitle_pixel = texture->color().pixel(); - - XSetWindowBorder(otk::OBDisplay::display, frame.title, - screen->getBorderColor()->pixel()); - - decorateLabel(); - } - - if (decorations & Decor_Border) { - frame.fborder_pixel = screen->getWindowStyle()->f_focus.color().pixel(); - frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.color().pixel(); - } - - if (decorations & Decor_Handle) { - texture = &(screen->getWindowStyle()->h_focus); - frame.fhandle = texture->render(frame.inside_w, frame.handle_h, - frame.fhandle); - if (! frame.fhandle) - frame.fhandle_pixel = texture->color().pixel(); - - texture = &(screen->getWindowStyle()->h_unfocus); - frame.uhandle = texture->render(frame.inside_w, frame.handle_h, - frame.uhandle); - if (! frame.uhandle) - frame.uhandle_pixel = texture->color().pixel(); - - texture = &(screen->getWindowStyle()->g_focus); - frame.fgrip = texture->render(frame.grip_w, frame.handle_h, frame.fgrip); - if (! frame.fgrip) - frame.fgrip_pixel = texture->color().pixel(); - - texture = &(screen->getWindowStyle()->g_unfocus); - frame.ugrip = texture->render(frame.grip_w, frame.handle_h, frame.ugrip); - if (! frame.ugrip) - frame.ugrip_pixel = texture->color().pixel(); - - XSetWindowBorder(otk::OBDisplay::display, frame.handle, - screen->getBorderColor()->pixel()); - XSetWindowBorder(otk::OBDisplay::display, frame.left_grip, - screen->getBorderColor()->pixel()); - XSetWindowBorder(otk::OBDisplay::display, frame.right_grip, - screen->getBorderColor()->pixel()); - } - - XSetWindowBorder(otk::OBDisplay::display, frame.window, - screen->getBorderColor()->pixel()); -} - - -void BlackboxWindow::decorateLabel(void) { - otk::BTexture *texture; - - texture = &(screen->getWindowStyle()->l_focus); - frame.flabel = texture->render(frame.label_w, frame.label_h, frame.flabel); - if (! frame.flabel) - frame.flabel_pixel = texture->color().pixel(); - - texture = &(screen->getWindowStyle()->l_unfocus); - frame.ulabel = texture->render(frame.label_w, frame.label_h, frame.ulabel); - if (! frame.ulabel) - frame.ulabel_pixel = texture->color().pixel(); -} - - -void BlackboxWindow::createHandle(void) { - frame.handle = createChildWindow(frame.window, - ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask | ExposureMask); - blackbox->saveWindowSearch(frame.handle, this); - - frame.left_grip = - createChildWindow(frame.handle, - ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask | ExposureMask, - blackbox->getLowerLeftAngleCursor()); - blackbox->saveWindowSearch(frame.left_grip, this); - - frame.right_grip = - createChildWindow(frame.handle, - ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask | ExposureMask, - blackbox->getLowerRightAngleCursor()); - blackbox->saveWindowSearch(frame.right_grip, this); -} - - -void BlackboxWindow::destroyHandle(void) { - if (frame.fhandle) - screen->getImageControl()->removeImage(frame.fhandle); - - if (frame.uhandle) - screen->getImageControl()->removeImage(frame.uhandle); - - if (frame.fgrip) - screen->getImageControl()->removeImage(frame.fgrip); - - if (frame.ugrip) - screen->getImageControl()->removeImage(frame.ugrip); - - blackbox->removeWindowSearch(frame.left_grip); - blackbox->removeWindowSearch(frame.right_grip); - - XDestroyWindow(otk::OBDisplay::display, frame.left_grip); - XDestroyWindow(otk::OBDisplay::display, frame.right_grip); - frame.left_grip = frame.right_grip = None; - - blackbox->removeWindowSearch(frame.handle); - XDestroyWindow(otk::OBDisplay::display, frame.handle); - frame.handle = None; -} - - -void BlackboxWindow::createTitlebar(void) { - frame.title = createChildWindow(frame.window, - ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask | ExposureMask); - frame.label = createChildWindow(frame.title, - ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask | ExposureMask); - blackbox->saveWindowSearch(frame.title, this); - blackbox->saveWindowSearch(frame.label, this); - - if (decorations & Decor_Iconify) createIconifyButton(); - if (decorations & Decor_Maximize) createMaximizeButton(); - if (decorations & Decor_Close) createCloseButton(); -} - - -void BlackboxWindow::destroyTitlebar(void) { - if (frame.close_button) - destroyCloseButton(); - - if (frame.iconify_button) - destroyIconifyButton(); - - if (frame.maximize_button) - destroyMaximizeButton(); - - if (frame.stick_button) - destroyStickyButton(); - - if (frame.ftitle) - screen->getImageControl()->removeImage(frame.ftitle); - - if (frame.utitle) - screen->getImageControl()->removeImage(frame.utitle); - - if (frame.flabel) - screen->getImageControl()->removeImage(frame.flabel); - - if( frame.ulabel) - screen->getImageControl()->removeImage(frame.ulabel); - - if (frame.fbutton) - screen->getImageControl()->removeImage(frame.fbutton); - - if (frame.ubutton) - screen->getImageControl()->removeImage(frame.ubutton); - - blackbox->removeWindowSearch(frame.title); - blackbox->removeWindowSearch(frame.label); - - XDestroyWindow(otk::OBDisplay::display, frame.label); - XDestroyWindow(otk::OBDisplay::display, frame.title); - frame.title = frame.label = None; -} - - -void BlackboxWindow::createCloseButton(void) { - if (frame.title != None) { - frame.close_button = createChildWindow(frame.title, - ButtonPressMask | - ButtonReleaseMask | - ButtonMotionMask | ExposureMask); - blackbox->saveWindowSearch(frame.close_button, this); - } -} - - -void BlackboxWindow::destroyCloseButton(void) { - blackbox->removeWindowSearch(frame.close_button); - XDestroyWindow(otk::OBDisplay::display, frame.close_button); - frame.close_button = None; -} - - -void BlackboxWindow::createIconifyButton(void) { - if (frame.title != None) { - frame.iconify_button = createChildWindow(frame.title, - ButtonPressMask | - ButtonReleaseMask | - ButtonMotionMask | ExposureMask); - blackbox->saveWindowSearch(frame.iconify_button, this); - } -} - - -void BlackboxWindow::destroyIconifyButton(void) { - blackbox->removeWindowSearch(frame.iconify_button); - XDestroyWindow(otk::OBDisplay::display, frame.iconify_button); - frame.iconify_button = None; -} - - -void BlackboxWindow::createMaximizeButton(void) { - if (frame.title != None) { - frame.maximize_button = createChildWindow(frame.title, - ButtonPressMask | - ButtonReleaseMask | - ButtonMotionMask | ExposureMask); - blackbox->saveWindowSearch(frame.maximize_button, this); - } -} - - -void BlackboxWindow::destroyMaximizeButton(void) { - blackbox->removeWindowSearch(frame.maximize_button); - XDestroyWindow(otk::OBDisplay::display, frame.maximize_button); - frame.maximize_button = None; -} - -void BlackboxWindow::createStickyButton(void) { - if (frame.title != None) { - frame.stick_button = createChildWindow(frame.title, - ButtonPressMask | - ButtonReleaseMask | - ButtonMotionMask | ExposureMask); - blackbox->saveWindowSearch(frame.stick_button, this); - } -} - -void BlackboxWindow::destroyStickyButton(void) { - blackbox->removeWindowSearch(frame.stick_button); - XDestroyWindow(otk::OBDisplay::display, frame.stick_button); - frame.stick_button = None; -} - -void BlackboxWindow::positionButtons(bool redecorate_label) { - string layout = blackbox->getTitlebarLayout(); - string parsed; - - bool hasclose, hasiconify, hasmaximize, haslabel, hasstick; - hasclose = hasiconify = hasmaximize = haslabel = hasstick = false; - - string::const_iterator it, end; - for (it = layout.begin(), end = layout.end(); it != end; ++it) { - switch(*it) { - case 'C': - if (! hasclose && (decorations & Decor_Close)) { - hasclose = true; - parsed += *it; - } - break; - case 'I': - if (! hasiconify && (decorations & Decor_Iconify)) { - hasiconify = true; - parsed += *it; - } - break; - case 'S': - if (!hasstick) { - hasstick = true; - parsed += *it; - } - break; - case 'M': - if (! hasmaximize && (decorations & Decor_Maximize)) { - hasmaximize = true; - parsed += *it; - } - break; - case 'L': - if (! haslabel) { - haslabel = true; - parsed += *it; - } - break; - } - } - - if (! hasclose && frame.close_button) - destroyCloseButton(); - if (! hasiconify && frame.iconify_button) - destroyIconifyButton(); - if (! hasmaximize && frame.maximize_button) - destroyMaximizeButton(); - if (! hasstick && frame.stick_button) - destroyStickyButton(); - if (! haslabel) - parsed += 'L'; // require that the label be in the layout - - const unsigned int bsep = frame.bevel_w + 1; // separation between elements - const unsigned int by = frame.bevel_w + 1; - const unsigned int ty = frame.bevel_w; - - frame.label_w = frame.inside_w - bsep * 2 - - (frame.button_w + bsep) * (parsed.size() - 1); - - unsigned int x = bsep; - for (it = parsed.begin(), end = parsed.end(); it != end; ++it) { - switch(*it) { - case 'C': - if (! frame.close_button) createCloseButton(); - XMoveResizeWindow(otk::OBDisplay::display, frame.close_button, x, by, - frame.button_w, frame.button_w); - x += frame.button_w + bsep; - break; - case 'I': - if (! frame.iconify_button) createIconifyButton(); - XMoveResizeWindow(otk::OBDisplay::display, frame.iconify_button, x, by, - frame.button_w, frame.button_w); - x += frame.button_w + bsep; - break; - case 'S': - if (! frame.stick_button) createStickyButton(); - XMoveResizeWindow(otk::OBDisplay::display, frame.stick_button, x, by, - frame.button_w, frame.button_w); - x += frame.button_w + bsep; - break; - case 'M': - if (! frame.maximize_button) createMaximizeButton(); - XMoveResizeWindow(otk::OBDisplay::display, frame.maximize_button, x, by, - frame.button_w, frame.button_w); - x += frame.button_w + bsep; - break; - case 'L': - XMoveResizeWindow(otk::OBDisplay::display, frame.label, x, ty, - frame.label_w, frame.label_h); - x += frame.label_w + bsep; - break; - } - } - - if (redecorate_label) decorateLabel(); - redrawLabel(); - redrawAllButtons(); -} - - -void BlackboxWindow::reconfigure(void) { - restoreGravity(client.rect); - upsize(); - applyGravity(frame.rect); - positionWindows(); - decorate(); - redrawWindowFrame(); - - ungrabButtons(); - grabButtons(); -} - - -void BlackboxWindow::grabButtons(void) { - mod_mask = blackbox->getMouseModMask(); - - if (! screen->isSloppyFocus() || screen->doClickRaise()) - // grab button 1 for changing focus/raising - otk::OBDisplay::grabButton(Button1, 0, frame.plate, True, ButtonPressMask, - GrabModeSync, GrabModeSync, frame.plate, None, - screen->allowScrollLock()); - - if (functions & Func_Move) - otk::OBDisplay::grabButton(Button1, mod_mask, frame.window, True, - ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, - GrabModeAsync, frame.window, None, - screen->allowScrollLock()); - if (functions & Func_Resize) - otk::OBDisplay::grabButton(Button3, mod_mask, frame.window, True, - ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, - GrabModeAsync, frame.window, None, - screen->allowScrollLock()); - // alt+middle lowers the window - otk::OBDisplay::grabButton(Button2, mod_mask, frame.window, True, - ButtonReleaseMask, GrabModeAsync, GrabModeAsync, - frame.window, None, screen->allowScrollLock()); -} - - -void BlackboxWindow::ungrabButtons(void) { - otk::OBDisplay::ungrabButton(Button1, 0, frame.plate); - otk::OBDisplay::ungrabButton(Button1, mod_mask, frame.window); - otk::OBDisplay::ungrabButton(Button2, mod_mask, frame.window); - otk::OBDisplay::ungrabButton(Button3, mod_mask, frame.window); -} - - -void BlackboxWindow::positionWindows(void) { - XMoveResizeWindow(otk::OBDisplay::display, frame.window, - frame.rect.x(), frame.rect.y(), frame.inside_w, - (flags.shaded) ? frame.title_h : frame.inside_h); - XSetWindowBorderWidth(otk::OBDisplay::display, frame.window, - frame.border_w); - XSetWindowBorderWidth(otk::OBDisplay::display, frame.plate, - frame.mwm_border_w); - XMoveResizeWindow(otk::OBDisplay::display, frame.plate, - frame.margin.left - frame.mwm_border_w - frame.border_w, - frame.margin.top - frame.mwm_border_w - frame.border_w, - client.rect.width(), client.rect.height()); - XMoveResizeWindow(otk::OBDisplay::display, client.window, - 0, 0, client.rect.width(), client.rect.height()); - // ensure client.rect contains the real location - client.rect.setPos(frame.rect.left() + frame.margin.left, - frame.rect.top() + frame.margin.top); - - if (decorations & Decor_Titlebar) { - if (frame.title == None) createTitlebar(); - - XSetWindowBorderWidth(otk::OBDisplay::display, frame.title, - frame.border_w); - XMoveResizeWindow(otk::OBDisplay::display, frame.title, -frame.border_w, - -frame.border_w, frame.inside_w, frame.title_h); - - positionButtons(); - XMapSubwindows(otk::OBDisplay::display, frame.title); - XMapWindow(otk::OBDisplay::display, frame.title); - } else if (frame.title) { - destroyTitlebar(); - } - if (decorations & Decor_Handle) { - if (frame.handle == None) createHandle(); - XSetWindowBorderWidth(otk::OBDisplay::display, frame.handle, - frame.border_w); - XSetWindowBorderWidth(otk::OBDisplay::display, frame.left_grip, - frame.border_w); - XSetWindowBorderWidth(otk::OBDisplay::display, frame.right_grip, - frame.border_w); - - // use client.rect here so the value is correct even if shaded - XMoveResizeWindow(otk::OBDisplay::display, frame.handle, - -frame.border_w, - client.rect.height() + frame.margin.top + - frame.mwm_border_w - frame.border_w, - frame.inside_w, frame.handle_h); - XMoveResizeWindow(otk::OBDisplay::display, frame.left_grip, - -frame.border_w, -frame.border_w, - frame.grip_w, frame.handle_h); - XMoveResizeWindow(otk::OBDisplay::display, frame.right_grip, - frame.inside_w - frame.grip_w - frame.border_w, - -frame.border_w, frame.grip_w, frame.handle_h); - - XMapSubwindows(otk::OBDisplay::display, frame.handle); - XMapWindow(otk::OBDisplay::display, frame.handle); - } else if (frame.handle) { - destroyHandle(); - } - XSync(otk::OBDisplay::display, False); -} - - -void BlackboxWindow::updateStrut(void) { - unsigned long num = 4; - unsigned long *data; - if (! xatom->get(client.window, otk::OBProperty::net_wm_strut, - otk::OBProperty::Atom_Cardinal, - &num, &data)) - return; - - if (num == 4) { - client.strut.left = data[0]; - client.strut.right = data[1]; - client.strut.top = data[2]; - client.strut.bottom = data[3]; - - screen->updateAvailableArea(); - } - - delete [] data; -} - - -bool BlackboxWindow::getWindowType(void) { - window_type = (WindowType) -1; - - unsigned long *val; - unsigned long num = (unsigned) -1; - if (xatom->get(client.window, otk::OBProperty::net_wm_window_type, - otk::OBProperty::Atom_Atom, - &num, &val)) { - for (unsigned long i = 0; i < num; ++i) { - if (val[i] == xatom->atom(otk::OBProperty::net_wm_window_type_desktop)) - window_type = Type_Desktop; - else if (val[i] == xatom->atom(otk::OBProperty::net_wm_window_type_dock)) - window_type = Type_Dock; - else if (val[i] == xatom->atom(otk::OBProperty::net_wm_window_type_toolbar)) - window_type = Type_Toolbar; - else if (val[i] == xatom->atom(otk::OBProperty::net_wm_window_type_menu)) - window_type = Type_Menu; - else if (val[i] == xatom->atom(otk::OBProperty::net_wm_window_type_utility)) - window_type = Type_Utility; - else if (val[i] == xatom->atom(otk::OBProperty::net_wm_window_type_splash)) - window_type = Type_Splash; - else if (val[i] == xatom->atom(otk::OBProperty::net_wm_window_type_dialog)) - window_type = Type_Dialog; - else if (val[i] == xatom->atom(otk::OBProperty::net_wm_window_type_normal)) - window_type = Type_Normal; - else if (val[i] == - xatom->atom(otk::OBProperty::kde_net_wm_window_type_override)) - mwm_decorations = 0; // prevent this window from getting any decor - } - delete val; - } - - if (window_type == (WindowType) -1) { - /* - * the window type hint was not set, which means we either classify ourself - * as a normal window or a dialog, depending on if we are a transient. - */ - if (isTransient()) - window_type = Type_Dialog; - else - window_type = Type_Normal; - - return False; - } - - return True; -} - - -void BlackboxWindow::getWMName(void) { - if (xatom->get(client.window, otk::OBProperty::net_wm_name, - otk::OBProperty::utf8, &client.title) && - !client.title.empty()) { - xatom->erase(client.window, otk::OBProperty::net_wm_visible_name); - return; - } - //fall through to using WM_NAME - if (xatom->get(client.window, otk::OBProperty::wm_name, - otk::OBProperty::ascii, &client.title) - && !client.title.empty()) { - xatom->erase(client.window, otk::OBProperty::net_wm_visible_name); - return; - } - // fall back to an internal default - client.title = "Unnamed"; - xatom->set(client.window, otk::OBProperty::net_wm_visible_name, - otk::OBProperty::utf8, client.title); - -#ifdef DEBUG_WITH_ID - // the 16 is the 8 chars of the debug text plus the number - char *tmp = new char[client.title.length() + 16]; - sprintf(tmp, "%s; id: 0x%lx", client.title.c_str(), client.window); - client.title = tmp; - delete tmp; -#endif -} - - -void BlackboxWindow::getWMIconName(void) { - if (xatom->get(client.window, otk::OBProperty::net_wm_icon_name, - otk::OBProperty::utf8, &client.icon_title) && - !client.icon_title.empty()) { - xatom->erase(client.window, otk::OBProperty::net_wm_visible_icon_name); - return; - } - //fall through to using WM_ICON_NAME - if (xatom->get(client.window, otk::OBProperty::wm_icon_name, - otk::OBProperty::ascii, - &client.icon_title) && - !client.icon_title.empty()) { - xatom->erase(client.window, otk::OBProperty::net_wm_visible_icon_name); - return; - } - // fall back to using the main name - client.icon_title = client.title; - xatom->set(client.window, otk::OBProperty::net_wm_visible_icon_name, - otk::OBProperty::utf8, - client.icon_title); -} - - -/* - * Retrieve which WM Protocols are supported by the client window. - * If the WM_DELETE_WINDOW protocol is supported, add the close button to the - * window's decorations and allow the close behavior. - * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates - * this. - */ -void BlackboxWindow::getWMProtocols(void) { - Atom *proto; - int num_return = 0; - - if (XGetWMProtocols(otk::OBDisplay::display, client.window, - &proto, &num_return)) { - for (int i = 0; i < num_return; ++i) { - if (proto[i] == xatom->atom(otk::OBProperty::wm_delete_window)) { - decorations |= Decor_Close; - functions |= Func_Close; - } else if (proto[i] == xatom->atom(otk::OBProperty::wm_take_focus)) - flags.send_focus_message = True; - } - - XFree(proto); - } -} - - -/* - * Gets the value of the WM_HINTS property. - * If the property is not set, then use a set of default values. - */ -void BlackboxWindow::getWMHints(void) { - focus_mode = F_Passive; - - // remove from current window group - if (client.window_group) { - BWindowGroup *group = blackbox->searchGroup(client.window_group); - if (group) group->removeWindow(this); - } - client.window_group = None; - - XWMHints *wmhint = XGetWMHints(otk::OBDisplay::display, client.window); - if (! wmhint) { - return; - } - - if (wmhint->flags & InputHint) { - if (wmhint->input == True) { - if (flags.send_focus_message) - focus_mode = F_LocallyActive; - } else { - if (flags.send_focus_message) - focus_mode = F_GloballyActive; - else - focus_mode = F_NoInput; - } - } - - if (wmhint->flags & StateHint) - current_state = wmhint->initial_state; - - if (wmhint->flags & WindowGroupHint) { - client.window_group = wmhint->window_group; - - // add window to the appropriate group - BWindowGroup *group = blackbox->searchGroup(client.window_group); - if (! group) { // no group found, create it! - new BWindowGroup(blackbox, client.window_group); - group = blackbox->searchGroup(client.window_group); - } - if (group) - group->addWindow(this); - } - - XFree(wmhint); -} - - -/* - * Gets the value of the WM_NORMAL_HINTS property. - * If the property is not set, then use a set of default values. - */ -void BlackboxWindow::getWMNormalHints(void) { - long icccm_mask; - XSizeHints sizehint; - - client.min_width = client.min_height = - client.width_inc = client.height_inc = 1; - client.base_width = client.base_height = 0; - client.win_gravity = NorthWestGravity; -#if 0 - client.min_aspect_x = client.min_aspect_y = - client.max_aspect_x = client.max_aspect_y = 1; -#endif - - // don't limit the size of a window, the default max width is the biggest - // possible - client.max_width = (unsigned) -1; - client.max_height = (unsigned) -1; - - - if (! XGetWMNormalHints(otk::OBDisplay::display, client.window, - &sizehint, &icccm_mask)) - return; - - client.normal_hint_flags = sizehint.flags; - - if (sizehint.flags & PMinSize) { - if (sizehint.min_width >= 0) - client.min_width = sizehint.min_width; - if (sizehint.min_height >= 0) - client.min_height = sizehint.min_height; - } - - if (sizehint.flags & PMaxSize) { - if (sizehint.max_width > static_cast(client.min_width)) - client.max_width = sizehint.max_width; - else - client.max_width = client.min_width; - - if (sizehint.max_height > static_cast(client.min_height)) - client.max_height = sizehint.max_height; - else - client.max_height = client.min_height; - } - - if (sizehint.flags & PResizeInc) { - client.width_inc = sizehint.width_inc; - client.height_inc = sizehint.height_inc; - } - -#if 0 // we do not support this at the moment - if (sizehint.flags & PAspect) { - client.min_aspect_x = sizehint.min_aspect.x; - client.min_aspect_y = sizehint.min_aspect.y; - client.max_aspect_x = sizehint.max_aspect.x; - client.max_aspect_y = sizehint.max_aspect.y; - } -#endif - - if (sizehint.flags & PBaseSize) { - client.base_width = sizehint.base_width; - client.base_height = sizehint.base_height; - } - - if (sizehint.flags & PWinGravity) - client.win_gravity = sizehint.win_gravity; -} - - -/* - * Gets the NETWM hints for the class' contained window. - */ -void BlackboxWindow::getNetWMHints(void) { - unsigned long workspace; - - if (xatom->get(client.window, otk::OBProperty::net_wm_desktop, - otk::OBProperty::Atom_Cardinal, - &workspace)) { - if (workspace == 0xffffffff) - flags.stuck = True; - else - blackbox_attrib.workspace = workspace; - } - - unsigned long *state; - unsigned long num = (unsigned) -1; - if (xatom->get(client.window, otk::OBProperty::net_wm_state, - otk::OBProperty::Atom_Atom, - &num, &state)) { - bool vert = False, - horz = False; - for (unsigned long i = 0; i < num; ++i) { - if (state[i] == xatom->atom(otk::OBProperty::net_wm_state_modal)) - flags.modal = True; - else if (state[i] == xatom->atom(otk::OBProperty::net_wm_state_shaded)) - flags.shaded = True; - else if (state[i] == xatom->atom(otk::OBProperty::net_wm_state_skip_taskbar)) - flags.skip_taskbar = True; - else if (state[i] == xatom->atom(otk::OBProperty::net_wm_state_skip_pager)) - flags.skip_pager = True; - else if (state[i] == xatom->atom(otk::OBProperty::net_wm_state_fullscreen)) - flags.fullscreen = True; - else if (state[i] == xatom->atom(otk::OBProperty::net_wm_state_hidden)) - setState(IconicState); - else if (state[i] == xatom->atom(otk::OBProperty::net_wm_state_maximized_vert)) - vert = True; - else if (state[i] == xatom->atom(otk::OBProperty::net_wm_state_maximized_horz)) - horz = True; - } - if (vert && horz) - flags.maximized = 1; - else if (vert) - flags.maximized = 2; - else if (horz) - flags.maximized = 3; - - delete [] state; - } -} - - -/* - * Gets the MWM hints for the class' contained window. - * This is used while initializing the window to its first state, and not - * thereafter. - * Returns: true if the MWM hints are successfully retreived and applied; - * false if they are not. - */ -void BlackboxWindow::getMWMHints(void) { - unsigned long num; - MwmHints *mwm_hint; - - num = PropMwmHintsElements; - if (! xatom->get(client.window, otk::OBProperty::motif_wm_hints, - otk::OBProperty::motif_wm_hints, &num, - (unsigned long **)&mwm_hint)) - return; - if (num < PropMwmHintsElements) { - delete [] mwm_hint; - return; - } - - if (mwm_hint->flags & MwmHintsDecorations) { - if (mwm_hint->decorations & MwmDecorAll) { - mwm_decorations = Decor_Titlebar | Decor_Handle | Decor_Border | - Decor_Iconify | Decor_Maximize; - } else { - mwm_decorations = 0; - - if (mwm_hint->decorations & MwmDecorBorder) - mwm_decorations |= Decor_Border; - if (mwm_hint->decorations & MwmDecorHandle) - mwm_decorations |= Decor_Handle; - if (mwm_hint->decorations & MwmDecorTitle) - mwm_decorations |= Decor_Titlebar; - if (mwm_hint->decorations & MwmDecorIconify) - mwm_decorations |= Decor_Iconify; - if (mwm_hint->decorations & MwmDecorMaximize) - mwm_decorations |= Decor_Maximize; - } - } - - if (mwm_hint->flags & MwmHintsFunctions) { - if (mwm_hint->functions & MwmFuncAll) { - functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize | - Func_Close; - } else { - functions = 0; - - if (mwm_hint->functions & MwmFuncResize) - functions |= Func_Resize; - if (mwm_hint->functions & MwmFuncMove) - functions |= Func_Move; - if (mwm_hint->functions & MwmFuncIconify) - functions |= Func_Iconify; - if (mwm_hint->functions & MwmFuncMaximize) - functions |= Func_Maximize; - if (mwm_hint->functions & MwmFuncClose) - functions |= Func_Close; - } - } - delete [] mwm_hint; -} - - -/* - * Gets the blackbox hints from the class' contained window. - * This is used while initializing the window to its first state, and not - * thereafter. - * Returns: true if the hints are successfully retreived and applied; false if - * they are not. - */ -bool BlackboxWindow::getBlackboxHints(void) { - unsigned long num; - BlackboxHints *blackbox_hint; - - num = PropBlackboxHintsElements; - if (! xatom->get(client.window, otk::OBProperty::blackbox_hints, - otk::OBProperty::blackbox_hints, &num, - (unsigned long **)&blackbox_hint)) - return False; - if (num < PropBlackboxHintsElements) { - delete [] blackbox_hint; - return False; - } - - if (blackbox_hint->flags & AttribShaded) - flags.shaded = (blackbox_hint->attrib & AttribShaded); - - if ((blackbox_hint->flags & AttribMaxHoriz) && - (blackbox_hint->flags & AttribMaxVert)) - flags.maximized = (blackbox_hint->attrib & - (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0; - else if (blackbox_hint->flags & AttribMaxVert) - flags.maximized = (blackbox_hint->attrib & AttribMaxVert) ? 2 : 0; - else if (blackbox_hint->flags & AttribMaxHoriz) - flags.maximized = (blackbox_hint->attrib & AttribMaxHoriz) ? 3 : 0; - - if (blackbox_hint->flags & AttribOmnipresent) - flags.stuck = (blackbox_hint->attrib & AttribOmnipresent); - - if (blackbox_hint->flags & AttribWorkspace) - blackbox_attrib.workspace = blackbox_hint->workspace; - - // if (blackbox_hint->flags & AttribStack) - // don't yet have always on top/bottom for blackbox yet... working - // on that - - if (blackbox_hint->flags & AttribDecoration) { - switch (blackbox_hint->decoration) { - case DecorNone: - blackbox_attrib.decoration = DecorNone; - break; - - case DecorTiny: - case DecorTool: - case DecorNormal: - default: - // blackbox_attrib.decoration defaults to DecorNormal - break; - } - } - - delete [] blackbox_hint; - - return True; -} - - -void BlackboxWindow::getTransientInfo(void) { - if (client.transient_for && - client.transient_for != (BlackboxWindow *) ~0ul) { - // reset transient_for in preparation of looking for a new owner - client.transient_for->client.transientList.remove(this); - } - - // we have no transient_for until we find a new one - client.transient_for = (BlackboxWindow *) 0; - - Window trans_for; - if (! XGetTransientForHint(otk::OBDisplay::display, client.window, - &trans_for)) { - // transient_for hint not set - return; - } - - if (trans_for == client.window) { - // wierd client... treat this window as a normal window - return; - } - - if (trans_for == None || trans_for == screen->getRootWindow()) { - // this is an undocumented interpretation of the ICCCM. a transient - // associated with None/Root/itself is assumed to be a modal root - // transient. we don't support the concept of a global transient, - // so we just associate this transient with nothing, and perhaps - // we will add support later for global modality. - client.transient_for = (BlackboxWindow *) ~0ul; - flags.modal = True; - return; - } - - client.transient_for = blackbox->searchWindow(trans_for); - if (! client.transient_for && - client.window_group && trans_for == client.window_group) { - // no direct transient_for, perhaps this is a group transient? - BWindowGroup *group = blackbox->searchGroup(client.window_group); - if (group) client.transient_for = group->find(screen); - } - - if (! client.transient_for || client.transient_for == this) { - // no transient_for found, or we have a wierd client that wants to be - // a transient for itself, so we treat this window as a normal window - client.transient_for = (BlackboxWindow*) 0; - return; - } - - // Check for a circular transient state: this can lock up Blackbox - // when it tries to find the non-transient window for a transient. - BlackboxWindow *w = this; - while(w->client.transient_for && - w->client.transient_for != (BlackboxWindow *) ~0ul) { - if(w->client.transient_for == this) { - client.transient_for = (BlackboxWindow*) 0; - break; - } - w = w->client.transient_for; - } - - if (client.transient_for && - client.transient_for != (BlackboxWindow *) ~0ul) { - // register ourselves with our new transient_for - client.transient_for->client.transientList.push_back(this); - flags.stuck = client.transient_for->flags.stuck; - } -} - - -BlackboxWindow *BlackboxWindow::getTransientFor(void) const { - if (client.transient_for && - client.transient_for != (BlackboxWindow*) ~0ul) - return client.transient_for; - return 0; -} - - -/* - * This function is responsible for updating both the client and the frame - * rectangles. - * According to the ICCCM a client message is not sent for a resize, only a - * move. - */ -void BlackboxWindow::configure(int dx, int dy, - int dw, int dh) { - bool send_event = ((frame.rect.x() != dx || frame.rect.y() != dy) && - ! flags.moving); - - if (dw != frame.rect.width() || dh != frame.rect.height()) { - frame.rect.setRect(dx, dy, dw, dh); - frame.inside_w = frame.rect.width() - (frame.border_w * 2); - frame.inside_h = frame.rect.height() - (frame.border_w * 2); - - if (frame.rect.right() <= 0 || frame.rect.bottom() <= 0) - frame.rect.setPos(0, 0); - - client.rect.setCoords(frame.rect.left() + frame.margin.left, - frame.rect.top() + frame.margin.top, - frame.rect.right() - frame.margin.right, - frame.rect.bottom() - frame.margin.bottom); - -#ifdef SHAPE - if (otk::OBDisplay::shape() && flags.shaped) { - configureShape(); - } -#endif // SHAPE - - positionWindows(); - decorate(); - redrawWindowFrame(); - } else { - frame.rect.setPos(dx, dy); - - XMoveWindow(otk::OBDisplay::display, frame.window, - frame.rect.x(), frame.rect.y()); - /* - we may have been called just after an opaque window move, so even though - the old coords match the new ones no ConfigureNotify has been sent yet. - There are likely other times when this will be relevant as well. - */ - if (! flags.moving) send_event = True; - } - - if (send_event) { - // if moving, the update and event will occur when the move finishes - client.rect.setPos(frame.rect.left() + frame.margin.left, - frame.rect.top() + frame.margin.top); - - XEvent event; - event.type = ConfigureNotify; - - event.xconfigure.display = otk::OBDisplay::display; - event.xconfigure.event = client.window; - event.xconfigure.window = client.window; - event.xconfigure.x = client.rect.x(); - event.xconfigure.y = client.rect.y(); - event.xconfigure.width = client.rect.width(); - event.xconfigure.height = client.rect.height(); - event.xconfigure.border_width = client.old_bw; - event.xconfigure.above = frame.window; - event.xconfigure.override_redirect = False; - - XSendEvent(otk::OBDisplay::display, client.window, False, - StructureNotifyMask, &event); - XFlush(otk::OBDisplay::display); - } -} - - -#ifdef SHAPE -void BlackboxWindow::configureShape(void) { - XShapeCombineShape(otk::OBDisplay::display, frame.window, ShapeBounding, - frame.margin.left - frame.border_w, - frame.margin.top - frame.border_w, - client.window, ShapeBounding, ShapeSet); - - int num = 0; - XRectangle xrect[2]; - - if (decorations & Decor_Titlebar) { - xrect[0].x = xrect[0].y = -frame.border_w; - xrect[0].width = frame.rect.width(); - xrect[0].height = frame.title_h + (frame.border_w * 2); - ++num; - } - - if (decorations & Decor_Handle) { - xrect[1].x = -frame.border_w; - xrect[1].y = frame.rect.height() - frame.margin.bottom + - frame.mwm_border_w - frame.border_w; - xrect[1].width = frame.rect.width(); - xrect[1].height = frame.handle_h + (frame.border_w * 2); - ++num; - } - - XShapeCombineRectangles(otk::OBDisplay::display, frame.window, - ShapeBounding, 0, 0, xrect, num, - ShapeUnion, Unsorted); -} - - -void BlackboxWindow::clearShape(void) { - XShapeCombineMask(otk::OBDisplay::display, frame.window, ShapeBounding, - frame.margin.left - frame.border_w, - frame.margin.top - frame.border_w, - None, ShapeSet); -} -#endif // SHAPE - - -bool BlackboxWindow::setInputFocus(void) { - if (flags.focused) return True; - - assert(flags.stuck || // window must be on the current workspace or sticky - blackbox_attrib.workspace == screen->getCurrentWorkspaceID()); - - /* - We only do this check for normal windows and dialogs because other windows - do this on purpose, such as kde's kicker, and we don't want to go moving - it. - */ - if (window_type == Type_Normal || window_type == Type_Dialog) - if (! frame.rect.intersects(screen->getRect())) { - // client is outside the screen, move it to the center - configure((screen->getWidth() - frame.rect.width()) / 2, - (screen->getHeight() - frame.rect.height()) / 2, - frame.rect.width(), frame.rect.height()); - } - - if (client.transientList.size() > 0) { - // transfer focus to any modal transients - BlackboxWindowList::iterator it, end = client.transientList.end(); - for (it = client.transientList.begin(); it != end; ++it) - if ((*it)->flags.modal) return (*it)->setInputFocus(); - } - - bool ret = True; - if (focus_mode == F_LocallyActive || focus_mode == F_Passive) { - XSetInputFocus(otk::OBDisplay::display, client.window, - RevertToPointerRoot, CurrentTime); - } else { - /* we could set the focus to none, since the window doesn't accept focus, - * but we shouldn't set focus to nothing since this would surely make - * someone angry - */ - ret = False; - } - - if (flags.send_focus_message) { - XEvent ce; - ce.xclient.type = ClientMessage; - ce.xclient.message_type = xatom->atom(otk::OBProperty::wm_protocols); - ce.xclient.display = otk::OBDisplay::display; - ce.xclient.window = client.window; - ce.xclient.format = 32; - ce.xclient.data.l[0] = xatom->atom(otk::OBProperty::wm_take_focus); - ce.xclient.data.l[1] = blackbox->getLastTime(); - ce.xclient.data.l[2] = 0l; - ce.xclient.data.l[3] = 0l; - ce.xclient.data.l[4] = 0l; - XSendEvent(otk::OBDisplay::display, client.window, False, - NoEventMask, &ce); - XFlush(otk::OBDisplay::display); - } - - return ret; -} - - -void BlackboxWindow::iconify(void) { - if (flags.iconic || ! (functions & Func_Iconify)) return; - - // We don't need to worry about resizing because resizing always grabs the X - // server. This should only ever happen if using opaque moving. - if (flags.moving) - endMove(); - - /* - * we don't want this XUnmapWindow call to generate an UnmapNotify event, so - * we need to clear the event mask on client.window for a split second. - * HOWEVER, since X11 is asynchronous, the window could be destroyed in that - * split second, leaving us with a ghost window... so, we need to do this - * while the X server is grabbed - */ - unsigned long event_mask = PropertyChangeMask | FocusChangeMask | - StructureNotifyMask; - XGrabServer(otk::OBDisplay::display); - XSelectInput(otk::OBDisplay::display, client.window, - event_mask & ~StructureNotifyMask); - XUnmapWindow(otk::OBDisplay::display, client.window); - XSelectInput(otk::OBDisplay::display, client.window, event_mask); - XUngrabServer(otk::OBDisplay::display); - - XUnmapWindow(otk::OBDisplay::display, frame.window); - flags.visible = False; - flags.iconic = True; - - setState(IconicState); - - screen->getWorkspace(blackbox_attrib.workspace)->removeWindow(this); - if (flags.stuck) { - for (unsigned int i = 0; i < screen->getNumberOfWorkspaces(); ++i) - if (i != blackbox_attrib.workspace) - screen->getWorkspace(i)->removeWindow(this, True); - } - - if (isTransient()) { - if (client.transient_for != (BlackboxWindow *) ~0ul && - ! client.transient_for->flags.iconic) { - // iconify our transient_for - client.transient_for->iconify(); - } - } - - screen->addIcon(this); - - if (client.transientList.size() > 0) { - // iconify all transients - BlackboxWindowList::iterator it, end = client.transientList.end(); - for (it = client.transientList.begin(); it != end; ++it) { - if (! (*it)->flags.iconic) (*it)->iconify(); - } - } - screen->updateStackingList(); -} - - -void BlackboxWindow::show(void) { - flags.visible = True; - flags.iconic = False; - - current_state = (flags.shaded) ? IconicState : NormalState; - setState(current_state); - - XMapWindow(otk::OBDisplay::display, client.window); - XMapSubwindows(otk::OBDisplay::display, frame.window); - XMapWindow(otk::OBDisplay::display, frame.window); - -#if 0 - int real_x, real_y; - Window child; - XTranslateCoordinates(otk::OBDisplay::display, client.window, - screen->getRootWindow(), - 0, 0, &real_x, &real_y, &child); - fprintf(stderr, "%s -- assumed: (%d, %d), real: (%d, %d)\n", getTitle(), - client.rect.left(), client.rect.top(), real_x, real_y); - assert(client.rect.left() == real_x && client.rect.top() == real_y); -#endif -} - - -void BlackboxWindow::deiconify(bool reassoc, bool raise) { - if (flags.iconic || reassoc) - screen->reassociateWindow(this, otk::BSENTINEL, False); - else if (blackbox_attrib.workspace != screen->getCurrentWorkspaceID()) - return; - - show(); - - // reassociate and deiconify all transients - if (reassoc && client.transientList.size() > 0) { - BlackboxWindowList::iterator it, end = client.transientList.end(); - for (it = client.transientList.begin(); it != end; ++it) - (*it)->deiconify(True, False); - } - - if (raise) - screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); -} - - -void BlackboxWindow::close(void) { - if (! (functions & Func_Close)) return; - - XEvent ce; - ce.xclient.type = ClientMessage; - ce.xclient.message_type = xatom->atom(otk::OBProperty::wm_protocols); - ce.xclient.display = otk::OBDisplay::display; - ce.xclient.window = client.window; - ce.xclient.format = 32; - ce.xclient.data.l[0] = xatom->atom(otk::OBProperty::wm_delete_window); - ce.xclient.data.l[1] = CurrentTime; - ce.xclient.data.l[2] = 0l; - ce.xclient.data.l[3] = 0l; - ce.xclient.data.l[4] = 0l; - XSendEvent(otk::OBDisplay::display, client.window, False, NoEventMask, &ce); - XFlush(otk::OBDisplay::display); -} - - -void BlackboxWindow::withdraw(void) { - // We don't need to worry about resizing because resizing always grabs the X - // server. This should only ever happen if using opaque moving. - if (flags.moving) - endMove(); - - flags.visible = False; - flags.iconic = False; - - setState(current_state); - - XUnmapWindow(otk::OBDisplay::display, frame.window); - - XGrabServer(otk::OBDisplay::display); - - unsigned long event_mask = PropertyChangeMask | FocusChangeMask | - StructureNotifyMask; - XSelectInput(otk::OBDisplay::display, client.window, - event_mask & ~StructureNotifyMask); - XUnmapWindow(otk::OBDisplay::display, client.window); - XSelectInput(otk::OBDisplay::display, client.window, event_mask); - - XUngrabServer(otk::OBDisplay::display); -} - - -void BlackboxWindow::maximize(unsigned int button) { - if (! (functions & Func_Maximize)) return; - - // We don't need to worry about resizing because resizing always grabs the X - // server. This should only ever happen if using opaque moving. - if (flags.moving) - endMove(); - - if (flags.maximized) { - flags.maximized = 0; - - blackbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert); - blackbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert); - - /* - when a resize finishes, maximize(0) is called to clear any maximization - flags currently set. Otherwise it still thinks it is maximized. - so we do not need to call configure() because resizing will handle it - */ - if (! flags.resizing) - configure(blackbox_attrib.premax_x, blackbox_attrib.premax_y, - blackbox_attrib.premax_w, blackbox_attrib.premax_h); - - blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0; - blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0; - - redrawAllButtons(); // in case it is not called in configure() - setState(current_state); - return; - } - - blackbox_attrib.premax_x = frame.rect.x(); - blackbox_attrib.premax_y = frame.rect.y(); - blackbox_attrib.premax_w = frame.rect.width(); - // use client.rect so that clients can be restored even if shaded - blackbox_attrib.premax_h = - client.rect.height() + frame.margin.top + frame.margin.bottom; - -#ifdef XINERAMA - if (screen->isXineramaActive() && blackbox->doXineramaMaximizing()) { - // find the area to use - RectList availableAreas = screen->allAvailableAreas(); - RectList::iterator it, end = availableAreas.end(); - - for (it = availableAreas.begin(); it != end; ++it) - if (it->intersects(frame.rect)) break; - if (it == end) // the window isn't inside an area - it = availableAreas.begin(); // so just default to the first one - - frame.changing = *it; - } else -#endif // XINERAMA - frame.changing = screen->availableArea(); - - switch(button) { - case 1: - blackbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert; - blackbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert; - break; - - case 2: - blackbox_attrib.flags |= AttribMaxVert; - blackbox_attrib.attrib |= AttribMaxVert; - - frame.changing.setX(frame.rect.x()); - frame.changing.setWidth(frame.rect.width()); - break; - - case 3: - blackbox_attrib.flags |= AttribMaxHoriz; - blackbox_attrib.attrib |= AttribMaxHoriz; - - frame.changing.setY(frame.rect.y()); - frame.changing.setHeight(frame.rect.height()); - break; - } - - constrain(TopLeft); - - if (flags.shaded) { - blackbox_attrib.flags ^= AttribShaded; - blackbox_attrib.attrib ^= AttribShaded; - flags.shaded = False; - } - - flags.maximized = button; - - configure(frame.changing.x(), frame.changing.y(), - frame.changing.width(), frame.changing.height()); - if (flags.focused) - screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); - redrawAllButtons(); // in case it is not called in configure() - setState(current_state); -} - - -// re-maximizes the window to take into account availableArea changes -void BlackboxWindow::remaximize(void) { - if (flags.shaded) { - // we only update the window's attributes otherwise we lose the shade bit - switch(flags.maximized) { - case 1: - blackbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert; - blackbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert; - break; - - case 2: - blackbox_attrib.flags |= AttribMaxVert; - blackbox_attrib.attrib |= AttribMaxVert; - break; - - case 3: - blackbox_attrib.flags |= AttribMaxHoriz; - blackbox_attrib.attrib |= AttribMaxHoriz; - break; - } - return; - } - - // save the original dimensions because maximize will wipe them out - int premax_x = blackbox_attrib.premax_x, - premax_y = blackbox_attrib.premax_y, - premax_w = blackbox_attrib.premax_w, - premax_h = blackbox_attrib.premax_h; - - unsigned int button = flags.maximized; - flags.maximized = 0; // trick maximize() into working - maximize(button); - - // restore saved values - blackbox_attrib.premax_x = premax_x; - blackbox_attrib.premax_y = premax_y; - blackbox_attrib.premax_w = premax_w; - blackbox_attrib.premax_h = premax_h; -} - - -void BlackboxWindow::setWorkspace(unsigned int n) { - blackbox_attrib.flags |= AttribWorkspace; - blackbox_attrib.workspace = n; - if (n == otk::BSENTINEL) { // iconified window - /* - we set the workspace to 'all workspaces' so that taskbars will show the - window. otherwise, it made uniconifying a window imposible without the - blackbox workspace menu - */ - n = 0xffffffff; - } - xatom->set(client.window, otk::OBProperty::net_wm_desktop, - otk::OBProperty::Atom_Cardinal, n); -} - - -void BlackboxWindow::shade(void) { - if (flags.shaded) { - XResizeWindow(otk::OBDisplay::display, frame.window, - frame.inside_w, frame.inside_h); - flags.shaded = False; - blackbox_attrib.flags ^= AttribShaded; - blackbox_attrib.attrib ^= AttribShaded; - - setState(NormalState); - - // set the frame rect to the normal size - frame.rect.setHeight(client.rect.height() + frame.margin.top + - frame.margin.bottom); - } else { - if (! (decorations & Decor_Titlebar)) - return; // can't shade it without a titlebar! - - XResizeWindow(otk::OBDisplay::display, frame.window, - frame.inside_w, frame.title_h); - flags.shaded = True; - blackbox_attrib.flags |= AttribShaded; - blackbox_attrib.attrib |= AttribShaded; - - setState(IconicState); - - // set the frame rect to the shaded size - frame.rect.setHeight(frame.title_h + (frame.border_w * 2)); - } -} - - -/* - * (Un)Sticks a window and its relatives. - */ -void BlackboxWindow::stick(void) { - if (flags.stuck) { - blackbox_attrib.flags ^= AttribOmnipresent; - blackbox_attrib.attrib ^= AttribOmnipresent; - - flags.stuck = False; - - for (unsigned int i = 0; i < screen->getNumberOfWorkspaces(); ++i) - if (i != blackbox_attrib.workspace) - screen->getWorkspace(i)->removeWindow(this, True); - - if (! flags.iconic) - screen->reassociateWindow(this, otk::BSENTINEL, True); - // temporary fix since sticky windows suck. set the hint to what we - // actually hold in our data. - xatom->set(client.window, otk::OBProperty::net_wm_desktop, - otk::OBProperty::Atom_Cardinal, - blackbox_attrib.workspace); - - setState(current_state); - } else { - flags.stuck = True; - - blackbox_attrib.flags |= AttribOmnipresent; - blackbox_attrib.attrib |= AttribOmnipresent; - - // temporary fix since sticky windows suck. set the hint to a different - // value than that contained in the class' data. - xatom->set(client.window, otk::OBProperty::net_wm_desktop, - otk::OBProperty::Atom_Cardinal, - 0xffffffff); - - for (unsigned int i = 0; i < screen->getNumberOfWorkspaces(); ++i) - if (i != blackbox_attrib.workspace) - screen->getWorkspace(i)->addWindow(this, False, True); - - setState(current_state); - } - - redrawAllButtons(); - - // go up the chain - if (isTransient() && client.transient_for != (BlackboxWindow *) ~0ul && - client.transient_for->isStuck() != flags.stuck) - client.transient_for->stick(); - // go down the chain - BlackboxWindowList::iterator it; - const BlackboxWindowList::iterator end = client.transientList.end(); - for (it = client.transientList.begin(); it != end; ++it) - if ((*it)->isStuck() != flags.stuck) - (*it)->stick(); -} - - -void BlackboxWindow::redrawWindowFrame(void) const { - if (decorations & Decor_Titlebar) { - if (flags.focused) { - if (frame.ftitle) - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.title, frame.ftitle); - else - XSetWindowBackground(otk::OBDisplay::display, - frame.title, frame.ftitle_pixel); - } else { - if (frame.utitle) - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.title, frame.utitle); - else - XSetWindowBackground(otk::OBDisplay::display, - frame.title, frame.utitle_pixel); - } - XClearWindow(otk::OBDisplay::display, frame.title); - - redrawLabel(); - redrawAllButtons(); - } - - if (decorations & Decor_Handle) { - if (flags.focused) { - if (frame.fhandle) - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.handle, frame.fhandle); - else - XSetWindowBackground(otk::OBDisplay::display, - frame.handle, frame.fhandle_pixel); - - if (frame.fgrip) { - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.left_grip, frame.fgrip); - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.right_grip, frame.fgrip); - } else { - XSetWindowBackground(otk::OBDisplay::display, - frame.left_grip, frame.fgrip_pixel); - XSetWindowBackground(otk::OBDisplay::display, - frame.right_grip, frame.fgrip_pixel); - } - } else { - if (frame.uhandle) - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.handle, frame.uhandle); - else - XSetWindowBackground(otk::OBDisplay::display, - frame.handle, frame.uhandle_pixel); - - if (frame.ugrip) { - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.left_grip, frame.ugrip); - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.right_grip, frame.ugrip); - } else { - XSetWindowBackground(otk::OBDisplay::display, - frame.left_grip, frame.ugrip_pixel); - XSetWindowBackground(otk::OBDisplay::display, - frame.right_grip, frame.ugrip_pixel); - } - } - XClearWindow(otk::OBDisplay::display, frame.handle); - XClearWindow(otk::OBDisplay::display, frame.left_grip); - XClearWindow(otk::OBDisplay::display, frame.right_grip); - } - - if (decorations & Decor_Border) { - if (flags.focused) - XSetWindowBorder(otk::OBDisplay::display, - frame.plate, frame.fborder_pixel); - else - XSetWindowBorder(otk::OBDisplay::display, - frame.plate, frame.uborder_pixel); - } -} - - -void BlackboxWindow::setFocusFlag(bool focus) { - // only focus a window if it is visible - if (focus && ! flags.visible) - return; - - flags.focused = focus; - - redrawWindowFrame(); - - if (flags.focused) - blackbox->setFocusedWindow(this); -} - - -void BlackboxWindow::installColormap(bool install) { - int i = 0, ncmap = 0; - Colormap *cmaps = XListInstalledColormaps(otk::OBDisplay::display, - client.window, &ncmap); - if (cmaps) { - XWindowAttributes wattrib; - if (XGetWindowAttributes(otk::OBDisplay::display, - client.window, &wattrib)) { - if (install) { - // install the window's colormap - for (i = 0; i < ncmap; i++) { - if (*(cmaps + i) == wattrib.colormap) - // this window is using an installed color map... do not install - install = False; - } - // otherwise, install the window's colormap - if (install) - XInstallColormap(otk::OBDisplay::display, wattrib.colormap); - } else { - // uninstall the window's colormap - for (i = 0; i < ncmap; i++) { - if (*(cmaps + i) == wattrib.colormap) - // we found the colormap to uninstall - XUninstallColormap(otk::OBDisplay::display, wattrib.colormap); - } - } - } - - XFree(cmaps); - } -} - - -void BlackboxWindow::setAllowedActions(void) { - Atom actions[7]; - int num = 0; - - actions[num++] = xatom->atom(otk::OBProperty::net_wm_action_shade); - actions[num++] = xatom->atom(otk::OBProperty::net_wm_action_change_desktop); - actions[num++] = xatom->atom(otk::OBProperty::net_wm_action_close); - - if (functions & Func_Move) - actions[num++] = xatom->atom(otk::OBProperty::net_wm_action_move); - if (functions & Func_Resize) - actions[num++] = xatom->atom(otk::OBProperty::net_wm_action_resize); - if (functions & Func_Maximize) { - actions[num++] = xatom->atom(otk::OBProperty::net_wm_action_maximize_horz); - actions[num++] = xatom->atom(otk::OBProperty::net_wm_action_maximize_vert); - } - - xatom->set(client.window, otk::OBProperty::net_wm_allowed_actions, - otk::OBProperty::Atom_Atom, - actions, num); -} - - -void BlackboxWindow::setState(unsigned long new_state) { - current_state = new_state; - - unsigned long state[2]; - state[0] = current_state; - state[1] = None; - xatom->set(client.window, otk::OBProperty::wm_state, otk::OBProperty::wm_state, state, 2); - - xatom->set(client.window, otk::OBProperty::blackbox_attributes, - otk::OBProperty::blackbox_attributes, (unsigned long *)&blackbox_attrib, - PropBlackboxAttributesElements); - - Atom netstate[8]; - int num = 0; - if (flags.modal) - netstate[num++] = xatom->atom(otk::OBProperty::net_wm_state_modal); - if (flags.shaded) - netstate[num++] = xatom->atom(otk::OBProperty::net_wm_state_shaded); - if (flags.iconic) - netstate[num++] = xatom->atom(otk::OBProperty::net_wm_state_hidden); - if (flags.skip_taskbar) - netstate[num++] = xatom->atom(otk::OBProperty::net_wm_state_skip_taskbar); - if (flags.skip_pager) - netstate[num++] = xatom->atom(otk::OBProperty::net_wm_state_skip_pager); - if (flags.fullscreen) - netstate[num++] = xatom->atom(otk::OBProperty::net_wm_state_fullscreen); - if (flags.maximized == 1 || flags.maximized == 2) - netstate[num++] = xatom->atom(otk::OBProperty::net_wm_state_maximized_vert); - if (flags.maximized == 1 || flags.maximized == 3) - netstate[num++] = xatom->atom(otk::OBProperty::net_wm_state_maximized_horz); - xatom->set(client.window, otk::OBProperty::net_wm_state, - otk::OBProperty::Atom_Atom, - netstate, num); -} - - -bool BlackboxWindow::getState(void) { - bool ret = xatom->get(client.window, otk::OBProperty::wm_state, - otk::OBProperty::wm_state, ¤t_state); - if (! ret) current_state = 0; - return ret; -} - - -void BlackboxWindow::restoreAttributes(void) { - unsigned long num = PropBlackboxAttributesElements; - BlackboxAttributes *net; - if (! xatom->get(client.window, otk::OBProperty::blackbox_attributes, - otk::OBProperty::blackbox_attributes, &num, - (unsigned long **)&net)) - return; - if (num < PropBlackboxAttributesElements) { - delete [] net; - return; - } - - if (net->flags & AttribShaded && net->attrib & AttribShaded) { - flags.shaded = False; - unsigned long orig_state = current_state; - shade(); - - /* - At this point in the life of a window, current_state should only be set - to IconicState if the window was an *icon*, not if it was shaded. - */ - if (orig_state != IconicState) - current_state = WithdrawnState; - } - - if (net->workspace != screen->getCurrentWorkspaceID() && - net->workspace < screen->getWorkspaceCount()) - screen->reassociateWindow(this, net->workspace, True); - - if ((blackbox_attrib.workspace != screen->getCurrentWorkspaceID()) && - (blackbox_attrib.workspace < screen->getWorkspaceCount())) { - // set to WithdrawnState so it will be mapped on the new workspace - if (current_state == NormalState) current_state = WithdrawnState; - } else if (current_state == WithdrawnState) { - // the window is on this workspace and is Withdrawn, so it is waiting to - // be mapped - current_state = NormalState; - } - - if (net->flags & AttribOmnipresent && net->attrib & AttribOmnipresent && - ! flags.stuck) { - stick(); - - // if the window was on another workspace, it was going to be hidden. this - // specifies that the window should be mapped since it is sticky. - if (current_state == WithdrawnState) current_state = NormalState; - } - - if (net->flags & AttribMaxHoriz || net->flags & AttribMaxVert) { - int x = net->premax_x, y = net->premax_y; - unsigned int w = net->premax_w, h = net->premax_h; - flags.maximized = 0; - - unsigned int m = 0; - if ((net->flags & AttribMaxHoriz) && - (net->flags & AttribMaxVert)) - m = (net->attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0; - else if (net->flags & AttribMaxVert) - m = (net->attrib & AttribMaxVert) ? 2 : 0; - else if (net->flags & AttribMaxHoriz) - m = (net->attrib & AttribMaxHoriz) ? 3 : 0; - - if (m) maximize(m); - - blackbox_attrib.premax_x = x; - blackbox_attrib.premax_y = y; - blackbox_attrib.premax_w = w; - blackbox_attrib.premax_h = h; - } - - if (net->flags & AttribDecoration) { - switch (net->decoration) { - case DecorNone: - enableDecor(False); - break; - - /* since tools only let you toggle this anyways, we'll just make that all - it supports for now. - */ - default: - case DecorNormal: - case DecorTiny: - case DecorTool: - enableDecor(True); - break; - } - } - - // with the state set it will then be the map event's job to read the - // window's state and behave accordingly - - delete [] net; -} - - -/* - * Positions the Rect r according the the client window position and - * window gravity. - */ -void BlackboxWindow::applyGravity(otk::Rect &r) { - // apply horizontal window gravity - switch (client.win_gravity) { - default: - case NorthWestGravity: - case SouthWestGravity: - case WestGravity: - r.setX(client.rect.x()); - break; - - case NorthGravity: - case SouthGravity: - case CenterGravity: - r.setX(client.rect.x() - (frame.margin.left + frame.margin.right) / 2); - break; - - case NorthEastGravity: - case SouthEastGravity: - case EastGravity: - r.setX(client.rect.x() - frame.margin.left - frame.margin.right + 2); - break; - - case ForgetGravity: - case StaticGravity: - r.setX(client.rect.x() - frame.margin.left); - break; - } - - // apply vertical window gravity - switch (client.win_gravity) { - default: - case NorthWestGravity: - case NorthEastGravity: - case NorthGravity: - r.setY(client.rect.y()); - break; - - case CenterGravity: - case EastGravity: - case WestGravity: - r.setY(client.rect.y() - (frame.margin.top + frame.margin.bottom) / 2); - break; - - case SouthWestGravity: - case SouthEastGravity: - case SouthGravity: - r.setY(client.rect.y() - frame.margin.top - frame.margin.bottom + 2); - break; - - case ForgetGravity: - case StaticGravity: - r.setY(client.rect.y() - frame.margin.top); - break; - } -} - - -/* - * The reverse of the applyGravity function. - * - * Positions the Rect r according to the frame window position and - * window gravity. - */ -void BlackboxWindow::restoreGravity(otk::Rect &r) { - // restore horizontal window gravity - switch (client.win_gravity) { - default: - case NorthWestGravity: - case SouthWestGravity: - case WestGravity: - r.setX(frame.rect.x()); - break; - - case NorthGravity: - case SouthGravity: - case CenterGravity: - r.setX(frame.rect.x() + (frame.margin.left + frame.margin.right) / 2); - break; - - case NorthEastGravity: - case SouthEastGravity: - case EastGravity: - r.setX(frame.rect.x() + frame.margin.left + frame.margin.right - 2); - break; - - case ForgetGravity: - case StaticGravity: - r.setX(frame.rect.x() + frame.margin.left); - break; - } - - // restore vertical window gravity - switch (client.win_gravity) { - default: - case NorthWestGravity: - case NorthEastGravity: - case NorthGravity: - r.setY(frame.rect.y()); - break; - - case CenterGravity: - case EastGravity: - case WestGravity: - r.setY(frame.rect.y() + (frame.margin.top + frame.margin.bottom) / 2); - break; - - case SouthWestGravity: - case SouthEastGravity: - case SouthGravity: - r.setY(frame.rect.y() + frame.margin.top + frame.margin.bottom - 2); - break; - - case ForgetGravity: - case StaticGravity: - r.setY(frame.rect.y() + frame.margin.top); - break; - } -} - - -void BlackboxWindow::redrawLabel(void) const { - if (flags.focused) { - if (frame.flabel) - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.label, frame.flabel); - else - XSetWindowBackground(otk::OBDisplay::display, - frame.label, frame.flabel_pixel); - } else { - if (frame.ulabel) - XSetWindowBackgroundPixmap(otk::OBDisplay::display, - frame.label, frame.ulabel); - else - XSetWindowBackground(otk::OBDisplay::display, - frame.label, frame.ulabel_pixel); - } - XClearWindow(otk::OBDisplay::display, frame.label); - - otk::Style *style = screen->getWindowStyle(); - - int pos = frame.bevel_w * 2; - style->doJustify(client.title.c_str(), pos, frame.label_w, frame.bevel_w * 4); - style->font->drawString(frame.label, pos, 1, - (flags.focused ? style->l_text_focus : - style->l_text_unfocus), - client.title); -} - - -void BlackboxWindow::redrawAllButtons(void) const { - if (frame.iconify_button) redrawIconifyButton(False); - if (frame.maximize_button) redrawMaximizeButton(flags.maximized); - if (frame.close_button) redrawCloseButton(False); - if (frame.stick_button) redrawStickyButton(flags.stuck); -} - - -void BlackboxWindow::redrawButton(bool pressed, Window win, - Pixmap fppix, unsigned long fppixel, - Pixmap uppix, unsigned long uppixel, - Pixmap fpix, unsigned long fpixel, - Pixmap upix, unsigned long upixel) const { - Pixmap p; - unsigned long pix; - - if (pressed) { - if (flags.focused) { - p = fppix; - pix = fppixel; - } else { - p = uppix; - pix = uppixel; - } - } else { - if (flags.focused) { - p = fpix; - pix = fpixel; - } else { - p = upix; - pix = upixel; - } - } - - if (p) - XSetWindowBackgroundPixmap(otk::OBDisplay::display, win, p); - else - XSetWindowBackground(otk::OBDisplay::display, win, pix); - -} - -void BlackboxWindow::redrawIconifyButton(bool pressed) const { - redrawButton(pressed, frame.iconify_button, - frame.pfbutton, frame.pfbutton_pixel, - frame.pubutton, frame.pubutton_pixel, - frame.fbutton, frame.fbutton_pixel, - frame.ubutton, frame.ubutton_pixel); - - XClearWindow(otk::OBDisplay::display, frame.iconify_button); - otk::BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : - screen->getWindowStyle()->b_pic_unfocus); - - otk::Style::PixmapMask pm = screen->getWindowStyle()->icon_button; - - if (screen->getWindowStyle()->icon_button.mask != None) { - XSetClipMask(otk::OBDisplay::display, pen.gc(), pm.mask); - XSetClipOrigin(otk::OBDisplay::display, pen.gc(), - (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2); - - XFillRectangle(otk::OBDisplay::display, frame.iconify_button, pen.gc(), - (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2, - (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2); - - XSetClipMask(otk::OBDisplay::display, pen.gc(), None); - XSetClipOrigin(otk::OBDisplay::display, pen.gc(), 0, 0); - } else { - XDrawRectangle(otk::OBDisplay::display, frame.iconify_button, pen.gc(), - 2, (frame.button_w - 5), (frame.button_w - 5), 2); - } -} - - -void BlackboxWindow::redrawMaximizeButton(bool pressed) const { - redrawButton(pressed, frame.maximize_button, - frame.pfbutton, frame.pfbutton_pixel, - frame.pubutton, frame.pubutton_pixel, - frame.fbutton, frame.fbutton_pixel, - frame.ubutton, frame.ubutton_pixel); - - XClearWindow(otk::OBDisplay::display, frame.maximize_button); - - otk::BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : - screen->getWindowStyle()->b_pic_unfocus); - - otk::Style::PixmapMask pm = screen->getWindowStyle()->max_button; - - if (pm.mask != None) { - XSetClipMask(otk::OBDisplay::display, pen.gc(), pm.mask); - XSetClipOrigin(otk::OBDisplay::display, pen.gc(), - (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2); - - XFillRectangle(otk::OBDisplay::display, frame.maximize_button, pen.gc(), - (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2, - (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2); - - XSetClipOrigin(otk::OBDisplay::display, pen.gc(), 0, 0 ); - XSetClipMask( otk::OBDisplay::display, pen.gc(), None ); - } else { - XDrawRectangle(otk::OBDisplay::display, frame.maximize_button, pen.gc(), - 2, 2, (frame.button_w - 5), (frame.button_w - 5)); - XDrawLine(otk::OBDisplay::display, frame.maximize_button, pen.gc(), - 2, 3, (frame.button_w - 3), 3); - } -} - - -void BlackboxWindow::redrawCloseButton(bool pressed) const { - redrawButton(pressed, frame.close_button, - frame.pfbutton, frame.pfbutton_pixel, - frame.pubutton, frame.pubutton_pixel, - frame.fbutton, frame.fbutton_pixel, - frame.ubutton, frame.ubutton_pixel); - - XClearWindow(otk::OBDisplay::display, frame.close_button); - - otk::BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : - screen->getWindowStyle()->b_pic_unfocus); - - otk::Style::PixmapMask pm = screen->getWindowStyle()->close_button; - - if (pm.mask != None) { - XSetClipMask(otk::OBDisplay::display, pen.gc(), pm.mask); - XSetClipOrigin(otk::OBDisplay::display, pen.gc(), - (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2); - - XFillRectangle(otk::OBDisplay::display, frame.close_button, pen.gc(), - (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2, - (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2); - - - XSetClipOrigin(otk::OBDisplay::display, pen.gc(), 0, 0 ); - XSetClipMask( otk::OBDisplay::display, pen.gc(), None ); - } else { - XDrawLine(otk::OBDisplay::display, frame.close_button, pen.gc(), - 2, 2, (frame.button_w - 3), (frame.button_w - 3)); - XDrawLine(otk::OBDisplay::display, frame.close_button, pen.gc(), - 2, (frame.button_w - 3), (frame.button_w - 3), 2); - } -} - -void BlackboxWindow::redrawStickyButton(bool pressed) const { - redrawButton(pressed, frame.stick_button, - frame.pfbutton, frame.pfbutton_pixel, - frame.pubutton, frame.pubutton_pixel, - frame.fbutton, frame.fbutton_pixel, - frame.ubutton, frame.ubutton_pixel); - - XClearWindow(otk::OBDisplay::display, frame.stick_button); - - otk::BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : - screen->getWindowStyle()->b_pic_unfocus); - - otk::Style::PixmapMask pm = screen->getWindowStyle()->stick_button; - - if (pm.mask != None) { - XSetClipMask(otk::OBDisplay::display, pen.gc(), pm.mask); - XSetClipOrigin(otk::OBDisplay::display, pen.gc(), - (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2); - - XFillRectangle(otk::OBDisplay::display, frame.stick_button, pen.gc(), - (frame.button_w - pm.w)/2, (frame.button_w - pm.h)/2, - (frame.button_w + pm.w)/2, (frame.button_w + pm.h)/2); - - - XSetClipOrigin(otk::OBDisplay::display, pen.gc(), 0, 0 ); - XSetClipMask( otk::OBDisplay::display, pen.gc(), None ); - } else { - XFillRectangle(otk::OBDisplay::display, frame.stick_button, pen.gc(), - frame.button_w/2 - 1, frame.button_w/2 -1, 2, 2 ); - } -} - -void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) { - if (re->window != client.window) - return; - -#ifdef DEBUG - fprintf(stderr, "BlackboxWindow::mapRequestEvent() for 0x%lx\n", - client.window); -#endif // DEBUG - - /* - Even though the window wants to be shown, if it is not on the current - workspace, then it isn't going to be shown right now. - */ - if (! flags.stuck && - blackbox_attrib.workspace != screen->getCurrentWorkspaceID() && - blackbox_attrib.workspace < screen->getWorkspaceCount()) - if (current_state == NormalState) current_state = WithdrawnState; - - switch (current_state) { - case IconicState: - iconify(); - break; - - case WithdrawnState: - withdraw(); - break; - - case NormalState: - case InactiveState: - case ZoomState: - default: - show(); - screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); - if (isNormal()) { - if (blackbox->state() != Openbox::State_Starting) { - XSync(otk::OBDisplay::display, False); // make sure the frame is mapped - if (screen->doFocusNew() || (isTransient() && getTransientFor() && - getTransientFor()->isFocused())) { - setInputFocus(); - } - if (screen->getPlacementPolicy() == BScreen::ClickMousePlacement) { - int x, y, rx, ry; - Window c, r; - unsigned int m; - XQueryPointer(otk::OBDisplay::display, screen->getRootWindow(), - &r, &c, &rx, &ry, &x, &y, &m); - beginMove(rx, ry); - } - } - } - break; - } -} - - -void BlackboxWindow::unmapNotifyEvent(const XUnmapEvent *ue) { - if (ue->window != client.window) - return; - -#ifdef DEBUG - fprintf(stderr, "BlackboxWindow::unmapNotifyEvent() for 0x%lx\n", - client.window); -#endif // DEBUG - - screen->unmanageWindow(this, False); -} - - -void BlackboxWindow::destroyNotifyEvent(const XDestroyWindowEvent *de) { - if (de->window != client.window) - return; - -#ifdef DEBUG - fprintf(stderr, "BlackboxWindow::destroyNotifyEvent() for 0x%lx\n", - client.window); -#endif // DEBUG - - screen->unmanageWindow(this, False); -} - - -void BlackboxWindow::reparentNotifyEvent(const XReparentEvent *re) { - if (re->window != client.window || re->parent == frame.plate) - return; - -#ifdef DEBUG - fprintf(stderr, "BlackboxWindow::reparentNotifyEvent(): reparent 0x%lx to " - "0x%lx.\n", client.window, re->parent); -#endif // DEBUG - - XEvent ev; - ev.xreparent = *re; - XPutBackEvent(otk::OBDisplay::display, &ev); - screen->unmanageWindow(this, True); -} - - -void BlackboxWindow::propertyNotifyEvent(const XPropertyEvent *pe) { - if (pe->state == PropertyDelete || ! validateClient()) - return; - -#if 0 - fprintf(stderr, "BlackboxWindow::propertyNotifyEvent(): for 0x%lx\n", - client.window); -#endif - - switch(pe->atom) { - case XA_WM_CLASS: - case XA_WM_CLIENT_MACHINE: - case XA_WM_COMMAND: - break; - - case XA_WM_TRANSIENT_FOR: { - bool s = flags.stuck; - - // determine if this is a transient window - getTransientInfo(); - - if (flags.stuck != s) stick(); - - // adjust the window decorations based on transience - if (isTransient()) { - functions &= ~Func_Maximize; - setAllowedActions(); - setupDecor(); - } - - reconfigure(); - } - break; - - case XA_WM_HINTS: - getWMHints(); - break; - - case XA_WM_ICON_NAME: - getWMIconName(); - if (flags.iconic) screen->propagateWindowName(this); - break; - - case otk::OBProperty::net_wm_name: - case XA_WM_NAME: - getWMName(); - - if (decorations & Decor_Titlebar) - redrawLabel(); - - screen->propagateWindowName(this); - break; - - case XA_WM_NORMAL_HINTS: { - getWMNormalHints(); - - if ((client.normal_hint_flags & PMinSize) && - (client.normal_hint_flags & PMaxSize)) { - // the window now can/can't resize itself, so the buttons need to be - // regrabbed. - ungrabButtons(); - if (client.max_width <= client.min_width && - client.max_height <= client.min_height) { - functions &= ~(Func_Resize | Func_Maximize); - } else { - if (! isTransient()) - functions |= Func_Maximize; - functions |= Func_Resize; - } - grabButtons(); - setAllowedActions(); - setupDecor(); - } - - otk::Rect old_rect = frame.rect; - - upsize(); - - if (old_rect != frame.rect) - reconfigure(); - - break; - } - - default: - if (pe->atom == xatom->atom(otk::OBProperty::wm_protocols)) { - getWMProtocols(); - - if ((decorations & Decor_Close) && (! frame.close_button)) { - createCloseButton(); - if (decorations & Decor_Titlebar) { - positionButtons(True); - XMapSubwindows(otk::OBDisplay::display, frame.title); - } - } - } else if (pe->atom == xatom->atom(otk::OBProperty::net_wm_strut)) { - updateStrut(); - } - - break; - } -} - - -void BlackboxWindow::exposeEvent(const XExposeEvent *ee) { -#if 0 - fprintf(stderr, "BlackboxWindow::exposeEvent() for 0x%lx\n", client.window); -#endif - - if (frame.label == ee->window && (decorations & Decor_Titlebar)) - redrawLabel(); - else if (frame.close_button == ee->window) - redrawCloseButton(False); - else if (frame.maximize_button == ee->window) - redrawMaximizeButton(flags.maximized); - else if (frame.iconify_button == ee->window) - redrawIconifyButton(False); - else if (frame.stick_button == ee->window) - redrawStickyButton(flags.stuck); -} - - -void BlackboxWindow::configureRequestEvent(const XConfigureRequestEvent *cr) { - if (cr->window != client.window || flags.iconic) - return; - - if (cr->value_mask & CWBorderWidth) - client.old_bw = cr->border_width; - - if (cr->value_mask & (CWX | CWY | CWWidth | CWHeight)) { - frame.changing = frame.rect; - - if (cr->value_mask & (CWX | CWY)) { - if (cr->value_mask & CWX) - client.rect.setX(cr->x); - if (cr->value_mask & CWY) - client.rect.setY(cr->y); - - applyGravity(frame.changing); - } - - if (cr->value_mask & (CWWidth | CWHeight)) { - if (cr->value_mask & CWWidth) - frame.changing.setWidth(cr->width + - frame.margin.left + frame.margin.right); - - if (cr->value_mask & CWHeight) - frame.changing.setHeight(cr->height + - frame.margin.top + frame.margin.bottom); - - /* - if a position change has been specified, then that position will be - used instead of determining a position based on the window's gravity. - */ - if (! (cr->value_mask & (CWX | CWY))) { - Corner corner; - switch (client.win_gravity) { - case NorthEastGravity: - case EastGravity: - corner = TopRight; - break; - case SouthWestGravity: - case SouthGravity: - corner = BottomLeft; - break; - case SouthEastGravity: - corner = BottomRight; - break; - default: // NorthWest, Static, etc - corner = TopLeft; - } - constrain(corner); - } - } - - configure(frame.changing.x(), frame.changing.y(), - frame.changing.width(), frame.changing.height()); - } - - if (cr->value_mask & CWStackMode && !isDesktop()) { - switch (cr->detail) { - case Below: - case BottomIf: - screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this); - break; - - case Above: - case TopIf: - default: - screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); - break; - } - } -} - - -void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) { -#ifdef DEBUG - fprintf(stderr, "BlackboxWindow::buttonPressEvent() for 0x%lx\n", - client.window); -#endif - - if (frame.maximize_button == be->window && be->button <= 3) { - redrawMaximizeButton(True); - } else if (be->button == 1 || (be->button == 3 && be->state == mod_mask)) { - if (! flags.focused) - setInputFocus(); - - if (frame.iconify_button == be->window) { - redrawIconifyButton(True); - } else if (frame.close_button == be->window) { - redrawCloseButton(True); - } else if (frame.stick_button == be->window) { - redrawStickyButton(True); - } else if (frame.plate == be->window) { - screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); - - XAllowEvents(otk::OBDisplay::display, ReplayPointer, be->time); - } else { - if (frame.title == be->window || frame.label == be->window) { - if (((be->time - lastButtonPressTime) <= - blackbox->getDoubleClickInterval()) || - (be->state == ControlMask)) { - lastButtonPressTime = 0; - shade(); - } else { - lastButtonPressTime = be->time; - } - } - - screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); - } - } else if (be->button == 2 && (be->window != frame.iconify_button) && - (be->window != frame.close_button) && - (be->window != frame.stick_button)) { - screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this); - // mouse wheel up - } else if (be->button == 4) { - if ((be->window == frame.label || - be->window == frame.title || - be->window == frame.maximize_button || - be->window == frame.iconify_button || - be->window == frame.close_button || - be->window == frame.stick_button) && - ! flags.shaded) - shade(); - // mouse wheel down - } else if (be->button == 5) { - if ((be->window == frame.label || - be->window == frame.title || - be->window == frame.maximize_button || - be->window == frame.iconify_button || - be->window == frame.close_button || - be->window == frame.stick_button) && - flags.shaded) - shade(); - } -} - - -void BlackboxWindow::buttonReleaseEvent(const XButtonEvent *re) { -#ifdef DEBUG - fprintf(stderr, "BlackboxWindow::buttonReleaseEvent() for 0x%lx\n", - client.window); -#endif - - if (re->window == frame.maximize_button && - re->button >= 1 && re->button <= 3) { - if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && - (re->y >= 0 && re->y <= static_cast(frame.button_w))) { - maximize(re->button); - } else { - redrawMaximizeButton(flags.maximized); - } - } else if (re->window == frame.iconify_button && re->button == 1) { - if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && - (re->y >= 0 && re->y <= static_cast(frame.button_w))) { - iconify(); - } else { - redrawIconifyButton(False); - } - } else if (re->window == frame.stick_button && re->button == 1) { - if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && - (re->y >= 0 && re->y <= static_cast(frame.button_w))) { - stick(); - } else { - redrawStickyButton(False); - } - } else if (re->window == frame.close_button & re->button == 1) { - if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && - (re->y >= 0 && re->y <= static_cast(frame.button_w))) - close(); - redrawCloseButton(False); - } else if (flags.moving) { - endMove(); - } else if (flags.resizing) { - endResize(); - } else if (re->window == frame.window) { - if (re->button == 2 && re->state == mod_mask) - XUngrabPointer(otk::OBDisplay::display, CurrentTime); - } -} - - - -void BlackboxWindow::beginMove(int x_root, int y_root) { - if (! (functions & Func_Move)) return; - - assert(! (flags.resizing || flags.moving)); - - /* - Only one window can be moved/resized at a time. If another window is already - being moved or resized, then stop it before whating to work with this one. - */ - BlackboxWindow *changing = blackbox->getChangingWindow(); - if (changing && changing != this) { - if (changing->flags.moving) - changing->endMove(); - else // if (changing->flags.resizing) - changing->endResize(); - } - - XGrabPointer(otk::OBDisplay::display, frame.window, False, - PointerMotionMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, - None, blackbox->getMoveCursor(), CurrentTime); - - flags.moving = True; - blackbox->setChangingWindow(this); - - if (! screen->doOpaqueMove()) { - XGrabServer(otk::OBDisplay::display); - - frame.changing = frame.rect; - screen->showPosition(frame.changing.x(), frame.changing.y()); - - XDrawRectangle(otk::OBDisplay::display, screen->getRootWindow(), - screen->getOpGC(), - frame.changing.x(), - frame.changing.y(), - frame.changing.width() - 1, - frame.changing.height() - 1); - } - - frame.grab_x = x_root - frame.rect.x() - frame.border_w; - frame.grab_y = y_root - frame.rect.y() - frame.border_w; -} - - -void BlackboxWindow::doMove(int x_root, int y_root) { - assert(flags.moving); - assert(blackbox->getChangingWindow() == this); - - int dx = x_root - frame.grab_x, dy = y_root - frame.grab_y; - dx -= frame.border_w; - dy -= frame.border_w; - - doWindowSnapping(dx, dy); - - if (screen->doOpaqueMove()) { - if (screen->doWorkspaceWarping()) - doWorkspaceWarping(x_root, y_root, dx); - - configure(dx, dy, frame.rect.width(), frame.rect.height()); - } else { - XDrawRectangle(otk::OBDisplay::display, screen->getRootWindow(), - screen->getOpGC(), - frame.changing.x(), - frame.changing.y(), - frame.changing.width() - 1, - frame.changing.height() - 1); - - if (screen->doWorkspaceWarping()) - doWorkspaceWarping(x_root, y_root, dx); - - frame.changing.setPos(dx, dy); - - XDrawRectangle(otk::OBDisplay::display, screen->getRootWindow(), - screen->getOpGC(), - frame.changing.x(), - frame.changing.y(), - frame.changing.width() - 1, - frame.changing.height() - 1); - } - - screen->showPosition(dx, dy); -} - - -void BlackboxWindow::doWorkspaceWarping(int x_root, int y_root, int &dx) { - // workspace warping - bool warp = False; - unsigned int dest = screen->getCurrentWorkspaceID(); - if (x_root <= 0) { - warp = True; - - if (dest > 0) dest--; - else dest = screen->getNumberOfWorkspaces() - 1; - - } else if (x_root >= screen->getRect().right()) { - warp = True; - - if (dest < screen->getNumberOfWorkspaces() - 1) dest++; - else dest = 0; - } - if (! warp) - return; - - bool focus = flags.focused; // had focus while moving? - - int dest_x = x_root; - if (x_root <= 0) { - dest_x += screen->getRect().width() - 1; - dx += screen->getRect().width() - 1; - } else { - dest_x -= screen->getRect().width() - 1; - dx -= screen->getRect().width() - 1; - } - - if (! flags.stuck) - screen->reassociateWindow(this, dest, False); - screen->changeWorkspaceID(dest); - - if (screen->doOpaqueMove()) - XGrabServer(otk::OBDisplay::display); - - XUngrabPointer(otk::OBDisplay::display, CurrentTime); - XWarpPointer(otk::OBDisplay::display, None, - screen->getRootWindow(), 0, 0, 0, 0, - dest_x, y_root); - XGrabPointer(otk::OBDisplay::display, frame.window, False, - PointerMotionMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, - None, blackbox->getMoveCursor(), CurrentTime); - - if (screen->doOpaqueMove()) - XUngrabServer(otk::OBDisplay::display); - - if (focus) - setInputFocus(); - -} - - -void BlackboxWindow::doWindowSnapping(int &dx, int &dy) { - // how much resistance to edges to provide - const int resistance_size = screen->getResistanceSize(); - - // how far away to snap - const int snap_distance = screen->getSnapThreshold(); - - // how to snap windows - const int snap_to_windows = screen->getWindowToWindowSnap(); - const int snap_to_edges = screen->getWindowToEdgeSnap(); - // the amount of space away from the edge to provide resistance/snap - const int snap_offset = screen->getSnapOffset(); - - // find the geomeetery where the moving window currently is - const otk::Rect &moving = - screen->doOpaqueMove() ? frame.rect : frame.changing; - - // window corners - const int wleft = dx, - wright = dx + frame.rect.width() - 1, - wtop = dy, - wbottom = dy + frame.rect.height() - 1; - - if (snap_to_windows) { - otk::RectList rectlist; - - Workspace *w = screen->getWorkspace(getWorkspaceNumber()); - assert(w); - - // add windows on the workspace to the rect list - const BlackboxWindowList& stack_list = w->getStackingList(); - BlackboxWindowList::const_iterator st_it, st_end = stack_list.end(); - for (st_it = stack_list.begin(); st_it != st_end; ++st_it) - if (*st_it != this) // don't snap to ourself - rectlist.push_back( (*st_it)->frameRect() ); - - otk::RectList::const_iterator it, end = rectlist.end(); - for (it = rectlist.begin(); it != end; ++it) { - bool snapped = False; - const otk::Rect &winrect = *it; - otk::Rect offsetrect; - offsetrect.setCoords(winrect.left() - snap_offset, - winrect.top() - snap_offset, - winrect.right() + snap_offset, - winrect.bottom() + snap_offset); - - if (snap_to_windows == BScreen::WindowResistance) - // if the window is already over top of this snap target, then - // resistance is futile, so just ignore it - if (winrect.intersects(moving)) - continue; - - int dleft, dright, dtop, dbottom; - - // if the windows are in the same plane vertically - if (wtop >= (signed)(winrect.y() - frame.rect.height() + 1) && - wtop < (signed)(winrect.y() + winrect.height() - 1)) { - - if (snap_to_windows == BScreen::WindowResistance) { - dleft = wright - offsetrect.left(); - dright = offsetrect.right() - wleft; - - // snap left of other window? - if (dleft >= 0 && dleft < resistance_size && - dleft < (wright - wleft)) { - dx = offsetrect.left() - frame.rect.width(); - snapped = True; - } - // snap right of other window? - else if (dright >= 0 && dright < resistance_size && - dright < (wright - wleft)) { - dx = offsetrect.right() + 1; - snapped = True; - } - } else { // BScreen::WindowSnap - dleft = abs(wright - offsetrect.left()); - dright = abs(wleft - offsetrect.right()); - - // snap left of other window? - if (dleft < snap_distance && dleft <= dright) { - dx = offsetrect.left() - frame.rect.width(); - snapped = True; - } - // snap right of other window? - else if (dright < snap_distance) { - dx = offsetrect.right() + 1; - snapped = True; - } - } - - if (snapped) { - if (screen->getWindowCornerSnap()) { - // try corner-snap to its other sides - if (snap_to_windows == BScreen::WindowResistance) { - dtop = winrect.top() - wtop; - dbottom = wbottom - winrect.bottom(); - if (dtop > 0 && dtop < resistance_size) { - // if we're already past the top edge, then don't provide - // resistance - if (moving.top() >= winrect.top()) - dy = winrect.top(); - } else if (dbottom > 0 && dbottom < resistance_size) { - // if we're already past the bottom edge, then don't provide - // resistance - if (moving.bottom() <= winrect.bottom()) - dy = winrect.bottom() - frame.rect.height() + 1; - } - } else { // BScreen::WindowSnap - dtop = abs(wtop - winrect.top()); - dbottom = abs(wbottom - winrect.bottom()); - if (dtop < snap_distance && dtop <= dbottom) - dy = winrect.top(); - else if (dbottom < snap_distance) - dy = winrect.bottom() - frame.rect.height() + 1; - } - } - - continue; - } - } - - // if the windows are on the same plane horizontally - if (wleft >= (signed)(winrect.x() - frame.rect.width() + 1) && - wleft < (signed)(winrect.x() + winrect.width() - 1)) { - - if (snap_to_windows == BScreen::WindowResistance) { - dtop = wbottom - offsetrect.top(); - dbottom = offsetrect.bottom() - wtop; - - // snap top of other window? - if (dtop >= 0 && dtop < resistance_size && dtop < (wbottom - wtop)) { - dy = offsetrect.top() - frame.rect.height(); - snapped = True; - } - // snap bottom of other window? - else if (dbottom >= 0 && dbottom < resistance_size && - dbottom < (wbottom - wtop)) { - dy = offsetrect.bottom() + 1; - snapped = True; - } - } else { // BScreen::WindowSnap - dtop = abs(wbottom - offsetrect.top()); - dbottom = abs(wtop - offsetrect.bottom()); - - // snap top of other window? - if (dtop < snap_distance && dtop <= dbottom) { - dy = offsetrect.top() - frame.rect.height(); - snapped = True; - } - // snap bottom of other window? - else if (dbottom < snap_distance) { - dy = offsetrect.bottom() + 1; - snapped = True; - } - - } - - if (snapped) { - if (screen->getWindowCornerSnap()) { - // try corner-snap to its other sides - if (snap_to_windows == BScreen::WindowResistance) { - dleft = winrect.left() - wleft; - dright = wright - winrect.right(); - if (dleft > 0 && dleft < resistance_size) { - // if we're already past the left edge, then don't provide - // resistance - if (moving.left() >= winrect.left()) - dx = winrect.left(); - } else if (dright > 0 && dright < resistance_size) { - // if we're already past the right edge, then don't provide - // resistance - if (moving.right() <= winrect.right()) - dx = winrect.right() - frame.rect.width() + 1; - } - } else { // BScreen::WindowSnap - dleft = abs(wleft - winrect.left()); - dright = abs(wright - winrect.right()); - if (dleft < snap_distance && dleft <= dright) - dx = winrect.left(); - else if (dright < snap_distance) - dx = winrect.right() - frame.rect.width() + 1; - } - } - - continue; - } - } - } - } - - if (snap_to_edges) { - otk::RectList rectlist; - - // snap to the screen edges (and screen boundaries for xinerama) -#ifdef XINERAMA - if (screen->isXineramaActive() && blackbox->doXineramaSnapping()) { - rectlist.insert(rectlist.begin(), - screen->getXineramaAreas().begin(), - screen->getXineramaAreas().end()); - } else -#endif // XINERAMA - rectlist.push_back(screen->getRect()); - - otk::RectList::const_iterator it, end = rectlist.end(); - for (it = rectlist.begin(); it != end; ++it) { - const otk::Rect &srect = *it; - otk::Rect offsetrect; - offsetrect.setCoords(srect.left() + snap_offset, - srect.top() + snap_offset, - srect.right() - snap_offset, - srect.bottom() - snap_offset); - - if (snap_to_edges == BScreen::WindowResistance) { - // if we're not in the rectangle then don't snap to it. - if (! srect.contains(moving)) - continue; - } else { // BScreen::WindowSnap - // if we're not in the rectangle then don't snap to it. - if (! srect.intersects(otk::Rect(wleft, wtop, frame.rect.width(), - frame.rect.height()))) - continue; - } - - if (snap_to_edges == BScreen::WindowResistance) { - int dleft = offsetrect.left() - wleft, - dright = wright - offsetrect.right(), - dtop = offsetrect.top() - wtop, - dbottom = wbottom - offsetrect.bottom(); - - // snap left? - if (dleft > 0 && dleft < resistance_size) - dx = offsetrect.left(); - // snap right? - else if (dright > 0 && dright < resistance_size) - dx = offsetrect.right() - frame.rect.width() + 1; - - // snap top? - if (dtop > 0 && dtop < resistance_size) - dy = offsetrect.top(); - // snap bottom? - else if (dbottom > 0 && dbottom < resistance_size) - dy = offsetrect.bottom() - frame.rect.height() + 1; - } else { // BScreen::WindowSnap - int dleft = abs(wleft - offsetrect.left()), - dright = abs(wright - offsetrect.right()), - dtop = abs(wtop - offsetrect.top()), - dbottom = abs(wbottom - offsetrect.bottom()); - - // snap left? - if (dleft < snap_distance && dleft <= dright) - dx = offsetrect.left(); - // snap right? - else if (dright < snap_distance) - dx = offsetrect.right() - frame.rect.width() + 1; - - // snap top? - if (dtop < snap_distance && dtop <= dbottom) - dy = offsetrect.top(); - // snap bottom? - else if (dbottom < snap_distance) - dy = offsetrect.bottom() - frame.rect.height() + 1; - } - } - } -} - - -void BlackboxWindow::endMove(void) { - assert(flags.moving); - assert(blackbox->getChangingWindow() == this); - - flags.moving = False; - blackbox->setChangingWindow(0); - - if (! screen->doOpaqueMove()) { - /* when drawing the rubber band, we need to make sure we only draw inside - * the frame... frame.changing_* contain the new coords for the window, - * so we need to subtract 1 from changing_w/changing_h every where we - * draw the rubber band (for both moving and resizing) - */ - XDrawRectangle(otk::OBDisplay::display, screen->getRootWindow(), - screen->getOpGC(), frame.changing.x(), frame.changing.y(), - frame.changing.width() - 1, frame.changing.height() - 1); - XUngrabServer(otk::OBDisplay::display); - - configure(frame.changing.x(), frame.changing.y(), - frame.changing.width(), frame.changing.height()); - } else { - configure(frame.rect.x(), frame.rect.y(), - frame.rect.width(), frame.rect.height()); - } - screen->hideGeometry(); - - XUngrabPointer(otk::OBDisplay::display, CurrentTime); - - // if there are any left over motions from the move, drop them now - XSync(otk::OBDisplay::display, false); // make sure we don't miss any - XEvent e; - while (XCheckTypedWindowEvent(otk::OBDisplay::display, frame.window, - MotionNotify, &e)); -} - - -void BlackboxWindow::beginResize(int x_root, int y_root, Corner dir) { - if (! (functions & Func_Resize)) return; - - assert(! (flags.resizing || flags.moving)); - - /* - Only one window can be moved/resized at a time. If another window is - already being moved or resized, then stop it before whating to work with - this one. - */ - BlackboxWindow *changing = blackbox->getChangingWindow(); - if (changing && changing != this) { - if (changing->flags.moving) - changing->endMove(); - else // if (changing->flags.resizing) - changing->endResize(); - } - - resize_dir = dir; - - Cursor cursor; - Corner anchor; - - switch (resize_dir) { - case BottomLeft: - anchor = TopRight; - cursor = blackbox->getLowerLeftAngleCursor(); - break; - - case BottomRight: - anchor = TopLeft; - cursor = blackbox->getLowerRightAngleCursor(); - break; - - case TopLeft: - anchor = BottomRight; - cursor = blackbox->getUpperLeftAngleCursor(); - break; - - case TopRight: - anchor = BottomLeft; - cursor = blackbox->getUpperRightAngleCursor(); - break; - - default: - assert(false); // unhandled Corner - return; // unreachable, for the compiler - } - - XGrabServer(otk::OBDisplay::display); - XGrabPointer(otk::OBDisplay::display, frame.window, False, - PointerMotionMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime); - - flags.resizing = True; - blackbox->setChangingWindow(this); - - unsigned int gw, gh; - frame.changing = frame.rect; - - constrain(anchor, &gw, &gh); - - XDrawRectangle(otk::OBDisplay::display, screen->getRootWindow(), - screen->getOpGC(), frame.changing.x(), frame.changing.y(), - frame.changing.width() - 1, frame.changing.height() - 1); - - screen->showGeometry(gw, gh); - - frame.grab_x = x_root; - frame.grab_y = y_root; -} - - -void BlackboxWindow::doResize(int x_root, int y_root) { - assert(flags.resizing); - assert(blackbox->getChangingWindow() == this); - - XDrawRectangle(otk::OBDisplay::display, screen->getRootWindow(), - screen->getOpGC(), frame.changing.x(), frame.changing.y(), - frame.changing.width() - 1, frame.changing.height() - 1); - - unsigned int gw, gh; - Corner anchor; - int dx, dy; // the amount of change in the size of the window - - switch (resize_dir) { - case BottomLeft: - anchor = TopRight; - dx = - (x_root - frame.grab_x); - dy = + (y_root - frame.grab_y); - break; - case BottomRight: - anchor = TopLeft; - dx = + (x_root - frame.grab_x); - dy = + (y_root - frame.grab_y); - break; - case TopLeft: - anchor = BottomRight; - dx = - (x_root - frame.grab_x); - dy = - (y_root - frame.grab_y); - break; - case TopRight: - anchor = BottomLeft; - dx = + (x_root - frame.grab_x); - dy = - (y_root - frame.grab_y); - break; - - default: - assert(false); // unhandled Corner - return; // unreachable, for the compiler - } - - // make sure the user cant resize the window smaller than 0, which makes it - // wrap around and become huge - if (dx < -(signed)client.rect.width()) dx = -(signed)client.rect.width(); - if (dy < -(signed)client.rect.height()) dy = -(signed)client.rect.height(); - - frame.changing.setSize(frame.rect.width() + dx, frame.rect.height() + dy); - - constrain(anchor, &gw, &gh); - - XDrawRectangle(otk::OBDisplay::display, screen->getRootWindow(), - screen->getOpGC(), frame.changing.x(), frame.changing.y(), - frame.changing.width() - 1, frame.changing.height() - 1); - - screen->showGeometry(gw, gh); -} - - -void BlackboxWindow::endResize(void) { - assert(flags.resizing); - assert(blackbox->getChangingWindow() == this); - - XDrawRectangle(otk::OBDisplay::display, screen->getRootWindow(), - screen->getOpGC(), frame.changing.x(), frame.changing.y(), - frame.changing.width() - 1, frame.changing.height() - 1); - XUngrabServer(otk::OBDisplay::display); - - // unset maximized state after resized when fully maximized - if (flags.maximized == 1) - maximize(0); - - flags.resizing = False; - blackbox->setChangingWindow(0); - - configure(frame.changing.x(), frame.changing.y(), - frame.changing.width(), frame.changing.height()); - screen->hideGeometry(); - - XUngrabPointer(otk::OBDisplay::display, CurrentTime); - - // if there are any left over motions from the resize, drop them now - XSync(otk::OBDisplay::display, false); // make sure we don't miss any - XEvent e; - while (XCheckTypedWindowEvent(otk::OBDisplay::display, frame.window, - MotionNotify, &e)); -} - - -void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) { -#if 0 - fprintf(stderr, "BlackboxWindow::motionNotifyEvent() for 0x%lx\n", - client.window); -#endif - - if (flags.moving) { - doMove(me->x_root, me->y_root); - } else if (flags.resizing) { - doResize(me->x_root, me->y_root); - } else { - if ((functions & Func_Move) && - (me->state & Button1Mask) && - (frame.title == me->window || frame.label == me->window || - frame.handle == me->window || frame.window == me->window)) { - beginMove(me->x_root, me->y_root); - } else if ((functions & Func_Resize) && - ((me->state & Button1Mask) && - (me->window == frame.right_grip || - me->window == frame.left_grip)) || - ((me->state & Button3Mask) && (me->state & mod_mask) && - (frame.title == me->window || frame.label == me->window || - frame.handle == me->window || frame.window == me->window || - frame.right_grip == me->window || - frame.left_grip == me->window))) { - unsigned int zones = screen->getResizeZones(); - Corner corner; - - if (me->window == frame.left_grip) { - corner = BottomLeft; - } else if (me->window == frame.right_grip || zones == 1) { - corner = BottomRight; - } else { - bool top; - bool left = (me->x_root - frame.rect.x() <= - static_cast(frame.rect.width() / 2)); - if (zones == 2) - top = False; - else // (zones == 4) - top = (me->y_root - frame.rect.y() <= - static_cast(frame.rect.height() / 2)); - corner = (top ? (left ? TopLeft : TopRight) : - (left ? BottomLeft : BottomRight)); - } - - beginResize(me->x_root, me->y_root, corner); - } - } -} - - -void BlackboxWindow::enterNotifyEvent(const XCrossingEvent* ce) { - if (! (screen->isSloppyFocus() && isVisible() && isNormal())) - return; - - XEvent e; - bool leave = False, inferior = False; - - while (XCheckTypedWindowEvent(otk::OBDisplay::display, ce->window, - LeaveNotify, &e)) { - if (e.type == LeaveNotify && e.xcrossing.mode == NotifyNormal) { - leave = True; - inferior = (e.xcrossing.detail == NotifyInferior); - } - } - - if (! leave || inferior) { - if (! isFocused()) { - bool success = setInputFocus(); - if (success) // if focus succeeded install the colormap - installColormap(True); // XXX: shouldnt we honour no install? - - /* - We only auto-raise when the window wasn't focused because otherwise - we run into problems with gtk+ drop-down lists. The window ends up - raising over the list. - */ - if (screen->doAutoRaise()) - timer->start(); - } - } -} - - -void BlackboxWindow::leaveNotifyEvent(const XCrossingEvent*) { - if (! (screen->isSloppyFocus() && screen->doAutoRaise() && isNormal())) - return; - - installColormap(False); - - timer->stop(); -} - - -#ifdef SHAPE -void BlackboxWindow::shapeEvent(XShapeEvent *e) { - if (otk::OBDisplay::shape()) { - if (! e->shaped && flags.shaped) { - clearShape(); - flags.shaped = False; - } else if (e->shaped) { - configureShape(); - flags.shaped = True; - } - } -} -#endif // SHAPE - - -bool BlackboxWindow::validateClient(void) const { - XSync(otk::OBDisplay::display, False); - - XEvent e; - if (XCheckTypedWindowEvent(otk::OBDisplay::display, client.window, - DestroyNotify, &e) || - XCheckTypedWindowEvent(otk::OBDisplay::display, client.window, - UnmapNotify, &e)) { - XPutBackEvent(otk::OBDisplay::display, &e); - - return False; - } - - return True; -} - - -void BlackboxWindow::restore(bool remap) { - XChangeSaveSet(otk::OBDisplay::display, client.window, SetModeDelete); - XSelectInput(otk::OBDisplay::display, client.window, NoEventMask); - XSelectInput(otk::OBDisplay::display, frame.plate, NoEventMask); - - // do not leave a shaded window as an icon unless it was an icon - if (flags.shaded && ! flags.iconic) - setState(NormalState); - - // erase the netwm stuff that we read when a window maps, so that it - // doesn't persist between mappings. - // (these are the ones read in getNetWMFlags().) - xatom->erase(client.window, otk::OBProperty::net_wm_desktop); - xatom->erase(client.window, otk::OBProperty::net_wm_state); - - restoreGravity(client.rect); - - XUnmapWindow(otk::OBDisplay::display, frame.window); - XUnmapWindow(otk::OBDisplay::display, client.window); - - XSetWindowBorderWidth(otk::OBDisplay::display, client.window, client.old_bw); - - XEvent ev; - if (XCheckTypedWindowEvent(otk::OBDisplay::display, client.window, - ReparentNotify, &ev)) { - remap = True; - } else { - // according to the ICCCM - if the client doesn't reparent to - // root, then we have to do it for them - XReparentWindow(otk::OBDisplay::display, client.window, - screen->getRootWindow(), - client.rect.x(), client.rect.y()); - } - - if (remap) XMapWindow(otk::OBDisplay::display, client.window); -} - - -// timer for autoraise -void BlackboxWindow::timeout(BlackboxWindow *t) { - t->screen->getWorkspace(t->blackbox_attrib.workspace)->raiseWindow(t); - printf("TIMED OUT YA YAY\n"); -} - - -void BlackboxWindow::changeBlackboxHints(const BlackboxHints *net) { - if ((net->flags & AttribShaded) && - ((blackbox_attrib.attrib & AttribShaded) != - (net->attrib & AttribShaded))) - shade(); - - if (flags.visible && // watch out for requests when we can not be seen - (net->flags & (AttribMaxVert | AttribMaxHoriz)) && - ((blackbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) != - (net->attrib & (AttribMaxVert | AttribMaxHoriz)))) { - if (flags.maximized) { - maximize(0); - } else { - int button = 0; - - if ((net->flags & AttribMaxHoriz) && (net->flags & AttribMaxVert)) - button = ((net->attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0); - else if (net->flags & AttribMaxVert) - button = ((net->attrib & AttribMaxVert) ? 2 : 0); - else if (net->flags & AttribMaxHoriz) - button = ((net->attrib & AttribMaxHoriz) ? 3 : 0); - - maximize(button); - } - } - - if ((net->flags & AttribOmnipresent) && - ((blackbox_attrib.attrib & AttribOmnipresent) != - (net->attrib & AttribOmnipresent))) - stick(); - - if ((net->flags & AttribWorkspace) && - (blackbox_attrib.workspace != net->workspace)) { - screen->reassociateWindow(this, net->workspace, True); - - if (screen->getCurrentWorkspaceID() != net->workspace) { - withdraw(); - } else { - show(); - screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); - } - } - - if (net->flags & AttribDecoration) { - switch (net->decoration) { - case DecorNone: - enableDecor(False); - break; - - default: - case DecorNormal: - case DecorTiny: - case DecorTool: - enableDecor(True); - break; - } - } -} - - -/* - * Set the sizes of all components of the window frame - * (the window decorations). - * These values are based upon the current style settings and the client - * window's dimensions. - */ -void BlackboxWindow::upsize(void) { - frame.bevel_w = screen->getWindowStyle()->getBevelWidth(); - - if (decorations & Decor_Border) { - frame.border_w = screen->getWindowStyle()->getBorderWidth(); - if (! isTransient()) - frame.mwm_border_w = screen->getWindowStyle()->getFrameWidth(); - else - frame.mwm_border_w = 0; - } else { - frame.mwm_border_w = frame.border_w = 0; - } - - if (decorations & Decor_Titlebar) { - // the height of the titlebar is based upon the height of the font being - // used to display the window's title - otk::Style *style = screen->getWindowStyle(); - frame.title_h = style->font->height() + (frame.bevel_w * 2) + 2; - - frame.label_h = frame.title_h - (frame.bevel_w * 2); - frame.button_w = (frame.label_h - 2); - - // set the top frame margin - frame.margin.top = frame.border_w + frame.title_h + - frame.border_w + frame.mwm_border_w; - } else { - frame.title_h = 0; - frame.label_h = 0; - frame.button_w = 0; - - // set the top frame margin - frame.margin.top = frame.border_w + frame.mwm_border_w; - } - - // set the left/right frame margin - frame.margin.left = frame.margin.right = frame.border_w + frame.mwm_border_w; - - if (decorations & Decor_Handle) { - frame.grip_w = frame.button_w * 2; - frame.handle_h = screen->getWindowStyle()->getHandleWidth(); - - // set the bottom frame margin - frame.margin.bottom = frame.border_w + frame.handle_h + - frame.border_w + frame.mwm_border_w; - } else { - frame.handle_h = 0; - frame.grip_w = 0; - - // set the bottom frame margin - frame.margin.bottom = frame.border_w + frame.mwm_border_w; - } - - /* - We first get the normal dimensions and use this to define the inside_w/h - then we modify the height if shading is in effect. - If the shade state is not considered then frame.rect gets reset to the - normal window size on a reconfigure() call resulting in improper - dimensions appearing in move/resize and other events. - */ - unsigned int - height = client.rect.height() + frame.margin.top + frame.margin.bottom, - width = client.rect.width() + frame.margin.left + frame.margin.right; - - frame.inside_w = width - (frame.border_w * 2); - frame.inside_h = height - (frame.border_w * 2); - - if (flags.shaded) - height = frame.title_h + (frame.border_w * 2); - frame.rect.setSize(width, height); -} - - -/* - * Calculate the size of the client window and constrain it to the - * size specified by the size hints of the client window. - * - * The logical width and height are placed into pw and ph, if they - * are non-zero. Logical size refers to the users perception of - * the window size (for example an xterm resizes in cells, not in pixels). - * pw and ph are then used to display the geometry during window moves, resize, - * etc. - * - * The physical geometry is placed into frame.changing_{x,y,width,height}. - * Physical geometry refers to the geometry of the window in pixels. - */ -void BlackboxWindow::constrain(Corner anchor, - unsigned int *pw, unsigned int *ph) { - // frame.changing represents the requested frame size, we need to - // strip the frame margin off and constrain the client size - frame.changing.setCoords(frame.changing.left() + frame.margin.left, - frame.changing.top() + frame.margin.top, - frame.changing.right() - frame.margin.right, - frame.changing.bottom() - frame.margin.bottom); - - unsigned int dw = frame.changing.width(), dh = frame.changing.height(), - base_width = (client.base_width) ? client.base_width : client.min_width, - base_height = (client.base_height) ? client.base_height : - client.min_height; - - // constrain, but only if the min/max are being used. if they aren't, then - // this resize is going to be from a ConfigureRequest because the window - // isn't allowed to be resized by the user. And in that case, we don't want - // to limit what the app can do - if (client.max_width > client.min_width || - client.max_height > client.min_height) { - if (dw < client.min_width) dw = client.min_width; - if (dh < client.min_height) dh = client.min_height; - if (dw > client.max_width) dw = client.max_width; - if (dh > client.max_height) dh = client.max_height; - } - - if (client.width_inc > 1) { - dw -= base_width; - dw /= client.width_inc; - } - if (client.height_inc > 1) { - dh -= base_height; - dh /= client.height_inc; - } - - if (pw) - *pw = dw; - - if (ph) - *ph = dh; - - if (client.width_inc > 1) { - dw *= client.width_inc; - dw += base_width; - } - if (client.height_inc > 1) { - dh *= client.height_inc; - dh += base_height; - } - - frame.changing.setSize(dw, dh); - - // add the frame margin back onto frame.changing - frame.changing.setCoords(frame.changing.left() - frame.margin.left, - frame.changing.top() - frame.margin.top, - frame.changing.right() + frame.margin.right, - frame.changing.bottom() + frame.margin.bottom); - - // move frame.changing to the specified anchor - int dx = 0, - dy = 0; - switch (anchor) { - case TopLeft: - break; - - case TopRight: - dx = frame.rect.right() - frame.changing.right(); - break; - - case BottomLeft: - dy = frame.rect.bottom() - frame.changing.bottom(); - break; - - case BottomRight: - dx = frame.rect.right() - frame.changing.right(); - dy = frame.rect.bottom() - frame.changing.bottom(); - break; - - default: - assert(false); // unhandled corner - } - frame.changing.setPos(frame.changing.x() + dx, frame.changing.y() + dy); -} - - -BWindowGroup::BWindowGroup(Blackbox *b, Window _group) - : blackbox(b), group(_group) { - XWindowAttributes wattrib; - if (! XGetWindowAttributes(otk::OBDisplay::display, group, &wattrib)) { - // group window doesn't seem to exist anymore - delete this; - return; - } - - XSelectInput(otk::OBDisplay::display, group, - PropertyChangeMask | FocusChangeMask | StructureNotifyMask); - - blackbox->saveGroupSearch(group, this); -} - - -BWindowGroup::~BWindowGroup(void) { - blackbox->removeGroupSearch(group); -} - - -BlackboxWindow * -BWindowGroup::find(BScreen *screen, bool allow_transients) const { - BlackboxWindow *ret = blackbox->getFocusedWindow(); - - // does the focus window match (or any transient_fors)? - for (; ret; ret = ret->getTransientFor()) { - if (ret->getScreen() == screen && ret->getGroupWindow() == group && - (! ret->isTransient() || allow_transients)) - break; - } - - if (ret) return ret; - - // the focus window didn't match, look in the group's window list - BlackboxWindowList::const_iterator it, end = windowList.end(); - for (it = windowList.begin(); it != end; ++it) { - ret = *it; - if (ret->getScreen() == screen && ret->getGroupWindow() == group && - (! ret->isTransient() || allow_transients)) - break; - } - - return ret; -} - -} diff --git a/src/bbwindow.hh b/src/bbwindow.hh deleted file mode 100644 index 8417d1bc..00000000 --- a/src/bbwindow.hh +++ /dev/null @@ -1,416 +0,0 @@ -// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __Window_hh -#define __Window_hh - -extern "C" { -#include -#include -#ifdef SHAPE -# include -#endif // SHAPE -} - -#include - -#include "otk/timer.hh" -#include "otk/property.hh" -#include "otk/rect.hh" -#include "otk/strut.hh" -#include "blackbox.hh" -#include "otk/util.hh" - -#define MwmHintsFunctions (1l << 0) -#define MwmHintsDecorations (1l << 1) - -#define MwmFuncAll (1l << 0) -#define MwmFuncResize (1l << 1) -#define MwmFuncMove (1l << 2) -#define MwmFuncIconify (1l << 3) -#define MwmFuncMaximize (1l << 4) -#define MwmFuncClose (1l << 5) - -#define MwmDecorAll (1l << 0) -#define MwmDecorBorder (1l << 1) -#define MwmDecorHandle (1l << 2) -#define MwmDecorTitle (1l << 3) -#define MwmDecorMenu (1l << 4) // not used -#define MwmDecorIconify (1l << 5) -#define MwmDecorMaximize (1l << 6) - -namespace ob { - -// this structure only contains 3 elements... the Motif 2.0 structure contains -// 5... we only need the first 3... so that is all we will define -typedef struct MwmHints { - unsigned long flags, functions, decorations; -} MwmHints; - -#define PropMwmHintsElements 3 - -class BWindowGroup { -private: - Blackbox *blackbox; - Window group; - BlackboxWindowList windowList; - -public: - BWindowGroup(Blackbox *b, Window _group); - ~BWindowGroup(void); - - inline Window groupWindow(void) const { return group; } - - inline bool empty(void) const { return windowList.empty(); } - - void addWindow(BlackboxWindow *w) { windowList.push_back(w); } - void removeWindow(BlackboxWindow *w) { windowList.remove(w); } - - /* - find a window on the specified screen. the focused window (if any) is - checked first, otherwise the first matching window found is returned. - transients are returned only if allow_transients is True. - */ - BlackboxWindow *find(BScreen *screen, bool allow_transients = False) const; -}; - - -class BlackboxWindow { -public: - enum Function { Func_Resize = (1l << 0), - Func_Move = (1l << 1), - Func_Iconify = (1l << 2), - Func_Maximize = (1l << 3), - Func_Close = (1l << 4) }; - typedef unsigned char FunctionFlags; - - enum Decoration { Decor_Titlebar = (1l << 0), - Decor_Handle = (1l << 1), - Decor_Border = (1l << 2), - Decor_Iconify = (1l << 3), - Decor_Maximize = (1l << 4), - Decor_Close = (1l << 5) }; - typedef unsigned char DecorationFlags; - - enum WindowType { Type_Desktop, - Type_Dock, - Type_Toolbar, - Type_Menu, - Type_Utility, - Type_Splash, - Type_Dialog, - Type_Normal }; - - enum Corner { TopLeft, - TopRight, - BottomLeft, - BottomRight }; - -private: - Blackbox *blackbox; - BScreen *screen; - otk::OBProperty *xatom; - otk::OBTimer *timer; - BlackboxAttributes blackbox_attrib; - - Time lastButtonPressTime; // used for double clicks, when were we clicked - - unsigned int window_number; - unsigned long current_state; - unsigned int mod_mask; // the mod mask used to grab buttons - - enum FocusMode { F_NoInput = 0, F_Passive, - F_LocallyActive, F_GloballyActive }; - FocusMode focus_mode; - - struct _flags { - bool moving, // is moving? - resizing, // is resizing? - shaded, // is shaded? - visible, // is visible? - iconic, // is iconified? - focused, // has focus? - stuck, // is omnipresent? - modal, // is modal? (must be dismissed to continue) - skip_taskbar, // skipped by taskbars? - skip_pager, // skipped by pagers? - fullscreen, // a fullscreen window? - send_focus_message, // should we send focus messages to our client? - shaped; // does the frame use the shape extension? - unsigned int maximized; // maximize is special, the number corresponds - // with a mouse button - // if 0, not maximized - // 1 = HorizVert, 2 = Vertical, 3 = Horizontal - } flags; - - struct _client { - Window window, // the client's window - window_group; - BlackboxWindow *transient_for; // which window are we a transient for? - BlackboxWindowList transientList; // which windows are our transients? - - std::string title, icon_title; - - otk::Rect rect; - otk::Strut strut; - - int old_bw; // client's borderwidth - - unsigned int - min_width, min_height, // can not be resized smaller - max_width, max_height, // can not be resized larger - width_inc, height_inc, // increment step -#if 0 // not supported at the moment - min_aspect_x, min_aspect_y, // minimum aspect ratio - max_aspect_x, max_aspect_y, // maximum aspect ratio -#endif - base_width, base_height, - win_gravity; - - unsigned long initial_state, normal_hint_flags; - } client; - - FunctionFlags functions; - /* - * what decorations do we have? - * this is based on the type of the client window as well as user input - */ - DecorationFlags decorations; - DecorationFlags mwm_decorations; - Corner resize_dir; - WindowType window_type; - - /* - * client window = the application's window - * frame window = the window drawn around the outside of the client window - * by the window manager which contains items like the - * titlebar and close button - * title = the titlebar drawn above the client window, it displays the - * window's name and any buttons for interacting with the window, - * such as iconify, maximize, and close - * label = the window in the titlebar where the title is drawn - * buttons = maximize, iconify, close - * handle = the bar drawn at the bottom of the window, which contains the - * left and right grips used for resizing the window - * grips = the smaller reactangles in the handle, one of each side of it. - * When clicked and dragged, these resize the window interactively - * border = the line drawn around the outside edge of the frame window, - * between the title, the bordered client window, and the handle. - * Also drawn between the grips and the handle - */ - - struct _frame { - // u -> unfocused, f -> has focus, p -> pressed - unsigned long ulabel_pixel, flabel_pixel, utitle_pixel, - ftitle_pixel, uhandle_pixel, fhandle_pixel, ubutton_pixel, - fbutton_pixel, pfbutton_pixel, pubutton_pixel, - uborder_pixel, fborder_pixel, ugrip_pixel, fgrip_pixel; - Pixmap ulabel, flabel, utitle, ftitle, uhandle, fhandle, - ubutton, fbutton, pfbutton, pubutton, ugrip, fgrip; - - Window window, // the frame - plate, // holds the client - title, - label, - handle, - close_button, iconify_button, maximize_button, stick_button, - right_grip, left_grip; - - /* - * size and location of the box drawn while the window dimensions or - * location is being changed, ie. resized or moved - */ - otk::Rect changing; - - otk::Rect rect; // frame geometry - otk::Strut margin; // margins between the frame and client - - int grab_x, grab_y; // where was the window when it was grabbed? - - unsigned int inside_w, inside_h, // window w/h without border_w - title_h, label_w, label_h, handle_h, - button_w, grip_w, mwm_border_w, border_w, - bevel_w; - } frame; - - BlackboxWindow(const BlackboxWindow&); - BlackboxWindow& operator=(const BlackboxWindow&); - - bool getState(void); - Window createToplevelWindow(); - Window createChildWindow(Window parent, unsigned long event_mask, - Cursor = None); - - bool getWindowType(void); - void updateStrut(void); - void getWMName(void); - void getWMIconName(void); - void getWMNormalHints(void); - void getWMProtocols(void); - void getWMHints(void); - void getNetWMHints(void); - void getMWMHints(void); - bool getBlackboxHints(void); - void getTransientInfo(void); - void setNetWMAttributes(void); - void associateClientWindow(void); - void decorate(void); - void decorateLabel(void); - void positionButtons(bool redecorate_label = False); - void positionWindows(void); - void createHandle(void); - void destroyHandle(void); - void createTitlebar(void); - void destroyTitlebar(void); - void createCloseButton(void); - void destroyCloseButton(void); - void createIconifyButton(void); - void destroyIconifyButton(void); - void createMaximizeButton(void); - void destroyMaximizeButton(void); - void createStickyButton(void); - void destroyStickyButton(void); - void redrawWindowFrame(void) const; - void redrawLabel(void) const; - void redrawAllButtons(void) const; - void redrawButton(bool pressed, Window win, - Pixmap fppix, unsigned long fppixel, - Pixmap uppix, unsigned long uppixel, - Pixmap fpix, unsigned long fpixel, - Pixmap upix, unsigned long upixel) const; - void redrawCloseButton(bool pressed) const; - void redrawIconifyButton(bool pressed) const; - void redrawMaximizeButton(bool pressed) const; - void redrawStickyButton(bool pressed) const; - void applyGravity(otk::Rect &r); - void restoreGravity(otk::Rect &r); - void setAllowedActions(void); - void setState(unsigned long new_state); - void upsize(void); - void doMove(int x_root, int y_root); - void doWorkspaceWarping(int x_root, int y_root, int &dx); - void doWindowSnapping(int &dx, int &dy); - void endMove(void); - void doResize(int x_root, int y_root); - void endResize(void); - - void constrain(Corner anchor, unsigned int *pw = 0, unsigned int *ph = 0); - -public: - BlackboxWindow(Blackbox *b, Window w, BScreen *s); - virtual ~BlackboxWindow(void); - - inline bool isTransient(void) const { return client.transient_for != 0; } - inline bool isFocused(void) const { return flags.focused; } - inline bool isVisible(void) const { return flags.visible; } - inline bool isIconic(void) const { return flags.iconic; } - inline bool isShaded(void) const { return flags.shaded; } - inline bool isMaximized(void) const { return flags.maximized; } - inline bool isMaximizedHoriz(void) const { return flags.maximized == 3; } - inline bool isMaximizedVert(void) const { return flags.maximized == 2; } - inline bool isMaximizedFull(void) const { return flags.maximized == 1; } - inline bool isStuck(void) const { return flags.stuck; } - inline bool isModal(void) const { return flags.modal; } - inline bool isIconifiable(void) const { return functions & Func_Iconify; } - inline bool isMaximizable(void) const { return functions & Func_Maximize; } - inline bool isResizable(void) const { return functions & Func_Resize; } - inline bool isClosable(void) const { return functions & Func_Close; } - - // is a 'normal' window? meaning, a standard client application - inline bool isNormal(void) const - { return window_type == Type_Dialog || window_type == Type_Normal || - window_type == Type_Toolbar || window_type == Type_Utility; } - inline bool isTopmost(void) const - { return window_type == Type_Toolbar || window_type == Type_Utility; } - inline bool isDesktop(void) const { return window_type == Type_Desktop; } - - inline bool hasTitlebar(void) const { return decorations & Decor_Titlebar; } - - inline const BlackboxWindowList &getTransients(void) const - { return client.transientList; } - BlackboxWindow *getTransientFor(void) const; - - inline BScreen *getScreen(void) const { return screen; } - - inline Window getFrameWindow(void) const { return frame.window; } - inline Window getClientWindow(void) const { return client.window; } - inline Window getGroupWindow(void) const { return client.window_group; } - - inline const char *getTitle(void) const - { return client.title.c_str(); } - inline const char *getIconTitle(void) const - { return client.icon_title.c_str(); } - - inline unsigned int getWorkspaceNumber(void) const - { return blackbox_attrib.workspace; } - inline unsigned int getWindowNumber(void) const { return window_number; } - - inline const otk::Rect &frameRect(void) const { return frame.rect; } - inline const otk::Rect &clientRect(void) const { return client.rect; } - - inline unsigned int getTitleHeight(void) const - { return frame.title_h; } - - inline void setWindowNumber(int n) { window_number = n; } - - bool validateClient(void) const; - bool setInputFocus(void); - - // none of these are used by the window manager, they are here to persist - // them properly in the window's netwm state property. - inline bool skipTaskbar(void) const { return flags.skip_taskbar; } - inline void setSkipTaskbar(const bool s) { flags.skip_taskbar = s; } - inline bool skipPager(void) const { return flags.skip_pager; } - inline void setSkipPager(const bool s) { flags.skip_pager = s; } - inline bool isFullscreen(void) const { return flags.fullscreen; } - inline void setFullscreen(const bool f) { flags.fullscreen = f; } - - inline void setModal(const bool m) { flags.modal = m; } - - void beginMove(int x_root, int y_root); - void beginResize(int x_root, int y_root, Corner dir); - void enableDecor(bool enable); - void setupDecor(); - void setFocusFlag(bool focus); - void iconify(void); - void deiconify(bool reassoc = True, bool raise = True); - void show(void); - void close(void); - void withdraw(void); - void maximize(unsigned int button); - void remaximize(void); - void shade(void); - void stick(void); - void reconfigure(void); - void grabButtons(void); - void ungrabButtons(void); - void installColormap(bool install); - void restore(bool remap); - void configure(int dx, int dy, int dw, int dh); - void setWorkspace(unsigned int n); - void changeBlackboxHints(const BlackboxHints *net); - void restoreAttributes(void); - - void buttonPressEvent(const XButtonEvent *be); - void buttonReleaseEvent(const XButtonEvent *re); - void motionNotifyEvent(const XMotionEvent *me); - void destroyNotifyEvent(const XDestroyWindowEvent* /*unused*/); - void mapRequestEvent(const XMapRequestEvent *mre); - void unmapNotifyEvent(const XUnmapEvent* /*unused*/); - void reparentNotifyEvent(const XReparentEvent* /*unused*/); - void propertyNotifyEvent(const XPropertyEvent *pe); - void exposeEvent(const XExposeEvent *ee); - void configureRequestEvent(const XConfigureRequestEvent *cr); - void enterNotifyEvent(const XCrossingEvent *ce); - void leaveNotifyEvent(const XCrossingEvent* /*unused*/); - -#ifdef SHAPE - void configureShape(void); - void clearShape(void); - void shapeEvent(XShapeEvent * /*unused*/); -#endif // SHAPE - - static void timeout(BlackboxWindow *t); -}; - -} - -#endif // __Window_hh diff --git a/src/bindings.cc b/src/bindings.cc index 007b0334..2b81381c 100644 --- a/src/bindings.cc +++ b/src/bindings.cc @@ -142,7 +142,7 @@ OBBindings::OBBindings() : _curpos(&_keytree), _resetkey(0,0), _timer(Openbox::instance->timerManager(), - (otk::OBTimeoutHandler)reset, this) + (otk::OBTimeoutHandler)resetChains, this) { _timer.setTimeout(5000); // chains reset after 5 seconds @@ -402,7 +402,14 @@ bool OBBindings::addButton(const std::string &but, MouseContext context, bind->binding.key = b.key; bind->binding.modifiers = b.modifiers; _buttons[context].push_back(bind); - // XXX GRAB the new button everywhere! + // grab the button on all clients + for (int sn = 0; sn < Openbox::instance->screenCount(); ++sn) { + OBScreen *s = Openbox::instance->screen(sn); + OBScreen::ClientList::iterator c_it, c_end = s->clients.end(); + for (c_it = s->clients.begin(); c_it != c_end; ++c_it) { + grabButton(true, bind->binding, context, *c_it); + } + } } else bind = *it; Py_XDECREF(bind->callback[action]); // if it was already bound, unbind it @@ -413,45 +420,57 @@ bool OBBindings::addButton(const std::string &but, MouseContext context, void OBBindings::removeAllButtons() { - // XXX: UNGRAB shits for (int i = i; i < NUM_MOUSE_CONTEXT; ++i) { ButtonBindingList::iterator it, end = _buttons[i].end(); - for (it = _buttons[i].begin(); it != end; ++it) + for (it = _buttons[i].begin(); it != end; ++it) { for (int a = 0; a < NUM_MOUSE_ACTION; ++a) { Py_XDECREF((*it)->callback[a]); (*it)->callback[a] = 0; } + // ungrab the button on all clients + for (int sn = 0; sn < Openbox::instance->screenCount(); ++sn) { + OBScreen *s = Openbox::instance->screen(sn); + OBScreen::ClientList::iterator c_it, c_end = s->clients.end(); + for (c_it = s->clients.begin(); c_it != c_end; ++c_it) { + grabButton(false, (*it)->binding, (MouseContext)i, *c_it); + } + } + } + } +} + +void OBBindings::grabButton(bool grab, const Binding &b, MouseContext context, + OBClient *client) +{ + Window win; + int mode = GrabModeAsync; + switch(context) { + case MC_Frame: + win = client->frame->window(); + break; + case MC_Window: + win = client->frame->plate(); + mode = GrabModeSync; // this is handled in fireButton + break; + default: + // any other elements already get button events, don't grab on them + return; } + if (grab) + otk::OBDisplay::grabButton(b.key, b.modifiers, win, false, + ButtonPressMask | ButtonMotionMask | + ButtonReleaseMask, mode, GrabModeAsync, + None, None, false); + else + otk::OBDisplay::ungrabButton(b.key, b.modifiers, win); } void OBBindings::grabButtons(bool grab, OBClient *client) { for (int i = 0; i < NUM_MOUSE_CONTEXT; ++i) { - Window win; - int mode = GrabModeAsync; - switch (i) { - case MC_Frame: - win = client->frame->window(); - break; - case MC_Window: - win = client->frame->plate(); - mode = GrabModeSync; // this is handled in fireButton - break; - default: - // any other elements already get button events, don't grab on them - continue; - } ButtonBindingList::iterator it, end = _buttons[i].end(); for (it = _buttons[i].begin(); it != end; ++it) - if (grab) - otk::OBDisplay::grabButton((*it)->binding.key, - (*it)->binding.modifiers, win, false, - ButtonPressMask | ButtonMotionMask | - ButtonReleaseMask, mode, GrabModeAsync, - None, None, false); - else - otk::OBDisplay::ungrabButton((*it)->binding.key, - (*it)->binding.modifiers, win); + grabButton(grab, (*it)->binding, (MouseContext)i, client); } } diff --git a/src/bindings.hh b/src/bindings.hh index b3078d85..71df3011 100644 --- a/src/bindings.hh +++ b/src/bindings.hh @@ -82,6 +82,9 @@ private: typedef std::list ButtonBindingList; ButtonBindingList _buttons[NUM_MOUSE_CONTEXT]; + void grabButton(bool grab, const Binding &b, MouseContext context, + OBClient *client); + public: //! Initializes an OBBindings object OBBindings(); diff --git a/src/openbox.cc b/src/openbox.cc index 4d2f1024..9761b468 100644 --- a/src/openbox.cc +++ b/src/openbox.cc @@ -172,6 +172,9 @@ Openbox::~Openbox() { _state = State_Exiting; // time to kill everything + // return input focus to the root + XSetInputFocus(otk::OBDisplay::display, PointerRoot, None, CurrentTime); + std::for_each(_screens.begin(), _screens.end(), otk::PointerAssassin()); delete _bindings; @@ -179,9 +182,12 @@ Openbox::~Openbox() delete _property; python_destroy(); + + XSync(otk::OBDisplay::display, False); // close the X display otk::OBDisplay::destroy(); + printf("Exiting!\n"); } diff --git a/src/screen.cc b/src/screen.cc index f0b0eb3d..419ba0b9 100644 --- a/src/screen.cc +++ b/src/screen.cc @@ -122,6 +122,11 @@ OBScreen::~OBScreen() { if (! _managed) return; + XSelectInput(otk::OBDisplay::display, _info->rootWindow(), NoEventMask); + XSync(otk::OBDisplay::display, False); + + XDestroyWindow(otk::OBDisplay::display, _focuswindow); + // unmanage all windows while (!clients.empty()) unmanageWindow(clients.front()); -- 2.39.2