+++ /dev/null
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif // HAVE_CONFIG_H
-
-extern "C" {
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-
-#ifdef XINERAMA
-# include <X11/Xlib.h>
-# include <X11/extensions/Xinerama.h>
-#endif // XINERAMA
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif // HAVE_STDLIB_H
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif // HAVE_STRING_H
-
-#ifdef HAVE_CTYPE_H
-# include <ctype.h>
-#endif // HAVE_CTYPE_H
-
-#ifdef HAVE_UNISTD_H
-# include <sys/types.h>
-# include <unistd.h>
-#endif // HAVE_UNISTD_H
-
-#ifdef HAVE_DIRENT_H
-# include <dirent.h>
-#endif // HAVE_DIRENT_H
-
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif // HAVE_LOCALE_H
-
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif // HAVE_SYS_STAT_H
-
-#ifdef HAVE_STDARG_H
-# include <stdarg.h>
-#endif // HAVE_STDARG_H
-}
-
-#include <assert.h>
-
-#include <algorithm>
-#include <functional>
-#include <string>
-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<int> 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));
-}
-
-}
+++ /dev/null
-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
-
-#ifdef HAVE_CONFIG_H
-# include "../config.h"
-#endif // HAVE_CONFIG_H
-
-extern "C" {
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif // HAVE_STRING_H
-
-#ifdef DEBUG
-# ifdef HAVE_STDIO_H
-# include <stdio.h>
-# endif // HAVE_STDIO_H
-#endif // DEBUG
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#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<signed>(client.min_width))
- client.max_width = sizehint.max_width;
- else
- client.max_width = client.min_width;
-
- if (sizehint.max_height > static_cast<signed>(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<signed>(frame.button_w)) &&
- (re->y >= 0 && re->y <= static_cast<signed>(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<signed>(frame.button_w)) &&
- (re->y >= 0 && re->y <= static_cast<signed>(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<signed>(frame.button_w)) &&
- (re->y >= 0 && re->y <= static_cast<signed>(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<signed>(frame.button_w)) &&
- (re->y >= 0 && re->y <= static_cast<signed>(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<signed>(frame.rect.width() / 2));
- if (zones == 2)
- top = False;
- else // (zones == 4)
- top = (me->y_root - frame.rect.y() <=
- static_cast<signed>(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;
-}
-
-}