From 8794d357e67abddf9fda9db77b235e294d0ec590 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sat, 25 May 2002 00:29:44 +0000 Subject: [PATCH] import from bb-cvs added slit and enable-clobber defines back in Makefile.am --- src/BaseDisplay.cc | 397 +-- src/BaseDisplay.h | 367 -- src/BaseDisplay.hh | 156 + src/Basemenu.cc | 590 ++-- src/Basemenu.h | 169 - src/Clientmenu.cc | 42 +- src/{Clientmenu.h => Clientmenu.hh} | 17 +- src/Color.cc | 242 ++ src/Color.hh | 128 + src/Configmenu.cc | 292 +- src/{Configmenu.h => Configmenu.hh} | 46 +- src/GCCache.cc | 197 ++ src/GCCache.hh | 133 + src/Geometry.cc | 145 - src/Geometry.h | 116 - src/Iconmenu.cc | 29 +- src/Iconmenu.h | 44 - src/Image.cc | 1731 +++------ src/Image.h | 242 -- src/Image.hh | 179 + src/ImageControl.cc | 604 ++++ src/Makefile.am | 167 +- src/Netizen.cc | 66 +- src/{Netizen.h => Netizen.hh} | 17 +- src/Resource.cc | 192 - src/Resource.h | 76 - src/Rootmenu.cc | 62 +- src/{Rootmenu.h => Rootmenu.hh} | 20 +- src/Screen.cc | 3657 ++++++++----------- src/Screen.h | 336 -- src/Screen.hh | 372 ++ src/Slit.cc | 939 +++-- src/Slit.h | 175 - src/Texture.cc | 200 ++ src/Texture.hh | 108 + src/Timer.cc | 82 +- src/Timer.h | 78 - src/Timer.hh | 131 + src/Toolbar.cc | 1992 +++++------ src/Toolbar.h | 176 - src/Toolbar.hh | 173 + src/Util.cc | 210 +- src/Util.h | 39 - src/Util.hh | 102 + src/Window.cc | 3871 ++++++++++----------- src/Window.h | 361 -- src/Window.hh | 363 ++ src/Windowmenu.cc | 195 +- src/Windowmenu.h | 78 - src/Workspace.cc | 836 +++-- src/Workspace.h | 94 - src/Workspace.hh | 109 + src/Workspacemenu.cc | 56 +- src/{Workspacemenu.h => Workspacemenu.hh} | 14 +- src/XAtom.cc | 348 -- src/XAtom.h | 238 -- src/XDisplay.cc | 260 -- src/XDisplay.h | 97 - src/XScreen.cc | 86 - src/XScreen.h | 63 - src/blackbox.cc | 1680 +++++++++ src/blackbox.hh | 410 +++ src/bsd-snprintf.c | 788 ----- src/bsd-snprintf.h | 17 - src/i18n.cc | 37 +- src/{i18n.h => i18n.hh} | 10 +- src/main.cc | 125 +- src/openbox.cc | 1109 ------ src/openbox.h | 239 -- 69 files changed, 11847 insertions(+), 14873 deletions(-) delete mode 100644 src/BaseDisplay.h create mode 100644 src/BaseDisplay.hh delete mode 100644 src/Basemenu.h rename src/{Clientmenu.h => Clientmenu.hh} (77%) create mode 100644 src/Color.cc create mode 100644 src/Color.hh rename src/{Configmenu.h => Configmenu.hh} (63%) create mode 100644 src/GCCache.cc create mode 100644 src/GCCache.hh delete mode 100644 src/Geometry.cc delete mode 100644 src/Geometry.h delete mode 100644 src/Iconmenu.h delete mode 100644 src/Image.h create mode 100644 src/Image.hh create mode 100644 src/ImageControl.cc rename src/{Netizen.h => Netizen.hh} (86%) delete mode 100644 src/Resource.cc delete mode 100644 src/Resource.h rename src/{Rootmenu.h => Rootmenu.hh} (79%) delete mode 100644 src/Screen.h create mode 100644 src/Screen.hh delete mode 100644 src/Slit.h create mode 100644 src/Texture.cc create mode 100644 src/Texture.hh delete mode 100644 src/Timer.h create mode 100644 src/Timer.hh delete mode 100644 src/Toolbar.h create mode 100644 src/Toolbar.hh delete mode 100644 src/Util.h create mode 100644 src/Util.hh delete mode 100644 src/Window.h create mode 100644 src/Window.hh delete mode 100644 src/Windowmenu.h delete mode 100644 src/Workspace.h create mode 100644 src/Workspace.hh rename src/{Workspacemenu.h => Workspacemenu.hh} (78%) delete mode 100644 src/XAtom.cc delete mode 100644 src/XAtom.h delete mode 100644 src/XDisplay.cc delete mode 100644 src/XDisplay.h delete mode 100644 src/XScreen.cc delete mode 100644 src/XScreen.h create mode 100644 src/blackbox.cc create mode 100644 src/blackbox.hh delete mode 100644 src/bsd-snprintf.c delete mode 100644 src/bsd-snprintf.h rename src/{i18n.h => i18n.hh} (92%) delete mode 100644 src/openbox.cc delete mode 100644 src/openbox.h diff --git a/src/BaseDisplay.cc b/src/BaseDisplay.cc index 3ee81fb0..6726cbac 100644 --- a/src/BaseDisplay.cc +++ b/src/BaseDisplay.cc @@ -1,5 +1,6 @@ -// BaseDisplay.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// BaseDisplay.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,20 +21,14 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H +extern "C" { #include #include #include -#include #include #ifdef SHAPE @@ -48,11 +43,11 @@ # include #endif // HAVE_STDIO_H -#ifdef HAVE_STDLIB_H +#ifdef HAVE_STDLIB_H # include #endif // HAVE_STDLIB_H -#ifdef HAVE_STRING_H +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H @@ -81,34 +76,37 @@ # include # include #endif // HAVE_SYS_WAIT_H +} -#if defined(HAVE_PROCESS_H) && defined(__EMX__) -# include -#endif // HAVE_PROCESS_H __EMX__ +#include +using std::string; -#include "i18n.h" -#include "BaseDisplay.h" -#include "Timer.h" +#include "i18n.hh" +#include "BaseDisplay.hh" +#include "GCCache.hh" +#include "Timer.hh" +#include "Util.hh" -#include // X error handler to handle any and all X errors while the application is // running -static Bool internal_error = False; +static bool internal_error = False; static Window last_bad_window = None; BaseDisplay *base_display; -static int handleXErrors(Display *d, XErrorEvent *e) { #ifdef DEBUG +static int handleXErrors(Display *d, XErrorEvent *e) { char errtxt[128]; XGetErrorText(d, e->error_code, errtxt, 128); - fprintf(stderr, i18n(BaseDisplaySet, BaseDisplayXError, - "%s: X error: %s(%d) opcodes %d/%d\n resource 0x%lx\n" - ), + fprintf(stderr, + i18n(BaseDisplaySet, BaseDisplayXError, + "%s: X error: %s(%d) opcodes %d/%d\n resource 0x%lx\n"), base_display->getApplicationName(), errtxt, e->error_code, e->request_code, e->minor_code, e->resourceid); +#else +static int handleXErrors(Display *, XErrorEvent *e) { #endif // DEBUG if (e->error_code == BadWindow) last_bad_window = e->resourceid; @@ -121,11 +119,11 @@ static int handleXErrors(Display *d, XErrorEvent *e) { // signal handler to allow for proper and gentle shutdown #ifndef HAVE_SIGACTION -static RETSIGTYPE signalhandler(int sig) +static RETSIGTYPE signalhandler(int sig) { #else // HAVE_SIGACTION -static void signalhandler(int sig) +static void signalhandler(int sig) { #endif // HAVE_SIGACTION -{ + static int re_enter = 0; switch (sig) { @@ -177,31 +175,10 @@ static void signalhandler(int sig) } -// convenience functions -#ifndef __EMX__ -void bexec(const char *command, char* displaystring) { - if (! fork()) { - setsid(); - putenv(displaystring); - execl("/bin/sh", "/bin/sh", "-c", command, NULL); - exit(0); - } -} -#endif // !__EMX__ +BaseDisplay::BaseDisplay(const char *app_name, const char *dpy_name) { + application_name = app_name; -char *bstrdup(const char *s) { - const int l = strlen(s) + 1; - char *n = new char[l]; - strncpy(n, s, l); - return n; -} - -BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) { - application_name = bstrdup(app_name); - - _startup = True; - _shutdown = False; - server_grabs = 0; + run_state = STARTUP; last_bad_window = None; ::base_display = this; @@ -235,8 +212,9 @@ BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) { #endif // HAVE_SIGACTION if (! (display = XOpenDisplay(dpy_name))) { - fprintf(stderr, i18n(BaseDisplaySet, BaseDisplayXConnectFail, - "BaseDisplay::BaseDisplay: connection to X server failed.\n")); + fprintf(stderr, + i18n(BaseDisplaySet, BaseDisplayXConnectFail, + "BaseDisplay::BaseDisplay: connection to X server failed.\n")); ::exit(2); } else if (fcntl(ConnectionNumber(display), F_SETFD, 1) == -1) { fprintf(stderr, @@ -255,93 +233,12 @@ BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) { shape.extensions = False; #endif // SHAPE - xa_wm_colormap_windows = - XInternAtom(display, "WM_COLORMAP_WINDOWS", False); - xa_wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False); - xa_wm_state = XInternAtom(display, "WM_STATE", False); - xa_wm_change_state = XInternAtom(display, "WM_CHANGE_STATE", False); - xa_wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False); - xa_wm_take_focus = XInternAtom(display, "WM_TAKE_FOCUS", False); - motif_wm_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False); - - openbox_hints = XInternAtom(display, "_BLACKBOX_HINTS", False); - openbox_attributes = XInternAtom(display, "_BLACKBOX_ATTRIBUTES", False); - openbox_change_attributes = - XInternAtom(display, "_BLACKBOX_CHANGE_ATTRIBUTES", False); - - openbox_structure_messages = - XInternAtom(display, "_BLACKBOX_STRUCTURE_MESSAGES", False); - openbox_notify_startup = - XInternAtom(display, "_BLACKBOX_NOTIFY_STARTUP", False); - openbox_notify_window_add = - XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_ADD", False); - openbox_notify_window_del = - XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_DEL", False); - openbox_notify_current_workspace = - XInternAtom(display, "_BLACKBOX_NOTIFY_CURRENT_WORKSPACE", False); - openbox_notify_workspace_count = - XInternAtom(display, "_BLACKBOX_NOTIFY_WORKSPACE_COUNT", False); - openbox_notify_window_focus = - XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_FOCUS", False); - openbox_notify_window_raise = - XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_RAISE", False); - openbox_notify_window_lower = - XInternAtom(display, "_BLACKBOX_NOTIFY_WINDOW_LOWER", False); - - openbox_change_workspace = - XInternAtom(display, "_BLACKBOX_CHANGE_WORKSPACE", False); - openbox_change_window_focus = - XInternAtom(display, "_BLACKBOX_CHANGE_WINDOW_FOCUS", False); - openbox_cycle_window_focus = - XInternAtom(display, "_BLACKBOX_CYCLE_WINDOW_FOCUS", False); - -#ifdef NEWWMSPEC - - net_supported = XInternAtom(display, "_NET_SUPPORTED", False); - net_client_list = XInternAtom(display, "_NET_CLIENT_LIST", False); - net_client_list_stacking = XInternAtom(display, "_NET_CLIENT_LIST_STACKING", False); - net_number_of_desktops = XInternAtom(display, "_NET_NUMBER_OF_DESKTOPS", False); - net_desktop_geometry = XInternAtom(display, "_NET_DESKTOP_GEOMETRY", False); - net_desktop_viewport = XInternAtom(display, "_NET_DESKTOP_VIEWPORT", False); - net_current_desktop = XInternAtom(display, "_NET_CURRENT_DESKTOP", False); - net_desktop_names = XInternAtom(display, "_NET_DESKTOP_NAMES", False); - net_active_window = XInternAtom(display, "_NET_ACTIVE_WINDOW", False); - net_workarea = XInternAtom(display, "_NET_WORKAREA", False); - net_supporting_wm_check = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False); - net_virtual_roots = XInternAtom(display, "_NET_VIRTUAL_ROOTS", False); - - net_close_window = XInternAtom(display, "_NET_CLOSE_WINDOW", False); - net_wm_moveresize = XInternAtom(display, "_NET_WM_MOVERESIZE", False); - - net_properties = XInternAtom(display, "_NET_PROPERTIES", False); - net_wm_name = XInternAtom(display, "_NET_WM_NAME", False); - net_wm_desktop = XInternAtom(display, "_NET_WM_DESKTOP", False); - net_wm_window_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); - net_wm_state = XInternAtom(display, "_NET_WM_STATE", False); - net_wm_strut = XInternAtom(display, "_NET_WM_STRUT", False); - net_wm_icon_geometry = XInternAtom(display, "_NET_WM_ICON_GEOMETRY", False); - net_wm_icon = XInternAtom(display, "_NET_WM_ICON", False); - net_wm_pid = XInternAtom(display, "_NET_WM_PID", False); - net_wm_handled_icons = XInternAtom(display, "_NET_WM_HANDLED_ICONS", False); - - net_wm_ping = XInternAtom(display, "_NET_WM_PING", False); - -#endif // NEWWMSPEC - - cursor.session = XCreateFontCursor(display, XC_left_ptr); - cursor.move = XCreateFontCursor(display, XC_fleur); - cursor.ll_angle = XCreateFontCursor(display, XC_ll_angle); - cursor.lr_angle = XCreateFontCursor(display, XC_lr_angle); - cursor.ul_angle = XCreateFontCursor(display, XC_ul_angle); - cursor.ur_angle = XCreateFontCursor(display, XC_ur_angle); - XSetErrorHandler((XErrorHandler) handleXErrors); - screenInfoList.reserve(numberOfScreens()); - for (unsigned int s = 0; s < numberOfScreens(); s++) - screenInfoList.push_back(new ScreenInfo(*this, s)); + screenInfoList.reserve(ScreenCount(display)); + for (int i = 0; i < ScreenCount(display); ++i) + screenInfoList.push_back(ScreenInfo(this, i)); -#ifndef NOCLOBBER NumLockMask = ScrollLockMask = 0; const XModifierKeymap* const modmap = XGetModifierMapping(display); @@ -355,15 +252,15 @@ BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) { // get the values of the keyboard lock modifiers // Note: Caps lock is not retrieved the same way as Scroll and Num lock // since it doesn't need to be. - const KeyCode num_lock_code = XKeysymToKeycode(display, XK_Num_Lock); - const KeyCode scroll_lock_code = XKeysymToKeycode(display, XK_Scroll_Lock); + const KeyCode num_lock = XKeysymToKeycode(display, XK_Num_Lock); + const KeyCode scroll_lock = XKeysymToKeycode(display, XK_Scroll_Lock); for (size_t cnt = 0; cnt < size; ++cnt) { if (! modmap->modifiermap[cnt]) continue; - if (num_lock_code == modmap->modifiermap[cnt]) + if (num_lock == modmap->modifiermap[cnt]) NumLockMask = mask_table[cnt / modmap->max_keypermod]; - if (scroll_lock_code == modmap->modifiermap[cnt]) + if (scroll_lock == modmap->modifiermap[cnt]) ScrollLockMask = mask_table[cnt / modmap->max_keypermod]; } } @@ -379,20 +276,13 @@ BaseDisplay::BaseDisplay(const char *app_name, char *dpy_name) { MaskListLength = sizeof(MaskList) / sizeof(MaskList[0]); if (modmap) XFreeModifiermap(const_cast(modmap)); -#else - NumLockMask = Mod2Mask; - ScrollLockMask = Mod5Mask; -#endif // NOCLOBBER + + gccache = 0; } BaseDisplay::~BaseDisplay(void) { - std::for_each(screenInfoList.begin(), screenInfoList.end(), - PointerAssassin()); - // we don't create the BTimers, we don't delete them - - if (application_name != NULL) - delete [] application_name; + delete gccache; XCloseDisplay(display); } @@ -401,24 +291,18 @@ BaseDisplay::~BaseDisplay(void) { void BaseDisplay::eventLoop(void) { run(); - int xfd = ConnectionNumber(display); + const int xfd = ConnectionNumber(display); - while ((! _shutdown) && (! internal_error)) { + while (run_state == RUNNING && ! internal_error) { if (XPending(display)) { XEvent e; XNextEvent(display, &e); - if (last_bad_window != None && e.xany.window == last_bad_window) { -#ifdef DEBUG - fprintf(stderr, i18n(BaseDisplaySet, - BaseDisplayBadWindowRemove, - "BaseDisplay::eventLoop(): removing bad window " - "from event queue\n")); -#endif // DEBUG - } else { - last_bad_window = None; - process_event(&e); - } + if (last_bad_window != None && e.xany.window == last_bad_window) + continue; + + last_bad_window = None; + process_event(&e); } else { fd_set rfds; timeval now, tm, *timeout = (timeval *) 0; @@ -426,33 +310,11 @@ void BaseDisplay::eventLoop(void) { FD_ZERO(&rfds); FD_SET(xfd, &rfds); - if (!timerList.empty()) { - gettimeofday(&now, 0); - - tm.tv_sec = tm.tv_usec = 0l; - - BTimer *timer = timerList.front(); - ASSERT(timer != NULL); + if (! timerList.empty()) { + const BTimer* const timer = timerList.top(); - tm.tv_sec = timer->getStartTime().tv_sec + - timer->getTimeout().tv_sec - now.tv_sec; - tm.tv_usec = timer->getStartTime().tv_usec + - timer->getTimeout().tv_usec - now.tv_usec; - - while (tm.tv_usec >= 1000000) { - tm.tv_sec++; - tm.tv_usec -= 1000000; - } - - while (tm.tv_usec < 0) { - if (tm.tv_sec > 0) { - tm.tv_sec--; - tm.tv_usec += 1000000; - } else { - tm.tv_usec = 0; - break; - } - } + gettimeofday(&now, 0); + tm = timer->timeRemaining(now); timeout = &tm; } @@ -462,105 +324,53 @@ void BaseDisplay::eventLoop(void) { // check for timer timeout gettimeofday(&now, 0); - TimerList::iterator it; - for (it = timerList.begin(); it != timerList.end(); ++it) { - BTimer *timer = *it; - ASSERT(timer != NULL); - - tm.tv_sec = timer->getStartTime().tv_sec + - timer->getTimeout().tv_sec; - tm.tv_usec = timer->getStartTime().tv_usec + - timer->getTimeout().tv_usec; - - if ((now.tv_sec < tm.tv_sec) || - (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec)) + // there is a small chance for deadlock here: + // *IF* the timer list keeps getting refreshed *AND* the time between + // timer->start() and timer->shouldFire() is within the timer's period + // then the timer will keep firing. This should be VERY near impossible. + while (! timerList.empty()) { + BTimer *timer = timerList.top(); + if (! timer->shouldFire(now)) break; - timer->fireTimeout(); + timerList.pop(); - // restart the current timer so that the start time is updated - if (! timer->doOnce()) { - // reorder - removeTimer(timer); - addTimer(timer); + timer->fireTimeout(); + timer->halt(); + if (timer->isRecurring()) timer->start(); - } else - timer->stop(); - it = timerList.begin(); // we no longer have any idea if the iterator is - // valid, but what was at the front() is no - // longer. } } } } -const Bool BaseDisplay::validateWindow(Window window) { - XEvent event; - if (XCheckTypedWindowEvent(display, window, DestroyNotify, &event)) { - XPutBackEvent(display, &event); - - return False; - } - - return True; -} - - -void BaseDisplay::grab(void) { - if (! server_grabs++) - XGrabServer(display); -} - - -void BaseDisplay::ungrab(void) { - if (! --server_grabs) - XUngrabServer(display); -} - - void BaseDisplay::addTimer(BTimer *timer) { - ASSERT(timer != (BTimer *) 0); - - TimerList::iterator it; - for (it = timerList.begin(); it != timerList.end(); ++it) { - BTimer *tmp = *it; - if ((tmp->getTimeout().tv_sec > timer->getTimeout().tv_sec) || - ((tmp->getTimeout().tv_sec == timer->getTimeout().tv_sec) && - (tmp->getTimeout().tv_usec >= timer->getTimeout().tv_usec))) - break; - } + if (! timer) return; - timerList.insert(it, timer); + timerList.push(timer); } void BaseDisplay::removeTimer(BTimer *timer) { - ASSERT(timer != (BTimer *) 0); - timerList.remove(timer); + timerList.release(timer); } /* - * Grabs a button, but also grabs the button in every possible combination with - * the keyboard lock keys, so that they do not cancel out the event. + * Grabs a button, but also grabs the button in every possible combination + * with the keyboard lock keys, so that they do not cancel out the event. */ void BaseDisplay::grabButton(unsigned int button, unsigned int modifiers, - Window grab_window, Bool owner_events, + Window grab_window, bool owner_events, unsigned int event_mask, int pointer_mode, - int keybaord_mode, Window confine_to, - Cursor cursor) const -{ -#ifndef NOCLOBBER - for (size_t cnt = 0; cnt < MaskListLength; ++cnt) + int keyboard_mode, Window confine_to, + Cursor cursor) const { + for (size_t cnt = 0; cnt < MaskListLength; ++cnt) { XGrabButton(display, button, modifiers | MaskList[cnt], grab_window, - owner_events, event_mask, pointer_mode, keybaord_mode, + owner_events, event_mask, pointer_mode, keyboard_mode, confine_to, cursor); -#else // NOCLOBBER - XGrabButton(display, button, modifiers, grab_window, - owner_events, event_mask, pointer_mode, keybaord_mode, - confine_to, cursor); -#endif // NOCLOBBER + } } /* @@ -569,26 +379,37 @@ void BaseDisplay::grabButton(unsigned int button, unsigned int modifiers, */ void BaseDisplay::ungrabButton(unsigned int button, unsigned int modifiers, Window grab_window) const { -#ifndef NOCLOBBER - for (size_t cnt = 0; cnt < MaskListLength; ++cnt) + for (size_t cnt = 0; cnt < MaskListLength; ++cnt) { XUngrabButton(display, button, modifiers | MaskList[cnt], grab_window); -#else // NOCLOBBER - XUngrabButton(display, button, modifiers, grab_window); -#endif // NOCLOBBER + } +} + + +const ScreenInfo* BaseDisplay::getScreenInfo(unsigned int s) const { + if (s < screenInfoList.size()) + return &screenInfoList[s]; + return (const ScreenInfo*) 0; } -ScreenInfo::ScreenInfo(BaseDisplay &d, int num) : basedisplay(d), -screen_number(num) +BGCCache *BaseDisplay::gcCache(void) const { + if (! gccache) gccache = new BGCCache(this); + return gccache; +} + - root_window = RootWindow(basedisplay.getXDisplay(), screen_number); - depth = DefaultDepth(basedisplay.getXDisplay(), screen_number); +ScreenInfo::ScreenInfo(BaseDisplay *d, unsigned int num) { + basedisplay = d; + screen_number = num; - m_size = Size(WidthOfScreen(ScreenOfDisplay(basedisplay.getXDisplay(), - screen_number)), - HeightOfScreen(ScreenOfDisplay(basedisplay.getXDisplay(), - screen_number))); + root_window = RootWindow(basedisplay->getXDisplay(), screen_number); + depth = DefaultDepth(basedisplay->getXDisplay(), screen_number); + + rect.setSize(WidthOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(), + screen_number)), + HeightOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(), + screen_number))); // search for a TrueColor Visual... if we can't find one... we will use the // default visual for the screen @@ -600,10 +421,10 @@ screen_number(num) visual = (Visual *) 0; - if ((vinfo_return = XGetVisualInfo(basedisplay.getXDisplay(), - VisualScreenMask | VisualClassMask, - &vinfo_template, &vinfo_nitems)) && - vinfo_nitems > 0) { + vinfo_return = XGetVisualInfo(basedisplay->getXDisplay(), + VisualScreenMask | VisualClassMask, + &vinfo_template, &vinfo_nitems); + if (vinfo_return && vinfo_nitems > 0) { for (int i = 0; i < vinfo_nitems; i++) { if (depth < (vinfo_return + i)->depth) { depth = (vinfo_return + i)->depth; @@ -615,10 +436,20 @@ screen_number(num) } if (visual) { - colormap = XCreateColormap(basedisplay.getXDisplay(), root_window, + colormap = XCreateColormap(basedisplay->getXDisplay(), root_window, visual, AllocNone); } else { - visual = DefaultVisual(basedisplay.getXDisplay(), screen_number); - colormap = DefaultColormap(basedisplay.getXDisplay(), screen_number); + visual = DefaultVisual(basedisplay->getXDisplay(), screen_number); + colormap = DefaultColormap(basedisplay->getXDisplay(), screen_number); } + + // get the default display string and strip the screen number + string default_string = DisplayString(basedisplay->getXDisplay()); + const string::size_type pos = default_string.rfind("."); + if (pos != string::npos) + default_string.resize(pos); + + std::ostringstream formatter; + formatter << "DISPLAY=" << default_string << '.' << screen_number; + display_string = formatter.str(); } diff --git a/src/BaseDisplay.h b/src/BaseDisplay.h deleted file mode 100644 index 8bd13e89..00000000 --- a/src/BaseDisplay.h +++ /dev/null @@ -1,367 +0,0 @@ -// BaseDisplay.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __BaseDisplay_hh -#define __BaseDisplay_hh - -#include -#include - -// forward declaration -class BaseDisplay; -class ScreenInfo; - -#include "Timer.h" -#include "Geometry.h" -#include "Util.h" -#include -#include - -#define AttribShaded (1l << 0) -#define AttribMaxHoriz (1l << 1) -#define AttribMaxVert (1l << 2) -#define AttribOmnipresent (1l << 3) -#define AttribWorkspace (1l << 4) -#define AttribStack (1l << 5) -#define AttribDecoration (1l << 6) - -#define StackTop (0) -#define StackNormal (1) -#define StackBottom (2) - -#define DecorNone (0) -#define DecorNormal (1) -#define DecorTiny (2) -#define DecorTool (3) - -typedef struct _openbox_hints { - unsigned long flags, attrib, workspace, stack, decoration; -} OpenboxHints; - -typedef struct _openbox_attributes { - unsigned long flags, attrib, workspace, stack, decoration; - int premax_x, premax_y; - unsigned int premax_w, premax_h; -} OpenboxAttributes; - -#define PropOpenboxHintsElements (5) -#define PropOpenboxAttributesElements (9) - -#ifndef __EMX__ -void bexec(const char *, char *); -#endif // !__EMX__ - -char *bstrdup(const char *); - -class BaseDisplay { -private: - struct cursor { - Cursor session, move, ll_angle, lr_angle, ul_angle, ur_angle; - } cursor; - - struct shape { - Bool extensions; - int event_basep, error_basep; - } shape; - -#ifndef NOCLOBBER - unsigned int MaskList[8]; - size_t MaskListLength; -#endif // NOCLOBBER - - Atom xa_wm_colormap_windows, xa_wm_protocols, xa_wm_state, - xa_wm_delete_window, xa_wm_take_focus, xa_wm_change_state, - motif_wm_hints; - - // NETAttributes - Atom openbox_attributes, openbox_change_attributes, openbox_hints; - - // NETStructureMessages - Atom openbox_structure_messages, openbox_notify_startup, - openbox_notify_window_add, openbox_notify_window_del, - openbox_notify_window_focus, openbox_notify_current_workspace, - openbox_notify_workspace_count, openbox_notify_window_raise, - openbox_notify_window_lower; - - // message_types for client -> wm messages - Atom openbox_change_workspace, openbox_change_window_focus, - openbox_cycle_window_focus; - -#ifdef NEWWMSPEC - - // root window properties - Atom net_supported, net_client_list, net_client_list_stacking, - net_number_of_desktops, net_desktop_geometry, net_desktop_viewport, - net_current_desktop, net_desktop_names, net_active_window, net_workarea, - net_supporting_wm_check, net_virtual_roots; - - // root window messages - Atom net_close_window, net_wm_moveresize; - - // application window properties - Atom net_properties, net_wm_name, net_wm_desktop, net_wm_window_type, - net_wm_state, net_wm_strut, net_wm_icon_geometry, net_wm_icon, net_wm_pid, - net_wm_handled_icons; - - // application protocols - Atom net_wm_ping; - -#endif // NEWWMSPEC - - Bool _startup, _shutdown; - Display *display; - - typedef std::vector ScreenInfoList; - ScreenInfoList screenInfoList; - - typedef std::list TimerList; - TimerList timerList; - - char *display_name, *application_name; - unsigned int server_grabs, colors_per_channel; - - -protected: - // pure virtual function... you must override this - virtual void process_event(XEvent *) = 0; - - // the masks of the modifiers which are ignored in button events. - int NumLockMask, ScrollLockMask; - - -public: - BaseDisplay(const char *, char * = 0); - virtual ~BaseDisplay(); - - inline const Atom &getWMChangeStateAtom() const - { return xa_wm_change_state; } - inline const Atom &getWMStateAtom() const - { return xa_wm_state; } - inline const Atom &getWMDeleteAtom() const - { return xa_wm_delete_window; } - inline const Atom &getWMProtocolsAtom() const - { return xa_wm_protocols; } - inline const Atom &getWMTakeFocusAtom() const - { return xa_wm_take_focus; } - inline const Atom &getWMColormapAtom() const - { return xa_wm_colormap_windows; } - inline const Atom &getMotifWMHintsAtom() const - { return motif_wm_hints; } - - // this atom is for normal app->WM hints about decorations, stacking, - // starting workspace etc... - inline const Atom &getOpenboxHintsAtom() const - { return openbox_hints;} - - // these atoms are for normal app->WM interaction beyond the scope of the - // ICCCM... - inline const Atom &getOpenboxAttributesAtom() const - { return openbox_attributes; } - inline const Atom &getOpenboxChangeAttributesAtom() const - { return openbox_change_attributes; } - - // these atoms are for window->WM interaction, with more control and - // information on window "structure"... common examples are - // notifying apps when windows are raised/lowered... when the user changes - // workspaces... i.e. "pager talk" - inline const Atom &getOpenboxStructureMessagesAtom() const - { return openbox_structure_messages; } - - // *Notify* portions of the NETStructureMessages protocol - inline const Atom &getOpenboxNotifyStartupAtom() const - { return openbox_notify_startup; } - inline const Atom &getOpenboxNotifyWindowAddAtom() const - { return openbox_notify_window_add; } - inline const Atom &getOpenboxNotifyWindowDelAtom() const - { return openbox_notify_window_del; } - inline const Atom &getOpenboxNotifyWindowFocusAtom() const - { return openbox_notify_window_focus; } - inline const Atom &getOpenboxNotifyCurrentWorkspaceAtom() const - { return openbox_notify_current_workspace; } - inline const Atom &getOpenboxNotifyWorkspaceCountAtom() const - { return openbox_notify_workspace_count; } - inline const Atom &getOpenboxNotifyWindowRaiseAtom() const - { return openbox_notify_window_raise; } - inline const Atom &getOpenboxNotifyWindowLowerAtom() const - { return openbox_notify_window_lower; } - - // atoms to change that request changes to the desktop environment during - // runtime... these messages can be sent by any client... as the sending - // client window id is not included in the ClientMessage event... - inline const Atom &getOpenboxChangeWorkspaceAtom() const - { return openbox_change_workspace; } - inline const Atom &getOpenboxChangeWindowFocusAtom() const - { return openbox_change_window_focus; } - inline const Atom &getOpenboxCycleWindowFocusAtom() const - { return openbox_cycle_window_focus; } - -#ifdef NEWWMSPEC - - // root window properties - inline const Atom &getNETSupportedAtom() const - { return net_supported; } - inline const Atom &getNETClientListAtom() const - { return net_client_list; } - inline const Atom &getNETClientListStackingAtom() const - { return net_client_list_stacking; } - inline const Atom &getNETNumberOfDesktopsAtom() const - { return net_number_of_desktops; } - inline const Atom &getNETDesktopGeometryAtom() const - { return net_desktop_geometry; } - inline const Atom &getNETDesktopViewportAtom() const - { return net_desktop_viewport; } - inline const Atom &getNETCurrentDesktopAtom() const - { return net_current_desktop; } - inline const Atom &getNETDesktopNamesAtom() const - { return net_desktop_names; } - inline const Atom &getNETActiveWindowAtom() const - { return net_active_window; } - inline const Atom &getNETWorkareaAtom() const - { return net_workarea; } - inline const Atom &getNETSupportingWMCheckAtom() const - { return net_supporting_wm_check; } - inline const Atom &getNETVirtualRootsAtom() const - { return net_virtual_roots; } - - // root window messages - inline const Atom &getNETCloseWindowAtom() const - { return net_close_window; } - inline const Atom &getNETWMMoveResizeAtom() const - { return net_wm_moveresize; } - - // application window properties - inline const Atom &getNETPropertiesAtom() const - { return net_properties; } - inline const Atom &getNETWMNameAtom() const - { return net_wm_name; } - inline const Atom &getNETWMDesktopAtom() const - { return net_wm_desktop; } - inline const Atom &getNETWMWindowTypeAtom() const - { return net_wm_window_type; } - inline const Atom &getNETWMStateAtom() const - { return net_wm_state; } - inline const Atom &getNETWMStrutAtom() const - { return net_wm_strut; } - inline const Atom &getNETWMIconGeometryAtom() const - { return net_wm_icon_geometry; } - inline const Atom &getNETWMIconAtom() const - { return net_wm_icon; } - inline const Atom &getNETWMPidAtom() const - { return net_wm_pid; } - inline const Atom &getNETWMHandledIconsAtom() const - { return net_wm_handled_icons; } - - // application protocols - inline const Atom &getNETWMPingAtom() const - { return net_wm_ping; } - -#endif // NEWWMSPEC - - inline ScreenInfo *getScreenInfo(unsigned int s) { - ASSERT(s < screenInfoList.size()); - return screenInfoList[s]; - } - - inline const Bool &hasShapeExtensions() const - { return shape.extensions; } - inline const Bool &doShutdown() const - { return _shutdown; } - inline const Bool &isStartup() const - { return _startup; } - - inline const Cursor &getSessionCursor() const - { return cursor.session; } - inline const Cursor &getMoveCursor() const - { return cursor.move; } - inline const Cursor &getLowerLeftAngleCursor() const - { return cursor.ll_angle; } - inline const Cursor &getLowerRightAngleCursor() const - { return cursor.lr_angle; } - inline const Cursor &getUpperLeftAngleCursor() const - { return cursor.ul_angle; } - inline const Cursor &getUpperRightAngleCursor() const - { return cursor.ur_angle; } - - inline Display *getXDisplay() { return display; } - - inline const char *getXDisplayName() const - { return (const char *) display_name; } - inline const char *getApplicationName() const - { return (const char *) application_name; } - - inline const unsigned int numberOfScreens() const - { return ScreenCount(display); } - inline const int &getShapeEventBase() const - { return shape.event_basep; } - - inline void shutdown() { _shutdown = True; } - inline void run() { _startup = _shutdown = False; } - - const Bool validateWindow(Window); - - void grabButton(unsigned int, unsigned int, Window, Bool, unsigned int, int, - int, Window, Cursor) const; - void ungrabButton(unsigned int button, unsigned int modifiers, - Window grab_window) const; - - void grab(); - void ungrab(); - void eventLoop(); - void addTimer(BTimer *); - void removeTimer(BTimer *); - - // another pure virtual... this is used to handle signals that BaseDisplay - // doesn't understand itself - virtual Bool handleSignal(int) = 0; -}; - - -class ScreenInfo { -private: - BaseDisplay &basedisplay; - Visual *visual; - Window root_window; - Colormap colormap; - - int depth, screen_number; - Size m_size; - - -public: - ScreenInfo(BaseDisplay &, int); - - inline BaseDisplay &getBaseDisplay() { return basedisplay; } - - inline Visual *getVisual() const { return visual; } - inline const Window &getRootWindow() const { return root_window; } - inline const Colormap &getColormap() const { return colormap; } - - inline const int &getDepth() const { return depth; } - inline const int &getScreenNumber() const { return screen_number; } - -// inline const unsigned int &getWidth() const { return width; } -// inline const unsigned int &getHeight() const { return height; } - inline const Size &size() const { return m_size; } -}; - - -#endif // __BaseDisplay_hh diff --git a/src/BaseDisplay.hh b/src/BaseDisplay.hh new file mode 100644 index 00000000..7a6251da --- /dev/null +++ b/src/BaseDisplay.hh @@ -0,0 +1,156 @@ +// -*- mode: C++; indent-tabs-mode: nil; -*- +// BaseDisplay.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef __BaseDisplay_hh +#define __BaseDisplay_hh + +extern "C" { +#include +#include +} + +#include +#include + +// forward declaration +class BaseDisplay; +class BGCCache; + +#include "Timer.hh" +#include "Util.hh" + +class ScreenInfo { +private: + BaseDisplay *basedisplay; + Visual *visual; + Window root_window; + Colormap colormap; + + int depth; + unsigned int screen_number; + std::string display_string; + Rect rect; + +public: + ScreenInfo(BaseDisplay *d, unsigned int num); + + inline BaseDisplay *getBaseDisplay(void) const { return basedisplay; } + inline Visual *getVisual(void) const { return visual; } + inline Window getRootWindow(void) const { return root_window; } + inline Colormap getColormap(void) const { return colormap; } + inline int getDepth(void) const { return depth; } + inline unsigned int getScreenNumber(void) const + { return screen_number; } + inline const Rect& getRect(void) const { return rect; } + inline unsigned int getWidth(void) const { return rect.width(); } + inline unsigned int getHeight(void) const { return rect.height(); } + inline const std::string& displayString(void) const + { return display_string; } +}; + + +class BaseDisplay: public TimerQueueManager { +private: + struct BShape { + bool extensions; + int event_basep, error_basep; + }; + BShape shape; + + unsigned int MaskList[8]; + size_t MaskListLength; + + enum RunState { STARTUP, RUNNING, SHUTDOWN }; + RunState run_state; + + Display *display; + mutable BGCCache *gccache; + + typedef std::vector ScreenInfoList; + ScreenInfoList screenInfoList; + TimerQueue timerList; + + const char *display_name, *application_name; + + // no copying! + BaseDisplay(const BaseDisplay &); + BaseDisplay& operator=(const BaseDisplay&); + +protected: + // pure virtual function... you must override this + virtual void process_event(XEvent *e) = 0; + + // the masks of the modifiers which are ignored in button events. + int NumLockMask, ScrollLockMask; + + +public: + BaseDisplay(const char *app_name, const char *dpy_name = 0); + virtual ~BaseDisplay(void); + + const ScreenInfo* getScreenInfo(const unsigned int s) const; + + BGCCache *gcCache(void) const; + + inline bool hasShapeExtensions(void) const + { return shape.extensions; } + inline bool doShutdown(void) const + { return run_state == SHUTDOWN; } + inline bool isStartup(void) const + { return run_state == STARTUP; } + + inline Display *getXDisplay(void) const { return display; } + + inline const char *getXDisplayName(void) const + { return display_name; } + inline const char *getApplicationName(void) const + { return application_name; } + + inline unsigned int getNumberOfScreens(void) const + { return screenInfoList.size(); } + inline int getShapeEventBase(void) const + { return shape.event_basep; } + + inline void shutdown(void) { run_state = SHUTDOWN; } + inline void run(void) { run_state = RUNNING; } + + void grabButton(unsigned int button, unsigned int modifiers, + Window grab_window, bool owner_events, + unsigned int event_mask, int pointer_mode, + int keyboard_mode, Window confine_to, Cursor cursor) const; + void ungrabButton(unsigned int button, unsigned int modifiers, + Window grab_window) const; + + void eventLoop(void); + + // from TimerQueueManager interface + virtual void addTimer(BTimer *timer); + virtual void removeTimer(BTimer *timer); + + // another pure virtual... this is used to handle signals that BaseDisplay + // doesn't understand itself + virtual bool handleSignal(int sig) = 0; +}; + + +#endif // __BaseDisplay_hh diff --git a/src/Basemenu.cc b/src/Basemenu.cc index c3052826..fa2f4b00 100644 --- a/src/Basemenu.cc +++ b/src/Basemenu.cc @@ -1,5 +1,6 @@ -// Basemenu.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Basemenu.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,42 +21,43 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H +extern "C" { #ifdef HAVE_STDIO_H # include #endif // HAVE_STDIO_H -#ifdef HAVE_STDLIB_H +#ifdef HAVE_STDLIB_H # include #endif // HAVE_STDLIB_H -#ifdef HAVE_STRING_H +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H +} #include -using std::min; -using std::max; +using namespace std; + +#include "i18n.hh" +#include "blackbox.hh" +#include "Basemenu.hh" +#include "GCCache.hh" +#include "Image.hh" +#include "Screen.hh" +#include "Util.hh" -#include "i18n.h" -#include "openbox.h" -#include "Basemenu.h" -#include "Screen.h" static Basemenu *shown = (Basemenu *) 0; -Basemenu::Basemenu(BScreen &scrn) : openbox(scrn.getOpenbox()), screen(scrn) { - image_ctrl = screen.getImageControl(); - display = openbox.getXDisplay(); +Basemenu::Basemenu(BScreen *scrn) { + screen = scrn; + blackbox = screen->getBlackbox(); + image_ctrl = screen->getImageControl(); + display = blackbox->getXDisplay(); parent = (Basemenu *) 0; alignment = AlignDontCare; @@ -85,24 +87,22 @@ Basemenu::Basemenu(BScreen &scrn) : openbox(scrn.getOpenbox()), screen(scrn) { menu.hilite_pixmap = menu.sel_pixmap = None; - menu.bevel_w = screen.getBevelWidth(); + menu.bevel_w = screen->getBevelWidth(); if (i18n.multibyte()) menu.width = menu.title_h = menu.item_w = menu.frame_h = - screen.getMenuStyle()->t_fontset_extents->max_ink_extent.height + + screen->getMenuStyle()->t_fontset_extents->max_ink_extent.height + (menu.bevel_w * 2); else menu.width = menu.title_h = menu.item_w = menu.frame_h = - screen.getMenuStyle()->t_font->ascent + - screen.getMenuStyle()->t_font->descent + (menu.bevel_w * 2); - - menu.label = 0; + screen->getMenuStyle()->t_font->ascent + + screen->getMenuStyle()->t_font->descent + (menu.bevel_w * 2); menu.sublevels = menu.persub = menu.minsub = 0; - MenuStyle *style = screen.getMenuStyle(); + MenuStyle *style = screen->getMenuStyle(); if (i18n.multibyte()) { menu.item_h = style->f_fontset_extents->max_ink_extent.height + (menu.bevel_w); @@ -111,59 +111,71 @@ Basemenu::Basemenu(BScreen &scrn) : openbox(scrn.getOpenbox()), screen(scrn) { (menu.bevel_w); } - menu.height = menu.title_h + screen.getBorderWidth() + menu.frame_h; + menu.height = menu.title_h + screen->getBorderWidth() + menu.frame_h; unsigned long attrib_mask = CWBackPixmap | CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask; XSetWindowAttributes attrib; attrib.background_pixmap = None; attrib.background_pixel = attrib.border_pixel = - screen.getBorderColor()->getPixel(); - attrib.colormap = screen.getColormap(); + screen->getBorderColor()->pixel(); + attrib.colormap = screen->getColormap(); attrib.override_redirect = True; attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | ExposureMask; menu.window = - XCreateWindow(display, screen.getRootWindow(), menu.x, menu.y, menu.width, - menu.height, screen.getBorderWidth(), screen.getDepth(), - InputOutput, screen.getVisual(), attrib_mask, &attrib); - openbox.saveMenuSearch(menu.window, this); + XCreateWindow(display, screen->getRootWindow(), + menu.x, menu.y, menu.width, menu.height, + screen->getBorderWidth(), screen->getDepth(), + InputOutput, screen->getVisual(), attrib_mask, &attrib); + blackbox->saveMenuSearch(menu.window, this); attrib_mask = CWBackPixmap | CWBackPixel | CWBorderPixel | CWEventMask; - attrib.background_pixel = screen.getBorderColor()->getPixel(); + attrib.background_pixel = screen->getBorderColor()->pixel(); attrib.event_mask |= EnterWindowMask | LeaveWindowMask; menu.title = XCreateWindow(display, menu.window, 0, 0, menu.width, menu.height, 0, - screen.getDepth(), InputOutput, screen.getVisual(), + screen->getDepth(), InputOutput, screen->getVisual(), attrib_mask, &attrib); - openbox.saveMenuSearch(menu.title, this); + blackbox->saveMenuSearch(menu.title, this); attrib.event_mask |= PointerMotionMask; menu.frame = XCreateWindow(display, menu.window, 0, - menu.title_h + screen.getBorderWidth(), + menu.title_h + screen->getBorderWidth(), menu.width, menu.frame_h, 0, - screen.getDepth(), InputOutput, - screen.getVisual(), attrib_mask, &attrib); - openbox.saveMenuSearch(menu.frame, this); + screen->getDepth(), InputOutput, + screen->getVisual(), attrib_mask, &attrib); + blackbox->saveMenuSearch(menu.frame, this); // even though this is the end of the constructor the menu is still not // completely created. items must be inserted and it must be update()'d } - Basemenu::~Basemenu(void) { XUnmapWindow(display, menu.window); if (shown && shown->getWindowID() == getWindowID()) shown = (Basemenu *) 0; - while (!menuitems.empty()) - remove(0); + MenuItems::const_iterator it = menuitems.begin(); + while (it != menuitems.end()) { + BasemenuItem *item = *it; + if ((! internal_menu)) { + Basemenu *tmp = (Basemenu *) item->submenu(); + if (tmp) { + if (! tmp->internal_menu) { + delete tmp; + } else { + tmp->internal_hide(); + } + } + } + ++it; + } - if (menu.label) - delete [] menu.label; + std::for_each(menuitems.begin(), menuitems.end(), PointerAssassin()); if (menu.title_pixmap) image_ctrl->removeImage(menu.title_pixmap); @@ -177,98 +189,84 @@ Basemenu::~Basemenu(void) { if (menu.sel_pixmap) image_ctrl->removeImage(menu.sel_pixmap); - openbox.removeMenuSearch(menu.title); + blackbox->removeMenuSearch(menu.title); XDestroyWindow(display, menu.title); - openbox.removeMenuSearch(menu.frame); + blackbox->removeMenuSearch(menu.frame); XDestroyWindow(display, menu.frame); - openbox.removeMenuSearch(menu.window); + blackbox->removeMenuSearch(menu.window); XDestroyWindow(display, menu.window); } -int Basemenu::insert(const char *l, int function, const char *e, int pos) { - char *label = 0, *exec = 0; +BasemenuItem::~BasemenuItem(void) {} - if (l) label = bstrdup(l); - if (e) exec = bstrdup(e); - BasemenuItem *item = new BasemenuItem(label, function, exec); - if (pos == -1) - menuitems.push_back(item); - else - menuitems.insert(menuitems.begin() + pos, item); +BasemenuItem *Basemenu::find(int index) { + if (index < 0 || index > static_cast(menuitems.size())) + return (BasemenuItem*) 0; - return menuitems.size(); + return *(menuitems.begin() + index); } -int Basemenu::insert(const char *l, Basemenu *submenu, int pos) { - char *label = 0; - - if (l) label = bstrdup(l); - - BasemenuItem *item = new BasemenuItem(label, submenu); - if (pos == -1) +int Basemenu::insert(BasemenuItem *item, int pos) { + if (pos < 0) { menuitems.push_back(item); - else - menuitems.insert(menuitems.begin() + pos, item); + } else { + assert(pos < static_cast(menuitems.size())); + menuitems.insert((menuitems.begin() + pos), item); + } + return menuitems.size(); +} - submenu->parent = this; - return menuitems.size(); +int Basemenu::insert(const string& label, int function, + const string& exec, int pos) { + BasemenuItem *item = new BasemenuItem(label, function, exec); + return insert(item, pos); } -int Basemenu::insert(const char **ulabel, int pos, int function) { - BasemenuItem *item = new BasemenuItem(ulabel, function); - if (pos == -1) - menuitems.push_back(item); - else - menuitems.insert(menuitems.begin() + pos, item); +int Basemenu::insert(const string& label, Basemenu *submenu, int pos) { + BasemenuItem *item = new BasemenuItem(label, submenu); + submenu->parent = this; - return menuitems.size(); + return insert(item, pos); } int Basemenu::remove(int index) { - if (index < 0 || index > (signed)menuitems.size()) return -1; - - BasemenuItem *item = menuitems[index]; - menuitems.erase(menuitems.begin() + index); - - if (item) { - if ((!internal_menu) && (item->submenu())) { - Basemenu *tmp = (Basemenu *) item->submenu(); + BasemenuItem *item = find(index); + if (! item) return -1; + if ((! internal_menu)) { + Basemenu *tmp = (Basemenu *) item->submenu(); + if (tmp) { if (! tmp->internal_menu) { delete tmp; } else { tmp->internal_hide(); } } - - if (item->label()) - delete [] item->label(); - - if (item->exec()) - delete [] item->exec(); - - delete item; } + delete item; + if (which_sub == index) which_sub = -1; else if (which_sub > index) which_sub--; + menuitems.erase(menuitems.begin() + index); + return menuitems.size(); } void Basemenu::update(void) { - MenuStyle *style = screen.getMenuStyle(); + MenuStyle *style = screen->getMenuStyle(); if (i18n.multibyte()) { menu.item_h = style->f_fontset_extents->max_ink_extent.height + menu.bevel_w; @@ -282,18 +280,15 @@ void Basemenu::update(void) { } if (title_vis) { - const char *s = (menu.label) ? menu.label : - i18n(BasemenuSet, BasemenuOpenboxMenu, - "Openbox Menu"); + const char *s = getLabel(); int l = strlen(s); - if (i18n.multibyte()) { XRectangle ink, logical; - XmbTextExtents(screen.getMenuStyle()->t_fontset, s, l, &ink, &logical); + XmbTextExtents(screen->getMenuStyle()->t_fontset, s, l, &ink, &logical); menu.item_w = logical.width; } else { - menu.item_w = XTextWidth(screen.getMenuStyle()->t_font, s, l); + menu.item_w = XTextWidth(screen->getMenuStyle()->t_font, s, l); } menu.item_w += (menu.bevel_w * 2); @@ -301,37 +296,38 @@ void Basemenu::update(void) { menu.item_w = 1; } - int ii = 0; - menuitemList::const_iterator it = menuitems.begin(); - for (; it != menuitems.end(); it++) { - const char *s = (((*it)->u && *(*it)->u) ? *(*it)->u : - (((*it)->l) ? (*it)->l : (const char *) 0)); + unsigned int ii = 0; + MenuItems::iterator it = menuitems.begin(), end = menuitems.end(); + for (; it != end; ++it) { + BasemenuItem *tmp = *it; + const char *s = tmp->l.c_str(); int l = strlen(s); if (i18n.multibyte()) { XRectangle ink, logical; - XmbTextExtents(screen.getMenuStyle()->f_fontset, s, l, &ink, &logical); + XmbTextExtents(screen->getMenuStyle()->f_fontset, s, l, &ink, &logical); ii = logical.width; } else - ii = XTextWidth(screen.getMenuStyle()->f_font, s, l); + ii = XTextWidth(screen->getMenuStyle()->f_font, s, l); ii += (menu.bevel_w * 2) + (menu.item_h * 2); - menu.item_w = ((menu.item_w < (unsigned int) ii) ? ii : menu.item_w); + menu.item_w = ((menu.item_w < ii) ? ii : menu.item_w); } - if (menuitems.size()) { + if (! menuitems.empty()) { menu.sublevels = 1; - while (((menu.item_h * (menuitems.size() + 1) / menu.sublevels) - + menu.title_h + screen.getBorderWidth()) > - screen.size().h()) + unsigned int menu_size = menuitems.size(); + while (((menu.item_h * (menu_size + 1) / menu.sublevels) + + menu.title_h + screen->getBorderWidth()) > + screen->getHeight()) menu.sublevels++; if (menu.sublevels < menu.minsub) menu.sublevels = menu.minsub; - menu.persub = menuitems.size() / menu.sublevels; - if (menuitems.size() % menu.sublevels) menu.persub++; + menu.persub = menu_size / menu.sublevels; + if (menu_size % menu.sublevels) menu.persub++; } else { menu.sublevels = 0; menu.persub = 0; @@ -341,7 +337,7 @@ void Basemenu::update(void) { if (! menu.width) menu.width = menu.item_w; menu.frame_h = (menu.item_h * menu.persub); - menu.height = ((title_vis) ? menu.title_h + screen.getBorderWidth() : 0) + + menu.height = ((title_vis) ? menu.title_h + screen->getBorderWidth() : 0) + menu.frame_h; if (! menu.frame_h) menu.frame_h = 1; if (menu.height < 1) menu.height = 1; @@ -350,14 +346,14 @@ void Basemenu::update(void) { BTexture *texture; if (title_vis) { tmp = menu.title_pixmap; - texture = &(screen.getMenuStyle()->title); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { + texture = &(screen->getMenuStyle()->title); + if (texture->texture() == (BTexture::Flat | BTexture::Solid)) { menu.title_pixmap = None; XSetWindowBackground(display, menu.title, - texture->getColor()->getPixel()); + texture->color().pixel()); } else { menu.title_pixmap = - image_ctrl->renderImage(menu.width, menu.title_h, texture); + image_ctrl->renderImage(menu.width, menu.title_h, *texture); XSetWindowBackgroundPixmap(display, menu.title, menu.title_pixmap); } if (tmp) image_ctrl->removeImage(tmp); @@ -365,35 +361,35 @@ void Basemenu::update(void) { } tmp = menu.frame_pixmap; - texture = &(screen.getMenuStyle()->frame); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { + texture = &(screen->getMenuStyle()->frame); + if (texture->texture() == (BTexture::Flat | BTexture::Solid)) { menu.frame_pixmap = None; XSetWindowBackground(display, menu.frame, - texture->getColor()->getPixel()); + texture->color().pixel()); } else { menu.frame_pixmap = - image_ctrl->renderImage(menu.width, menu.frame_h, texture); + image_ctrl->renderImage(menu.width, menu.frame_h, *texture); XSetWindowBackgroundPixmap(display, menu.frame, menu.frame_pixmap); } if (tmp) image_ctrl->removeImage(tmp); tmp = menu.hilite_pixmap; - texture = &(screen.getMenuStyle()->hilite); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { + texture = &(screen->getMenuStyle()->hilite); + if (texture->texture() == (BTexture::Flat | BTexture::Solid)) { menu.hilite_pixmap = None; } else { menu.hilite_pixmap = - image_ctrl->renderImage(menu.item_w, menu.item_h, texture); + image_ctrl->renderImage(menu.item_w, menu.item_h, *texture); } if (tmp) image_ctrl->removeImage(tmp); tmp = menu.sel_pixmap; - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { + if (texture->texture() == (BTexture::Flat | BTexture::Solid)) { menu.sel_pixmap = None; } else { int hw = menu.item_h / 2; menu.sel_pixmap = - image_ctrl->renderImage(hw, hw, texture); + image_ctrl->renderImage(hw, hw, *texture); } if (tmp) image_ctrl->removeImage(tmp); @@ -404,7 +400,7 @@ void Basemenu::update(void) { XMoveResizeWindow(display, menu.frame, 0, ((title_vis) ? menu.title_h + - screen.getBorderWidth() : 0), menu.width, + screen->getBorderWidth() : 0), menu.width, menu.frame_h); XClearWindow(display, menu.window); @@ -413,7 +409,8 @@ void Basemenu::update(void) { if (title_vis && visible) redrawTitle(); - for (int i = 0; visible && i < (signed)menuitems.size(); i++) { + const int menu_size = menuitems.size(); + for (int i = 0; visible && i < menu_size; i++) { if (i == which_sub) { drawItem(i, True, 0); drawSubmenu(i); @@ -456,10 +453,9 @@ void Basemenu::hide(void) { void Basemenu::internal_hide(void) { - if (which_sub != -1) { - BasemenuItem *tmp = menuitems[which_sub]; + BasemenuItem *tmp = find(which_sub); + if (tmp) tmp->submenu()->internal_hide(); - } if (parent && (! torn)) { parent->drawItem(parent->which_sub, False, True); @@ -486,154 +482,156 @@ void Basemenu::move(int x, int y) { void Basemenu::redrawTitle(void) { - char *text = (char *) ((menu.label) ? menu.label : - i18n(BasemenuSet, BasemenuOpenboxMenu, - "Openbox Menu")); + const char *text = (! menu.label.empty()) ? getLabel() : + i18n(BasemenuSet, BasemenuBlackboxMenu, "Blackbox Menu"); int dx = menu.bevel_w, len = strlen(text); unsigned int l; if (i18n.multibyte()) { XRectangle ink, logical; - XmbTextExtents(screen.getMenuStyle()->t_fontset, text, len, &ink, &logical); + XmbTextExtents(screen->getMenuStyle()->t_fontset, text, len, + &ink, &logical); l = logical.width; } else { - l = XTextWidth(screen.getMenuStyle()->t_font, text, len); + l = XTextWidth(screen->getMenuStyle()->t_font, text, len); } l += (menu.bevel_w * 2); - switch (screen.getMenuStyle()->t_justify) { - case BScreen::RightJustify: + switch (screen->getMenuStyle()->t_justify) { + case RightJustify: dx += menu.width - l; break; - case BScreen::CenterJustify: + case CenterJustify: dx += (menu.width - l) / 2; break; + + case LeftJustify: + default: + break; } - MenuStyle *style = screen.getMenuStyle(); + MenuStyle *style = screen->getMenuStyle(); + BPen pen(style->t_text, style->t_font); if (i18n.multibyte()) - XmbDrawString(display, menu.title, style->t_fontset, style->t_text_gc, dx, + XmbDrawString(display, menu.title, style->t_fontset, pen.gc(), dx, (menu.bevel_w - style->t_fontset_extents->max_ink_extent.y), text, len); else - XDrawString(display, menu.title, style->t_text_gc, dx, + XDrawString(display, menu.title, pen.gc(), dx, (style->t_font->ascent + menu.bevel_w), text, len); } void Basemenu::drawSubmenu(int index) { - if (which_sub != -1 && which_sub != index) { - BasemenuItem *itmp = menuitems[which_sub]; + BasemenuItem *item = find(which_sub); + if (item && item->submenu() && ! item->submenu()->isTorn() && + which_sub != index) + item->submenu()->internal_hide(); + + item = find(index); + if (! item) + return; + Basemenu *submenu = item->submenu(); + + if (submenu && visible && ! submenu->isTorn() && item->isEnabled()) { + if (submenu->parent != this) submenu->parent = this; + int sbl = index / menu.persub, i = index - (sbl * menu.persub), + x = menu.x + ((menu.item_w * (sbl + 1)) + screen->getBorderWidth()), y; + + if (alignment == AlignTop) { + y = (((shifted) ? menu.y_shift : menu.y) + + ((title_vis) ? menu.title_h + screen->getBorderWidth() : 0) - + ((submenu->title_vis) ? + submenu->menu.title_h + screen->getBorderWidth() : 0)); + } else { + y = (((shifted) ? menu.y_shift : menu.y) + + (menu.item_h * i) + + ((title_vis) ? menu.title_h + screen->getBorderWidth() : 0) - + ((submenu->title_vis) ? + submenu->menu.title_h + screen->getBorderWidth() : 0)); + } - if (! itmp->submenu()->isTorn()) - itmp->submenu()->internal_hide(); - } + if (alignment == AlignBottom && + (y + submenu->menu.height) > ((shifted) ? menu.y_shift : + menu.y) + menu.height) + y = (((shifted) ? menu.y_shift : menu.y) + + menu.height - submenu->menu.height); - if (index >= 0 && index < (signed)menuitems.size()) { - BasemenuItem *item = menuitems[index]; - if (item->submenu() && visible && (! item->submenu()->isTorn()) && - item->isEnabled()) { - if (item->submenu()->parent != this) item->submenu()->parent = this; - int sbl = index / menu.persub, i = index - (sbl * menu.persub), - x = menu.x + - ((menu.item_w * (sbl + 1)) + screen.getBorderWidth()), y; - - if (alignment == AlignTop) - y = (((shifted) ? menu.y_shift : menu.y) + - ((title_vis) ? menu.title_h + screen.getBorderWidth() : 0) - - ((item->submenu()->title_vis) ? - item->submenu()->menu.title_h + screen.getBorderWidth() : 0)); - else - y = (((shifted) ? menu.y_shift : menu.y) + - (menu.item_h * i) + - ((title_vis) ? menu.title_h + screen.getBorderWidth() : 0) - - ((item->submenu()->title_vis) ? - item->submenu()->menu.title_h + screen.getBorderWidth() : 0)); - - if (alignment == AlignBottom && - (y + item->submenu()->menu.height) > ((shifted) ? menu.y_shift : - menu.y) + menu.height) - y = (((shifted) ? menu.y_shift : menu.y) + - menu.height - item->submenu()->menu.height); - - if ((x + item->submenu()->getWidth()) > screen.size().w()) { - x = ((shifted) ? menu.x_shift : menu.x) - - item->submenu()->getWidth() - screen.getBorderWidth(); - } + if ((x + submenu->getWidth()) > screen->getWidth()) + x = ((shifted) ? menu.x_shift : menu.x) - + submenu->getWidth() - screen->getBorderWidth(); - if (x < 0) x = 0; + if (x < 0) x = 0; - if ((y + item->submenu()->getHeight()) > screen.size().h()) - y = screen.size().h() - item->submenu()->getHeight() - - (screen.getBorderWidth() * 2); - if (y < 0) y = 0; + if ((y + submenu->getHeight()) > screen->getHeight()) + y = screen->getHeight() - submenu->getHeight() - + (screen->getBorderWidth() * 2); + if (y < 0) y = 0; - item->submenu()->move(x, y); - if (! moving) drawItem(index, True); + submenu->move(x, y); + if (! moving) drawItem(index, True); - if (! item->submenu()->isVisible()) - item->submenu()->show(); - item->submenu()->moving = moving; - which_sub = index; - } else { - which_sub = -1; - } + if (! submenu->isVisible()) + submenu->show(); + submenu->moving = moving; + which_sub = index; + } else { + which_sub = -1; } } bool Basemenu::hasSubmenu(int index) { - if (index < 0 | index >= (signed)menuitems.size()) - return false; - return (menuitems[index]->submenu()); + BasemenuItem *item = find(index); + if (item && item->submenu()) + return True; + return False; } -void Basemenu::drawItem(int index, Bool highlight, Bool clear, +void Basemenu::drawItem(int index, bool highlight, bool clear, int x, int y, unsigned int w, unsigned int h) { - if (index < 0 || index > (signed)menuitems.size()) return; - - BasemenuItem *item = menuitems[index]; + BasemenuItem *item = find(index); if (! item) return; - Bool dotext = True, dohilite = True, dosel = True; - const char *text = (item->ulabel()) ? *item->ulabel() : item->label(); + bool dotext = True, dohilite = True, dosel = True; + const char *text = item->label(); int sbl = index / menu.persub, i = index - (sbl * menu.persub); int item_x = (sbl * menu.item_w), item_y = (i * menu.item_h); int hilite_x = item_x, hilite_y = item_y, hoff_x = 0, hoff_y = 0; int text_x = 0, text_y = 0, len = strlen(text), sel_x = 0, sel_y = 0; unsigned int hilite_w = menu.item_w, hilite_h = menu.item_h, text_w = 0, - text_h = 0; + text_h = 0; unsigned int half_w = menu.item_h / 2, quarter_w = menu.item_h / 4; if (text) { if (i18n.multibyte()) { XRectangle ink, logical; - XmbTextExtents(screen.getMenuStyle()->f_fontset, + XmbTextExtents(screen->getMenuStyle()->f_fontset, text, len, &ink, &logical); text_w = logical.width; text_y = item_y + (menu.bevel_w / 2) - - screen.getMenuStyle()->f_fontset_extents->max_ink_extent.y; + screen->getMenuStyle()->f_fontset_extents->max_ink_extent.y; } else { - text_w = XTextWidth(screen.getMenuStyle()->f_font, text, len); + text_w = XTextWidth(screen->getMenuStyle()->f_font, text, len); text_y = item_y + - screen.getMenuStyle()->f_font->ascent + + screen->getMenuStyle()->f_font->ascent + (menu.bevel_w / 2); } - switch(screen.getMenuStyle()->f_justify) { - case BScreen::LeftJustify: + switch(screen->getMenuStyle()->f_justify) { + case LeftJustify: text_x = item_x + menu.bevel_w + menu.item_h + 1; break; - case BScreen::RightJustify: + case RightJustify: text_x = item_x + menu.item_w - (menu.item_h + menu.bevel_w + text_w); break; - case BScreen::CenterJustify: + case CenterJustify: text_x = item_x + ((menu.item_w + 1 - text_w) / 2); break; } @@ -641,16 +639,15 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear, text_h = menu.item_h - menu.bevel_w; } - GC gc = - ((highlight || item->isSelected()) ? screen.getMenuStyle()->h_text_gc : - screen.getMenuStyle()->f_text_gc), - tgc = - ((highlight) ? screen.getMenuStyle()->h_text_gc : - ((item->isEnabled()) ? screen.getMenuStyle()->f_text_gc : - screen.getMenuStyle()->d_text_gc)); + MenuStyle *style = screen->getMenuStyle(); + BPen pen((highlight || item->isSelected()) ? style->h_text : style->f_text), + textpen((highlight) ? style->h_text : + item->isEnabled() ? style->f_text : style->d_text, style->f_font), + hipen(style->hilite.color()); + sel_x = item_x; - if (screen.getMenuStyle()->bullet_pos == Right) + if (screen->getMenuStyle()->bullet_pos == Right) sel_x += (menu.item_w - menu.item_h - menu.bevel_w); sel_x += quarter_w; sel_y = item_y + quarter_w; @@ -660,8 +657,8 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear, False); } else if (! (x == y && y == -1 && w == h && h == 0)) { // calculate the which part of the hilite to redraw - if (! (max(item_x, x) <= (signed) min(item_x + menu.item_w, x + w) && - max(item_y, y) <= (signed) min(item_y + menu.item_h, y + h))) { + if (! (max(item_x, x) <= min(item_x + menu.item_w, x + w) && + max(item_y, y) <= min(item_y + menu.item_h, y + h))) { dohilite = False; } else { hilite_x = max(item_x, x); @@ -672,57 +669,53 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear, hoff_y = hilite_y % menu.item_h; } - // check if we need to redraw the text + // check if we need to redraw the text int text_ry = item_y + (menu.bevel_w / 2); - if (! (max(text_x, x) <= (signed) min(text_x + text_w, x + w) && - max(text_ry, y) <= (signed) min(text_ry + text_h, y + h))) + if (! (max(text_x, x) <= min(text_x + text_w, x + w) && + max(text_ry, y) <= min(text_ry + text_h, y + h))) dotext = False; // check if we need to redraw the select pixmap/menu bullet - if (! (max(sel_x, x) <= (signed) min(sel_x + half_w, x + w) && - max(sel_y, y) <= (signed) min(sel_y + half_w, y + h))) + if (! (max(sel_x, x) <= min(sel_x + half_w, x + w) && + max(sel_y, y) <= min(sel_y + half_w, y + h))) dosel = False; } if (dohilite && highlight && (menu.hilite_pixmap != ParentRelative)) { if (menu.hilite_pixmap) XCopyArea(display, menu.hilite_pixmap, menu.frame, - screen.getMenuStyle()->hilite_gc, hoff_x, hoff_y, + hipen.gc(), hoff_x, hoff_y, hilite_w, hilite_h, hilite_x, hilite_y); else - XFillRectangle(display, menu.frame, - screen.getMenuStyle()->hilite_gc, + XFillRectangle(display, menu.frame, hipen.gc(), hilite_x, hilite_y, hilite_w, hilite_h); } else if (dosel && item->isSelected() && (menu.sel_pixmap != ParentRelative)) { if (menu.sel_pixmap) - XCopyArea(display, menu.sel_pixmap, menu.frame, - screen.getMenuStyle()->hilite_gc, 0, 0, + XCopyArea(display, menu.sel_pixmap, menu.frame, hipen.gc(), 0, 0, half_w, half_w, sel_x, sel_y); else - XFillRectangle(display, menu.frame, - screen.getMenuStyle()->hilite_gc, - sel_x, sel_y, half_w, half_w); + XFillRectangle(display, menu.frame, hipen.gc(), sel_x, sel_y, half_w, half_w); } if (dotext && text) { if (i18n.multibyte()) - XmbDrawString(display, menu.frame, screen.getMenuStyle()->f_fontset, - tgc, text_x, text_y, text, len); + XmbDrawString(display, menu.frame, screen->getMenuStyle()->f_fontset, + textpen.gc(), text_x, text_y, text, len); else - XDrawString(display, menu.frame, tgc, text_x, text_y, text, len); + XDrawString(display, menu.frame, textpen.gc(), text_x, text_y, text, len); } if (dosel && item->submenu()) { - switch (screen.getMenuStyle()->bullet) { + switch (screen->getMenuStyle()->bullet) { case Square: - XDrawRectangle(display, menu.frame, gc, sel_x, sel_y, half_w, half_w); + XDrawRectangle(display, menu.frame, pen.gc(), sel_x, sel_y, half_w, half_w); break; case Triangle: XPoint tri[3]; - if (screen.getMenuStyle()->bullet_pos == Right) { + if (screen->getMenuStyle()->bullet_pos == Right) { tri[0].x = sel_x + quarter_w - 2; tri[0].y = sel_y + quarter_w - 2; tri[1].x = 4; @@ -738,7 +731,7 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear, tri[2].y = -4; } - XFillPolygon(display, menu.frame, gc, tri, 3, Convex, + XFillPolygon(display, menu.frame, pen.gc(), tri, 3, Convex, CoordModePrevious); break; @@ -754,7 +747,7 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear, dia[3].x = -3; dia[3].y = 3; - XFillPolygon(display, menu.frame, gc, dia, 4, Convex, + XFillPolygon(display, menu.frame, pen.gc(), dia, 4, Convex, CoordModePrevious); break; } @@ -762,18 +755,13 @@ void Basemenu::drawItem(int index, Bool highlight, Bool clear, } -void Basemenu::setLabel(const char *l) { - if (menu.label) - delete [] menu.label; - - if (l) menu.label = bstrdup(l); - else menu.label = 0; +void Basemenu::setLabel(const string& label) { + menu.label = label; } void Basemenu::setItemSelected(int index, bool sel) { - if (index < 0 || index >= (signed)menuitems.size()) return; - + assert(index >= 0); BasemenuItem *item = find(index); if (! item) return; @@ -783,18 +771,16 @@ void Basemenu::setItemSelected(int index, bool sel) { bool Basemenu::isItemSelected(int index) { - if (index < 0 || index >= (signed)menuitems.size()) return false; - + assert(index >= 0); BasemenuItem *item = find(index); - if (! item) return false; + if (! item) return False; return item->isSelected(); } void Basemenu::setItemEnabled(int index, bool enable) { - if (index < 0 || index >= (signed)menuitems.size()) return; - + assert(index >= 0); BasemenuItem *item = find(index); if (! item) return; @@ -804,8 +790,7 @@ void Basemenu::setItemEnabled(int index, bool enable) { bool Basemenu::isItemEnabled(int index) { - if (index < 0 || index >= (signed)menuitems.size()) return false; - + assert(index >= 0); BasemenuItem *item = find(index); if (! item) return False; @@ -818,11 +803,11 @@ void Basemenu::buttonPressEvent(XButtonEvent *be) { int sbl = (be->x / menu.item_w), i = (be->y / menu.item_h); int w = (sbl * menu.persub) + i; - if (w < (signed)menuitems.size() && w >= 0) { + BasemenuItem *item = find(w); + if (item) { which_press = i; which_sbl = sbl; - BasemenuItem *item = menuitems[w]; if (item->submenu()) drawSubmenu(w); @@ -845,32 +830,33 @@ void Basemenu::buttonReleaseEvent(XButtonEvent *re) { drawSubmenu(which_sub); } - if (re->x >= 0 && re->x <= (signed) menu.width && - re->y >= 0 && re->y <= (signed) menu.title_h) + if (re->x >= 0 && re->x <= static_cast(menu.width) && + re->y >= 0 && re->y <= static_cast(menu.title_h)) if (re->button == 3) hide(); } else if (re->window == menu.frame && - re->x >= 0 && re->x < (signed) menu.width && - re->y >= 0 && re->y < (signed) menu.frame_h) { + re->x >= 0 && re->x < static_cast(menu.width) && + re->y >= 0 && re->y < static_cast(menu.frame_h)) { if (re->button == 3) { hide(); } else { int sbl = (re->x / menu.item_w), i = (re->y / menu.item_h), - ix = sbl * menu.item_w, iy = i * menu.item_h, - w = (sbl * menu.persub) + i, - p = (which_sbl * menu.persub) + which_press; + ix = sbl * menu.item_w, iy = i * menu.item_h, + w = (sbl * menu.persub) + i, + p = (which_sbl * menu.persub) + which_press; - if (w < (signed)menuitems.size() && w >= 0) { + if (w >= 0 && w < static_cast(menuitems.size())) { drawItem(p, (p == which_sub), True); if (p == w && isItemEnabled(w)) { - if (re->x > ix && re->x < (signed) (ix + menu.item_w) && - re->y > iy && re->y < (signed) (iy + menu.item_h)) { + if (re->x > ix && re->x < static_cast(ix + menu.item_w) && + re->y > iy && re->y < static_cast(iy + menu.item_h)) { itemSelected(re->button, w); } } - } else + } else { drawItem(p, False, True); + } } } } @@ -891,7 +877,7 @@ void Basemenu::motionNotifyEvent(XMotionEvent *me) { drawSubmenu(which_sub); } else { menu.x = me->x_root - menu.x_move, - menu.y = me->y_root - menu.y_move; + menu.y = me->y_root - menu.y_move; XMoveWindow(display, menu.window, menu.x, menu.y); @@ -900,16 +886,16 @@ void Basemenu::motionNotifyEvent(XMotionEvent *me) { } } } else if ((! (me->state & Button1Mask)) && me->window == menu.frame && - me->x >= 0 && me->x < (signed) menu.width && - me->y >= 0 && me->y < (signed) menu.frame_h) { + me->x >= 0 && me->x < static_cast(menu.width) && + me->y >= 0 && me->y < static_cast(menu.frame_h)) { int sbl = (me->x / menu.item_w), i = (me->y / menu.item_h), - w = (sbl * menu.persub) + i; + w = (sbl * menu.persub) + i; if ((i != which_press || sbl != which_sbl) && - (w < (signed)menuitems.size() && w >= 0)) { + (w >= 0 && w < static_cast(menuitems.size()))) { if (which_press != -1 && which_sbl != -1) { int p = (which_sbl * menu.persub) + which_press; - BasemenuItem *item = menuitems[p]; + BasemenuItem *item = find(p); drawItem(p, False, True); if (item->submenu()) @@ -923,7 +909,7 @@ void Basemenu::motionNotifyEvent(XMotionEvent *me) { which_press = i; which_sbl = sbl; - BasemenuItem *itmp = menuitems[w]; + BasemenuItem *itmp = find(w); if (itmp->submenu()) drawSubmenu(w); @@ -943,20 +929,21 @@ void Basemenu::exposeEvent(XExposeEvent *ee) { // items down in that sublevel int sbl = (ee->x / menu.item_w), id = (ee->y / menu.item_h), - // next... figure out how many sublevels over the redraw spans - sbl_d = ((ee->x + ee->width) / menu.item_w), - // then we see how many items down to redraw - id_d = ((ee->y + ee->height) / menu.item_h); + // next... figure out how many sublevels over the redraw spans + sbl_d = ((ee->x + ee->width) / menu.item_w), + // then we see how many items down to redraw + id_d = ((ee->y + ee->height) / menu.item_h); if (id_d > menu.persub) id_d = menu.persub; // draw the sublevels and the number of items the exposure spans - menuitemList::const_iterator it = menuitems.begin(); + MenuItems::iterator it, + end = menuitems.end(); int i, ii; for (i = sbl; i <= sbl_d; i++) { // set the iterator to the first item in the sublevel needing redrawing it = menuitems.begin() + (id + (i * menu.persub)); - for (ii = id; ii <= id_d && it != menuitems.end(); it++, ii++) { + for (ii = id; ii <= id_d && it != end; ++it, ii++) { int index = ii + (i * menu.persub); // redraw the item drawItem(index, (which_sub == index), False, @@ -970,21 +957,21 @@ void Basemenu::exposeEvent(XExposeEvent *ee) { void Basemenu::enterNotifyEvent(XCrossingEvent *ce) { if (ce->window == menu.frame) { menu.x_shift = menu.x, menu.y_shift = menu.y; - if (menu.x + menu.width > screen.size().w()) { - menu.x_shift = screen.size().w() - menu.width - - screen.getBorderWidth(); + if (menu.x + menu.width > screen->getWidth()) { + menu.x_shift = screen->getWidth() - menu.width - + screen->getBorderWidth(); shifted = True; } else if (menu.x < 0) { - menu.x_shift = -screen.getBorderWidth(); + menu.x_shift = -screen->getBorderWidth(); shifted = True; } - if (menu.y + menu.height > screen.size().h()) { - menu.y_shift = screen.size().h() - menu.height - - screen.getBorderWidth(); + if (menu.y + menu.height > screen->getHeight()) { + menu.y_shift = screen->getHeight() - menu.height - + screen->getBorderWidth(); shifted = True; - } else if (menu.y + (signed) menu.title_h < 0) { - menu.y_shift = -screen.getBorderWidth(); + } else if (menu.y + static_cast(menu.title_h) < 0) { + menu.y_shift = -screen->getBorderWidth(); shifted = True; } @@ -992,10 +979,10 @@ void Basemenu::enterNotifyEvent(XCrossingEvent *ce) { XMoveWindow(display, menu.window, menu.x_shift, menu.y_shift); if (which_sub != -1) { - BasemenuItem *tmp = menuitems[which_sub]; + BasemenuItem *tmp = find(which_sub); if (tmp->submenu()->isVisible()) { int sbl = (ce->x / menu.item_w), i = (ce->y / menu.item_h), - w = (sbl * menu.persub) + i; + w = (sbl * menu.persub) + i; if (w != which_sub && (! tmp->submenu()->isTorn())) { tmp->submenu()->internal_hide(); @@ -1031,11 +1018,18 @@ void Basemenu::leaveNotifyEvent(XCrossingEvent *ce) { void Basemenu::reconfigure(void) { XSetWindowBackground(display, menu.window, - screen.getBorderColor()->getPixel()); + screen->getBorderColor()->pixel()); XSetWindowBorder(display, menu.window, - screen.getBorderColor()->getPixel()); - XSetWindowBorderWidth(display, menu.window, screen.getBorderWidth()); + screen->getBorderColor()->pixel()); + XSetWindowBorderWidth(display, menu.window, screen->getBorderWidth()); - menu.bevel_w = screen.getBevelWidth(); + menu.bevel_w = screen->getBevelWidth(); update(); } + + +void Basemenu::changeItemLabel(unsigned int index, const string& label) { + BasemenuItem *item = find(index); + assert(item); + item->newLabel(label); +} diff --git a/src/Basemenu.h b/src/Basemenu.h deleted file mode 100644 index 35a9791b..00000000 --- a/src/Basemenu.h +++ /dev/null @@ -1,169 +0,0 @@ -// Basemenu.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Basemenu_hh -#define __Basemenu_hh - -#include - -class Openbox; -class BImageControl; -class BScreen; -class Basemenu; -class BasemenuItem; -#include -typedef std::vector menuitemList; - -class Basemenu { -private: - menuitemList menuitems; - Openbox &openbox; - Basemenu *parent; - BImageControl *image_ctrl; - BScreen &screen; - - Bool moving, visible, movable, torn, internal_menu, title_vis, shifted, - hide_tree; - Display *display; - int which_sub, which_press, which_sbl, alignment; - - struct _menu { - Pixmap frame_pixmap, title_pixmap, hilite_pixmap, sel_pixmap; - Window window, frame, title; - - char *label; - int x, y, x_move, y_move, x_shift, y_shift, sublevels, persub, minsub, - grab_x, grab_y; - unsigned int width, height, title_h, frame_h, item_w, item_h, bevel_w, - bevel_h; - } menu; - - -protected: - inline BasemenuItem *find(int index) { return menuitems[index]; } - inline void setTitleVisibility(Bool b) { title_vis = b; } - inline void setMovable(Bool b) { movable = b; } - inline void setHideTree(Bool h) { hide_tree = h; } - inline void setMinimumSublevels(int m) { menu.minsub = m; } - - virtual void itemSelected(int, int) = 0; - virtual void drawItem(int, Bool = False, Bool = False, - int = -1, int = -1, unsigned int = 0, - unsigned int = 0); - virtual void redrawTitle(); - virtual void internal_hide(void); - - -public: - Basemenu(BScreen &); - virtual ~Basemenu(void); - - inline const Bool &isTorn(void) const { return torn; } - inline const Bool &isVisible(void) const { return visible; } - - inline BScreen &getScreen(void) { return screen; } - - inline const Window &getWindowID(void) const { return menu.window; } - - inline const char *getLabel(void) const { return menu.label; } - - int insert(const char *, int = 0, const char * = (const char *) 0, int = -1); - int insert(const char **, int = -1, int = 0); - int insert(const char *, Basemenu *, int = -1); - int remove(int); - - inline int getX(void) const { return menu.x; } - inline int getY(void) const { return menu.y; } - inline unsigned int getCount(void) { return menuitems.size(); } - inline int getCurrentSubmenu(void) const { return which_sub; } - - inline unsigned int getWidth(void) const { return menu.width; } - inline unsigned int getHeight(void) const { return menu.height; } - inline unsigned int getTitleHeight(void) const { return menu.title_h; } - - inline void setInternalMenu(void) { internal_menu = True; } - inline void setAlignment(int a) { alignment = a; } - inline void setTorn(void) { torn = True; } - inline void removeParent(void) - { if (internal_menu) parent = (Basemenu *) 0; } - - bool hasSubmenu(int); - bool isItemSelected(int); - bool isItemEnabled(int); - - void buttonPressEvent(XButtonEvent *); - void buttonReleaseEvent(XButtonEvent *); - void motionNotifyEvent(XMotionEvent *); - void enterNotifyEvent(XCrossingEvent *); - void leaveNotifyEvent(XCrossingEvent *); - void exposeEvent(XExposeEvent *); - void reconfigure(void); - void setLabel(const char *n); - void move(int, int); - void update(void); - void setItemSelected(int, bool); - void setItemEnabled(int, bool); - - virtual void drawSubmenu(int); - virtual void show(void); - virtual void hide(void); - - enum { AlignDontCare = 1, AlignTop, AlignBottom }; - enum { Right = 1, Left }; - enum { Empty = 0, Square, Triangle, Diamond }; -}; - - -class BasemenuItem { -private: - Basemenu *s; - const char **u, *l, *e; - int f, enabled, selected; - - friend class Basemenu; - -protected: - -public: - BasemenuItem(const char *lp, int fp, const char *ep = (const char *) 0): - s(0), u(0), l(lp), e(ep), f(fp), enabled(1), selected(0) {} - - BasemenuItem(const char *lp, Basemenu *mp): s(mp), u(0), l(lp), e(0), f(0), - enabled(1), selected(0) {} - - BasemenuItem(const char **up, int fp): s(0), u(up), l(0), e(0), f(fp), - enabled(1), selected(0) {} - - inline const char *exec(void) const { return e; } - inline const char *label(void) const { return l; } - inline const char **ulabel(void) const { return u; } - inline const int &function(void) const { return f; } - inline Basemenu *submenu(void) { return s; } - - inline const int &isEnabled(void) const { return enabled; } - inline void setEnabled(int e) { enabled = e; } - inline const int &isSelected(void) const { return selected; } - inline void setSelected(int s) { selected = s; } -}; - - -#endif // __Basemenu_hh diff --git a/src/Clientmenu.cc b/src/Clientmenu.cc index 34ed6f11..07f70439 100644 --- a/src/Clientmenu.cc +++ b/src/Clientmenu.cc @@ -1,5 +1,6 @@ -// Clientmenu.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Clientmenu.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,44 +21,39 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "openbox.h" -#include "Clientmenu.h" -#include "Screen.h" -#include "Window.h" -#include "Workspace.h" -#include "Workspacemenu.h" +#include "blackbox.hh" +#include "Clientmenu.hh" +#include "Screen.hh" +#include "Window.hh" +#include "Workspace.hh" +#include "Workspacemenu.hh" + +Clientmenu::Clientmenu(Workspace *ws) : Basemenu(ws->getScreen()) { + wkspc = ws; -Clientmenu::Clientmenu(Workspace &ws) : Basemenu(ws.getScreen()), - screen(ws.getScreen()), wkspc(ws) -{ setInternalMenu(); } -void Clientmenu::itemSelected(int button, int index) { +void Clientmenu::itemSelected(int button, unsigned int index) { if (button > 2) return; - OpenboxWindow *win = wkspc.getWindow(index); + BlackboxWindow *win = wkspc->getWindow(index); if (win) { if (button == 1) { - if (! wkspc.isCurrent()) wkspc.setCurrent(); + if (! wkspc->isCurrent()) wkspc->setCurrent(); } else if (button == 2) { - if (! wkspc.isCurrent()) win->deiconify(True, False); + if (! wkspc->isCurrent()) win->deiconify(True, False); } - wkspc.raiseWindow(win); + wkspc->raiseWindow(win); win->setInputFocus(); } - if (! (screen.getWorkspacemenu()->isTorn() || isTorn())) hide(); + Workspacemenu* wkspcmenu = wkspc->getScreen()->getWorkspacemenu(); + if (! (wkspcmenu->isTorn() || isTorn())) hide(); } diff --git a/src/Clientmenu.h b/src/Clientmenu.hh similarity index 77% rename from src/Clientmenu.h rename to src/Clientmenu.hh index 88aeba6c..70cc2aa0 100644 --- a/src/Clientmenu.h +++ b/src/Clientmenu.hh @@ -1,5 +1,6 @@ -// Clientmenu.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Clientmenu.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -23,20 +24,22 @@ #ifndef __Clientmenu_hh #define __Clientmenu_hh -#include "Basemenu.h" +#include "Basemenu.hh" class Workspace; class BScreen; class Clientmenu : public Basemenu { private: - BScreen &screen; - Workspace &wkspc; + Workspace *wkspc; + + Clientmenu(const Clientmenu&); + Clientmenu& operator=(const Clientmenu&); protected: - virtual void itemSelected(int, int); + virtual void itemSelected(int button, unsigned int index); public: - Clientmenu(Workspace &); + Clientmenu(Workspace *ws); }; diff --git a/src/Color.cc b/src/Color.cc new file mode 100644 index 00000000..7a36b03c --- /dev/null +++ b/src/Color.cc @@ -0,0 +1,242 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Color.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif // HAVE_CONFIG_H + +#include "Color.hh" +#include "BaseDisplay.hh" + +extern "C" { +#include +} + + +BColor::ColorCache BColor::colorcache; +bool BColor::cleancache = false; + +BColor::BColor(const BaseDisplay * const _display, unsigned int _screen) + : allocated(false), r(-1), g(-1), b(-1), p(0), dpy(_display), scrn(_screen) +{} + +BColor::BColor(int _r, int _g, int _b, + const BaseDisplay * const _display, unsigned int _screen) + : allocated(false), r(_r), g(_g), b(_b), p(0), dpy(_display), scrn(_screen) +{} + + +BColor::BColor(const std::string &_name, + const BaseDisplay * const _display, unsigned int _screen) + : allocated(false), r(-1), g(-1), b(-1), p(0), dpy(_display), scrn(_screen), + colorname(_name) { + parseColorName(); +} + + +BColor::~BColor(void) { + deallocate(); +} + + +void BColor::setDisplay(const BaseDisplay * const _display, + unsigned int _screen) { + if (_display == display() && _screen == screen()) { + // nothing to do + return; + } + + deallocate(); + + dpy = _display; + scrn = _screen; + + if (! colorname.empty()) { + parseColorName(); + } +} + + +unsigned long BColor::pixel(void) const { + if (! allocated) { + // mutable + BColor *that = (BColor *) this; + that->allocate(); + } + + return p; +} + + +void BColor::parseColorName(void) { + assert(dpy != 0); + + if (colorname.empty()) { + fprintf(stderr, "BColor: empty colorname, cannot parse (using black)\n"); + setRGB(0, 0, 0); + } + + if (scrn == ~(0u)) + scrn = DefaultScreen(display()->getXDisplay()); + Colormap colormap = display()->getScreenInfo(scrn)->getColormap(); + + // get rgb values from colorname + XColor xcol; + xcol.red = 0; + xcol.green = 0; + xcol.blue = 0; + xcol.pixel = 0; + + if (! XParseColor(display()->getXDisplay(), colormap, + colorname.c_str(), &xcol)) { + fprintf(stderr, "BColor::allocate: color parse error: \"%s\"\n", + colorname.c_str()); + setRGB(0, 0, 0); + return; + } + + setRGB(xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8); +} + + +void BColor::allocate(void) { + assert(dpy != 0); + + if (scrn == ~(0u)) scrn = DefaultScreen(display()->getXDisplay()); + Colormap colormap = display()->getScreenInfo(scrn)->getColormap(); + + if (! isValid()) { + if (colorname.empty()) { + fprintf(stderr, "BColor: cannot allocate invalid color (using black)\n"); + setRGB(0, 0, 0); + } else { + parseColorName(); + } + } + + // see if we have allocated this color before + RGB rgb(display(), scrn, r, g, b); + ColorCache::iterator it = colorcache.find(rgb); + if (it != colorcache.end()) { + // found + allocated = true; + p = (*it).second.p; + (*it).second.count++; + return; + } + + // allocate color from rgb values + XColor xcol; + xcol.red = r | r << 8; + xcol.green = g | g << 8; + xcol.blue = b | b << 8; + xcol.pixel = 0; + + if (! XAllocColor(display()->getXDisplay(), colormap, &xcol)) { + fprintf(stderr, "BColor::allocate: color alloc error: rgb:%x/%x/%x\n", + r, g, b); + xcol.pixel = 0; + } + + p = xcol.pixel; + allocated = true; + + colorcache.insert(ColorCacheItem(rgb, PixelRef(p))); + + if (cleancache) + doCacheCleanup(); +} + + +void BColor::deallocate(void) { + if (! allocated) + return; + + assert(dpy != 0); + + ColorCache::iterator it = colorcache.find(RGB(display(), scrn, r, g, b)); + if (it != colorcache.end()) { + if ((*it).second.count >= 1) + (*it).second.count--; + } + + if (cleancache) + doCacheCleanup(); + + allocated = false; +} + + +BColor &BColor::operator=(const BColor &c) { + deallocate(); + + setRGB(c.r, c.g, c.b); + colorname = c.colorname; + dpy = c.dpy; + scrn = c.scrn; + return *this; +} + + +void BColor::cleanupColorCache(void) { + cleancache = true; +} + + +void BColor::doCacheCleanup(void) { + // ### TODO - support multiple displays! + ColorCache::iterator it = colorcache.begin(); + if (it == colorcache.end()) { + // nothing to do + return; + } + + const BaseDisplay* const display = (*it).first.display; + unsigned long *pixels = new unsigned long[ colorcache.size() ]; + unsigned int i, count; + + for (i = 0; i < display->getNumberOfScreens(); i++) { + count = 0; + it = colorcache.begin(); + + while (it != colorcache.end()) { + if ((*it).second.count != 0 || (*it).first.screen != i) { + ++it; + continue; + } + + pixels[ count++ ] = (*it).second.p; + ColorCache::iterator it2 = it; + ++it; + colorcache.erase(it2); + } + + if (count > 0) + XFreeColors(display->getXDisplay(), + display->getScreenInfo(i)->getColormap(), + pixels, count, 0); + } + + delete [] pixels; + cleancache = false; +} diff --git a/src/Color.hh b/src/Color.hh new file mode 100644 index 00000000..9eb8ef2e --- /dev/null +++ b/src/Color.hh @@ -0,0 +1,128 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Color.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef COLOR_HH +#define COLOR_HH + +extern "C" { +#include +} + +#include +#include + +class BaseDisplay; + +class BColor { +public: + BColor(const BaseDisplay * const _display = 0, unsigned int _screen = ~(0u)); + BColor(int _r, int _g, int _b, + const BaseDisplay * const _display, unsigned int _screen = ~(0u)); + BColor(const std::string &_name, + const BaseDisplay * const _display, unsigned int _screen = ~(0u)); + ~BColor(void); + + inline const std::string &name(void) const { return colorname; } + + inline int red(void) const { return r; } + inline int green(void) const { return g; } + inline int blue(void) const { return b; } + void setRGB(int _r, int _g, int _b) { + deallocate(); + r = _r; + g = _g; + b = _b; + } + + inline const BaseDisplay *display(void) const { return dpy; } + inline unsigned int screen(void) const { return scrn; } + void setDisplay(const BaseDisplay * const _display, + unsigned int _screen = ~(0u)); + + inline bool isAllocated(void) const { return allocated; } + + inline bool isValid(void) const { return r != -1 && g != -1 && b != -1; } + + unsigned long pixel(void) const; + + // operators + BColor &operator=(const BColor &c); + inline bool operator==(const BColor &c) const + { return (r == c.r && b == c.b && b == c.b); } + inline bool operator!=(const BColor &c) const + { return (! operator==(c)); } + + static void cleanupColorCache(void); + +private: + void parseColorName(void); + void allocate(void); + void deallocate(void); + + bool allocated; + int r, g, b; + unsigned long p; + const BaseDisplay *dpy; + unsigned int scrn; + std::string colorname; + + // global color allocator/deallocator + struct RGB { + const BaseDisplay* const display; + const unsigned int screen; + const int r, g, b; + + RGB(void) : display(0), screen(~(0u)), r(-1), g(-1), b(-1) { } + RGB(const BaseDisplay * const a, const unsigned int b, + const int x, const int y, const int z) + : display(a), screen(b), r(x), g(y), b(z) {} + RGB(const RGB &x) + : display(x.display), screen(x.screen), r(x.r), g(x.g), b(x.b) {} + + inline bool operator==(const RGB &x) const { + return display == x.display && + screen == x.screen && + r == x.r && g == x.g && b == x.b; + } + + inline bool operator<(const RGB &x) const { + unsigned long p1, p2; + p1 = (screen << 24 | r << 16 | g << 8 | b) & 0x00ffffff; + p2 = (x.screen << 24 | x.r << 16 | x.g << 8 | x.b) & 0x00ffffff; + return p1 < p2; + } + }; + struct PixelRef { + const unsigned long p; + unsigned int count; + inline PixelRef(void) : p(0), count(0) { } + inline PixelRef(const unsigned long x) : p(x), count(1) { } + }; + typedef std::map ColorCache; + typedef ColorCache::value_type ColorCacheItem; + static ColorCache colorcache; + static bool cleancache; + static void doCacheCleanup(void); +}; + +#endif // COLOR_HH diff --git a/src/Configmenu.cc b/src/Configmenu.cc index 7a16576d..3a314af5 100644 --- a/src/Configmenu.cc +++ b/src/Configmenu.cc @@ -1,6 +1,6 @@ -// Configmenu.cc for Openbox -// Copyright (c) 2002 - 2002 Ben Jansens -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Configmenu.cc for Blackbox - An X11 Window Manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -21,26 +21,19 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "i18n.h" -#include "Configmenu.h" -#include "Toolbar.h" -#include "Window.h" -#include "Screen.h" +#include "i18n.hh" +#include "Configmenu.hh" +#include "Image.hh" +#include "Toolbar.hh" +#include "Window.hh" +#include "Screen.hh" -Configmenu::Configmenu(BScreen &scr) : Basemenu(scr), screen(scr) -{ - setLabel(i18n(ConfigmenuSet, ConfigmenuConfigOptions, - "Config options")); +Configmenu::Configmenu(BScreen *scr) : Basemenu(scr) { + setLabel(i18n(ConfigmenuSet, ConfigmenuConfigOptions, "Config options")); setInternalMenu(); focusmenu = new Focusmenu(this); @@ -60,28 +53,21 @@ Configmenu::Configmenu(BScreen &scr) : Basemenu(scr), screen(scr) "Focus New Windows"), 4); insert(i18n(ConfigmenuSet, ConfigmenuFocusLast, "Focus Last Window on Workspace"), 5); - insert(i18n(ConfigmenuSet, ConfigmenuHideToolbar, - "Hide toolbar"), 6); update(); - setValues(); -} - -void Configmenu::setValues() { - setItemSelected(2, screen.imageDither()); - setItemSelected(3, screen.opaqueMove()); - setItemSelected(4, screen.fullMax()); - setItemSelected(5, screen.focusNew()); - setItemSelected(6, screen.focusLast()); - setItemSelected(7, screen.hideToolbar()); + setItemSelected(2, getScreen()->getImageControl()->doDither()); + setItemSelected(3, getScreen()->doOpaqueMove()); + setItemSelected(4, getScreen()->doFullMax()); + setItemSelected(5, getScreen()->doFocusNew()); + setItemSelected(6, getScreen()->doFocusLast()); } -Configmenu::~Configmenu() { +Configmenu::~Configmenu(void) { delete focusmenu; delete placementmenu; } -void Configmenu::itemSelected(int button, int index) { +void Configmenu::itemSelected(int button, unsigned int index) { if (button != 1) return; @@ -92,87 +78,73 @@ void Configmenu::itemSelected(int button, int index) { switch(item->function()) { case 1: { // dither - screen.setImageDither(!screen.imageDither()); + getScreen()->getImageControl()-> + setDither((! getScreen()->getImageControl()->doDither())); - setItemSelected(index, screen.imageDither()); + setItemSelected(index, getScreen()->getImageControl()->doDither()); break; } case 2: { // opaque move - screen.setOpaqueMove(!screen.opaqueMove()); + getScreen()->saveOpaqueMove((! getScreen()->doOpaqueMove())); - setItemSelected(index, screen.opaqueMove()); + setItemSelected(index, getScreen()->doOpaqueMove()); break; } case 3: { // full maximization - screen.setFullMax(!screen.fullMax()); + getScreen()->saveFullMax((! getScreen()->doFullMax())); - setItemSelected(index, screen.fullMax()); + setItemSelected(index, getScreen()->doFullMax()); break; } case 4: { // focus new windows - screen.setFocusNew(!screen.focusNew()); + getScreen()->saveFocusNew((! getScreen()->doFocusNew())); - setItemSelected(index, screen.focusNew()); + setItemSelected(index, getScreen()->doFocusNew()); break; } case 5: { // focus last window on workspace - screen.setFocusLast(!screen.focusLast()); - setItemSelected(index, screen.focusLast()); - break; - } - case 6:{ //toggle toolbar hide - screen.setHideToolbar(!screen.hideToolbar()); - setItemSelected(index, screen.hideToolbar()); + getScreen()->saveFocusLast((! getScreen()->doFocusLast())); + setItemSelected(index, getScreen()->doFocusLast()); break; } } // switch } -void Configmenu::reconfigure() { - setValues(); + +void Configmenu::reconfigure(void) { focusmenu->reconfigure(); placementmenu->reconfigure(); Basemenu::reconfigure(); } -Configmenu::Focusmenu::Focusmenu(Configmenu *cm) : Basemenu(cm->screen) { - configmenu = cm; - setLabel(i18n(ConfigmenuSet, ConfigmenuFocusModel, - "Focus Model")); +Configmenu::Focusmenu::Focusmenu(Configmenu *cm) : Basemenu(cm->getScreen()) { + setLabel(i18n(ConfigmenuSet, ConfigmenuFocusModel, "Focus Model")); setInternalMenu(); - insert(i18n(ConfigmenuSet, ConfigmenuClickToFocus, - "Click To Focus"), 1); - insert(i18n(ConfigmenuSet, ConfigmenuSloppyFocus, - "Sloppy Focus"), 2); - insert(i18n(ConfigmenuSet, ConfigmenuAutoRaise, - "Auto Raise"), 3); + insert(i18n(ConfigmenuSet, ConfigmenuClickToFocus, "Click To Focus"), 1); + insert(i18n(ConfigmenuSet, ConfigmenuSloppyFocus, "Sloppy Focus"), 2); + insert(i18n(ConfigmenuSet, ConfigmenuAutoRaise, "Auto Raise"), 3); + insert(i18n(ConfigmenuSet, ConfigmenuClickRaise, "Click Raise"), 4); update(); - setValues(); + setItemSelected(0, (! getScreen()->isSloppyFocus())); + setItemSelected(1, getScreen()->isSloppyFocus()); + setItemEnabled(2, getScreen()->isSloppyFocus()); + setItemSelected(2, getScreen()->doAutoRaise()); + setItemEnabled(3, getScreen()->isSloppyFocus()); + setItemSelected(3, getScreen()->doClickRaise()); } -void Configmenu::Focusmenu::setValues() { - setItemSelected(0, !configmenu->screen.sloppyFocus()); - setItemSelected(1, configmenu->screen.sloppyFocus()); - setItemEnabled(2, configmenu->screen.sloppyFocus()); - setItemSelected(2, configmenu->screen.autoRaise()); -} -void Configmenu::Focusmenu::reconfigure() { - setValues(); - Basemenu::reconfigure(); -} - -void Configmenu::Focusmenu::itemSelected(int button, int index) { +void Configmenu::Focusmenu::itemSelected(int button, unsigned int index) { if (button != 1) return; @@ -183,101 +155,81 @@ void Configmenu::Focusmenu::itemSelected(int button, int index) { switch (item->function()) { case 1: // click to focus - configmenu->screen.setSloppyFocus(false); - configmenu->screen.setAutoRaise(false); - // make windows all grab button1 clicks - configmenu->screen.reconfigure(); + getScreen()->toggleFocusModel(BScreen::ClickToFocus); break; case 2: // sloppy focus - configmenu->screen.setSloppyFocus(true); - // make windows stop grabbing button1 clicks - configmenu->screen.reconfigure(); + getScreen()->toggleFocusModel(BScreen::SloppyFocus); break; case 3: // auto raise with sloppy focus - configmenu->screen.setAutoRaise(!configmenu->screen.autoRaise()); + getScreen()->saveAutoRaise(! getScreen()->doAutoRaise()); + break; + + case 4: // click raise with sloppy focus + getScreen()->saveClickRaise(! getScreen()->doClickRaise()); + getScreen()->updateFocusModel(); break; } - setItemSelected(0, !configmenu->screen.sloppyFocus()); - setItemSelected(1, configmenu->screen.sloppyFocus()); - setItemEnabled(2, configmenu->screen.sloppyFocus()); - setItemSelected(2, configmenu->screen.autoRaise()); + setItemSelected(0, (! getScreen()->isSloppyFocus())); + setItemSelected(1, getScreen()->isSloppyFocus()); + setItemEnabled(2, getScreen()->isSloppyFocus()); + setItemSelected(2, getScreen()->doAutoRaise()); + setItemEnabled(3, getScreen()->isSloppyFocus()); + setItemSelected(3, getScreen()->doClickRaise()); } -Configmenu::Placementmenu::Placementmenu(Configmenu *cm) : -Basemenu(cm->screen) { - configmenu = cm; - setLabel(i18n(ConfigmenuSet, ConfigmenuWindowPlacement, - "Window Placement")); +Configmenu::Placementmenu::Placementmenu(Configmenu *cm): + Basemenu(cm->getScreen()) { + setLabel(i18n(ConfigmenuSet, ConfigmenuWindowPlacement, "Window Placement")); setInternalMenu(); - insert(i18n(ConfigmenuSet, ConfigmenuSmartRows, - "Smart Placement (Rows)"), + insert(i18n(ConfigmenuSet, ConfigmenuSmartRows, "Smart Placement (Rows)"), BScreen::RowSmartPlacement); - insert(i18n(ConfigmenuSet, ConfigmenuSmartCols, - "Smart Placement (Columns)"), + insert(i18n(ConfigmenuSet, ConfigmenuSmartCols, "Smart Placement (Columns)"), BScreen::ColSmartPlacement); - insert(i18n(ConfigmenuSet, ConfigmenuCascade, - "Cascade Placement"), BScreen::CascadePlacement); - insert(i18n(ConfigmenuSet, ConfigmenuBestFit, - "Best Fit Placement"), BScreen::BestFitPlacement); - insert(i18n(ConfigmenuSet, ConfigmenuUnderMouse, - "Under Mouse Placement"), - BScreen::UnderMousePlacement); - insert(i18n(ConfigmenuSet, ConfigmenuClickMouse, - "Click Mouse Placement"), - BScreen::ClickMousePlacement); - insert(i18n(ConfigmenuSet, ConfigmenuLeftRight, - "Left to Right"), BScreen::LeftRight); - insert(i18n(ConfigmenuSet, ConfigmenuRightLeft, - "Right to Left"), BScreen::RightLeft); - insert(i18n(ConfigmenuSet, ConfigmenuTopBottom, - "Top to Bottom"), BScreen::TopBottom); - insert(i18n(ConfigmenuSet, ConfigmenuBottomTop, - "Bottom to Top"), BScreen::BottomTop); + insert(i18n(ConfigmenuSet, ConfigmenuCascade, "Cascade Placement"), + BScreen::CascadePlacement); + insert(i18n(ConfigmenuSet, ConfigmenuLeftRight, "Left to Right"), + BScreen::LeftRight); + insert(i18n(ConfigmenuSet, ConfigmenuRightLeft, "Right to Left"), + BScreen::RightLeft); + insert(i18n(ConfigmenuSet, ConfigmenuTopBottom, "Top to Bottom"), + BScreen::TopBottom); + insert(i18n(ConfigmenuSet, ConfigmenuBottomTop, "Bottom to Top"), + BScreen::BottomTop); update(); - setValues(); -} + switch (getScreen()->getPlacementPolicy()) { + case BScreen::RowSmartPlacement: + setItemSelected(0, True); + break; + + case BScreen::ColSmartPlacement: + setItemSelected(1, True); + break; -void Configmenu::Placementmenu::setValues() { - const int p = configmenu->screen.placementPolicy(); - setItemSelected(0, p == BScreen::RowSmartPlacement); - setItemSelected(1, p == BScreen::ColSmartPlacement); - setItemSelected(2, p == BScreen::CascadePlacement); - setItemSelected(3, p == BScreen::BestFitPlacement); - setItemSelected(4, p == BScreen::UnderMousePlacement); - setItemSelected(5, p == BScreen::ClickMousePlacement); + case BScreen::CascadePlacement: + setItemSelected(2, True); + break; + } - bool rl = (configmenu->screen.rowPlacementDirection() == + bool rl = (getScreen()->getRowPlacementDirection() == BScreen::LeftRight), - tb = (configmenu->screen.colPlacementDirection() == - BScreen::TopBottom); - - setItemSelected(6, rl); - setItemEnabled(6, (p != BScreen::UnderMousePlacement && - p != BScreen::ClickMousePlacement)); - setItemSelected(7, !rl); - setItemEnabled(7, (p != BScreen::UnderMousePlacement && - p != BScreen::ClickMousePlacement)); - - setItemSelected(8, tb); - setItemEnabled(8, (p != BScreen::UnderMousePlacement && - p != BScreen::ClickMousePlacement)); - setItemSelected(9, !tb); - setItemEnabled(9, (p != BScreen::UnderMousePlacement && - p != BScreen::ClickMousePlacement)); -} + tb = (getScreen()->getColPlacementDirection() == + BScreen::TopBottom); -void Configmenu::Placementmenu::reconfigure() { - setValues(); - Basemenu::reconfigure(); + setItemSelected(3, rl); + setItemSelected(4, ! rl); + + setItemSelected(5, tb); + setItemSelected(6, ! tb); } -void Configmenu::Placementmenu::itemSelected(int button, int index) { + +void Configmenu::Placementmenu::itemSelected(int button, unsigned int index) { if (button != 1) return; @@ -288,44 +240,62 @@ void Configmenu::Placementmenu::itemSelected(int button, int index) { switch (item->function()) { case BScreen::RowSmartPlacement: - configmenu->screen.setPlacementPolicy(item->function()); + getScreen()->savePlacementPolicy(item->function()); + + setItemSelected(0, True); + setItemSelected(1, False); + setItemSelected(2, False); + break; case BScreen::ColSmartPlacement: - configmenu->screen.setPlacementPolicy(item->function()); - break; + getScreen()->savePlacementPolicy(item->function()); - case BScreen::CascadePlacement: - configmenu->screen.setPlacementPolicy(item->function()); - break; + setItemSelected(0, False); + setItemSelected(1, True); + setItemSelected(2, False); - case BScreen::BestFitPlacement: - configmenu->screen.setPlacementPolicy(item->function()); break; - case BScreen::UnderMousePlacement: - configmenu->screen.setPlacementPolicy(item->function()); - break; + case BScreen::CascadePlacement: + getScreen()->savePlacementPolicy(item->function()); + + setItemSelected(0, False); + setItemSelected(1, False); + setItemSelected(2, True); - case BScreen::ClickMousePlacement: - configmenu->screen.setPlacementPolicy(item->function()); break; case BScreen::LeftRight: - configmenu->screen.setRowPlacementDirection(BScreen::LeftRight); + getScreen()->saveRowPlacementDirection(BScreen::LeftRight); + + setItemSelected(3, True); + setItemSelected(4, False); + break; case BScreen::RightLeft: - configmenu->screen.setRowPlacementDirection(BScreen::RightLeft); + getScreen()->saveRowPlacementDirection(BScreen::RightLeft); + + setItemSelected(3, False); + setItemSelected(4, True); + break; case BScreen::TopBottom: - configmenu->screen.setColPlacementDirection(BScreen::TopBottom); + getScreen()->saveColPlacementDirection(BScreen::TopBottom); + + setItemSelected(5, True); + setItemSelected(6, False); + break; case BScreen::BottomTop: - configmenu->screen.setColPlacementDirection(BScreen::BottomTop); + getScreen()->saveColPlacementDirection(BScreen::BottomTop); + + setItemSelected(5, False); + setItemSelected(6, True); + break; } - setValues(); } diff --git a/src/Configmenu.h b/src/Configmenu.hh similarity index 63% rename from src/Configmenu.h rename to src/Configmenu.hh index dd343b6a..101b021b 100644 --- a/src/Configmenu.h +++ b/src/Configmenu.hh @@ -1,5 +1,6 @@ -// Configmenu.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Configmenu.hh for Blackbox - An X11 Window Manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -23,10 +24,10 @@ #ifndef __Configmenu_hh #define __Configmenu_hh -#include "Basemenu.h" +#include "Basemenu.hh" // forward declaration -class Openbox; +class Blackbox; class BScreen; class Configmenu; @@ -34,51 +35,48 @@ class Configmenu : public Basemenu { private: class Focusmenu : public Basemenu { private: - Configmenu *configmenu; + Focusmenu(const Focusmenu&); + Focusmenu& operator=(const Focusmenu&); protected: - virtual void itemSelected(int, int); - virtual void setValues(); + virtual void itemSelected(int button, unsigned int index); public: - Focusmenu(Configmenu *); - void reconfigure(); + Focusmenu(Configmenu *cm); }; class Placementmenu : public Basemenu { private: - Configmenu *configmenu; + Placementmenu(const Placementmenu&); + Placementmenu& operator=(const Placementmenu&); protected: - virtual void itemSelected(int, int); - virtual void setValues(); - + virtual void itemSelected(int button, unsigned int index); public: - Placementmenu(Configmenu *); - void reconfigure(); + Placementmenu(Configmenu *cm); }; - BScreen &screen; Focusmenu *focusmenu; Placementmenu *placementmenu; friend class Focusmenu; friend class Placementmenu; -protected: - virtual void itemSelected(int, int); - virtual void setValues(); + Configmenu(const Configmenu&); + Configmenu& operator=(const Configmenu&); +protected: + virtual void itemSelected(int button, unsigned int index); public: - Configmenu(BScreen &); - virtual ~Configmenu(); + Configmenu(BScreen *scr); + virtual ~Configmenu(void); - inline Basemenu *getFocusmenu() { return focusmenu; } - inline Basemenu *getPlacementmenu() { return placementmenu; } + inline Basemenu *getFocusmenu(void) { return focusmenu; } + inline Basemenu *getPlacementmenu(void) { return placementmenu; } - void reconfigure(); + void reconfigure(void); }; #endif // __Configmenu_hh diff --git a/src/GCCache.cc b/src/GCCache.cc new file mode 100644 index 00000000..941d67ef --- /dev/null +++ b/src/GCCache.cc @@ -0,0 +1,197 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// GCCache.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif // HAVE_CONFIG_H + +extern "C" { +#include +} + +#include "GCCache.hh" +#include "BaseDisplay.hh" +#include "Color.hh" +#include "Util.hh" + + +void BGCCacheContext::set(const BColor &_color, + const XFontStruct * const _font, + const int _function, const int _subwindow) { + XGCValues gcv; + pixel = gcv.foreground = _color.pixel(); + function = gcv.function = _function; + subwindow = gcv.subwindow_mode = _subwindow; + unsigned long mask = GCForeground | GCFunction | GCSubwindowMode; + + if (_font) { + fontid = gcv.font = _font->fid; + mask |= GCFont; + } else { + fontid = 0; + } + + XChangeGC(display->getXDisplay(), gc, mask, &gcv); +} + + +void BGCCacheContext::set(const XFontStruct * const _font) { + if (! _font) { + fontid = 0; + return; + } + + XGCValues gcv; + fontid = gcv.font = _font->fid; + XChangeGC(display->getXDisplay(), gc, GCFont, &gcv); +} + + +BGCCache::BGCCache(const BaseDisplay * const _display) + : display(_display), context_count(128u), + cache_size(16u), cache_buckets(8u), + cache_total_size(cache_size * cache_buckets) { + + contexts = new BGCCacheContext*[context_count]; + unsigned int i; + for (i = 0; i < context_count; i++) { + contexts[i] = new BGCCacheContext(display); + } + + cache = new BGCCacheItem*[cache_total_size]; + for (i = 0; i < cache_total_size; ++i) { + cache[i] = new BGCCacheItem; + } +} + + +BGCCache::~BGCCache(void) { + std::for_each(contexts, contexts + context_count, PointerAssassin()); + std::for_each(cache, cache + cache_total_size, PointerAssassin()); + delete [] cache; + delete [] contexts; + cache = 0; + contexts = 0; +} + + +BGCCacheContext *BGCCache::nextContext(unsigned int scr) { + Window hd = display->getScreenInfo(scr)->getRootWindow(); + + BGCCacheContext *c; + + for (unsigned int i = 0; i < context_count; ++i) { + c = contexts[i]; + + if (! c->gc) { + c->gc = XCreateGC(display->getXDisplay(), hd, 0, 0); + c->used = false; + c->screen = scr; + } + if (! c->used && c->screen == scr) { + c->used = true; + return c; + } + } + + fprintf(stderr, "BGCCache: context fault!\n"); + abort(); +} + + +void BGCCache::release(BGCCacheContext *ctx) { + ctx->used = false; +} + + +BGCCacheItem *BGCCache::find(const BColor &_color, + const XFontStruct * const _font, + int _function, int _subwindow) { + const unsigned long pixel = _color.pixel(); + const unsigned int screen = _color.screen(); + const int key = _color.red() ^ _color.green() ^ _color.blue(); + int k = (key % cache_size) * cache_buckets; + int i = 0; // loop variable + BGCCacheItem *c = cache[ k ], *prev = 0; + + // this will either loop 8 times then return/abort or it will stop matching + while (c->ctx && + (c->ctx->pixel != pixel || c->ctx->function != _function || + c->ctx->subwindow != _subwindow || c->ctx->screen != screen)) { + if (i < 7) { + prev = c; + c = cache[ ++k ]; + ++i; + continue; + } + if (c->count == 0 && c->ctx->screen == screen) { + // use this cache item + c->ctx->set(_color, _font, _function, _subwindow); + c->ctx->used = true; + c->count = 1; + c->hits = 1; + return c; + } + // cache fault! + fprintf(stderr, "BGCCache: cache fault\n"); + abort(); + } + + const unsigned long fontid = _font ? _font->fid : 0; + if (c->ctx) { + // reuse existing context + if (fontid && fontid != c->ctx->fontid) + c->ctx->set(_font); + c->count++; + c->hits++; + if (prev && c->hits > prev->hits) { + cache[ k ] = prev; + cache[ k - 1 ] = c; + } + } else { + c->ctx = nextContext(screen); + c->ctx->set(_color, _font, _function, _subwindow); + c->ctx->used = true; + c->count = 1; + c->hits = 1; + } + + return c; +} + + +void BGCCache::release(BGCCacheItem *_item) { + _item->count--; +} + + +void BGCCache::purge(void) { + for (unsigned int i = 0; i < cache_total_size; ++i) { + BGCCacheItem *d = cache[ i ]; + + if (d->ctx && d->count == 0) { + release(d->ctx); + d->ctx = 0; + } + } +} diff --git a/src/GCCache.hh b/src/GCCache.hh new file mode 100644 index 00000000..2e341390 --- /dev/null +++ b/src/GCCache.hh @@ -0,0 +1,133 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// GCCache.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef GCCACHE_HH +#define GCCACHE_HH + +extern "C" { +#include +} + +#include "BaseDisplay.hh" +#include "Color.hh" + +class BGCCacheItem; + +class BGCCacheContext { +public: + void set(const BColor &_color, const XFontStruct * const _font, + const int _function, const int _subwindow); + void set(const XFontStruct * const _font); + +private: + BGCCacheContext(const BaseDisplay * const _display) + : display(_display), gc(0), pixel(0ul), fontid(0ul), + function(0), subwindow(0), used(false), screen(~(0u)) {} + + const BaseDisplay *display; + GC gc; + unsigned long pixel; + unsigned long fontid; + int function; + int subwindow; + bool used; + unsigned int screen; + + BGCCacheContext(const BGCCacheContext &_nocopy); + BGCCacheContext &operator=(const BGCCacheContext &_nocopy); + + friend class BGCCache; + friend class BGCCacheItem; +}; + +class BGCCacheItem { +public: + inline const GC &gc(void) const { return ctx->gc; } + +private: + BGCCacheItem(void) : ctx(0), count(0), hits(0), fault(false) { } + + BGCCacheContext *ctx; + unsigned int count; + unsigned int hits; + bool fault; + + BGCCacheItem(const BGCCacheItem &_nocopy); + BGCCacheItem &operator=(const BGCCacheItem &_nocopy); + + friend class BGCCache; +}; + +class BGCCache { +public: + explicit BGCCache(const BaseDisplay * const _display); + ~BGCCache(void); + + // cleans up the cache + void purge(void); + + BGCCacheItem *find(const BColor &_color, const XFontStruct * const _font = 0, + int _function = GXcopy, int _subwindow = ClipByChildren); + void release(BGCCacheItem *_item); + +private: + BGCCacheContext *nextContext(unsigned int _screen); + void release(BGCCacheContext *ctx); + + // this is closely modelled after the Qt GC cache, but with some of the + // complexity stripped out + const BaseDisplay *display; + + const unsigned int context_count; + const unsigned int cache_size; + const unsigned int cache_buckets; + const unsigned int cache_total_size; + BGCCacheContext **contexts; + BGCCacheItem **cache; +}; + +class BPen { +public: + inline BPen(const BColor &_color, const XFontStruct * const _font = 0, + int _function = GXcopy, int _subwindow = ClipByChildren) + : color(_color), font(_font), function(_function), subwindow(_subwindow), + cache(_color.display()->gcCache()), item(0) { } + inline ~BPen(void) { if (item) cache->release(item); } + + inline const GC &gc(void) const { + if (! item) item = cache->find(color, font, function, subwindow); + return item->gc(); + } + +private: + const BColor &color; + const XFontStruct *font; + int function; + int subwindow; + + mutable BGCCache *cache; + mutable BGCCacheItem *item; +}; + + +#endif // GCCACHE_HH diff --git a/src/Geometry.cc b/src/Geometry.cc deleted file mode 100644 index cdc39474..00000000 --- a/src/Geometry.cc +++ /dev/null @@ -1,145 +0,0 @@ -// Geometry.cc for Openbox -// Copyright (c) 2002 - 2002 ben Jansens (ben@orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#include "Geometry.h" - -Point::Point() : m_x(0), m_y(0) { -} - -Point::Point(const Point &point) : m_x(point.m_x), m_y(point.m_y) { -} - -Point::Point(const int x, const int y) : m_x(x), m_y(y) { -} - -void Point::setX(const int x) { - m_x = x; -} - -void Point::setY(const int y) { - m_y = y; -} - -Size::Size() : m_w(0), m_h(0) { -} - -Size::Size(const Size &size) : m_w(size.m_w), m_h(size.m_h) { -} - -Size::Size(const unsigned int w, const unsigned int h) : m_w(w), m_h(h) { -} - -void Size::setW(const unsigned int w) { - m_w = w; -} - -void Size::setH(const unsigned int h) { - m_h = h; -} - -Rect::Rect() : m_origin(0, 0), m_size(0, 0) { -} - -Rect::Rect(const Point &origin, const Size &size) : m_origin(origin), - m_size(size) { -} - -Rect::Rect(const int x, const int y, const unsigned int w, const unsigned int h) - : m_origin(x, y), m_size(w, h) { -} - -void Rect::setSize(const Size &size) { - m_size = size; -} - -void Rect::setSize(const unsigned int w, const unsigned int h) { - m_size.setW(w); - m_size.setH(h); -} - -void Rect::setOrigin(const Point &origin) { - m_origin = origin; -} - -void Rect::setOrigin(const int x, const int y) { - m_origin.setX(x); - m_origin.setY(y); -} - -void Rect::setX(const int x) { - m_origin.setX(x); -} - -void Rect::setY(const int y) { - m_origin.setY(y); -} - -void Rect::setW(unsigned int w) { - m_size.setW(w); -} - -void Rect::setH(unsigned int h) { - m_size.setH(h); -} - -bool Rect::Intersect(const Rect &r) const { - return - (x() < (r.x()+(signed)r.w()) ) && - ( (x()+(signed)w()) > r.x()) && - (y() < (r.y()+(signed)r.h()) ) && - ( (y()+(signed)h()) > r.y()); -} - -Rect Rect::Inflate(const unsigned int i) const { - return Rect(x(), y(), w()+i, h()+i); -} - -Rect Rect::Inflate(const unsigned int iw, const unsigned int ih) const { - return Rect(x(), y(), w()+iw, h()+ih); -} - -Rect Rect::Inflate(const Size &i) const { - return Rect(x(), y(), w()+i.w(), h()+i.h()); -} - -Rect Rect::Deflate(const unsigned int d) const { - return Rect(x(), y(), w()-d, h()-d); -} - -Rect Rect::Deflate(const unsigned int dw, const unsigned int dh) const { - return Rect(x(), y(), w()-dw, h()-dh); -} - -Rect Rect::Deflate(const Size &d) const { - return Rect(x(), y(), w()-d.w(), h()-d.h()); -} - -Rect Rect::Translate(const int t) const { - return Rect(x()+t, y()+t, w(), h()); -} - -Rect Rect::Translate(const int tx, const int ty) const { - return Rect(x()+tx, y()+ty, w(), h()); -} - -Rect Rect::Translate(const Point &t) const { - return Rect(x()+t.x(), y()+t.y(), w(), h()); -} diff --git a/src/Geometry.h b/src/Geometry.h deleted file mode 100644 index 0ca914b5..00000000 --- a/src/Geometry.h +++ /dev/null @@ -1,116 +0,0 @@ -// Geometry.h for Openbox -// Copyright (c) 2002 - 2002 ben Jansens (ben@orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __geometry_h -#define __geometry_h - -class Point{ - int m_x, m_y; -public: - Point(); - Point(const Point &point); - Point(const int x, const int y); - - void setX(const int x); - inline int x() const { - return m_x; - } - - void setY(const int y); - inline int y() const { - return m_y; - } -}; - -class Size{ - unsigned int m_w, m_h; -public: - Size(); - Size(const Size &size); - Size(const unsigned int w, const unsigned int h); - - void setW(const unsigned int w); - inline unsigned int w() const { - return m_w; - } - - void setH(const unsigned int h); - inline unsigned int h() const { - return m_h; - } -}; - -class Rect{ - Point m_origin; - Size m_size; -public: - Rect(); - Rect(const Point &origin, const Size &size); - Rect(const int x, const int y, const unsigned int w, const unsigned int h); - - void setSize(const Size &size); - void setSize(const unsigned int w, const unsigned int h); - inline const Size &size() const { - return const_cast(m_size); - } - - void setOrigin(const Point &origin); - void setOrigin(const int x, const int y); - inline const Point &origin() const { - return const_cast(m_origin); - } - - void setX(const int x); - inline int x() const { - return m_origin.x(); - } - - void setY(const int y); - inline int y() const { - return m_origin.y(); - } - - void setW(const unsigned int w); - inline unsigned int w() const { - return m_size.w(); - } - - void setH(const unsigned int h); - inline unsigned int h() const { - return m_size.h(); - } - - bool Intersect(const Rect &r) const; - // returns a rect that is this rect increased in size by the passed in amount - Rect Inflate(const unsigned int i) const; - Rect Inflate(const unsigned int iw, const unsigned int ih) const; - Rect Inflate(const Size &i) const; - // returns a rect that is this rect decreased in size by the passed in amount - Rect Deflate(const unsigned int d) const; - Rect Deflate(const unsigned int dw, const unsigned int dh) const; - Rect Deflate(const Size &d) const; - // returns a rect that is moved the amount specified - Rect Translate(const int t) const; - Rect Translate(const int tx, const int ty) const; - Rect Translate(const Point &t) const; -}; - -#endif // __geometry_h diff --git a/src/Iconmenu.cc b/src/Iconmenu.cc index 984cdfa9..dba587a2 100644 --- a/src/Iconmenu.cc +++ b/src/Iconmenu.cc @@ -1,5 +1,6 @@ -// Iconmenu.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Icon.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,23 +21,17 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "i18n.h" -#include "Iconmenu.h" -#include "Screen.h" -#include "Window.h" +#include "i18n.hh" +#include "Iconmenu.hh" +#include "Screen.hh" +#include "Window.hh" -Iconmenu::Iconmenu(BScreen &scrn) : Basemenu(scrn), screen(scrn) { +Iconmenu::Iconmenu(BScreen *scrn) : Basemenu(scrn) { setInternalMenu(); setLabel(i18n(IconSet, IconIcons, "Icons")); @@ -44,12 +39,12 @@ Iconmenu::Iconmenu(BScreen &scrn) : Basemenu(scrn), screen(scrn) { } -void Iconmenu::itemSelected(int button, int index) { +void Iconmenu::itemSelected(int button, unsigned int index) { if (button != 1) return; - if (index >= 0 && index < screen.getIconCount()) { - OpenboxWindow *win = screen.getIcon(index); + if (index < getScreen()->getIconCount()) { + BlackboxWindow *win = getScreen()->getIcon(index); if (win) { win->deiconify(); @@ -57,6 +52,6 @@ void Iconmenu::itemSelected(int button, int index) { } } - if (! (screen.getWorkspacemenu()->isTorn() || isTorn())) + if (! (getScreen()->getWorkspacemenu()->isTorn() || isTorn())) hide(); } diff --git a/src/Iconmenu.h b/src/Iconmenu.h deleted file mode 100644 index 609f03a3..00000000 --- a/src/Iconmenu.h +++ /dev/null @@ -1,44 +0,0 @@ -// Iconmenu.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Icon_hh -#define __Icon_hh - -#include "Basemenu.h" - -// forward declaration -class Iconmenu; -class BScreen; - -class Iconmenu : public Basemenu { -private: - BScreen &screen; - -protected: - virtual void itemSelected(int, int); - -public: - Iconmenu(BScreen &); -}; - - -#endif // __Icon_hh diff --git a/src/Image.cc b/src/Image.cc index 0172f53f..c20c4f7c 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -1,5 +1,6 @@ -// Image.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Image.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,72 +21,29 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "i18n.h" -#include "BaseDisplay.h" -#include "Image.h" - -#ifdef HAVE_SYS_TYPES_H -# include -#endif // HAVE_SYS_TYPES_H - -#ifndef u_int32_t -# ifdef uint_32_t -typedef uint32_t u_int32_t; -# else -# ifdef __uint32_t -typedef __uint32_t u_int32_t; -# else -typedef unsigned int u_int32_t; -# endif -# endif -#endif - -#ifdef HAVE_STDLIB_H -# include -#endif // HAVE_STDLIB_H - -#ifdef HAVE_STRING_H -# include -#endif // HAVE_STRING_H - #ifdef HAVE_STDIO_H # include #endif // HAVE_STDIO_H -#ifdef HAVE_CTYPE_H -# include -#endif // HAVE_CTYPE_H - #include -using std::min; using std::max; +using std::min; -static unsigned long bsqrt(unsigned long x) { - if (x <= 0) return 0; - if (x == 1) return 1; +#include "blackbox.hh" +#include "i18n.hh" +#include "BaseDisplay.hh" +#include "GCCache.hh" +#include "Image.hh" +#include "Texture.hh" - unsigned long r = x >> 1; - unsigned long q; - while (1) { - q = x / r; - if (q >= r) return r; - r = (r + q) >> 1; - } -} +BImage::BImage(BImageControl *c, unsigned int w, unsigned int h) { + control = c; - -BImage::BImage(BImageControl &c, unsigned int w, unsigned int h) : control(c) { width = ((signed) w > 0) ? w : 1; height = ((signed) h > 0) ? h : 1; @@ -95,15 +53,15 @@ BImage::BImage(BImageControl &c, unsigned int w, unsigned int h) : control(c) { xtable = ytable = (unsigned int *) 0; - cpc = control.getColorsPerChannel(); + cpc = control->getColorsPerChannel(); cpccpc = cpc * cpc; - control.getColorTables(&red_table, &green_table, &blue_table, - &red_offset, &green_offset, &blue_offset, - &red_bits, &green_bits, &blue_bits); + control->getColorTables(&red_table, &green_table, &blue_table, + &red_offset, &green_offset, &blue_offset, + &red_bits, &green_bits, &blue_bits); - if (control.getVisual()->c_class != TrueColor) - control.getXColorTable(&colors, &ncolors); + if (control->getVisual()->c_class != TrueColor) + control->getXColorTable(&colors, &ncolors); } @@ -114,149 +72,122 @@ BImage::~BImage(void) { } -Pixmap BImage::render(BTexture *texture) { - if (texture->getTexture() & BImage_ParentRelative) +Pixmap BImage::render(const BTexture &texture) { + if ((texture.texture() & BTexture::Parent_Relative)) return ParentRelative; - else if (texture->getTexture() & BImage_Solid) + else if ((texture.texture() & BTexture::Solid)) return render_solid(texture); - else if (texture->getTexture() & BImage_Gradient) + else if ((texture.texture() & BTexture::Gradient)) return render_gradient(texture); - return None; } -Pixmap BImage::render_solid(BTexture *texture) { - Pixmap pixmap = XCreatePixmap(control.getBaseDisplay().getXDisplay(), - control.getDrawable(), width, - height, control.getDepth()); +Pixmap BImage::render_solid(const BTexture &texture) { + Pixmap pixmap = XCreatePixmap(control->getBaseDisplay()->getXDisplay(), + control->getDrawable(), width, + height, control->getDepth()); if (pixmap == None) { fprintf(stderr, i18n(ImageSet, ImageErrorCreatingSolidPixmap, "BImage::render_solid: error creating pixmap\n")); return None; } - XGCValues gcv; - GC gc, hgc, lgc; - - gcv.foreground = texture->getColor()->getPixel(); - gcv.fill_style = FillSolid; - gc = XCreateGC(control.getBaseDisplay().getXDisplay(), pixmap, - GCForeground | GCFillStyle, &gcv); - - gcv.foreground = texture->getHiColor()->getPixel(); - hgc = XCreateGC(control.getBaseDisplay().getXDisplay(), pixmap, - GCForeground, &gcv); - - gcv.foreground = texture->getLoColor()->getPixel(); - lgc = XCreateGC(control.getBaseDisplay().getXDisplay(), pixmap, - GCForeground, &gcv); + Display *display = control->getBaseDisplay()->getXDisplay(); - XFillRectangle(control.getBaseDisplay().getXDisplay(), pixmap, gc, 0, 0, - width, height); + BPen pen(texture.color()); + BPen penlight(texture.lightColor()); + BPen penshadow(texture.shadowColor()); -#ifdef INTERLACE - if (texture->getTexture() & BImage_Interlaced) { - gcv.foreground = texture->getColorTo()->getPixel(); - GC igc = XCreateGC(control.getBaseDisplay().getXDisplay(), pixmap, - GCForeground, &gcv); + XFillRectangle(display, pixmap, pen.gc(), 0, 0, width, height); + if (texture.texture() & BTexture::Interlaced) { + BPen peninterlace(texture.colorTo()); register unsigned int i = 0; for (; i < height; i += 2) - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, igc, - 0, i, width, i); - - XFreeGC(control.getBaseDisplay().getXDisplay(), igc); + XDrawLine(display, pixmap, peninterlace.gc(), 0, i, width, i); } -#endif // INTERLACE - - if (texture->getTexture() & BImage_Bevel1) { - if (texture->getTexture() & BImage_Raised) { - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc, + if (texture.texture() & BTexture::Bevel1) { + if (texture.texture() & BTexture::Raised) { + XDrawLine(display, pixmap, penshadow.gc(), 0, height - 1, width - 1, height - 1); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc, + XDrawLine(display, pixmap, penshadow.gc(), width - 1, height - 1, width - 1, 0); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc, + XDrawLine(display, pixmap, penlight.gc(), 0, 0, width - 1, 0); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc, + XDrawLine(display, pixmap, penlight.gc(), 0, height - 1, 0, 0); - } else if (texture->getTexture() & BImage_Sunken) { - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc, + } else if (texture.texture() & BTexture::Sunken) { + XDrawLine(display, pixmap, penlight.gc(), 0, height - 1, width - 1, height - 1); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc, + XDrawLine(display, pixmap, penlight.gc(), width - 1, height - 1, width - 1, 0); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc, + XDrawLine(display, pixmap, penshadow.gc(), 0, 0, width - 1, 0); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc, + XDrawLine(display, pixmap, penshadow.gc(), 0, height - 1, 0, 0); } - } else if (texture->getTexture() & BImage_Bevel2) { - if (texture->getTexture() & BImage_Raised) { - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc, + } else if (texture.texture() & BTexture::Bevel2) { + if (texture.texture() & BTexture::Raised) { + XDrawLine(display, pixmap, penshadow.gc(), 1, height - 3, width - 3, height - 3); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc, + XDrawLine(display, pixmap, penshadow.gc(), width - 3, height - 3, width - 3, 1); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc, + XDrawLine(display, pixmap, penlight.gc(), 1, 1, width - 3, 1); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc, + XDrawLine(display, pixmap, penlight.gc(), 1, height - 3, 1, 1); - } else if (texture->getTexture() & BImage_Sunken) { - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc, + } else if (texture.texture() & BTexture::Sunken) { + XDrawLine(display, pixmap, penlight.gc(), 1, height - 3, width - 3, height - 3); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, hgc, + XDrawLine(display, pixmap, penlight.gc(), width - 3, height - 3, width - 3, 1); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc, + XDrawLine(display, pixmap, penshadow.gc(), 1, 1, width - 3, 1); - XDrawLine(control.getBaseDisplay().getXDisplay(), pixmap, lgc, + XDrawLine(display, pixmap, penshadow.gc(), 1, height - 3, 1, 1); } } - XFreeGC(control.getBaseDisplay().getXDisplay(), gc); - XFreeGC(control.getBaseDisplay().getXDisplay(), hgc); - XFreeGC(control.getBaseDisplay().getXDisplay(), lgc); - return pixmap; } -Pixmap BImage::render_gradient(BTexture *texture) { - int inverted = 0; +Pixmap BImage::render_gradient(const BTexture &texture) { + int inverted = 0; -#ifdef INTERLACE - interlaced = texture->getTexture() & BImage_Interlaced; -#endif // INTERLACE + interlaced = texture.texture() & BTexture::Interlaced; - if (texture->getTexture() & BImage_Sunken) { - from = texture->getColorTo(); - to = texture->getColor(); + if (texture.texture() & BTexture::Sunken) { + from = texture.colorTo(); + to = texture.color(); - if (! (texture->getTexture() & BImage_Invert)) inverted = 1; + if (! (texture.texture() & BTexture::Invert)) inverted = 1; } else { - from = texture->getColor(); - to = texture->getColorTo(); + from = texture.color(); + to = texture.colorTo(); - if (texture->getTexture() & BImage_Invert) inverted = 1; + if (texture.texture() & BTexture::Invert) inverted = 1; } - control.getGradientBuffers(width, height, &xtable, &ytable); + control->getGradientBuffers(width, height, &xtable, &ytable); - if (texture->getTexture() & BImage_Diagonal) dgradient(); - else if (texture->getTexture() & BImage_Elliptic) egradient(); - else if (texture->getTexture() & BImage_Horizontal) hgradient(); - else if (texture->getTexture() & BImage_Pyramid) pgradient(); - else if (texture->getTexture() & BImage_Rectangle) rgradient(); - else if (texture->getTexture() & BImage_Vertical) vgradient(); - else if (texture->getTexture() & BImage_CrossDiagonal) cdgradient(); - else if (texture->getTexture() & BImage_PipeCross) pcgradient(); + if (texture.texture() & BTexture::Diagonal) dgradient(); + else if (texture.texture() & BTexture::Elliptic) egradient(); + else if (texture.texture() & BTexture::Horizontal) hgradient(); + else if (texture.texture() & BTexture::Pyramid) pgradient(); + else if (texture.texture() & BTexture::Rectangle) rgradient(); + else if (texture.texture() & BTexture::Vertical) vgradient(); + else if (texture.texture() & BTexture::CrossDiagonal) cdgradient(); + else if (texture.texture() & BTexture::PipeCross) pcgradient(); - if (texture->getTexture() & BImage_Bevel1) bevel1(); - else if (texture->getTexture() & BImage_Bevel2) bevel2(); + if (texture.texture() & BTexture::Bevel1) bevel1(); + else if (texture.texture() & BTexture::Bevel2) bevel2(); if (inverted) invert(); @@ -267,10 +198,253 @@ Pixmap BImage::render_gradient(BTexture *texture) { } +static const unsigned char dither4[4][4] = { + {0, 4, 1, 5}, + {6, 2, 7, 3}, + {1, 5, 0, 4}, + {7, 3, 6, 2} +}; + + +/* + * Helper function for TrueColorDither and renderXImage + * + * This handles the proper setting of the image data based on the image depth + * and the machine's byte ordering + */ +static inline +void assignPixelData(unsigned int bit_depth, unsigned char **data, + unsigned long pixel) { + unsigned char *pixel_data = *data; + switch (bit_depth) { + case 8: // 8bpp + *pixel_data++ = pixel; + break; + + case 16: // 16bpp LSB + *pixel_data++ = pixel; + *pixel_data++ = pixel >> 8; + break; + + case 17: // 16bpp MSB + *pixel_data++ = pixel >> 8; + *pixel_data++ = pixel; + break; + + case 24: // 24bpp LSB + *pixel_data++ = pixel; + *pixel_data++ = pixel >> 8; + *pixel_data++ = pixel >> 16; + break; + + case 25: // 24bpp MSB + *pixel_data++ = pixel >> 16; + *pixel_data++ = pixel >> 8; + *pixel_data++ = pixel; + break; + + case 32: // 32bpp LSB + *pixel_data++ = pixel; + *pixel_data++ = pixel >> 8; + *pixel_data++ = pixel >> 16; + *pixel_data++ = pixel >> 24; + break; + + case 33: // 32bpp MSB + *pixel_data++ = pixel >> 24; + *pixel_data++ = pixel >> 16; + *pixel_data++ = pixel >> 8; + *pixel_data++ = pixel; + break; + } + *data = pixel_data; // assign back so we don't lose our place +} + + +// algorithm: ordered dithering... many many thanks to rasterman +// (raster@rasterman.com) for telling me about this... portions of this +// code is based off of his code in Imlib +void BImage::TrueColorDither(unsigned int bit_depth, int bytes_per_line, + unsigned char *pixel_data) { + unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset; + unsigned char *ppixel_data = pixel_data; + unsigned long pixel; + + for (y = 0, offset = 0; y < height; y++) { + dithy = y & 0x3; + + for (x = 0; x < width; x++, offset++) { + dithx = x & 0x3; + r = red[offset]; + g = green[offset]; + b = blue[offset]; + + er = r & (red_bits - 1); + eg = g & (green_bits - 1); + eb = b & (blue_bits - 1); + + r = red_table[r]; + g = green_table[g]; + b = blue_table[b]; + + if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++; + if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++; + if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++; + + pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset); + assignPixelData(bit_depth, &pixel_data, pixel); + } + + pixel_data = (ppixel_data += bytes_per_line); + } +} + +#ifdef ORDEREDPSEUDO +const static unsigned char dither8[8][8] = { + { 0, 32, 8, 40, 2, 34, 10, 42}, + { 48, 16, 56, 24, 50, 18, 58, 26}, + { 12, 44, 4, 36, 14, 46, 6, 38}, + { 60, 28, 52, 20, 62, 30, 54, 22}, + { 3, 35, 11, 43, 1, 33, 9, 41}, + { 51, 19, 59, 27, 49, 17, 57, 25}, + { 15, 47, 7, 39, 13, 45, 5, 37}, + { 63, 31, 55, 23, 61, 29, 53, 21} +}; + +void BImage::OrderedPseudoColorDither(int bytes_per_line, + unsigned char *pixel_data) { + unsigned int x, y, dithx, dithy, r, g, b, er, eg, eb, offset; + unsigned long pixel; + unsigned char *ppixel_data = pixel_data; + + for (y = 0, offset = 0; y < height; y++) { + dithy = y & 7; + + for (x = 0; x < width; x++, offset++) { + dithx = x & 7; + + r = red[offset]; + g = green[offset]; + b = blue[offset]; + + er = r & (red_bits - 1); + eg = g & (green_bits - 1); + eb = b & (blue_bits - 1); + + r = red_table[r]; + g = green_table[g]; + b = blue_table[b]; + + if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++; + if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++; + if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++; + + pixel = (r * cpccpc) + (g * cpc) + b; + *(pixel_data++) = colors[pixel].pixel; + } + + pixel_data = (ppixel_data += bytes_per_line); + } +} +#endif + +void BImage::PseudoColorDither(int bytes_per_line, unsigned char *pixel_data) { + short *terr, + *rerr = new short[width + 2], + *gerr = new short[width + 2], + *berr = new short[width + 2], + *nrerr = new short[width + 2], + *ngerr = new short[width + 2], + *nberr = new short[width + 2]; + + int rr, gg, bb, rer, ger, ber; + int dd = 255 / control->getColorsPerChannel(); + unsigned int x, y, r, g, b, offset; + unsigned long pixel; + unsigned char *ppixel_data = pixel_data; + + for (x = 0; x < width; x++) { + *(rerr + x) = *(red + x); + *(gerr + x) = *(green + x); + *(berr + x) = *(blue + x); + } + + *(rerr + x) = *(gerr + x) = *(berr + x) = 0; + + for (y = 0, offset = 0; y < height; y++) { + if (y < (height - 1)) { + int i = offset + width; + for (x = 0; x < width; x++, i++) { + *(nrerr + x) = *(red + i); + *(ngerr + x) = *(green + i); + *(nberr + x) = *(blue + i); + } + + *(nrerr + x) = *(red + (--i)); + *(ngerr + x) = *(green + i); + *(nberr + x) = *(blue + i); + } + + for (x = 0; x < width; x++) { + rr = rerr[x]; + gg = gerr[x]; + bb = berr[x]; + + if (rr > 255) rr = 255; else if (rr < 0) rr = 0; + if (gg > 255) gg = 255; else if (gg < 0) gg = 0; + if (bb > 255) bb = 255; else if (bb < 0) bb = 0; + + r = red_table[rr]; + g = green_table[gg]; + b = blue_table[bb]; + + rer = rerr[x] - r*dd; + ger = gerr[x] - g*dd; + ber = berr[x] - b*dd; + + pixel = (r * cpccpc) + (g * cpc) + b; + *pixel_data++ = colors[pixel].pixel; + + r = rer >> 1; + g = ger >> 1; + b = ber >> 1; + rerr[x+1] += r; + gerr[x+1] += g; + berr[x+1] += b; + nrerr[x] += r; + ngerr[x] += g; + nberr[x] += b; + } + + offset += width; + + pixel_data = (ppixel_data += bytes_per_line); + + terr = rerr; + rerr = nrerr; + nrerr = terr; + + terr = gerr; + gerr = ngerr; + ngerr = terr; + + terr = berr; + berr = nberr; + nberr = terr; + } + + delete [] rerr; + delete [] gerr; + delete [] berr; + delete [] nrerr; + delete [] ngerr; + delete [] nberr; +} + XImage *BImage::renderXImage(void) { XImage *image = - XCreateImage(control.getBaseDisplay().getXDisplay(), - control.getVisual(), control.getDepth(), ZPixmap, 0, 0, + XCreateImage(control->getBaseDisplay()->getXDisplay(), + control->getVisual(), control->getDepth(), ZPixmap, 0, 0, width, height, 32, 0); if (! image) { @@ -283,347 +457,108 @@ XImage *BImage::renderXImage(void) { image->data = (char *) 0; unsigned char *d = new unsigned char[image->bytes_per_line * (height + 1)]; - register unsigned int x, y, dithx, dithy, r, g, b, o, er, eg, eb, offset; - unsigned char *pixel_data = d, *ppixel_data = d; - unsigned long pixel; + unsigned int o = image->bits_per_pixel + + ((image->byte_order == MSBFirst) ? 1 : 0); + + if (control->doDither() && width > 1 && height > 1) { + switch (control->getVisual()->c_class) { + case TrueColor: + TrueColorDither(o, image->bytes_per_line, d); + break; - o = image->bits_per_pixel + ((image->byte_order == MSBFirst) ? 1 : 0); - - if (control.doDither() && width > 1 && height > 1) { - unsigned char dither4[4][4] = { {0, 4, 1, 5}, - {6, 2, 7, 3}, - {1, 5, 0, 4}, - {7, 3, 6, 2} }; - -#ifdef ORDEREDPSEUDO - unsigned char dither8[8][8] = { { 0, 32, 8, 40, 2, 34, 10, 42 }, - { 48, 16, 56, 24, 50, 18, 58, 26 }, - { 12, 44, 4, 36, 14, 46, 6, 38 }, - { 60, 28, 52, 20, 62, 30, 54, 22 }, - { 3, 35, 11, 43, 1, 33, 9, 41 }, - { 51, 19, 59, 27, 49, 17, 57, 25 }, - { 15, 47, 7, 39, 13, 45, 5, 37 }, - { 63, 31, 55, 23, 61, 29, 53, 21 } }; -#endif // ORDEREDPSEUDO - - switch (control.getVisual()->c_class) { - case TrueColor: - // algorithm: ordered dithering... many many thanks to rasterman - // (raster@rasterman.com) for telling me about this... portions of this - // code is based off of his code in Imlib - for (y = 0, offset = 0; y < height; y++) { - dithy = y & 0x3; - - for (x = 0; x < width; x++, offset++) { - dithx = x & 0x3; - r = red[offset]; - g = green[offset]; - b = blue[offset]; - - er = r & (red_bits - 1); - eg = g & (green_bits - 1); - eb = b & (blue_bits - 1); - - r = red_table[r]; - g = green_table[g]; - b = blue_table[b]; - - if ((dither4[dithy][dithx] < er) && (r < red_table[255])) r++; - if ((dither4[dithy][dithx] < eg) && (g < green_table[255])) g++; - if ((dither4[dithy][dithx] < eb) && (b < blue_table[255])) b++; - - pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset); - - switch (o) { - case 8: // 8bpp - *pixel_data++ = pixel; - break; - - case 16: // 16bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - break; - - case 17: // 16bpp MSB - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; - - case 24: // 24bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel >> 16; - break; - - case 25: // 24bpp MSB - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; - - case 32: // 32bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 24; - break; - - case 33: // 32bpp MSB - *pixel_data++ = pixel >> 24; - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; - } - } - - pixel_data = (ppixel_data += image->bytes_per_line); - } - - break; - - case StaticColor: - case PseudoColor: { -#ifndef ORDEREDPSEUDO - short *terr, - *rerr = new short[width + 2], - *gerr = new short[width + 2], - *berr = new short[width + 2], - *nrerr = new short[width + 2], - *ngerr = new short[width + 2], - *nberr = new short[width + 2]; - int rr, gg, bb, rer, ger, ber; - int dd = 255 / control.getColorsPerChannel(); - - for (x = 0; x < width; x++) { - *(rerr + x) = *(red + x); - *(gerr + x) = *(green + x); - *(berr + x) = *(blue + x); - } - - *(rerr + x) = *(gerr + x) = *(berr + x) = 0; -#endif // ORDEREDPSEUDO - - for (y = 0, offset = 0; y < height; y++) { -#ifdef ORDEREDPSEUDO - dithy = y & 7; - - for (x = 0; x < width; x++, offset++) { - dithx = x & 7; - - r = red[offset]; - g = green[offset]; - b = blue[offset]; - - er = r & (red_bits - 1); - eg = g & (green_bits - 1); - eb = b & (blue_bits - 1); - - r = red_table[r]; - g = green_table[g]; - b = blue_table[b]; - - if ((dither8[dithy][dithx] < er) && (r < red_table[255])) r++; - if ((dither8[dithy][dithx] < eg) && (g < green_table[255])) g++; - if ((dither8[dithy][dithx] < eb) && (b < blue_table[255])) b++; - - pixel = (r * cpccpc) + (g * cpc) + b; - *(pixel_data++) = colors[pixel].pixel; - } - - pixel_data = (ppixel_data += image->bytes_per_line); - } -#else // !ORDEREDPSEUDO - if (y < (height - 1)) { - int i = offset + width; - for (x = 0; x < width; x++, i++) { - *(nrerr + x) = *(red + i); - *(ngerr + x) = *(green + i); - *(nberr + x) = *(blue + i); - } - - *(nrerr + x) = *(red + (--i)); - *(ngerr + x) = *(green + i); - *(nberr + x) = *(blue + i); - } - - for (x = 0; x < width; x++) { - rr = rerr[x]; - gg = gerr[x]; - bb = berr[x]; - - if (rr > 255) rr = 255; else if (rr < 0) rr = 0; - if (gg > 255) gg = 255; else if (gg < 0) gg = 0; - if (bb > 255) bb = 255; else if (bb < 0) bb = 0; - - r = red_table[rr]; - g = green_table[gg]; - b = blue_table[bb]; - - rer = rerr[x] - r*dd; - ger = gerr[x] - g*dd; - ber = berr[x] - b*dd; - - pixel = (r * cpccpc) + (g * cpc) + b; - *pixel_data++ = colors[pixel].pixel; - - r = rer >> 1; - g = ger >> 1; - b = ber >> 1; - rerr[x+1] += r; - gerr[x+1] += g; - berr[x+1] += b; - nrerr[x] += r; - ngerr[x] += g; - nberr[x] += b; - } - - offset += width; - - pixel_data = (ppixel_data += image->bytes_per_line); - - terr = rerr; - rerr = nrerr; - nrerr = terr; - - terr = gerr; - gerr = ngerr; - ngerr = terr; - - terr = berr; - berr = nberr; - nberr = terr; + case StaticColor: + case PseudoColor: { +#ifdef ORDEREDPSEUDO + OrderedPseudoColorDither(image->bytes_per_line, d); +#else + PseudoColorDither(image->bytes_per_line, d); +#endif + break; + } + + default: + fprintf(stderr, i18n(ImageSet, ImageUnsupVisual, + "BImage::renderXImage: unsupported visual\n")); + delete [] d; + XDestroyImage(image); + return (XImage *) 0; + } + } else { + register unsigned int x, y, r, g, b, offset; + + unsigned char *pixel_data = d, *ppixel_data = d; + unsigned long pixel; + + switch (control->getVisual()->c_class) { + case StaticColor: + case PseudoColor: + for (y = 0, offset = 0; y < height; y++) { + for (x = 0; x < width; x++, offset++) { + r = red_table[red[offset]]; + g = green_table[green[offset]]; + b = blue_table[blue[offset]]; + + pixel = (r * cpccpc) + (g * cpc) + b; + *pixel_data++ = colors[pixel].pixel; } - delete [] rerr; - delete [] gerr; - delete [] berr; - delete [] nrerr; - delete [] ngerr; - delete [] nberr; -#endif // ORDEREDPSUEDO - - break; } - - default: - fprintf(stderr, i18n(ImageSet, ImageUnsupVisual, - "BImage::renderXImage: unsupported visual\n")); - delete [] d; - XDestroyImage(image); - return (XImage *) 0; - } -} else { - switch (control.getVisual()->c_class) { - case StaticColor: - case PseudoColor: - for (y = 0, offset = 0; y < height; y++) { - for (x = 0; x < width; x++, offset++) { - r = red_table[red[offset]]; - g = green_table[green[offset]]; - b = blue_table[blue[offset]]; - - pixel = (r * cpccpc) + (g * cpc) + b; - *pixel_data++ = colors[pixel].pixel; + pixel_data = (ppixel_data += image->bytes_per_line); } - pixel_data = (ppixel_data += image->bytes_per_line); - } + break; - break; + case TrueColor: + for (y = 0, offset = 0; y < height; y++) { + for (x = 0; x < width; x++, offset++) { + r = red_table[red[offset]]; + g = green_table[green[offset]]; + b = blue_table[blue[offset]]; - case TrueColor: - for (y = 0, offset = 0; y < height; y++) { - for (x = 0; x < width; x++, offset++) { - r = red_table[red[offset]]; - g = green_table[green[offset]]; - b = blue_table[blue[offset]]; - - pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset); - - switch (o) { - case 8: // 8bpp - *pixel_data++ = pixel; - break; - - case 16: // 16bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - break; - - case 17: // 16bpp MSB - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; - - case 24: // 24bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel >> 16; - break; - - case 25: // 24bpp MSB - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; - - case 32: // 32bpp LSB - *pixel_data++ = pixel; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 24; - break; - - case 33: // 32bpp MSB - *pixel_data++ = pixel >> 24; - *pixel_data++ = pixel >> 16; - *pixel_data++ = pixel >> 8; - *pixel_data++ = pixel; - break; + pixel = (r << red_offset) | (g << green_offset) | (b << blue_offset); + assignPixelData(o, &pixel_data, pixel); } + + pixel_data = (ppixel_data += image->bytes_per_line); } - pixel_data = (ppixel_data += image->bytes_per_line); - } + break; - break; + case StaticGray: + case GrayScale: + for (y = 0, offset = 0; y < height; y++) { + for (x = 0; x < width; x++, offset++) { + r = *(red_table + *(red + offset)); + g = *(green_table + *(green + offset)); + b = *(blue_table + *(blue + offset)); - case StaticGray: - case GrayScale: - for (y = 0, offset = 0; y < height; y++) { - for (x = 0; x < width; x++, offset++) { - r = *(red_table + *(red + offset)); - g = *(green_table + *(green + offset)); - b = *(blue_table + *(blue + offset)); + g = ((r * 30) + (g * 59) + (b * 11)) / 100; + *pixel_data++ = colors[g].pixel; + } - g = ((r * 30) + (g * 59) + (b * 11)) / 100; - *pixel_data++ = colors[g].pixel; + pixel_data = (ppixel_data += image->bytes_per_line); } - pixel_data = (ppixel_data += image->bytes_per_line); - } - - break; + break; - default: - fprintf(stderr, i18n(ImageSet, ImageUnsupVisual, - "BImage::renderXImage: unsupported visual\n")); - delete [] d; - XDestroyImage(image); - return (XImage *) 0; + default: + fprintf(stderr, i18n(ImageSet, ImageUnsupVisual, + "BImage::renderXImage: unsupported visual\n")); + delete [] d; + XDestroyImage(image); + return (XImage *) 0; + } } -} -image->data = (char *) d; -return image; + image->data = (char *) d; + return image; } Pixmap BImage::renderPixmap(void) { Pixmap pixmap = - XCreatePixmap(control.getBaseDisplay().getXDisplay(), - control.getDrawable(), width, height, control.getDepth()); + XCreatePixmap(control->getBaseDisplay()->getXDisplay(), + control->getDrawable(), width, height, control->getDepth()); if (pixmap == None) { fprintf(stderr, i18n(ImageSet, ImageErrorCreatingPixmap, @@ -634,17 +569,17 @@ Pixmap BImage::renderPixmap(void) { XImage *image = renderXImage(); if (! image) { - XFreePixmap(control.getBaseDisplay().getXDisplay(), pixmap); + XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap); return None; } else if (! image->data) { XDestroyImage(image); - XFreePixmap(control.getBaseDisplay().getXDisplay(), pixmap); + XFreePixmap(control->getBaseDisplay()->getXDisplay(), pixmap); return None; } - XPutImage(control.getBaseDisplay().getXDisplay(), pixmap, - DefaultGC(control.getBaseDisplay().getXDisplay(), - control.getScreenInfo().getScreenNumber()), + XPutImage(control->getBaseDisplay()->getXDisplay(), pixmap, + DefaultGC(control->getBaseDisplay()->getXDisplay(), + control->getScreenInfo()->getScreenNumber()), image, 0, 0, 0, 0, width, height); if (image->data) { @@ -799,7 +734,7 @@ void BImage::bevel1(void) { void BImage::bevel2(void) { if (width > 4 && height > 4) { unsigned char r, g, b, rr ,gg ,bb, *pr = red + width + 1, - *pg = green + width + 1, *pb = blue + width + 1; + *pg = green + width + 1, *pb = blue + width + 1; unsigned int w = width - 2, h = height - 1, wh = width * (height - 3); while (--w) { @@ -900,17 +835,17 @@ void BImage::dgradient(void) { // modified for interlacing by Brad Hughes float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0, - xr = (float) from->getRed(), - xg = (float) from->getGreen(), - xb = (float) from->getBlue(); + xr = (float) from.red(), + xg = (float) from.green(), + xb = (float) from.blue(); unsigned char *pr = red, *pg = green, *pb = blue; unsigned int w = width * 2, h = height * 2, *xt = xtable, *yt = ytable; register unsigned int x, y; - dry = drx = (float) (to->getRed() - from->getRed()); - dgy = dgx = (float) (to->getGreen() - from->getGreen()); - dby = dbx = (float) (to->getBlue() - from->getBlue()); + dry = drx = (float) (to.red() - from.red()); + dgy = dgx = (float) (to.green() - from.green()); + dby = dbx = (float) (to.blue() - from.blue()); // Create X table drx /= w; @@ -944,10 +879,7 @@ void BImage::dgradient(void) { // Combine tables to create gradient -#ifdef INTERLACE if (! interlaced) { -#endif // INTERLACE - // normal dgradient for (yt = ytable, y = 0; y < height; y++, yt += 3) { for (xt = xtable, x = 0; x < width; x++) { @@ -956,8 +888,6 @@ void BImage::dgradient(void) { *(pb++) = *(xt++) + *(yt + 2); } } - -#ifdef INTERLACE } else { // faked interlacing effect unsigned char channel, channel2; @@ -998,29 +928,26 @@ void BImage::dgradient(void) { } } } -#endif // INTERLACE - } void BImage::hgradient(void) { float drx, dgx, dbx, - xr = (float) from->getRed(), - xg = (float) from->getGreen(), - xb = (float) from->getBlue(); + xr = (float) from.red(), + xg = (float) from.green(), + xb = (float) from.blue(); unsigned char *pr = red, *pg = green, *pb = blue; register unsigned int x, y; - drx = (float) (to->getRed() - from->getRed()); - dgx = (float) (to->getGreen() - from->getGreen()); - dbx = (float) (to->getBlue() - from->getBlue()); + drx = (float) (to.red() - from.red()); + dgx = (float) (to.green() - from.green()); + dbx = (float) (to.blue() - from.blue()); drx /= width; dgx /= width; dbx /= width; -#ifdef INTERLACE if (interlaced && height > 2) { // faked interlacing effect unsigned char channel, channel2; @@ -1076,8 +1003,6 @@ void BImage::hgradient(void) { memcpy(pb, (blue + offset), width); } } else { -#endif // INTERLACE - // normal hgradient for (x = 0; x < width; x++) { *(pr++) = (unsigned char) (xr); @@ -1094,32 +1019,27 @@ void BImage::hgradient(void) { memcpy(pg, green, width); memcpy(pb, blue, width); } - -#ifdef INTERLACE } -#endif // INTERLACE - } void BImage::vgradient(void) { float dry, dgy, dby, - yr = (float) from->getRed(), - yg = (float) from->getGreen(), - yb = (float) from->getBlue(); + yr = (float) from.red(), + yg = (float) from.green(), + yb = (float) from.blue(); unsigned char *pr = red, *pg = green, *pb = blue; register unsigned int y; - dry = (float) (to->getRed() - from->getRed()); - dgy = (float) (to->getGreen() - from->getGreen()); - dby = (float) (to->getBlue() - from->getBlue()); + dry = (float) (to.red() - from.red()); + dgy = (float) (to.green() - from.green()); + dby = (float) (to.blue() - from.blue()); dry /= height; dgy /= height; dby /= height; -#ifdef INTERLACE if (interlaced) { // faked interlacing effect unsigned char channel, channel2; @@ -1162,8 +1082,6 @@ void BImage::vgradient(void) { yb += dby; } } else { -#endif // INTERLACE - // normal vgradient for (y = 0; y < height; y++, pr += width, pg += width, pb += width) { memset(pr, (unsigned char) yr, width); @@ -1174,31 +1092,27 @@ void BImage::vgradient(void) { yg += dgy; yb += dby; } - -#ifdef INTERLACE } -#endif // INTERLACE - } void BImage::pgradient(void) { // pyramid gradient - based on original dgradient, written by // Mosfet (mosfet@kde.org) - // adapted from kde sources for Openbox by Brad Hughes + // adapted from kde sources for Blackbox by Brad Hughes float yr, yg, yb, drx, dgx, dbx, dry, dgy, dby, - xr, xg, xb; + xr, xg, xb; int rsign, gsign, bsign; unsigned char *pr = red, *pg = green, *pb = blue; - unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(), - *xt = xtable, *yt = ytable; + unsigned int tr = to.red(), tg = to.green(), tb = to.blue(), + *xt = xtable, *yt = ytable; register unsigned int x, y; - dry = drx = (float) (to->getRed() - from->getRed()); - dgy = dgx = (float) (to->getGreen() - from->getGreen()); - dby = dbx = (float) (to->getBlue() - from->getBlue()); + dry = drx = (float) (to.red() - from.red()); + dgy = dgx = (float) (to.green() - from.green()); + dby = dbx = (float) (to.blue() - from.blue()); rsign = (drx < 0) ? -1 : 1; gsign = (dgx < 0) ? -1 : 1; @@ -1240,10 +1154,7 @@ void BImage::pgradient(void) { // Combine tables to create gradient -#ifdef INTERLACE if (! interlaced) { -#endif // INTERLACE - // normal pgradient for (yt = ytable, y = 0; y < height; y++, yt += 3) { for (xt = xtable, x = 0; x < width; x++) { @@ -1252,8 +1163,6 @@ void BImage::pgradient(void) { *(pb++) = (unsigned char) (tb - (bsign * (*(xt++) + *(yt + 2)))); } } - -#ifdef INTERLACE } else { // faked interlacing effect unsigned char channel, channel2; @@ -1294,26 +1203,25 @@ void BImage::pgradient(void) { } } } -#endif // INTERLACE } void BImage::rgradient(void) { // rectangle gradient - based on original dgradient, written by // Mosfet (mosfet@kde.org) - // adapted from kde sources for Openbox by Brad Hughes + // adapted from kde sources for Blackbox by Brad Hughes float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb; int rsign, gsign, bsign; unsigned char *pr = red, *pg = green, *pb = blue; - unsigned int tr = to->getRed(), tg = to->getGreen(), tb = to->getBlue(), - *xt = xtable, *yt = ytable; + unsigned int tr = to.red(), tg = to.green(), tb = to.blue(), + *xt = xtable, *yt = ytable; register unsigned int x, y; - dry = drx = (float) (to->getRed() - from->getRed()); - dgy = dgx = (float) (to->getGreen() - from->getGreen()); - dby = dbx = (float) (to->getBlue() - from->getBlue()); + dry = drx = (float) (to.red() - from.red()); + dgy = dgx = (float) (to.green() - from.green()); + dby = dbx = (float) (to.blue() - from.blue()); rsign = (drx < 0) ? -2 : 2; gsign = (dgx < 0) ? -2 : 2; @@ -1355,10 +1263,7 @@ void BImage::rgradient(void) { // Combine tables to create gradient -#ifdef INTERLACE if (! interlaced) { -#endif // INTERLACE - // normal rgradient for (yt = ytable, y = 0; y < height; y++, yt += 3) { for (xt = xtable, x = 0; x < width; x++) { @@ -1367,8 +1272,6 @@ void BImage::rgradient(void) { *(pb++) = (unsigned char) (tb - (bsign * max(*(xt++), *(yt + 2)))); } } - -#ifdef INTERLACE } else { // faked interlacing effect unsigned char channel, channel2; @@ -1409,28 +1312,27 @@ void BImage::rgradient(void) { } } } -#endif // INTERLACE } void BImage::egradient(void) { // elliptic gradient - based on original dgradient, written by // Mosfet (mosfet@kde.org) - // adapted from kde sources for Openbox by Brad Hughes + // adapted from kde sources for Blackbox by Brad Hughes float drx, dgx, dbx, dry, dgy, dby, yr, yg, yb, xr, xg, xb; int rsign, gsign, bsign; unsigned char *pr = red, *pg = green, *pb = blue; unsigned int *xt = xtable, *yt = ytable, - tr = (unsigned long) to->getRed(), - tg = (unsigned long) to->getGreen(), - tb = (unsigned long) to->getBlue(); + tr = (unsigned long) to.red(), + tg = (unsigned long) to.green(), + tb = (unsigned long) to.blue(); register unsigned int x, y; - dry = drx = (float) (to->getRed() - from->getRed()); - dgy = dgx = (float) (to->getGreen() - from->getGreen()); - dby = dbx = (float) (to->getBlue() - from->getBlue()); + dry = drx = (float) (to.red() - from.red()); + dgy = dgx = (float) (to.green() - from.green()); + dby = dbx = (float) (to.blue() - from.blue()); rsign = (drx < 0) ? -1 : 1; gsign = (dgx < 0) ? -1 : 1; @@ -1472,23 +1374,18 @@ void BImage::egradient(void) { // Combine tables to create gradient -#ifdef INTERLACE if (! interlaced) { -#endif // INTERLACE - // normal egradient for (yt = ytable, y = 0; y < height; y++, yt += 3) { for (xt = xtable, x = 0; x < width; x++) { *(pr++) = (unsigned char) - (tr - (rsign * control.getSqrt(*(xt++) + *(yt)))); + (tr - (rsign * control->getSqrt(*(xt++) + *(yt)))); *(pg++) = (unsigned char) - (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1)))); + (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1)))); *(pb++) = (unsigned char) - (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2)))); + (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2)))); } } - -#ifdef INTERLACE } else { // faked interlacing effect unsigned char channel, channel2; @@ -1497,37 +1394,37 @@ void BImage::egradient(void) { for (xt = xtable, x = 0; x < width; x++) { if (y & 1) { channel = (unsigned char) - (tr - (rsign * control.getSqrt(*(xt++) + *(yt)))); + (tr - (rsign * control->getSqrt(*(xt++) + *(yt)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; *(pr++) = channel2; channel = (unsigned char) - (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1)))); + (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; *(pg++) = channel2; channel = (unsigned char) - (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2)))); + (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2)))); channel2 = (channel >> 1) + (channel >> 2); if (channel2 > channel) channel2 = 0; *(pb++) = channel2; } else { channel = (unsigned char) - (tr - (rsign * control.getSqrt(*(xt++) + *(yt)))); + (tr - (rsign * control->getSqrt(*(xt++) + *(yt)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; *(pr++) = channel2; channel = (unsigned char) - (tg - (gsign * control.getSqrt(*(xt++) + *(yt + 1)))); + (tg - (gsign * control->getSqrt(*(xt++) + *(yt + 1)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; *(pg++) = channel2; channel = (unsigned char) - (tb - (bsign * control.getSqrt(*(xt++) + *(yt + 2)))); + (tb - (bsign * control->getSqrt(*(xt++) + *(yt + 2)))); channel2 = channel + (channel >> 3); if (channel2 < channel) channel2 = ~0; *(pb++) = channel2; @@ -1535,28 +1432,27 @@ void BImage::egradient(void) { } } } -#endif // INTERLACE } void BImage::pcgradient(void) { // pipe cross gradient - based on original dgradient, written by // Mosfet (mosfet@kde.org) - // adapted from kde sources for Openbox by Brad Hughes + // adapted from kde sources for Blackbox by Brad Hughes float drx, dgx, dbx, dry, dgy, dby, xr, xg, xb, yr, yg, yb; int rsign, gsign, bsign; unsigned char *pr = red, *pg = green, *pb = blue; unsigned int *xt = xtable, *yt = ytable, - tr = to->getRed(), - tg = to->getGreen(), - tb = to->getBlue(); + tr = to.red(), + tg = to.green(), + tb = to.blue(); register unsigned int x, y; - dry = drx = (float) (to->getRed() - from->getRed()); - dgy = dgx = (float) (to->getGreen() - from->getGreen()); - dby = dbx = (float) (to->getBlue() - from->getBlue()); + dry = drx = (float) (to.red() - from.red()); + dgy = dgx = (float) (to.green() - from.green()); + dby = dbx = (float) (to.blue() - from.blue()); rsign = (drx < 0) ? -2 : 2; gsign = (dgx < 0) ? -2 : 2; @@ -1598,10 +1494,7 @@ void BImage::pcgradient(void) { // Combine tables to create gradient -#ifdef INTERLACE if (! interlaced) { -#endif // INTERLACE - // normal pcgradient for (yt = ytable, y = 0; y < height; y++, yt += 3) { for (xt = xtable, x = 0; x < width; x++) { @@ -1610,8 +1503,6 @@ void BImage::pcgradient(void) { *(pb++) = (unsigned char) (tb - (bsign * min(*(xt++), *(yt + 2)))); } } - -#ifdef INTERLACE } else { // faked interlacing effect unsigned char channel, channel2; @@ -1652,27 +1543,26 @@ void BImage::pcgradient(void) { } } } -#endif // INTERLACE } void BImage::cdgradient(void) { // cross diagonal gradient - based on original dgradient, written by // Mosfet (mosfet@kde.org) - // adapted from kde sources for Openbox by Brad Hughes + // adapted from kde sources for Blackbox by Brad Hughes float drx, dgx, dbx, dry, dgy, dby, yr = 0.0, yg = 0.0, yb = 0.0, - xr = (float) from->getRed(), - xg = (float) from->getGreen(), - xb = (float) from->getBlue(); + xr = (float) from.red(), + xg = (float) from.green(), + xb = (float) from.blue(); unsigned char *pr = red, *pg = green, *pb = blue; unsigned int w = width * 2, h = height * 2, *xt, *yt; register unsigned int x, y; - dry = drx = (float) (to->getRed() - from->getRed()); - dgy = dgx = (float) (to->getGreen() - from->getGreen()); - dby = dbx = (float) (to->getBlue() - from->getBlue()); + dry = drx = (float) (to.red() - from.red()); + dgy = dgx = (float) (to.green() - from.green()); + dby = dbx = (float) (to.blue() - from.blue()); // Create X table drx /= w; @@ -1706,10 +1596,7 @@ void BImage::cdgradient(void) { // Combine tables to create gradient -#ifdef INTERLACE if (! interlaced) { -#endif // INTERLACE - // normal cdgradient for (yt = ytable, y = 0; y < height; y++, yt += 3) { for (xt = xtable, x = 0; x < width; x++) { @@ -1718,8 +1605,6 @@ void BImage::cdgradient(void) { *(pb++) = *(xt++) + *(yt + 2); } } - -#ifdef INTERLACE } else { // faked interlacing effect unsigned char channel, channel2; @@ -1760,686 +1645,4 @@ void BImage::cdgradient(void) { } } } -#endif // INTERLACE -} - - -BImageControl::BImageControl(BaseDisplay &dpy, ScreenInfo &scrn, Bool _dither, - int _cpc, unsigned long cache_timeout, - unsigned long cmax) : basedisplay(dpy), -screeninfo(scrn) -{ - setDither(_dither); - setColorsPerChannel(_cpc); - - cache_max = cmax; -#ifdef TIMEDCACHE - if (cache_timeout) { - timer = new BTimer(basedisplay, *this); - timer->setTimeout(cache_timeout); - timer->start(); - } else - timer = (BTimer *) 0; -#endif // TIMEDCACHE - - colors = (XColor *) 0; - ncolors = 0; - - grad_xbuffer = grad_ybuffer = (unsigned int *) 0; - grad_buffer_width = grad_buffer_height = 0; - - sqrt_table = (unsigned long *) 0; - - screen_depth = screeninfo.getDepth(); - window = screeninfo.getRootWindow(); - screen_number = screeninfo.getScreenNumber(); - - int count; - XPixmapFormatValues *pmv = XListPixmapFormats(basedisplay.getXDisplay(), - &count); - colormap = screeninfo.getColormap(); - - if (pmv) { - bits_per_pixel = 0; - for (int i = 0; i < count; i++) - if (pmv[i].depth == screen_depth) { - bits_per_pixel = pmv[i].bits_per_pixel; - break; - } - - XFree(pmv); - } - - if (bits_per_pixel == 0) bits_per_pixel = screen_depth; - if (bits_per_pixel >= 24) setDither(False); - - red_offset = green_offset = blue_offset = 0; - - switch (getVisual()->c_class) { - case TrueColor: - { - int i; - - // compute color tables - unsigned long red_mask = getVisual()->red_mask, - green_mask = getVisual()->green_mask, - blue_mask = getVisual()->blue_mask; - - while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; } - while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; } - while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; } - - red_bits = 255 / red_mask; - green_bits = 255 / green_mask; - blue_bits = 255 / blue_mask; - - for (i = 0; i < 256; i++) { - red_color_table[i] = i / red_bits; - green_color_table[i] = i / green_bits; - blue_color_table[i] = i / blue_bits; - } - } - - break; - - case PseudoColor: - case StaticColor: - { - ncolors = colors_per_channel * colors_per_channel * colors_per_channel; - - if (ncolors > (1 << screen_depth)) { - colors_per_channel = (1 << screen_depth) / 3; - ncolors = colors_per_channel * colors_per_channel * colors_per_channel; - } - - if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) { - fprintf(stderr, i18n(ImageSet, ImageInvalidColormapSize, - "BImageControl::BImageControl: invalid colormap size %d " - "(%d/%d/%d) - reducing"), - ncolors, colors_per_channel, colors_per_channel, - colors_per_channel); - - colors_per_channel = (1 << screen_depth) / 3; - } - - colors = new XColor[ncolors]; - if (! colors) { - fprintf(stderr, i18n(ImageSet, - ImageErrorAllocatingColormap, - "BImageControl::BImageControl: error allocating " - "colormap\n")); - exit(1); - } - - int i = 0, ii, p, r, g, b, - -#ifdef ORDEREDPSEUDO - bits = 256 / colors_per_channel; -#else // !ORDEREDPSEUDO - bits = 255 / (colors_per_channel - 1); -#endif // ORDEREDPSEUDO - - red_bits = green_bits = blue_bits = bits; - - for (i = 0; i < 256; i++) - red_color_table[i] = green_color_table[i] = blue_color_table[i] = - i / bits; - - for (r = 0, i = 0; r < colors_per_channel; r++) - for (g = 0; g < colors_per_channel; g++) - for (b = 0; b < colors_per_channel; b++, i++) { - colors[i].red = (r * 0xffff) / (colors_per_channel - 1); - colors[i].green = (g * 0xffff) / (colors_per_channel - 1); - colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);; - colors[i].flags = DoRed|DoGreen|DoBlue; - } - - basedisplay.grab(); - - for (i = 0; i < ncolors; i++) - if (! XAllocColor(basedisplay.getXDisplay(), colormap, &colors[i])) { - fprintf(stderr, i18n(ImageSet, ImageColorAllocFail, - "couldn't alloc color %i %i %i\n"), - colors[i].red, colors[i].green, colors[i].blue); - colors[i].flags = 0; - } else - colors[i].flags = DoRed|DoGreen|DoBlue; - - basedisplay.ungrab(); - - XColor icolors[256]; - int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth)); - - for (i = 0; i < incolors; i++) - icolors[i].pixel = i; - - XQueryColors(basedisplay.getXDisplay(), colormap, icolors, incolors); - for (i = 0; i < ncolors; i++) { - if (! colors[i].flags) { - unsigned long chk = 0xffffffff, pixel, close = 0; - - p = 2; - while (p--) { - for (ii = 0; ii < incolors; ii++) { - r = (colors[i].red - icolors[i].red) >> 8; - g = (colors[i].green - icolors[i].green) >> 8; - b = (colors[i].blue - icolors[i].blue) >> 8; - pixel = (r * r) + (g * g) + (b * b); - - if (pixel < chk) { - chk = pixel; - close = ii; - } - - colors[i].red = icolors[close].red; - colors[i].green = icolors[close].green; - colors[i].blue = icolors[close].blue; - - if (XAllocColor(basedisplay.getXDisplay(), colormap, - &colors[i])) { - colors[i].flags = DoRed|DoGreen|DoBlue; - break; - } - } - } - } - } - - break; - } - - case GrayScale: - case StaticGray: - { - - if (getVisual()->c_class == StaticGray) { - ncolors = 1 << screen_depth; - } else { - ncolors = colors_per_channel * colors_per_channel * colors_per_channel; - - if (ncolors > (1 << screen_depth)) { - colors_per_channel = (1 << screen_depth) / 3; - ncolors = - colors_per_channel * colors_per_channel * colors_per_channel; - } - } - - if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) { - fprintf(stderr, i18n(ImageSet, ImageInvalidColormapSize, - "BImageControl::BImageControl: invalid colormap size %d " - "(%d/%d/%d) - reducing"), - ncolors, colors_per_channel, colors_per_channel, - colors_per_channel); - - colors_per_channel = (1 << screen_depth) / 3; - } - - colors = new XColor[ncolors]; - if (! colors) { - fprintf(stderr, i18n(ImageSet, - ImageErrorAllocatingColormap, - "BImageControl::BImageControl: error allocating " - "colormap\n")); - exit(1); - } - - int i = 0, ii, p, bits = 255 / (colors_per_channel - 1); - red_bits = green_bits = blue_bits = bits; - - for (i = 0; i < 256; i++) - red_color_table[i] = green_color_table[i] = blue_color_table[i] = - i / bits; - - basedisplay.grab(); - for (i = 0; i < ncolors; i++) { - colors[i].red = (i * 0xffff) / (colors_per_channel - 1); - colors[i].green = (i * 0xffff) / (colors_per_channel - 1); - colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);; - colors[i].flags = DoRed|DoGreen|DoBlue; - - if (! XAllocColor(basedisplay.getXDisplay(), colormap, - &colors[i])) { - fprintf(stderr, i18n(ImageSet, ImageColorAllocFail, - "couldn't alloc color %i %i %i\n"), - colors[i].red, colors[i].green, colors[i].blue); - colors[i].flags = 0; - } else - colors[i].flags = DoRed|DoGreen|DoBlue; - } - - basedisplay.ungrab(); - - XColor icolors[256]; - int incolors = (((1 << screen_depth) > 256) ? 256 : - (1 << screen_depth)); - - for (i = 0; i < incolors; i++) - icolors[i].pixel = i; - - XQueryColors(basedisplay.getXDisplay(), colormap, icolors, incolors); - for (i = 0; i < ncolors; i++) { - if (! colors[i].flags) { - unsigned long chk = 0xffffffff, pixel, close = 0; - - p = 2; - while (p--) { - for (ii = 0; ii < incolors; ii++) { - int r = (colors[i].red - icolors[i].red) >> 8; - int g = (colors[i].green - icolors[i].green) >> 8; - int b = (colors[i].blue - icolors[i].blue) >> 8; - pixel = (r * r) + (g * g) + (b * b); - - if (pixel < chk) { - chk = pixel; - close = ii; - } - - colors[i].red = icolors[close].red; - colors[i].green = icolors[close].green; - colors[i].blue = icolors[close].blue; - - if (XAllocColor(basedisplay.getXDisplay(), colormap, - &colors[i])) { - colors[i].flags = DoRed|DoGreen|DoBlue; - break; - } - } - } - } - } - - break; - } - - default: - fprintf(stderr, i18n(ImageSet, ImageUnsupVisual, - "BImageControl::BImageControl: unsupported visual %d\n"), - getVisual()->c_class); - exit(1); - } -} - - -BImageControl::~BImageControl(void) { - if (sqrt_table) { - delete [] sqrt_table; - } - - if (grad_xbuffer) { - delete [] grad_xbuffer; - } - - if (grad_ybuffer) { - delete [] grad_ybuffer; - } - - if (colors) { - unsigned long *pixels = new unsigned long [ncolors]; - - int i; - for (i = 0; i < ncolors; i++) - *(pixels + i) = (*(colors + i)).pixel; - - XFreeColors(basedisplay.getXDisplay(), colormap, pixels, ncolors, 0); - - delete [] colors; - } - - if (!cache.empty()) { - int i, n = cache.size(); - fprintf(stderr, i18n(ImageSet, ImagePixmapRelease, - "BImageContol::~BImageControl: pixmap cache - " - "releasing %d pixmaps\n"), n); - - for (i = 0; i < n; i++) { - Cache *tmp = cache.front(); - XFreePixmap(basedisplay.getXDisplay(), tmp->pixmap); - cache.remove(tmp); - delete tmp; - } - -#ifdef TIMEDCACHE - if (timer) { - timer->stop(); - delete timer; - } -#endif // TIMEDCACHE - } -} - - -Pixmap BImageControl::searchCache(unsigned int width, unsigned int height, - unsigned long texture, - BColor *c1, BColor *c2) { - if (!cache.empty()) { - - CacheList::iterator it; - for (it = cache.begin(); it != cache.end(); ++it) { - Cache *tmp = *it; - if ((tmp->width == width) && (tmp->height == height) && - (tmp->texture == texture) && (tmp->pixel1 == c1->getPixel())) - if (texture & BImage_Gradient) { - if (tmp->pixel2 == c2->getPixel()) { - tmp->count++; - return tmp->pixmap; - } - } else { - tmp->count++; - return tmp->pixmap; - } - } - } - - return None; -} - - -Pixmap BImageControl::renderImage(unsigned int width, unsigned int height, - BTexture *texture) { - if (texture->getTexture() & BImage_ParentRelative) return ParentRelative; - - Pixmap pixmap = searchCache(width, height, texture->getTexture(), - texture->getColor(), texture->getColorTo()); - if (pixmap) return pixmap; - - BImage image(*this, width, height); - pixmap = image.render(texture); - - if (pixmap) { - Cache *tmp = new Cache; - - tmp->pixmap = pixmap; - tmp->width = width; - tmp->height = height; - tmp->count = 1; - tmp->texture = texture->getTexture(); - tmp->pixel1 = texture->getColor()->getPixel(); - - if (texture->getTexture() & BImage_Gradient) - tmp->pixel2 = texture->getColorTo()->getPixel(); - else - tmp->pixel2 = 0l; - - cache.push_back(tmp); - - if ((unsigned) cache.size() > cache_max) { -#ifdef DEBUG - fprintf(stderr, i18n(ImageSet, ImagePixmapCacheLarge, - "BImageControl::renderImage: cache is large, " - "forcing cleanout\n")); -#endif // DEBUG - - timeout(); - } - - return pixmap; - } - - return None; -} - - -void BImageControl::removeImage(Pixmap pixmap) { - if (pixmap) { - CacheList::iterator it; - for (it = cache.begin(); it != cache.end(); ++it) { - Cache *tmp = *it; - if (tmp->pixmap == pixmap) { - if (tmp->count) { - tmp->count--; - -#ifdef TIMEDCACHE - if (! timer) timeout(); -#else // !TIMEDCACHE - if (! tmp->count) timeout(); -#endif // TIMEDCACHE - } - - return; - } - } - } -} - - -unsigned long BImageControl::getColor(const char *colorname, - unsigned char *r, unsigned char *g, - unsigned char *b) -{ - XColor color; - color.pixel = 0; - - if (! XParseColor(basedisplay.getXDisplay(), colormap, colorname, &color)) - fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n", - colorname); - else if (! XAllocColor(basedisplay.getXDisplay(), colormap, &color)) - fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n", - colorname); - - if (color.red == 65535) *r = 0xff; - else *r = (unsigned char) (color.red / 0xff); - if (color.green == 65535) *g = 0xff; - else *g = (unsigned char) (color.green / 0xff); - if (color.blue == 65535) *b = 0xff; - else *b = (unsigned char) (color.blue / 0xff); - - return color.pixel; -} - - -unsigned long BImageControl::getColor(const char *colorname) { - XColor color; - color.pixel = 0; - - if (! XParseColor(basedisplay.getXDisplay(), colormap, colorname, &color)) - fprintf(stderr, "BImageControl::getColor: color parse error: \"%s\"\n", - colorname); - else if (! XAllocColor(basedisplay.getXDisplay(), colormap, &color)) - fprintf(stderr, "BImageControl::getColor: color alloc error: \"%s\"\n", - colorname); - - return color.pixel; -} - - -void BImageControl::getColorTables(unsigned char **rmt, unsigned char **gmt, - unsigned char **bmt, - int *roff, int *goff, int *boff, - int *rbit, int *gbit, int *bbit) { - if (rmt) *rmt = red_color_table; - if (gmt) *gmt = green_color_table; - if (bmt) *bmt = blue_color_table; - - if (roff) *roff = red_offset; - if (goff) *goff = green_offset; - if (boff) *boff = blue_offset; - - if (rbit) *rbit = red_bits; - if (gbit) *gbit = green_bits; - if (bbit) *bbit = blue_bits; -} - - -void BImageControl::getXColorTable(XColor **c, int *n) { - if (c) *c = colors; - if (n) *n = ncolors; -} - - -void BImageControl::getGradientBuffers(unsigned int w, - unsigned int h, - unsigned int **xbuf, - unsigned int **ybuf) -{ - if (w > grad_buffer_width) { - if (grad_xbuffer) { - delete [] grad_xbuffer; - } - - grad_buffer_width = w; - - grad_xbuffer = new unsigned int[grad_buffer_width * 3]; - } - - if (h > grad_buffer_height) { - if (grad_ybuffer) { - delete [] grad_ybuffer; - } - - grad_buffer_height = h; - - grad_ybuffer = new unsigned int[grad_buffer_height * 3]; - } - - *xbuf = grad_xbuffer; - *ybuf = grad_ybuffer; -} - - -void BImageControl::installRootColormap(void) { - basedisplay.grab(); - - Bool install = True; - int i = 0, ncmap = 0; - Colormap *cmaps = - XListInstalledColormaps(basedisplay.getXDisplay(), window, &ncmap); - - if (cmaps) { - for (i = 0; i < ncmap; i++) - if (*(cmaps + i) == colormap) - install = False; - - if (install) - XInstallColormap(basedisplay.getXDisplay(), colormap); - - XFree(cmaps); - } - - basedisplay.ungrab(); -} - - -void BImageControl::setColorsPerChannel(int cpc) { - if (cpc < 2) cpc = 2; - if (cpc > 6) cpc = 6; - - colors_per_channel = cpc; -} - - -unsigned long BImageControl::getSqrt(unsigned int x) { - if (! sqrt_table) { - // build sqrt table for use with elliptic gradient - - sqrt_table = new unsigned long[(256 * 256 * 2) + 1]; - int i = 0; - - for (; i < (256 * 256 * 2); i++) - *(sqrt_table + i) = bsqrt(i); - } - - return (*(sqrt_table + x)); -} - - -void BImageControl::parseTexture(BTexture *texture, const char *t) { - if ((! texture) || (! t)) return; - - int t_len = strlen(t) + 1, i; - char *ts = new char[t_len]; - if (! ts) return; - - // convert to lower case - for (i = 0; i < t_len; i++) - *(ts + i) = tolower(*(t + i)); - - if (strstr(ts, "parentrelative")) { - texture->setTexture(BImage_ParentRelative); - } else { - texture->setTexture(0); - - if (strstr(ts, "solid")) - texture->addTexture(BImage_Solid); - else if (strstr(ts, "gradient")) { - texture->addTexture(BImage_Gradient); - if (strstr(ts, "crossdiagonal")) - texture->addTexture(BImage_CrossDiagonal); - else if (strstr(ts, "rectangle")) - texture->addTexture(BImage_Rectangle); - else if (strstr(ts, "pyramid")) - texture->addTexture(BImage_Pyramid); - else if (strstr(ts, "pipecross")) - texture->addTexture(BImage_PipeCross); - else if (strstr(ts, "elliptic")) - texture->addTexture(BImage_Elliptic); - else if (strstr(ts, "diagonal")) - texture->addTexture(BImage_Diagonal); - else if (strstr(ts, "horizontal")) - texture->addTexture(BImage_Horizontal); - else if (strstr(ts, "vertical")) - texture->addTexture(BImage_Vertical); - else - texture->addTexture(BImage_Diagonal); - } else - texture->addTexture(BImage_Solid); - - if (strstr(ts, "raised")) - texture->addTexture(BImage_Raised); - else if (strstr(ts, "sunken")) - texture->addTexture(BImage_Sunken); - else if (strstr(ts, "flat")) - texture->addTexture(BImage_Flat); - else - texture->addTexture(BImage_Raised); - - if (! (texture->getTexture() & BImage_Flat)) - if (strstr(ts, "bevel2")) - texture->addTexture(BImage_Bevel2); - else - texture->addTexture(BImage_Bevel1); - -#ifdef INTERLACE - if (strstr(ts, "interlaced")) - texture->addTexture(BImage_Interlaced); -#endif // INTERLACE - } - - delete [] ts; -} - - -void BImageControl::parseColor(BColor *color, const char *c) { - if (! color) return; - - if (color->isAllocated()) { - unsigned long pixel = color->getPixel(); - - XFreeColors(basedisplay.getXDisplay(), colormap, &pixel, 1, 0); - - color->setPixel(0l); - color->setRGB(0, 0, 0); - color->setAllocated(False); - } - - if (c) { - unsigned char r, g, b; - - color->setPixel(getColor(c, &r, &g, &b)); - color->setRGB(r, g, b); - color->setAllocated(True); - } -} - - -void BImageControl::timeout(void) { - CacheList::iterator it; - for (it = cache.begin(); it != cache.end(); ) { - Cache *tmp = *it; - ++it; // move on to the next item before this one is removed - if (tmp->count <= 0) { - XFreePixmap(basedisplay.getXDisplay(), tmp->pixmap); - cache.remove(tmp); - delete tmp; - } - } } diff --git a/src/Image.h b/src/Image.h deleted file mode 100644 index e342128b..00000000 --- a/src/Image.h +++ /dev/null @@ -1,242 +0,0 @@ -// Image.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Image_hh -#define __Image_hh - -#include -#include - -#include "Timer.h" -#include - -class ScreenInfo; -class BImage; -class BImageControl; - - -// bevel options -#define BImage_Flat (1l<<1) -#define BImage_Sunken (1l<<2) -#define BImage_Raised (1l<<3) - -// textures -#define BImage_Solid (1l<<4) -#define BImage_Gradient (1l<<5) - -// gradients -#define BImage_Horizontal (1l<<6) -#define BImage_Vertical (1l<<7) -#define BImage_Diagonal (1l<<8) -#define BImage_CrossDiagonal (1l<<9) -#define BImage_Rectangle (1l<<10) -#define BImage_Pyramid (1l<<11) -#define BImage_PipeCross (1l<<12) -#define BImage_Elliptic (1l<<13) - -// bevel types -#define BImage_Bevel1 (1l<<14) -#define BImage_Bevel2 (1l<<15) - -// inverted image -#define BImage_Invert (1l<<16) - -// parent relative image -#define BImage_ParentRelative (1l<<17) - -#ifdef INTERLACE -// fake interlaced image -# define BImage_Interlaced (1l<<18) -#endif // INTERLACE - -class BColor { -private: - int allocated; - unsigned char red, green, blue; - unsigned long pixel; - -public: - BColor(char r = 0, char g = 0, char b = 0) - { red = r; green = g; blue = b; pixel = 0; allocated = 0; } - - inline const int &isAllocated(void) const { return allocated; } - - inline const unsigned char &getRed(void) const { return red; } - inline const unsigned char &getGreen(void) const { return green; } - inline const unsigned char &getBlue(void) const { return blue; } - - inline const unsigned long &getPixel(void) const { return pixel; } - - inline void setAllocated(int a) { allocated = a; } - inline void setRGB(char r, char g, char b) { red = r; green = g; blue = b; } - inline void setPixel(unsigned long p) { pixel = p; } -}; - - -class BTexture { -private: - BColor color, colorTo, hiColor, loColor; - unsigned long texture; - -public: - BTexture(void) { texture = 0; } - - inline BColor *getColor(void) { return &color; } - inline BColor *getColorTo(void) { return &colorTo; } - inline BColor *getHiColor(void) { return &hiColor; } - inline BColor *getLoColor(void) { return &loColor; } - - inline const unsigned long &getTexture(void) const { return texture; } - - inline void setTexture(unsigned long t) { texture = t; } - inline void addTexture(unsigned long t) { texture |= t; } -}; - - -class BImage { -private: - BImageControl &control; - -#ifdef INTERLACE - Bool interlaced; -#endif // INTERLACE - - XColor *colors; - - BColor *from, *to; - int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits, - ncolors, cpc, cpccpc; - unsigned char *red, *green, *blue, *red_table, *green_table, *blue_table; - unsigned int width, height, *xtable, *ytable; - - -protected: - Pixmap renderPixmap(void); - - XImage *renderXImage(void); - - void invert(void); - void bevel1(void); - void bevel2(void); - void dgradient(void); - void egradient(void); - void hgradient(void); - void pgradient(void); - void rgradient(void); - void vgradient(void); - void cdgradient(void); - void pcgradient(void); - - -public: - BImage(BImageControl &, unsigned int, unsigned int); - ~BImage(void); - - Pixmap render(BTexture *); - Pixmap render_solid(BTexture *); - Pixmap render_gradient(BTexture *); -}; - - -class BImageControl : public TimeoutHandler { -private: - Bool dither; - BaseDisplay &basedisplay; - ScreenInfo &screeninfo; -#ifdef TIMEDCACHE - BTimer *timer; -#endif // TIMEDCACHE - - Colormap colormap; - - Window window; - XColor *colors; - int colors_per_channel, ncolors, screen_number, screen_depth, - bits_per_pixel, red_offset, green_offset, blue_offset, - red_bits, green_bits, blue_bits; - unsigned char red_color_table[256], green_color_table[256], - blue_color_table[256]; - unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width, - grad_buffer_height; - unsigned long *sqrt_table, cache_max; - - typedef struct Cache { - Pixmap pixmap; - - unsigned int count, width, height; - unsigned long pixel1, pixel2, texture; - } Cache; - - typedef std::list CacheList; - CacheList cache; - - -protected: - Pixmap searchCache(unsigned int, unsigned int, unsigned long, BColor *, - BColor *); - - -public: - BImageControl(BaseDisplay &, ScreenInfo &, Bool = False, int = 4, - unsigned long = 300000l, unsigned long = 200l); - virtual ~BImageControl(void); - - inline BaseDisplay &getBaseDisplay(void) { return basedisplay; } - - inline const Bool &doDither(void) { return dither; } - - inline ScreenInfo &getScreenInfo(void) { return screeninfo; } - - inline const Window &getDrawable(void) const { return window; } - - inline Visual *getVisual(void) const { return screeninfo.getVisual(); } - - inline const int &getBitsPerPixel(void) const { return bits_per_pixel; } - inline const int &getDepth(void) const { return screen_depth; } - inline const int &getColorsPerChannel(void) const - { return colors_per_channel; } - - unsigned long getColor(const char *); - unsigned long getColor(const char *, unsigned char *, unsigned char *, - unsigned char *); - unsigned long getSqrt(unsigned int); - - Pixmap renderImage(unsigned int, unsigned int, BTexture *); - - void installRootColormap(void); - void removeImage(Pixmap); - void getColorTables(unsigned char **, unsigned char **, unsigned char **, - int *, int *, int *, int *, int *, int *); - void getXColorTable(XColor **, int *); - void getGradientBuffers(unsigned int, unsigned int, - unsigned int **, unsigned int **); - void setDither(Bool d) { dither = d; } - void setColorsPerChannel(int); - void parseTexture(BTexture *, const char *); - void parseColor(BColor *, const char * = 0); - - virtual void timeout(void); -}; - - -#endif // __Image_hh - diff --git a/src/Image.hh b/src/Image.hh new file mode 100644 index 00000000..4d72bc14 --- /dev/null +++ b/src/Image.hh @@ -0,0 +1,179 @@ +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Image.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef __Image_hh +#define __Image_hh + +extern "C" { +#include +#include +} + +#include + +#include "Timer.hh" +#include "BaseDisplay.hh" +#include "Color.hh" + +class BImageControl; +class BTexture; +class BImageCache; + +class BImage { +private: + BImageControl *control; + bool interlaced; + XColor *colors; + + BColor from, to; + int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits, + ncolors, cpc, cpccpc; + unsigned char *red, *green, *blue, *red_table, *green_table, *blue_table; + unsigned int width, height, *xtable, *ytable; + + void TrueColorDither(unsigned int bit_depth, int bytes_per_line, + unsigned char *pixel_data); + void PseudoColorDither(int bytes_per_line, unsigned char *pixel_data); +#ifdef ORDEREDPSEUDO + void OrderedPseudoColorDither(int bytes_per_line, unsigned char *pixel_data); +#endif + + Pixmap renderPixmap(void); + + XImage *renderXImage(void); + + void invert(void); + void bevel1(void); + void bevel2(void); + void dgradient(void); + void egradient(void); + void hgradient(void); + void pgradient(void); + void rgradient(void); + void vgradient(void); + void cdgradient(void); + void pcgradient(void); + + +public: + BImage(BImageControl *c, unsigned int w, unsigned int h); + ~BImage(void); + + Pixmap render(const BTexture &texture); + Pixmap render_solid(const BTexture &texture); + Pixmap render_gradient(const BTexture &texture); + + // static methods for the builtin cache + static unsigned long maximumCacheSize(void); + static void setMaximumCacheSize(const unsigned long cache_max); + + static unsigned long cacheTimeout(void); + static void setCacheTimeout(const unsigned long cache_timeout); + +private: + // global image cache + static BImageCache *imagecache; +}; + + +class BImageControl : public TimeoutHandler { +public: + struct CachedImage { + Pixmap pixmap; + + unsigned int count, width, height; + unsigned long pixel1, pixel2, texture; + }; + + BImageControl(BaseDisplay *dpy, const ScreenInfo *scrn, + bool _dither= False, int _cpc = 4, + unsigned long cache_timeout = 300000l, + unsigned long cmax = 200l); + virtual ~BImageControl(void); + + inline BaseDisplay *getBaseDisplay(void) const { return basedisplay; } + + inline bool doDither(void) { return dither; } + + inline const ScreenInfo *getScreenInfo(void) { return screeninfo; } + + inline Window getDrawable(void) const { return window; } + + inline Visual *getVisual(void) { return screeninfo->getVisual(); } + + inline int getBitsPerPixel(void) const { return bits_per_pixel; } + inline int getDepth(void) const { return screen_depth; } + inline int getColorsPerChannel(void) const + { return colors_per_channel; } + + unsigned long getSqrt(unsigned int x); + + Pixmap renderImage(unsigned int width, unsigned int height, + const BTexture &texture); + + void installRootColormap(void); + void removeImage(Pixmap pixmap); + void getColorTables(unsigned char **rmt, unsigned char **gmt, + unsigned char **bmt, + int *roff, int *goff, int *boff, + int *rbit, int *gbit, int *bbit); + void getXColorTable(XColor **c, int *n); + void getGradientBuffers(unsigned int w, unsigned int h, + unsigned int **xbuf, unsigned int **ybuf); + void setDither(bool d) { dither = d; } + void setColorsPerChannel(int cpc); + + virtual void timeout(void); + +private: + bool dither; + BaseDisplay *basedisplay; + const ScreenInfo *screeninfo; +#ifdef TIMEDCACHE + BTimer *timer; +#endif // TIMEDCACHE + + Colormap colormap; + + Window window; + XColor *colors; + int colors_per_channel, ncolors, screen_number, screen_depth, + bits_per_pixel, red_offset, green_offset, blue_offset, + red_bits, green_bits, blue_bits; + unsigned char red_color_table[256], green_color_table[256], + blue_color_table[256]; + unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width, + grad_buffer_height; + unsigned long *sqrt_table, cache_max; + + typedef std::list CacheContainer; + CacheContainer cache; + + Pixmap searchCache(const unsigned int width, const unsigned int height, + const unsigned long texture, + const BColor &c1, const BColor &c2); +}; + + +#endif // __Image_hh + diff --git a/src/ImageControl.cc b/src/ImageControl.cc new file mode 100644 index 00000000..eed97734 --- /dev/null +++ b/src/ImageControl.cc @@ -0,0 +1,604 @@ +// -*- mode: C++; indent-tabs-mode: nil; -*- +// ImageControl.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif // HAVE_CONFIG_H + +extern "C" { +#ifdef HAVE_STDIO_H +# include +#endif // HAVE_STDIO_H + +#ifdef HAVE_CTYPE_H +# include +#endif // HAVE_CTYPE_H + +#include +} + +#include + +#include "blackbox.hh" +#include "i18n.hh" +#include "BaseDisplay.hh" +#include "Color.hh" +#include "Image.hh" +#include "Texture.hh" + +static unsigned long bsqrt(unsigned long x) { + if (x <= 0) return 0; + if (x == 1) return 1; + + unsigned long r = x >> 1; + unsigned long q; + + while (1) { + q = x / r; + if (q >= r) return r; + r = (r + q) >> 1; + } +} + +BImageControl *ctrl = 0; + +BImageControl::BImageControl(BaseDisplay *dpy, const ScreenInfo *scrn, + bool _dither, int _cpc, + unsigned long cache_timeout, + unsigned long cmax) +{ + if (! ctrl) ctrl = this; + + basedisplay = dpy; + screeninfo = scrn; + setDither(_dither); + setColorsPerChannel(_cpc); + + cache_max = cmax; +#ifdef TIMEDCACHE + if (cache_timeout) { + timer = new BTimer(basedisplay, this); + timer->setTimeout(cache_timeout); + timer->start(); + } else { + timer = (BTimer *) 0; + } +#endif // TIMEDCACHE + + colors = (XColor *) 0; + ncolors = 0; + + grad_xbuffer = grad_ybuffer = (unsigned int *) 0; + grad_buffer_width = grad_buffer_height = 0; + + sqrt_table = (unsigned long *) 0; + + screen_depth = screeninfo->getDepth(); + window = screeninfo->getRootWindow(); + screen_number = screeninfo->getScreenNumber(); + colormap = screeninfo->getColormap(); + + int count; + XPixmapFormatValues *pmv = XListPixmapFormats(basedisplay->getXDisplay(), + &count); + if (pmv) { + bits_per_pixel = 0; + for (int i = 0; i < count; i++) + if (pmv[i].depth == screen_depth) { + bits_per_pixel = pmv[i].bits_per_pixel; + break; + } + + XFree(pmv); + } + + if (bits_per_pixel == 0) bits_per_pixel = screen_depth; + if (bits_per_pixel >= 24) setDither(False); + + red_offset = green_offset = blue_offset = 0; + + switch (getVisual()->c_class) { + case TrueColor: { + int i; + + // compute color tables + unsigned long red_mask = getVisual()->red_mask, + green_mask = getVisual()->green_mask, + blue_mask = getVisual()->blue_mask; + + while (! (red_mask & 1)) { red_offset++; red_mask >>= 1; } + while (! (green_mask & 1)) { green_offset++; green_mask >>= 1; } + while (! (blue_mask & 1)) { blue_offset++; blue_mask >>= 1; } + + red_bits = 255 / red_mask; + green_bits = 255 / green_mask; + blue_bits = 255 / blue_mask; + + for (i = 0; i < 256; i++) { + red_color_table[i] = i / red_bits; + green_color_table[i] = i / green_bits; + blue_color_table[i] = i / blue_bits; + } + break; + } + + case PseudoColor: + case StaticColor: { + ncolors = colors_per_channel * colors_per_channel * colors_per_channel; + + if (ncolors > (1 << screen_depth)) { + colors_per_channel = (1 << screen_depth) / 3; + ncolors = colors_per_channel * colors_per_channel * colors_per_channel; + } + + if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) { + fprintf(stderr, + i18n(ImageSet, ImageInvalidColormapSize, + "BImageControl::BImageControl: invalid colormap size %d " + "(%d/%d/%d) - reducing"), + ncolors, colors_per_channel, colors_per_channel, + colors_per_channel); + + colors_per_channel = (1 << screen_depth) / 3; + } + + colors = new XColor[ncolors]; + if (! colors) { + fprintf(stderr, i18n(ImageSet, ImageErrorAllocatingColormap, + "BImageControl::BImageControl: error allocating " + "colormap\n")); + exit(1); + } + + int i = 0, ii, p, r, g, b, + +#ifdef ORDEREDPSEUDO + bits = 256 / colors_per_channel; +#else // !ORDEREDPSEUDO + bits = 255 / (colors_per_channel - 1); +#endif // ORDEREDPSEUDO + + red_bits = green_bits = blue_bits = bits; + + for (i = 0; i < 256; i++) + red_color_table[i] = green_color_table[i] = blue_color_table[i] = + i / bits; + + for (r = 0, i = 0; r < colors_per_channel; r++) + for (g = 0; g < colors_per_channel; g++) + for (b = 0; b < colors_per_channel; b++, i++) { + colors[i].red = (r * 0xffff) / (colors_per_channel - 1); + colors[i].green = (g * 0xffff) / (colors_per_channel - 1); + colors[i].blue = (b * 0xffff) / (colors_per_channel - 1);; + colors[i].flags = DoRed|DoGreen|DoBlue; + } + + for (i = 0; i < ncolors; i++) { + if (! XAllocColor(basedisplay->getXDisplay(), colormap, &colors[i])) { + fprintf(stderr, i18n(ImageSet, ImageColorAllocFail, + "couldn't alloc color %i %i %i\n"), + colors[i].red, colors[i].green, colors[i].blue); + colors[i].flags = 0; + } else { + colors[i].flags = DoRed|DoGreen|DoBlue; + } + } + + XColor icolors[256]; + int incolors = (((1 << screen_depth) > 256) ? 256 : (1 << screen_depth)); + + for (i = 0; i < incolors; i++) + icolors[i].pixel = i; + + XQueryColors(basedisplay->getXDisplay(), colormap, icolors, incolors); + for (i = 0; i < ncolors; i++) { + if (! colors[i].flags) { + unsigned long chk = 0xffffffff, pixel, close = 0; + + p = 2; + while (p--) { + for (ii = 0; ii < incolors; ii++) { + r = (colors[i].red - icolors[i].red) >> 8; + g = (colors[i].green - icolors[i].green) >> 8; + b = (colors[i].blue - icolors[i].blue) >> 8; + pixel = (r * r) + (g * g) + (b * b); + + if (pixel < chk) { + chk = pixel; + close = ii; + } + + colors[i].red = icolors[close].red; + colors[i].green = icolors[close].green; + colors[i].blue = icolors[close].blue; + + if (XAllocColor(basedisplay->getXDisplay(), colormap, + &colors[i])) { + colors[i].flags = DoRed|DoGreen|DoBlue; + break; + } + } + } + } + } + + break; + } + + case GrayScale: + case StaticGray: { + if (getVisual()->c_class == StaticGray) { + ncolors = 1 << screen_depth; + } else { + ncolors = colors_per_channel * colors_per_channel * colors_per_channel; + + if (ncolors > (1 << screen_depth)) { + colors_per_channel = (1 << screen_depth) / 3; + ncolors = + colors_per_channel * colors_per_channel * colors_per_channel; + } + } + + if (colors_per_channel < 2 || ncolors > (1 << screen_depth)) { + fprintf(stderr, + i18n(ImageSet, ImageInvalidColormapSize, + "BImageControl::BImageControl: invalid colormap size %d " + "(%d/%d/%d) - reducing"), + ncolors, colors_per_channel, colors_per_channel, + colors_per_channel); + + colors_per_channel = (1 << screen_depth) / 3; + } + + colors = new XColor[ncolors]; + if (! colors) { + fprintf(stderr, + i18n(ImageSet, ImageErrorAllocatingColormap, + "BImageControl::BImageControl: error allocating colormap\n")); + exit(1); + } + + int i = 0, ii, p, bits = 255 / (colors_per_channel - 1); + red_bits = green_bits = blue_bits = bits; + + for (i = 0; i < 256; i++) + red_color_table[i] = green_color_table[i] = blue_color_table[i] = + i / bits; + + for (i = 0; i < ncolors; i++) { + colors[i].red = (i * 0xffff) / (colors_per_channel - 1); + colors[i].green = (i * 0xffff) / (colors_per_channel - 1); + colors[i].blue = (i * 0xffff) / (colors_per_channel - 1);; + colors[i].flags = DoRed|DoGreen|DoBlue; + + if (! XAllocColor(basedisplay->getXDisplay(), colormap, + &colors[i])) { + fprintf(stderr, i18n(ImageSet, ImageColorAllocFail, + "couldn't alloc color %i %i %i\n"), + colors[i].red, colors[i].green, colors[i].blue); + colors[i].flags = 0; + } else { + colors[i].flags = DoRed|DoGreen|DoBlue; + } + } + + XColor icolors[256]; + int incolors = (((1 << screen_depth) > 256) ? 256 : + (1 << screen_depth)); + + for (i = 0; i < incolors; i++) + icolors[i].pixel = i; + + XQueryColors(basedisplay->getXDisplay(), colormap, icolors, incolors); + for (i = 0; i < ncolors; i++) { + if (! colors[i].flags) { + unsigned long chk = 0xffffffff, pixel, close = 0; + + p = 2; + while (p--) { + for (ii = 0; ii < incolors; ii++) { + int r = (colors[i].red - icolors[i].red) >> 8; + int g = (colors[i].green - icolors[i].green) >> 8; + int b = (colors[i].blue - icolors[i].blue) >> 8; + pixel = (r * r) + (g * g) + (b * b); + + if (pixel < chk) { + chk = pixel; + close = ii; + } + + colors[i].red = icolors[close].red; + colors[i].green = icolors[close].green; + colors[i].blue = icolors[close].blue; + + if (XAllocColor(basedisplay->getXDisplay(), colormap, + &colors[i])) { + colors[i].flags = DoRed|DoGreen|DoBlue; + break; + } + } + } + } + } + + break; + } + + default: + fprintf(stderr, + i18n(ImageSet, ImageUnsupVisual, + "BImageControl::BImageControl: unsupported visual %d\n"), + getVisual()->c_class); + exit(1); + } +} + + +BImageControl::~BImageControl(void) { + delete [] sqrt_table; + + delete [] grad_xbuffer; + + delete [] grad_ybuffer; + + if (colors) { + unsigned long *pixels = new unsigned long [ncolors]; + + int i; + for (i = 0; i < ncolors; i++) + *(pixels + i) = (*(colors + i)).pixel; + + XFreeColors(basedisplay->getXDisplay(), colormap, pixels, ncolors, 0); + + delete [] colors; + } + + if (!cache.empty()) { + //#ifdef DEBUG + fprintf(stderr, i18n(ImageSet, ImagePixmapRelease, + "BImageContol::~BImageControl: pixmap cache - " + "releasing %d pixmaps\n"), cache.size()); + //#endif + CacheContainer::iterator it = cache.begin(); + const CacheContainer::iterator end = cache.end(); + for (; it != end; ++it) { + XFreePixmap(basedisplay->getXDisplay(), (*it).pixmap); + } + } +#ifdef TIMEDCACHE + if (timer) { + timer->stop(); + delete timer; + } +#endif // TIMEDCACHE +} + + +Pixmap BImageControl::searchCache(const unsigned int width, + const unsigned int height, + const unsigned long texture, + const BColor &c1, const BColor &c2) { + if (cache.empty()) + return None; + + CacheContainer::iterator it = cache.begin(); + const CacheContainer::iterator end = cache.end(); + for (; it != end; ++it) { + CachedImage& tmp = *it; + if ((tmp.width == width) && (tmp.height == height) && + (tmp.texture == texture) && (tmp.pixel1 == c1.pixel())) + if (texture & BTexture::Gradient) { + if (tmp.pixel2 == c2.pixel()) { + tmp.count++; + return tmp.pixmap; + } + } else { + tmp.count++; + return tmp.pixmap; + } + } + return None; +} + + +Pixmap BImageControl::renderImage(unsigned int width, unsigned int height, + const BTexture &texture) { + if (texture.texture() & BTexture::Parent_Relative) return ParentRelative; + + Pixmap pixmap = searchCache(width, height, texture.texture(), + texture.color(), texture.colorTo()); + if (pixmap) return pixmap; + + BImage image(this, width, height); + pixmap = image.render(texture); + + if (!pixmap) + return None; + + CachedImage tmp; + + tmp.pixmap = pixmap; + tmp.width = width; + tmp.height = height; + tmp.count = 1; + tmp.texture = texture.texture(); + tmp.pixel1 = texture.color().pixel(); + + if (texture.texture() & BTexture::Gradient) + tmp.pixel2 = texture.colorTo().pixel(); + else + tmp.pixel2 = 0l; + + cache.push_back(tmp); + + if (cache.size() > cache_max) { +#ifdef DEBUG + fprintf(stderr, i18n(ImageSet, ImagePixmapCacheLarge, + "BImageControl::renderImage: cache is large, " + "forcing cleanout\n")); +#endif // DEBUG + + timeout(); + } + + return pixmap; +} + + +void BImageControl::removeImage(Pixmap pixmap) { + if (!pixmap) + return; + + CacheContainer::iterator it = cache.begin(); + const CacheContainer::iterator end = cache.end(); + for (; it != end; ++it) { + CachedImage &tmp = *it; + if (tmp.pixmap == pixmap && tmp.count > 0) + tmp.count--; + } + +#ifdef TIMEDCACHE + if (! timer) +#endif // TIMEDCACHE + timeout(); +} + + +void BImageControl::getColorTables(unsigned char **rmt, unsigned char **gmt, + unsigned char **bmt, + int *roff, int *goff, int *boff, + int *rbit, int *gbit, int *bbit) { + if (rmt) *rmt = red_color_table; + if (gmt) *gmt = green_color_table; + if (bmt) *bmt = blue_color_table; + + if (roff) *roff = red_offset; + if (goff) *goff = green_offset; + if (boff) *boff = blue_offset; + + if (rbit) *rbit = red_bits; + if (gbit) *gbit = green_bits; + if (bbit) *bbit = blue_bits; +} + + +void BImageControl::getXColorTable(XColor **c, int *n) { + if (c) *c = colors; + if (n) *n = ncolors; +} + + +void BImageControl::getGradientBuffers(unsigned int w, + unsigned int h, + unsigned int **xbuf, + unsigned int **ybuf) +{ + if (w > grad_buffer_width) { + if (grad_xbuffer) { + delete [] grad_xbuffer; + } + + grad_buffer_width = w; + + grad_xbuffer = new unsigned int[grad_buffer_width * 3]; + } + + if (h > grad_buffer_height) { + if (grad_ybuffer) { + delete [] grad_ybuffer; + } + + grad_buffer_height = h; + + grad_ybuffer = new unsigned int[grad_buffer_height * 3]; + } + + *xbuf = grad_xbuffer; + *ybuf = grad_ybuffer; +} + + +void BImageControl::installRootColormap(void) { + int ncmap = 0; + Colormap *cmaps = + XListInstalledColormaps(basedisplay->getXDisplay(), window, &ncmap); + + if (cmaps) { + bool install = True; + for (int i = 0; i < ncmap; i++) + if (*(cmaps + i) == colormap) + install = False; + + if (install) + XInstallColormap(basedisplay->getXDisplay(), colormap); + + XFree(cmaps); + } +} + + +void BImageControl::setColorsPerChannel(int cpc) { + if (cpc < 2) cpc = 2; + if (cpc > 6) cpc = 6; + + colors_per_channel = cpc; +} + + +unsigned long BImageControl::getSqrt(unsigned int x) { + if (! sqrt_table) { + // build sqrt table for use with elliptic gradient + + sqrt_table = new unsigned long[(256 * 256 * 2) + 1]; + + for (int i = 0; i < (256 * 256 * 2); i++) + *(sqrt_table + i) = bsqrt(i); + } + + return (*(sqrt_table + x)); +} + + +struct ZeroRefCheck { + inline bool operator()(const BImageControl::CachedImage &image) const { + return (image.count == 0); + } +}; + +struct CacheCleaner { + Display *display; + ZeroRefCheck ref_check; + CacheCleaner(Display *d): display(d) {} + inline void operator()(const BImageControl::CachedImage& image) const { + if (ref_check(image)) + XFreePixmap(display, image.pixmap); + } +}; + + +void BImageControl::timeout(void) { + CacheCleaner cleaner(basedisplay->getXDisplay()); + std::for_each(cache.begin(), cache.end(), cleaner); + cache.remove_if(cleaner.ref_check); +} + diff --git a/src/Makefile.am b/src/Makefile.am index 2f695aa6..8cccea61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -# src/Makefile.am for Openbox +# src/Makefile.am for Blackbox - an X11 Window manager # Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) # # Permission is hereby granted, free of charge, to any person obtaining a @@ -20,17 +20,17 @@ # DEALINGS IN THE SOFTWARE. DEFAULT_MENU=$(pkgdatadir)/menu -DEFAULT_STYLE=$(pkgdatadir)/styles/steelblue +DEFAULT_STYLE=$(pkgdatadir)/styles/Results -CPPFLAGS= @CPPFLAGS@ @SHAPE@ @SLIT@ @INTERLACE@ @ORDEREDPSEUDO@ \ -@DEBUG@ @NEWWMSPEC@ @NLS@ @TIMEDCACHE@ @CLOBBER@ \ +CPPFLAGS= @CPPFLAGS@ @SHAPE@ @ORDEREDPSEUDO@ \ +@DEBUG@ @NLS@ @TIMEDCACHE@ @SLIT@ @CLOBBER@ \ -DLOCALEPATH=\"$(pkgdatadir)/nls\" \ -DDEFAULTMENU=\"$(DEFAULT_MENU)\" \ -DDEFAULTSTYLE=\"$(DEFAULT_STYLE)\" -bin_PROGRAMS= openbox +bin_PROGRAMS= blackbox -openbox_SOURCES= BaseDisplay.cc Basemenu.cc Clientmenu.cc Configmenu.cc Geometry.cc Iconmenu.cc Image.cc Netizen.cc Resource.cc Rootmenu.cc Screen.cc Slit.cc Timer.cc Toolbar.cc Window.cc Windowmenu.cc Workspace.cc Workspacemenu.cc XAtom.cc openbox.cc bsd-snprintf.c i18n.cc main.cc +blackbox_SOURCES= BaseDisplay.cc Basemenu.cc Clientmenu.cc Color.cc Configmenu.cc GCCache.cc Iconmenu.cc Image.cc ImageControl.cc Netizen.cc Rootmenu.cc Screen.cc Slit.cc Texture.cc Timer.cc Toolbar.cc Util.cc Window.cc Windowmenu.cc Workspace.cc Workspacemenu.cc blackbox.cc i18n.cc main.cc MAINTAINERCLEANFILES= Makefile.in @@ -39,74 +39,87 @@ distclean-local: # local dependencies -BaseDisplay.o: BaseDisplay.cc i18n.h BaseDisplay.h \ - Timer.h -Basemenu.o: Basemenu.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Iconmenu.h Basemenu.h \ - Windowmenu.h Slit.h Screen.h Configmenu.h Netizen.h Rootmenu.h \ - Workspace.h Workspacemenu.h Resource.h -Clientmenu.o: Clientmenu.cc openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \ - Clientmenu.h Workspace.h Screen.h Configmenu.h Netizen.h \ - Rootmenu.h Workspacemenu.h Resource.h Geometry.h -Configmenu.o: Configmenu.cc i18n.h Configmenu.h Basemenu.h \ - Screen.h BaseDisplay.h Timer.h Iconmenu.h Netizen.h \ - Rootmenu.h Workspace.h Workspacemenu.h openbox.h Image.h \ - Window.h Windowmenu.h Slit.h Toolbar.h Resource.h Geometry.h -Geometry.o: Geometry.cc Geometry.h -Icon.o: Iconmenu.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \ - Screen.h Configmenu.h Netizen.h Rootmenu.h Workspace.h \ - Workspacemenu.h Toolbar.h Resource.h Geometry.h -Image.o: Image.cc i18n.h BaseDisplay.h Timer.h \ - Image.h -Netizen.o: Netizen.cc Netizen.h BaseDisplay.h Timer.h \ - Screen.h Configmenu.h Basemenu.h openbox.h Image.h Window.h \ - Iconmenu.h Windowmenu.h Slit.h Rootmenu.h Workspace.h \ - Workspacemenu.h Resource.h Geometry.h -Resource.o: Resource.cc Resource.h Util.h -Rootmenu.o: Rootmenu.cc openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \ - Rootmenu.h Screen.h Configmenu.h Netizen.h Workspace.h \ - Workspacemenu.h Resource.h Geometry.h -Screen.o: Screen.cc i18n.h bsd-snprintf.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h \ - Windowmenu.h Slit.h Clientmenu.h Workspace.h Screen.h Configmenu.h \ - Netizen.h Rootmenu.h Workspacemenu.h Toolbar.h Resource.h Geometry.h -Slit.o: Slit.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \ - Screen.h Configmenu.h Netizen.h Rootmenu.h Workspace.h \ - Workspacemenu.h Toolbar.h Resource.h Geometry.h -Timer.o: Timer.cc BaseDisplay.h Timer.h -Toolbar.o: Toolbar.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \ - Clientmenu.h Workspace.h Rootmenu.h Screen.h Configmenu.h \ - Netizen.h Workspacemenu.h Toolbar.h Resource.h Geometry.h -XAtom.o: XAtom.cc XAtom.h Geometry.h Util.h -Window.o: Window.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h Windowmenu.h Slit.h \ - Screen.h Configmenu.h Netizen.h Rootmenu.h Workspace.h \ - Workspacemenu.h Toolbar.h Resource.h Geometry.h -Windowmenu.o: Windowmenu.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h \ - Windowmenu.h Slit.h Screen.h Configmenu.h Netizen.h Rootmenu.h \ - Workspace.h Workspacemenu.h Resource.h Geometry.h -Workspace.o: Workspace.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h \ - Windowmenu.h Slit.h Clientmenu.h Workspace.h Screen.h \ - Configmenu.h Netizen.h Rootmenu.h Workspacemenu.h Toolbar.h Resource.h \ - Geometry.h Geometry.h Util.h -Workspacemenu.o: Workspacemenu.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h \ - Windowmenu.h Slit.h Screen.h Configmenu.h Netizen.h Rootmenu.h \ - Workspace.h Workspacemenu.h Toolbar.h Resource.h Geometry.h -openbox.o: openbox.cc i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h \ - Windowmenu.h Slit.h Clientmenu.h Workspace.h Rootmenu.h \ - Screen.h Configmenu.h Netizen.h Workspacemenu.h Toolbar.h Resource.h \ - Geometry.h Util.h -bsd-snprintf.o: bsd-snprintf.c bsd-snprintf.h -i18n.o: i18n.cc i18n.h -main.o: main.cc ../version.h i18n.h openbox.h BaseDisplay.h \ - Timer.h Image.h Window.h Iconmenu.h Basemenu.h \ - Windowmenu.h Slit.h Resource.h Geometry.h +BaseDisplay.o: BaseDisplay.cc ../config.h i18n.hh \ + ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh GCCache.hh Color.hh \ + Util.hh +Basemenu.o: Basemenu.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + blackbox.hh BaseDisplay.hh Timer.hh Basemenu.hh GCCache.hh Color.hh \ + Image.hh Screen.hh Texture.hh Util.hh Configmenu.hh Iconmenu.hh \ + Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh +Clientmenu.o: Clientmenu.cc ../config.h blackbox.hh i18n.hh \ + ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh Clientmenu.hh \ + Basemenu.hh Screen.hh Color.hh Texture.hh Util.hh Configmenu.hh \ + Iconmenu.hh Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh \ + Window.hh Windowmenu.hh +Color.o: Color.cc ../config.h Color.hh BaseDisplay.hh Timer.hh +Configmenu.o: Configmenu.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + Configmenu.hh Basemenu.hh Image.hh Timer.hh BaseDisplay.hh Color.hh \ + Toolbar.hh Screen.hh Texture.hh Util.hh Iconmenu.hh Netizen.hh \ + Rootmenu.hh Workspace.hh Workspacemenu.hh blackbox.hh Window.hh \ + Windowmenu.hh +GCCache.o: GCCache.cc ../config.h GCCache.hh BaseDisplay.hh Timer.hh \ + Color.hh Util.hh +Iconmenu.o: Iconmenu.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + Iconmenu.hh Basemenu.hh Screen.hh Color.hh Texture.hh Util.hh \ + Configmenu.hh Netizen.hh Rootmenu.hh Timer.hh Workspace.hh \ + Workspacemenu.hh blackbox.hh BaseDisplay.hh Window.hh Windowmenu.hh +Image.o: Image.cc ../config.h blackbox.hh i18n.hh \ + ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh GCCache.hh Color.hh \ + Image.hh Texture.hh Util.hh +ImageControl.o: ImageControl.cc ../config.h blackbox.hh i18n.hh \ + ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh Color.hh Image.hh \ + Texture.hh Util.hh +Netizen.o: Netizen.cc ../config.h Netizen.hh Screen.hh Color.hh \ + Texture.hh Util.hh Configmenu.hh Basemenu.hh Iconmenu.hh Rootmenu.hh \ + Timer.hh Workspace.hh Workspacemenu.hh blackbox.hh i18n.hh \ + ../nls/blackbox-nls.hh BaseDisplay.hh +Rootmenu.o: Rootmenu.cc ../config.h blackbox.hh i18n.hh \ + ../nls/blackbox-nls.hh BaseDisplay.hh Timer.hh Rootmenu.hh \ + Basemenu.hh Screen.hh Color.hh Texture.hh Util.hh Configmenu.hh \ + Iconmenu.hh Netizen.hh Workspace.hh Workspacemenu.hh +Screen.o: Screen.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + blackbox.hh BaseDisplay.hh Timer.hh Clientmenu.hh Basemenu.hh \ + GCCache.hh Color.hh Iconmenu.hh Image.hh Screen.hh Texture.hh Util.hh \ + Configmenu.hh Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh \ + Slit.hh Toolbar.hh Window.hh Windowmenu.hh +Slit.o: Slit.cc ../config.h i18n.hh ../nls/blackbox-nls.hh blackbox.hh \ + BaseDisplay.hh Timer.hh Image.hh Color.hh Screen.hh Texture.hh \ + Util.hh Configmenu.hh Basemenu.hh Iconmenu.hh Netizen.hh Rootmenu.hh \ + Workspace.hh Workspacemenu.hh Slit.hh Toolbar.hh +Texture.o: Texture.cc ../config.h Texture.hh Color.hh Util.hh \ + BaseDisplay.hh Timer.hh Image.hh Screen.hh Configmenu.hh Basemenu.hh \ + Iconmenu.hh Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh \ + blackbox.hh i18n.hh ../nls/blackbox-nls.hh +Timer.o: Timer.cc ../config.h BaseDisplay.hh Timer.hh Util.hh +Toolbar.o: Toolbar.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + blackbox.hh BaseDisplay.hh Timer.hh Clientmenu.hh Basemenu.hh \ + GCCache.hh Color.hh Iconmenu.hh Image.hh Rootmenu.hh Screen.hh \ + Texture.hh Util.hh Configmenu.hh Netizen.hh Workspace.hh \ + Workspacemenu.hh Toolbar.hh Window.hh Windowmenu.hh Slit.hh +Util.o: Util.cc ../config.h Util.hh +Window.o: Window.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + blackbox.hh BaseDisplay.hh Timer.hh GCCache.hh Color.hh Iconmenu.hh \ + Basemenu.hh Image.hh Screen.hh Texture.hh Util.hh Configmenu.hh \ + Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh Toolbar.hh \ + Window.hh Windowmenu.hh Slit.hh +Windowmenu.o: Windowmenu.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + blackbox.hh BaseDisplay.hh Timer.hh Screen.hh Color.hh Texture.hh \ + Util.hh Configmenu.hh Basemenu.hh Iconmenu.hh Netizen.hh Rootmenu.hh \ + Workspace.hh Workspacemenu.hh Window.hh Windowmenu.hh +Workspace.o: Workspace.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + blackbox.hh BaseDisplay.hh Timer.hh Clientmenu.hh Basemenu.hh \ + Netizen.hh Screen.hh Color.hh Texture.hh Util.hh Configmenu.hh \ + Iconmenu.hh Rootmenu.hh Workspace.hh Workspacemenu.hh Toolbar.hh \ + Window.hh Windowmenu.hh +Workspacemenu.o: Workspacemenu.cc ../config.h i18n.hh \ + ../nls/blackbox-nls.hh blackbox.hh BaseDisplay.hh Timer.hh Screen.hh \ + Color.hh Texture.hh Util.hh Configmenu.hh Basemenu.hh Iconmenu.hh \ + Netizen.hh Rootmenu.hh Workspace.hh Workspacemenu.hh Toolbar.hh +blackbox.o: blackbox.cc ../config.h i18n.hh ../nls/blackbox-nls.hh \ + blackbox.hh BaseDisplay.hh Timer.hh Basemenu.hh Clientmenu.hh \ + GCCache.hh Color.hh Image.hh Rootmenu.hh Screen.hh Texture.hh Util.hh \ + Configmenu.hh Iconmenu.hh Netizen.hh Workspace.hh Workspacemenu.hh \ + Slit.hh Toolbar.hh Window.hh Windowmenu.hh +i18n.o: i18n.cc ../config.h i18n.hh ../nls/blackbox-nls.hh +main.o: main.cc ../version.h ../config.h i18n.hh \ + ../nls/blackbox-nls.hh blackbox.hh BaseDisplay.hh Timer.hh diff --git a/src/Netizen.cc b/src/Netizen.cc index 6fbb99ac..6d73be95 100644 --- a/src/Netizen.cc +++ b/src/Netizen.cc @@ -1,4 +1,5 @@ -// Netizen.cc for Openbox +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Netizen.cc for Blackbox - An X11 Window Manager // Copyright (c) 2001 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // @@ -20,95 +21,94 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H #include "../config.h" #endif // HAVE_CONFIG_H -#include "Netizen.h" -#include "Screen.h" +#include "Netizen.hh" +#include "Screen.hh" + +Netizen::Netizen(BScreen *scr, Window win) { + screen = scr; + blackbox = scr->getBlackbox(); + window = win; -Netizen::Netizen(BScreen &scr, Window win) :basedisplay(scr.getBaseDisplay()), - screen(scr), window(win) -{ event.type = ClientMessage; - event.xclient.message_type = basedisplay.getOpenboxStructureMessagesAtom(); - event.xclient.display = basedisplay.getXDisplay(); + event.xclient.message_type = + blackbox->getBlackboxStructureMessagesAtom(); + event.xclient.display = blackbox->getXDisplay(); event.xclient.window = window; event.xclient.format = 32; - event.xclient.data.l[0] = basedisplay.getOpenboxNotifyStartupAtom(); + event.xclient.data.l[0] = blackbox->getBlackboxNotifyStartupAtom(); event.xclient.data.l[1] = event.xclient.data.l[2] = event.xclient.data.l[3] = event.xclient.data.l[4] = 0l; - XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event); } void Netizen::sendWorkspaceCount(void) { - event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWorkspaceCountAtom(); - event.xclient.data.l[1] = screen.getWorkspaceCount(); + event.xclient.data.l[0] = + blackbox->getBlackboxNotifyWorkspaceCountAtom(); + event.xclient.data.l[1] = screen->getWorkspaceCount(); - XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event); } void Netizen::sendCurrentWorkspace(void) { - event.xclient.data.l[0] = basedisplay.getOpenboxNotifyCurrentWorkspaceAtom(); - event.xclient.data.l[1] = screen.getCurrentWorkspaceID(); + event.xclient.data.l[0] = + blackbox->getBlackboxNotifyCurrentWorkspaceAtom(); + event.xclient.data.l[1] = screen->getCurrentWorkspaceID(); - XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event); } void Netizen::sendWindowFocus(Window w) { - event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowFocusAtom(); + event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowFocusAtom(); event.xclient.data.l[1] = w; - XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event); } void Netizen::sendWindowAdd(Window w, unsigned long p) { - event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowAddAtom(); + event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowAddAtom(); event.xclient.data.l[1] = w; event.xclient.data.l[2] = p; - XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event); event.xclient.data.l[2] = 0l; } void Netizen::sendWindowDel(Window w) { - event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowDelAtom(); + event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowDelAtom(); event.xclient.data.l[1] = w; - XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event); } void Netizen::sendWindowRaise(Window w) { - event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowRaiseAtom(); + event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowRaiseAtom(); event.xclient.data.l[1] = w; - XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event); } void Netizen::sendWindowLower(Window w) { - event.xclient.data.l[0] = basedisplay.getOpenboxNotifyWindowLowerAtom(); + event.xclient.data.l[0] = blackbox->getBlackboxNotifyWindowLowerAtom(); event.xclient.data.l[1] = w; - XSendEvent(basedisplay.getXDisplay(), window, False, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), window, False, NoEventMask, &event); } void Netizen::sendConfigNotify(XEvent *e) { - XSendEvent(basedisplay.getXDisplay(), window, False, + XSendEvent(blackbox->getXDisplay(), window, False, StructureNotifyMask, e); } diff --git a/src/Netizen.h b/src/Netizen.hh similarity index 86% rename from src/Netizen.h rename to src/Netizen.hh index 9de223d7..2f7cbda2 100644 --- a/src/Netizen.h +++ b/src/Netizen.hh @@ -1,4 +1,5 @@ -// Netizen.h for Openbox +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Netizen.hh for Blackbox - An X11 Window Manager // Copyright (c) 2001 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // @@ -23,26 +24,26 @@ #ifndef __Netizen_hh #define __Netizen_hh +extern "C" { #include +} // forward declaration -class BaseDisplay; +class Blackbox; class BScreen; class Netizen; class Netizen { private: - BaseDisplay &basedisplay; - BScreen &screen; + Blackbox *blackbox; + BScreen *screen; Window window; XEvent event; -protected: - public: - Netizen(BScreen &, Window); + Netizen(BScreen *, Window); - inline const Window &getWindowID(void) const { return window; } + inline Window getWindowID(void) const { return window; } void sendWorkspaceCount(void); void sendCurrentWorkspace(void); diff --git a/src/Resource.cc b/src/Resource.cc deleted file mode 100644 index 2a678f89..00000000 --- a/src/Resource.cc +++ /dev/null @@ -1,192 +0,0 @@ -// Resource.cc for Openbox -// Copyright (c) 2002 - 2002 Ben Jansens (ben@orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#include "Resource.h" -#include "Util.h" - -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif // HAVE_CONFIG_H - -#ifdef HAVE_STDLIB_H -# include -#endif // HAVE_STDLIB_H - -#ifdef HAVE_STDIO_H -# include -#endif // HAVE_STDIO_H - -bool Resource::m_initialized = false; - -Resource::Resource(const std::string &file) { - setFile(file); - m_modified = false; - m_database = NULL; - m_autosave = true; - if (!m_initialized) { - XrmInitialize(); - m_initialized = true; - } -} - -Resource::Resource() { - m_modified = false; - m_database = NULL; - m_autosave = true; - if (!m_initialized) { - XrmInitialize(); - m_initialized = true; - } -} - -Resource::~Resource() { - if (m_database != NULL) - XrmDestroyDatabase(m_database); -} - -void Resource::setFile(const std::string &file) { - m_file = file; -} - -void Resource::setAutoSave(bool autosave) { - m_autosave = autosave; -} - -void Resource::save() { - ASSERT(m_database != NULL); - XrmPutFileDatabase(m_database, m_file.c_str()); - m_modified = false; -} - -bool Resource::load() { - if (m_database != NULL) - XrmDestroyDatabase(m_database); - m_modified = false; - if (NULL == (m_database = XrmGetFileDatabase(m_file.c_str()))) - return false; - return true; -} - -void Resource::create() { - if (m_database != NULL) - XrmDestroyDatabase(m_database); - m_modified = false; - ASSERT(NULL != (m_database = XrmGetStringDatabase(""))); -} - -void Resource::setValue(const std::string &rname, bool value) { - ASSERT(m_database != NULL); - - const char *val = (value ? "True" : "False"); - std::string rc_string = rname + ": " + val; - XrmPutLineResource(&m_database, rc_string.c_str()); - - m_modified = true; - if (m_autosave) - save(); -} - -void Resource::setValue(const std::string &rname, int value) { - setValue(rname, (long)value); -} - -void Resource::setValue(const std::string &rname, long value) { - ASSERT(m_database != NULL); - - char val[11]; - sprintf(val, "%ld", value); - std::string rc_string = rname + ": " + val; - XrmPutLineResource(&m_database, rc_string.c_str()); - - m_modified = true; - if (m_autosave) - save(); -} - -void Resource::setValue(const std::string &rname, const char *value) { - ASSERT(m_database != NULL); - ASSERT(value != NULL); - - std::string rc_string = rname + ": " + value; - XrmPutLineResource(&m_database, rc_string.c_str()); - - m_modified = true; - if (m_autosave) - save(); -} - -void Resource::setValue(const std::string &rname, const std::string &value) { - ASSERT(m_database != NULL); - - std::string rc_string = rname + ": " + value; - XrmPutLineResource(&m_database, rc_string.c_str()); - - m_modified = true; - if (m_autosave) - save(); -} - -bool Resource::getValue(const std::string &rname, const std::string &rclass, - bool &value) const { - ASSERT(rclass.c_str() != NULL); - ASSERT(m_database != NULL); - - char *rettype; - XrmValue retvalue; - if (0 == XrmGetResource(m_database, rname.c_str(), rclass.c_str(), - &rettype, &retvalue) || retvalue.addr == NULL) - return false; - std::string val = retvalue.addr; - if (0 == strncasecmp(val.c_str(), "true", val.length())) - value = true; - else - value = false; - return true; -} - -bool Resource::getValue(const std::string &rname, const std::string &rclass, - long &value) const { - ASSERT(m_database != NULL); - - char *rettype; - XrmValue retvalue; - if (0 == XrmGetResource(m_database, rname.c_str(), rclass.c_str(), - &rettype, &retvalue) || retvalue.addr == NULL) - return false; - char *end; - value = strtol(retvalue.addr, &end, 10); - if (end == retvalue.addr) - return false; - return true; -} - -bool Resource::getValue(const std::string &rname, const std::string &rclass, - std::string &value) const { - ASSERT(m_database != NULL); - - char *rettype; - XrmValue retvalue; - if (0 == XrmGetResource(m_database, rname.c_str(), rclass.c_str(), - &rettype, &retvalue) || retvalue.addr == NULL) - return false; - value = retvalue.addr; - return true; -} diff --git a/src/Resource.h b/src/Resource.h deleted file mode 100644 index e75b8718..00000000 --- a/src/Resource.h +++ /dev/null @@ -1,76 +0,0 @@ -// Resource.h for Openbox -// Copyright (c) 2002 - 2002 Ben Jansens (ben@orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Resource_hh -#define __Resource_hh - -#include - -#include -#include - -class Resource { -public: - explicit Resource(const std::string &file); - Resource(); - virtual ~Resource(); - - inline const std::string &file() const { - return static_cast(m_file); - } - void setFile(const std::string &file); - - // defaults to true! - inline bool autoSave() const { - return m_autosave; - } - void setAutoSave(bool); - - inline bool isModified() const { - return m_modified; - } - - void save(); - bool load(); - void create(); - - void setValue(const std::string &rname, bool value); - void setValue(const std::string &rname, int value); - void setValue(const std::string &rname, long value); - void setValue(const std::string &rname, const std::string &value); - void setValue(const std::string &rname, const char *value); - - bool getValue(const std::string &rname, const std::string &rclass, - bool &value) const; - bool getValue(const std::string &rname, const std::string &rclass, - long &value) const; - bool getValue(const std::string &rname, const std::string &rclass, - std::string &value) const; - -private: - static bool m_initialized; - std::string m_file; - bool m_modified; - bool m_autosave; - XrmDatabase m_database; -}; - -#endif // __Resource_hh diff --git a/src/Rootmenu.cc b/src/Rootmenu.cc index 4728f507..3fbc844c 100644 --- a/src/Rootmenu.cc +++ b/src/Rootmenu.cc @@ -1,5 +1,6 @@ -// Rootmenu.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Rootmenu.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,48 +21,38 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "openbox.h" -#include "Rootmenu.h" -#include "Screen.h" - +extern "C" { #ifdef HAVE_STDIO_H # include #endif // HAVE_STDIO_H -#ifdef HAVE_STDLIB_H +#ifdef HAVE_STDLIB_H # include #endif // HAVE_STDLIB_H -#ifdef HAVE_STRING_H +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H #ifdef HAVE_SYS_PARAM_H # include #endif // HAVE_SYS_PARAM_H +} -#ifndef MAXPATHLEN -#define MAXPATHLEN 255 -#endif // MAXPATHLEN +#include "blackbox.hh" +#include "Rootmenu.hh" +#include "Screen.hh" +#include "Util.hh" -Rootmenu::Rootmenu(BScreen &scrn) : Basemenu(scrn), openbox(scrn.getOpenbox()), - screen(scrn) -{ -} +Rootmenu::Rootmenu(BScreen *scrn) : Basemenu(scrn) { } -void Rootmenu::itemSelected(int button, int index) { +void Rootmenu::itemSelected(int button, unsigned int index) { if (button != 1) return; @@ -72,44 +63,33 @@ void Rootmenu::itemSelected(int button, int index) { switch (item->function()) { case BScreen::Execute: - if (item->exec()) { -#ifndef __EMX__ - char displaystring[MAXPATHLEN]; - sprintf(displaystring, "DISPLAY=%s", - DisplayString(screen.getBaseDisplay().getXDisplay())); - sprintf(displaystring + strlen(displaystring) - 1, "%d", - screen.getScreenNumber()); - - bexec(item->exec(), displaystring); -#else // __EMX__ - spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", item->exec(), NULL); -#endif // !__EMX__ - } + if (item->exec()) + bexec(item->exec(), getScreen()->displayString()); break; case BScreen::Restart: - openbox.restart(); + getScreen()->getBlackbox()->restart(); break; case BScreen::RestartOther: if (item->exec()) - openbox.restart(item->exec()); + getScreen()->getBlackbox()->restart(item->exec()); break; case BScreen::Exit: - openbox.shutdown(); + getScreen()->getBlackbox()->shutdown(); break; case BScreen::SetStyle: if (item->exec()) - openbox.setStyleFilename(item->exec()); + getScreen()->getBlackbox()->saveStyleFilename(item->exec()); case BScreen::Reconfigure: - openbox.reconfigure(); + getScreen()->getBlackbox()->reconfigure(); return; } - if (! (screen.getRootmenu()->isTorn() || isTorn()) && + if (! (getScreen()->getRootmenu()->isTorn() || isTorn()) && item->function() != BScreen::Reconfigure && item->function() != BScreen::SetStyle) hide(); diff --git a/src/Rootmenu.h b/src/Rootmenu.hh similarity index 79% rename from src/Rootmenu.h rename to src/Rootmenu.hh index 63597d33..e436397d 100644 --- a/src/Rootmenu.h +++ b/src/Rootmenu.hh @@ -1,5 +1,6 @@ -// Rootmenu.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Rootmenu.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -24,26 +25,21 @@ #define __Rootmenu_hh // forward declarations -class Rootmenu; - -class Openbox; class BScreen; -#include "Basemenu.h" +#include "Basemenu.hh" class Rootmenu : public Basemenu { private: - Openbox &openbox; - BScreen &screen; - + Rootmenu(const Rootmenu&); + Rootmenu& operator=(const Rootmenu&); protected: - virtual void itemSelected(int, int); - + virtual void itemSelected(int button, unsigned int index); public: - Rootmenu(BScreen &); + Rootmenu(BScreen *scrn); }; diff --git a/src/Screen.cc b/src/Screen.cc index 2225e2ce..2844d874 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -1,5 +1,6 @@ -// Screen.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Screen.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,53 +21,36 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H +extern "C" { #include #include -#include "i18n.h" -#include "openbox.h" -#include "Clientmenu.h" -#include "Iconmenu.h" -#include "Image.h" -#include "Screen.h" - -#ifdef SLIT -#include "Slit.h" -#endif // SLIT - -#include "Rootmenu.h" -#include "Toolbar.h" -#include "Window.h" -#include "Workspace.h" -#include "Workspacemenu.h" -#include "Util.h" - -#ifdef HAVE_STDLIB_H +// for strcasestr() +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif // _GNU_SOURCE + +#ifdef HAVE_STDLIB_H # include #endif // HAVE_STDLIB_H -#ifdef HAVE_STRING_H +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H -#ifdef HAVE_SYS_TYPES_H -# include -#endif // HAVE_SYS_TYPES_H - #ifdef HAVE_CTYPE_H # include #endif // HAVE_CTYPE_H +#ifdef HAVE_UNISTD_H +# include +# include +#endif // HAVE_UNISTD_H + #ifdef HAVE_DIRENT_H # include #endif // HAVE_DIRENT_H @@ -75,11 +59,6 @@ # include #endif // HAVE_LOCALE_H -#ifdef HAVE_UNISTD_H -# include -# include -#endif // HAVE_UNISTD_H - #ifdef HAVE_SYS_STAT_H # include #endif // HAVE_SYS_STAT_H @@ -87,31 +66,38 @@ #ifdef HAVE_STDARG_H # include #endif // HAVE_STDARG_H +} -#ifndef HAVE_SNPRINTF -# include "bsd-snprintf.h" -#endif // !HAVE_SNPRINTF - -#ifndef MAXPATHLEN -#define MAXPATHLEN 255 -#endif // MAXPATHLEN +#include +#include +using std::string; + +#include "i18n.hh" +#include "blackbox.hh" +#include "Clientmenu.hh" +#include "GCCache.hh" +#include "Iconmenu.hh" +#include "Image.hh" +#include "Screen.hh" +#include "Slit.hh" +#include "Rootmenu.hh" +#include "Toolbar.hh" +#include "Util.hh" +#include "Window.hh" +#include "Workspace.hh" +#include "Workspacemenu.hh" #ifndef FONT_ELEMENT_SIZE #define FONT_ELEMENT_SIZE 50 #endif // FONT_ELEMENT_SIZE -#include -#include -#include -#include -using std::ends; -static Bool running = True; +static bool running = True; static int anotherWMRunning(Display *display, XErrorEvent *) { fprintf(stderr, i18n(ScreenSet, ScreenAnotherWMRunning, - "BScreen::BScreen: an error occured while querying the X server.\n" - " another window manager already running on display %s.\n"), + "BScreen::BScreen: an error occured while querying the X server.\n" + " another window manager already running on display %s.\n"), DisplayString(display)); running = False; @@ -119,86 +105,16 @@ static int anotherWMRunning(Display *display, XErrorEvent *) { return(-1); } -struct dcmp { - bool operator()(const char *one, const char *two) const { - return (strcmp(one, two) < 0) ? True : False; - } -}; - -#ifndef HAVE_STRCASESTR -static const char * strcasestr(const char *str, const char *ptn) { - const char *s2, *p2; - for( ; *str; str++) { - for(s2=str,p2=ptn; ; s2++,p2++) { - if (!*p2) return str; - if (toupper(*s2) != toupper(*p2)) break; - } - } - return NULL; -} -#endif // HAVE_STRCASESTR - -static const char *getFontElement(const char *pattern, char *buf, int bufsiz, ...) { - const char *p, *v; - char *p2; - va_list va; - - va_start(va, bufsiz); - buf[bufsiz-1] = 0; - buf[bufsiz-2] = '*'; - while((v = va_arg(va, char *)) != NULL) { - p = strcasestr(pattern, v); - if (p) { - strncpy(buf, p+1, bufsiz-2); - p2 = strchr(buf, '-'); - if (p2) *p2=0; - va_end(va); - return p; - } - } - va_end(va); - strncpy(buf, "*", bufsiz); - return NULL; -} - -static const char *getFontSize(const char *pattern, int *size) { - const char *p; - const char *p2=NULL; - int n=0; - - for (p=pattern; 1; p++) { - if (!*p) { - if (p2!=NULL && n>1 && n<72) { - *size = n; return p2+1; - } else { - *size = 16; return NULL; - } - } else if (*p=='-') { - if (n>1 && n<72 && p2!=NULL) { - *size = n; - return p2+1; - } - p2=p; n=0; - } else if (*p>='0' && *p<='9' && p2!=NULL) { - n *= 10; - n += *p-'0'; - } else { - p2=NULL; n=0; - } - } -} +BScreen::BScreen(Blackbox *bb, unsigned int scrn) : ScreenInfo(bb, scrn) { + blackbox = bb; -BScreen::BScreen(Openbox &ob, int scrn, Resource &conf) : ScreenInfo(ob, scrn), -openbox(ob), config(conf) -{ event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask | - SubstructureRedirectMask | KeyPressMask | KeyReleaseMask | - ButtonPressMask | ButtonReleaseMask; + SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask; XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning); - XSelectInput(getBaseDisplay().getXDisplay(), getRootWindow(), event_mask); - XSync(getBaseDisplay().getXDisplay(), False); + XSelectInput(getBaseDisplay()->getXDisplay(), getRootWindow(), event_mask); + XSync(getBaseDisplay()->getXDisplay(), False); XSetErrorHandler((XErrorHandler) old); managed = running; @@ -211,131 +127,51 @@ openbox(ob), config(conf) getDepth()); rootmenu = 0; + resource.stylerc = 0; resource.mstyle.t_fontset = resource.mstyle.f_fontset = - resource.tstyle.fontset = resource.wstyle.fontset = NULL; + resource.tstyle.fontset = resource.wstyle.fontset = (XFontSet) 0; resource.mstyle.t_font = resource.mstyle.f_font = resource.tstyle.font = - resource.wstyle.font = NULL; - resource.root_command = NULL; -#ifdef HAVE_STRFTIME - resource.strftime_format = NULL; -#endif // HAVE_STRFTIME - -#ifdef SLIT - slit = NULL; -#endif // SLIT - toolbar = NULL; - current_workspace = (Workspace *) 0; + resource.wstyle.font = (XFontStruct *) 0; #ifdef HAVE_GETPID pid_t bpid = getpid(); - XChangeProperty(getBaseDisplay().getXDisplay(), getRootWindow(), - openbox.getOpenboxPidAtom(), XA_CARDINAL, + XChangeProperty(blackbox->getXDisplay(), getRootWindow(), + blackbox->getBlackboxPidAtom(), XA_CARDINAL, sizeof(pid_t) * 8, PropModeReplace, (unsigned char *) &bpid, 1); #endif // HAVE_GETPID - XDefineCursor(getBaseDisplay().getXDisplay(), getRootWindow(), - openbox.getSessionCursor()); + XDefineCursor(blackbox->getXDisplay(), getRootWindow(), + blackbox->getSessionCursor()); + + // start off full screen, top left. + usableArea.setSize(getWidth(), getHeight()); image_control = - new BImageControl(openbox, *this, True, openbox.getColorsPerChannel(), - openbox.getCacheLife(), openbox.getCacheMax()); + new BImageControl(blackbox, this, True, blackbox->getColorsPerChannel(), + blackbox->getCacheLife(), blackbox->getCacheMax()); image_control->installRootColormap(); root_colormap_installed = True; - load(); // load config options from Resources + blackbox->load_rc(this); + + image_control->setDither(resource.image_dither); + LoadStyle(); XGCValues gcv; unsigned long gc_value_mask = GCForeground; if (! i18n.multibyte()) gc_value_mask |= GCFont; - gcv.foreground = WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber()) - ^ BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber()); + gcv.foreground = WhitePixel(blackbox->getXDisplay(), getScreenNumber()) + ^ BlackPixel(blackbox->getXDisplay(), getScreenNumber()); gcv.function = GXxor; gcv.subwindow_mode = IncludeInferiors; - opGC = XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), + opGC = XCreateGC(blackbox->getXDisplay(), getRootWindow(), GCForeground | GCFunction | GCSubwindowMode, &gcv); - gcv.foreground = resource.wstyle.l_text_focus.getPixel(); - if (resource.wstyle.font) - gcv.font = resource.wstyle.font->fid; - resource.wstyle.l_text_focus_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.wstyle.l_text_unfocus.getPixel(); - if (resource.wstyle.font) - gcv.font = resource.wstyle.font->fid; - resource.wstyle.l_text_unfocus_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.wstyle.b_pic_focus.getPixel(); - resource.wstyle.b_pic_focus_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - GCForeground, &gcv); - - gcv.foreground = resource.wstyle.b_pic_unfocus.getPixel(); - resource.wstyle.b_pic_unfocus_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - GCForeground, &gcv); - - gcv.foreground = resource.mstyle.t_text.getPixel(); - if (resource.mstyle.t_font) - gcv.font = resource.mstyle.t_font->fid; - resource.mstyle.t_text_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.mstyle.f_text.getPixel(); - if (resource.mstyle.f_font) - gcv.font = resource.mstyle.f_font->fid; - resource.mstyle.f_text_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.mstyle.h_text.getPixel(); - resource.mstyle.h_text_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.mstyle.d_text.getPixel(); - resource.mstyle.d_text_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.mstyle.hilite.getColor()->getPixel(); - resource.mstyle.hilite_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.tstyle.l_text.getPixel(); - if (resource.tstyle.font) - gcv.font = resource.tstyle.font->fid; - resource.tstyle.l_text_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.tstyle.w_text.getPixel(); - resource.tstyle.w_text_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.tstyle.c_text.getPixel(); - resource.tstyle.c_text_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - - gcv.foreground = resource.tstyle.b_pic.getPixel(); - resource.tstyle.b_pic_gc = - XCreateGC(getBaseDisplay().getXDisplay(), getRootWindow(), - gc_value_mask, &gcv); - const char *s = i18n(ScreenSet, ScreenPositionLength, "0: 0000 x 0: 0000"); int l = strlen(s); @@ -358,134 +194,107 @@ openbox(ob), config(conf) XSetWindowAttributes attrib; unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder; - attrib.border_pixel = getBorderColor()->getPixel(); + attrib.border_pixel = getBorderColor()->pixel(); attrib.colormap = getColormap(); attrib.save_under = True; - geom_window = - XCreateWindow(getBaseDisplay().getXDisplay(), getRootWindow(), - 0, 0, geom_w, geom_h, resource.border_width, getDepth(), - InputOutput, getVisual(), mask, &attrib); + geom_window = XCreateWindow(blackbox->getXDisplay(), getRootWindow(), + 0, 0, geom_w, geom_h, resource.border_width, + getDepth(), InputOutput, getVisual(), + mask, &attrib); geom_visible = False; - if (resource.wstyle.l_focus.getTexture() & BImage_ParentRelative) { - if (resource.wstyle.t_focus.getTexture() == - (BImage_Flat | BImage_Solid)) { - geom_pixmap = None; - XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window, - resource.wstyle.t_focus.getColor()->getPixel()); - } else { - geom_pixmap = image_control->renderImage(geom_w, geom_h, - &resource.wstyle.t_focus); - XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(), - geom_window, geom_pixmap); - } - } else { - if (resource.wstyle.l_focus.getTexture() == - (BImage_Flat | BImage_Solid)) { - geom_pixmap = None; - XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window, - resource.wstyle.l_focus.getColor()->getPixel()); - } else { - geom_pixmap = image_control->renderImage(geom_w, geom_h, - &resource.wstyle.l_focus); - XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(), - geom_window, geom_pixmap); - } - } + BTexture* texture = &(resource.wstyle.l_focus); + geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap); + if (! geom_pixmap) + XSetWindowBackground(blackbox->getXDisplay(), geom_window, + texture->color().pixel()); + else + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + geom_window, geom_pixmap); - workspacemenu = new Workspacemenu(*this); - iconmenu = new Iconmenu(*this); - configmenu = new Configmenu(*this); + workspacemenu = new Workspacemenu(this); + iconmenu = new Iconmenu(this); + configmenu = new Configmenu(this); - Workspace *wkspc = NULL; + Workspace *wkspc = (Workspace *) 0; if (resource.workspaces != 0) { - for (int i = 0; i < resource.workspaces; ++i) { - wkspc = new Workspace(*this, workspacesList.size()); + for (unsigned int i = 0; i < resource.workspaces; ++i) { + wkspc = new Workspace(this, workspacesList.size()); workspacesList.push_back(wkspc); workspacemenu->insert(wkspc->getName(), wkspc->getMenu()); } } else { - setWorkspaceCount(1); - wkspc = new Workspace(*this, workspacesList.size()); + wkspc = new Workspace(this, workspacesList.size()); workspacesList.push_back(wkspc); workspacemenu->insert(wkspc->getName(), wkspc->getMenu()); } - saveWorkspaceNames(); - workspacemenu->insert(i18n(IconSet, IconIcons, "Icons"), - iconmenu); + workspacemenu->insert(i18n(IconSet, IconIcons, "Icons"), iconmenu); workspacemenu->update(); current_workspace = workspacesList.front(); workspacemenu->setItemSelected(2, True); - toolbar = new Toolbar(*this, config); + toolbar = new Toolbar(this); -#ifdef SLIT - slit = new Slit(*this, config); -#endif // SLIT + slit = new Slit(this); InitMenu(); raiseWindows(0, 0); rootmenu->update(); + updateAvailableArea(); + changeWorkspaceID(0); - int i; - unsigned int nchild; + unsigned int i, j, nchild; Window r, p, *children; - XQueryTree(getBaseDisplay().getXDisplay(), getRootWindow(), &r, &p, + XQueryTree(blackbox->getXDisplay(), getRootWindow(), &r, &p, &children, &nchild); // preen the window list of all icon windows... for better dockapp support - for (i = 0; i < (int) nchild; i++) { + for (i = 0; i < nchild; i++) { if (children[i] == None) continue; - XWMHints *wmhints = XGetWMHints(getBaseDisplay().getXDisplay(), + XWMHints *wmhints = XGetWMHints(blackbox->getXDisplay(), children[i]); if (wmhints) { if ((wmhints->flags & IconWindowHint) && - (wmhints->icon_window != children[i])) - for (int j = 0; j < (int) nchild; j++) + (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 < (int) nchild; ++i) { - if (children[i] == None || (! openbox.validateWindow(children[i]))) + for (i = 0; i < nchild; ++i) { + if (children[i] == None || (! blackbox->validateWindow(children[i]))) continue; XWindowAttributes attrib; - if (XGetWindowAttributes(getBaseDisplay().getXDisplay(), children[i], - &attrib)) { + if (XGetWindowAttributes(blackbox->getXDisplay(), children[i], &attrib)) { if (attrib.override_redirect) continue; if (attrib.map_state != IsUnmapped) { - new OpenboxWindow(openbox, children[i], this); - - OpenboxWindow *win = openbox.searchWindow(children[i]); - if (win) { - XMapRequestEvent mre; - mre.window = children[i]; - win->restoreAttributes(); - win->mapRequestEvent(&mre); - } + manageWindow(children[i]); } } } XFree(children); - XFlush(getBaseDisplay().getXDisplay()); + + // call this again just in case a window we found updates the Strut list + updateAvailableArea(); } @@ -496,1798 +305,830 @@ BScreen::~BScreen(void) { image_control->removeImage(geom_pixmap); if (geom_window != None) - XDestroyWindow(getBaseDisplay().getXDisplay(), geom_window); - - removeWorkspaceNames(); + XDestroyWindow(blackbox->getXDisplay(), geom_window); std::for_each(workspacesList.begin(), workspacesList.end(), PointerAssassin()); + std::for_each(iconList.begin(), iconList.end(), PointerAssassin()); - std::for_each(netizenList.begin(), netizenList.end(), PointerAssassin()); -#ifdef HAVE_STRFTIME - if (resource.strftime_format) - delete [] resource.strftime_format; -#endif // HAVE_STRFTIME + std::for_each(netizenList.begin(), netizenList.end(), PointerAssassin()); delete rootmenu; delete workspacemenu; delete iconmenu; delete configmenu; - -#ifdef SLIT delete slit; -#endif // SLIT - delete toolbar; delete image_control; if (resource.wstyle.fontset) - XFreeFontSet(getBaseDisplay().getXDisplay(), resource.wstyle.fontset); + XFreeFontSet(blackbox->getXDisplay(), resource.wstyle.fontset); if (resource.mstyle.t_fontset) - XFreeFontSet(getBaseDisplay().getXDisplay(), resource.mstyle.t_fontset); + XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.t_fontset); if (resource.mstyle.f_fontset) - XFreeFontSet(getBaseDisplay().getXDisplay(), resource.mstyle.f_fontset); + XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.f_fontset); if (resource.tstyle.fontset) - XFreeFontSet(getBaseDisplay().getXDisplay(), resource.tstyle.fontset); + XFreeFontSet(blackbox->getXDisplay(), resource.tstyle.fontset); if (resource.wstyle.font) - XFreeFont(getBaseDisplay().getXDisplay(), resource.wstyle.font); + XFreeFont(blackbox->getXDisplay(), resource.wstyle.font); if (resource.mstyle.t_font) - XFreeFont(getBaseDisplay().getXDisplay(), resource.mstyle.t_font); + XFreeFont(blackbox->getXDisplay(), resource.mstyle.t_font); if (resource.mstyle.f_font) - XFreeFont(getBaseDisplay().getXDisplay(), resource.mstyle.f_font); + XFreeFont(blackbox->getXDisplay(), resource.mstyle.f_font); if (resource.tstyle.font) - XFreeFont(getBaseDisplay().getXDisplay(), resource.tstyle.font); - if (resource.root_command != NULL) - delete [] resource.root_command; - - XFreeGC(getBaseDisplay().getXDisplay(), opGC); - - XFreeGC(getBaseDisplay().getXDisplay(), - resource.wstyle.l_text_focus_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.wstyle.l_text_unfocus_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.wstyle.b_pic_focus_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.wstyle.b_pic_unfocus_gc); - - XFreeGC(getBaseDisplay().getXDisplay(), - resource.mstyle.t_text_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.mstyle.f_text_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.mstyle.h_text_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.mstyle.d_text_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.mstyle.hilite_gc); - - XFreeGC(getBaseDisplay().getXDisplay(), - resource.tstyle.l_text_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.tstyle.w_text_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.tstyle.c_text_gc); - XFreeGC(getBaseDisplay().getXDisplay(), - resource.tstyle.b_pic_gc); + XFreeFont(blackbox->getXDisplay(), resource.tstyle.font); + + XFreeGC(blackbox->getXDisplay(), opGC); } -Rect BScreen::availableArea() const { - // the following code is temporary and will be taken care of by Screen in the - // future (with the NETWM 'strut') - Rect space(0, 0, size().w(), size().h()); - if (!resource.full_max) { -#ifdef SLIT - int slit_x = slit->autoHide() ? slit->hiddenOrigin().x() : slit->area().x(), - slit_y = slit->autoHide() ? slit->hiddenOrigin().y() : slit->area().y(); - unsigned int tbarh = resource.hide_toolbar ? 0 : - toolbar->getExposedHeight() + resource.border_width * 2; - bool tbartop; - switch (toolbar->placement()) { - case Toolbar::TopLeft: - case Toolbar::TopCenter: - case Toolbar::TopRight: - tbartop = true; - break; - case Toolbar::BottomLeft: - case Toolbar::BottomCenter: - case Toolbar::BottomRight: - tbartop = false; - break; - default: - ASSERT(false); // unhandled placement - } - if ((slit->direction() == Slit::Horizontal && - (slit->placement() == Slit::TopLeft || - slit->placement() == Slit::TopRight)) || - slit->placement() == Slit::TopCenter) { - // exclude top - if (tbartop && slit_y + slit->area().h() < tbarh) { - space.setY(space.y() + tbarh); - space.setH(space.h() - tbarh); - } else { - space.setY(space.y() + (slit_y + slit->area().h() + - resource.border_width * 2)); - space.setH(space.h() - (slit_y + slit->area().h() + - resource.border_width * 2)); - if (!tbartop) - space.setH(space.h() - tbarh); - } - } else if ((slit->direction() == Slit::Vertical && - (slit->placement() == Slit::TopRight || - slit->placement() == Slit::BottomRight)) || - slit->placement() == Slit::CenterRight) { - // exclude right - space.setW(space.w() - (size().w() - slit_x)); - if (tbartop) - space.setY(space.y() + tbarh); - space.setH(space.h() - tbarh); - } else if ((slit->direction() == Slit::Horizontal && - (slit->placement() == Slit::BottomLeft || - slit->placement() == Slit::BottomRight)) || - slit->placement() == Slit::BottomCenter) { - // exclude bottom - if (!tbartop && (size().h() - slit_y) < tbarh) { - space.setH(space.h() - tbarh); - } else { - space.setH(space.h() - (size().h() - slit_y)); - if (tbartop) { - space.setY(space.y() + tbarh); - space.setH(space.h() - tbarh); - } - } - } else {// if ((slit->direction() == Slit::Vertical && - // (slit->placement() == Slit::TopLeft || - // slit->placement() == Slit::BottomLeft)) || - // slit->placement() == Slit::CenterLeft) - // exclude left - space.setX(slit_x + slit->area().w() + - resource.border_width * 2); - space.setW(space.w() - (slit_x + slit->area().w() + - resource.border_width * 2)); - if (tbartop) - space.setY(space.y() + tbarh); - space.setH(space.h() - tbarh); - } -#else // !SLIT - int tbarh = resource.hide_toolbar ? 0 : - toolbar->getExposedHeight() + resource.border_width * 2; - switch (toolbar->placement()) { - case Toolbar::TopLeft: - case Toolbar::TopCenter: - case Toolbar::TopRight: - space.setY(toolbar->getExposedHeight()); - space.setH(space.h() - toolbar->getExposedHeight()); - break; - case Toolbar::BottomLeft: - case Toolbar::BottomCenter: - case Toolbar::BottomRight: - space.setH(space.h() - tbarh); - break; - default: - ASSERT(false); // unhandled placement - } -#endif // SLIT - } - return space; +void BScreen::removeWorkspaceNames(void) { + workspaceNames.clear(); } -void BScreen::readDatabaseTexture(const char *rname, const char *rclass, - BTexture *texture, - unsigned long default_pixel) -{ - std::string s; +void BScreen::reconfigure(void) { + LoadStyle(); - if (resource.styleconfig.getValue(rname, rclass, s)) - image_control->parseTexture(texture, s.c_str()); - else - texture->setTexture(BImage_Solid | BImage_Flat); - - if (texture->getTexture() & BImage_Solid) { - int clen = strlen(rclass) + 32, nlen = strlen(rname) + 32; - - char *colorclass = new char[clen], *colorname = new char[nlen]; - - sprintf(colorclass, "%s.Color", rclass); - sprintf(colorname, "%s.color", rname); - - readDatabaseColor(colorname, colorclass, texture->getColor(), - default_pixel); - -#ifdef INTERLACE - sprintf(colorclass, "%s.ColorTo", rclass); - sprintf(colorname, "%s.colorTo", rname); - - readDatabaseColor(colorname, colorclass, texture->getColorTo(), - default_pixel); -#endif // INTERLACE - - delete [] colorclass; - delete [] colorname; - - if ((! texture->getColor()->isAllocated()) || - (texture->getTexture() & BImage_Flat)) - return; - - XColor xcol; - - xcol.red = (unsigned int) (texture->getColor()->getRed() + - (texture->getColor()->getRed() >> 1)); - if (xcol.red >= 0xff) xcol.red = 0xffff; - else xcol.red *= 0xff; - xcol.green = (unsigned int) (texture->getColor()->getGreen() + - (texture->getColor()->getGreen() >> 1)); - if (xcol.green >= 0xff) xcol.green = 0xffff; - else xcol.green *= 0xff; - xcol.blue = (unsigned int) (texture->getColor()->getBlue() + - (texture->getColor()->getBlue() >> 1)); - if (xcol.blue >= 0xff) xcol.blue = 0xffff; - else xcol.blue *= 0xff; - - if (! XAllocColor(getBaseDisplay().getXDisplay(), - getColormap(), &xcol)) - xcol.pixel = 0; - - texture->getHiColor()->setPixel(xcol.pixel); - - xcol.red = - (unsigned int) ((texture->getColor()->getRed() >> 2) + - (texture->getColor()->getRed() >> 1)) * 0xff; - xcol.green = - (unsigned int) ((texture->getColor()->getGreen() >> 2) + - (texture->getColor()->getGreen() >> 1)) * 0xff; - xcol.blue = - (unsigned int) ((texture->getColor()->getBlue() >> 2) + - (texture->getColor()->getBlue() >> 1)) * 0xff; - - if (! XAllocColor(getBaseDisplay().getXDisplay(), - getColormap(), &xcol)) - xcol.pixel = 0; - - texture->getLoColor()->setPixel(xcol.pixel); - } else if (texture->getTexture() & BImage_Gradient) { - int clen = strlen(rclass) + 10, nlen = strlen(rname) + 10; - - char *colorclass = new char[clen], *colorname = new char[nlen], - *colortoclass = new char[clen], *colortoname = new char[nlen]; - - sprintf(colorclass, "%s.Color", rclass); - sprintf(colorname, "%s.color", rname); - - sprintf(colortoclass, "%s.ColorTo", rclass); - sprintf(colortoname, "%s.colorTo", rname); - - readDatabaseColor(colorname, colorclass, texture->getColor(), - default_pixel); - readDatabaseColor(colortoname, colortoclass, texture->getColorTo(), - default_pixel); - - delete [] colorclass; - delete [] colorname; - delete [] colortoclass; - delete [] colortoname; - } -} + XGCValues gcv; + unsigned long gc_value_mask = GCForeground; + if (! i18n.multibyte()) gc_value_mask |= GCFont; + gcv.foreground = WhitePixel(blackbox->getXDisplay(), + getScreenNumber()); + gcv.function = GXinvert; + gcv.subwindow_mode = IncludeInferiors; + XChangeGC(blackbox->getXDisplay(), opGC, + GCForeground | GCFunction | GCSubwindowMode, &gcv); -void BScreen::readDatabaseColor(const char *rname, const char *rclass, - BColor *color, unsigned long default_pixel) -{ - std::string s; + const char *s = i18n(ScreenSet, ScreenPositionLength, + "0: 0000 x 0: 0000"); + int l = strlen(s); - if (resource.styleconfig.getValue(rname, rclass, s)) - image_control->parseColor(color, s.c_str()); - else { - // parsing with no color std::string just deallocates the color, if it has - // been previously allocated - image_control->parseColor(color); - color->setPixel(default_pixel); + if (i18n.multibyte()) { + XRectangle ink, logical; + XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical); + geom_w = logical.width; + + geom_h = resource.wstyle.fontset_extents->max_ink_extent.height; + } else { + geom_w = XTextWidth(resource.wstyle.font, s, l); + + geom_h = resource.wstyle.font->ascent + resource.wstyle.font->descent; } -} + geom_w += (resource.bevel_width * 2); + geom_h += (resource.bevel_width * 2); + + BTexture* texture = &(resource.wstyle.l_focus); + geom_pixmap = texture->render(geom_w, geom_h, geom_pixmap); + if (! geom_pixmap) + XSetWindowBackground(blackbox->getXDisplay(), geom_window, + texture->color().pixel()); + else + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + geom_window, geom_pixmap); + + XSetWindowBorderWidth(blackbox->getXDisplay(), geom_window, + resource.border_width); + XSetWindowBorder(blackbox->getXDisplay(), geom_window, + resource.border_color.pixel()); -void BScreen::readDatabaseFontSet(const char *rname, const char *rclass, - XFontSet *fontset) { - if (! fontset) return; + workspacemenu->reconfigure(); + iconmenu->reconfigure(); - static char *defaultFont = "fixed"; - bool load_default = false; - std::string s; + int remember_sub = rootmenu->getCurrentSubmenu(); + InitMenu(); + raiseWindows(0, 0); + rootmenu->reconfigure(); + rootmenu->drawSubmenu(remember_sub); - if (*fontset) - XFreeFontSet(getBaseDisplay().getXDisplay(), *fontset); + configmenu->reconfigure(); - if (resource.styleconfig.getValue(rname, rclass, s)) { - if (! (*fontset = createFontSet(s.c_str()))) - load_default = true; - } else - load_default = true; + toolbar->reconfigure(); - if (load_default) { - *fontset = createFontSet(defaultFont); + slit->reconfigure(); - if (! *fontset) { - fprintf(stderr, i18n(ScreenSet, ScreenDefaultFontLoadFail, - "BScreen::LoadStyle(): couldn't load default font.\n")); - exit(2); - } + 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(); } + + image_control->timeout(); } -void BScreen::readDatabaseFont(const char *rname, const char *rclass, - XFontStruct **font) { - if (! font) return; +void BScreen::rereadMenu(void) { + InitMenu(); + raiseWindows(0, 0); - static char *defaultFont = "fixed"; - bool load_default = false; - std::string s; + rootmenu->reconfigure(); +} - if (*font) - XFreeFont(getBaseDisplay().getXDisplay(), *font); - if (resource.styleconfig.getValue(rname, rclass, s)) { - if ((*font = XLoadQueryFont(getBaseDisplay().getXDisplay(), - s.c_str())) == NULL) { - fprintf(stderr, i18n(ScreenSet, ScreenFontLoadFail, - "BScreen::LoadStyle(): couldn't load font '%s'\n"), - s.c_str()); - load_default = true; - } - } else - load_default = true; +void BScreen::LoadStyle(void) { + resource.stylerc = XrmGetFileDatabase(blackbox->getStyleFilename()); + if (! resource.stylerc) + resource.stylerc = XrmGetFileDatabase(DEFAULTSTYLE); - if (load_default) { - if ((*font = XLoadQueryFont(getBaseDisplay().getXDisplay(), - defaultFont)) == NULL) { - fprintf(stderr, i18n(ScreenSet, ScreenDefaultFontLoadFail, - "BScreen::LoadStyle(): couldn't load default font.\n")); - exit(2); - } - } -} + XrmValue value; + char *value_type; + // load fonts/fontsets + if (resource.wstyle.fontset) + XFreeFontSet(blackbox->getXDisplay(), resource.wstyle.fontset); + if (resource.tstyle.fontset) + XFreeFontSet(blackbox->getXDisplay(), resource.tstyle.fontset); + if (resource.mstyle.f_fontset) + XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.f_fontset); + if (resource.mstyle.t_fontset) + XFreeFontSet(blackbox->getXDisplay(), resource.mstyle.t_fontset); + resource.wstyle.fontset = 0; + resource.tstyle.fontset = 0; + resource.mstyle.f_fontset = 0; + resource.mstyle.t_fontset = 0; + if (resource.wstyle.font) + XFreeFont(blackbox->getXDisplay(), resource.wstyle.font); + if (resource.tstyle.font) + XFreeFont(blackbox->getXDisplay(), resource.tstyle.font); + if (resource.mstyle.f_font) + XFreeFont(blackbox->getXDisplay(), resource.mstyle.f_font); + if (resource.mstyle.t_font) + XFreeFont(blackbox->getXDisplay(), resource.mstyle.t_font); + resource.wstyle.font = 0; + resource.tstyle.font = 0; + resource.mstyle.f_font = 0; + resource.mstyle.t_font = 0; -XFontSet BScreen::createFontSet(const char *fontname) { - XFontSet fs; - char **missing, *def = "-"; - int nmissing, pixel_size = 0, buf_size = 0; - char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE]; + if (i18n.multibyte()) { + resource.wstyle.fontset = + readDatabaseFontSet("window.font", "Window.Font"); + resource.tstyle.fontset = + readDatabaseFontSet("toolbar.font", "Toolbar.Font"); + resource.mstyle.t_fontset = + readDatabaseFontSet("menu.title.font", "Menu.Title.Font"); + resource.mstyle.f_fontset = + readDatabaseFontSet("menu.frame.font", "Menu.Frame.Font"); + + resource.mstyle.t_fontset_extents = + XExtentsOfFontSet(resource.mstyle.t_fontset); + resource.mstyle.f_fontset_extents = + XExtentsOfFontSet(resource.mstyle.f_fontset); + resource.tstyle.fontset_extents = + XExtentsOfFontSet(resource.tstyle.fontset); + resource.wstyle.fontset_extents = + XExtentsOfFontSet(resource.wstyle.fontset); + } else { + resource.wstyle.font = + readDatabaseFont("window.font", "Window.Font"); + resource.tstyle.font = + readDatabaseFont("toolbar.font", "Toolbar.Font"); + resource.mstyle.t_font = + readDatabaseFont("menu.title.font", "Menu.Title.Font"); + resource.mstyle.f_font = + readDatabaseFont("menu.frame.font", "Menu.Frame.Font"); + } - fs = XCreateFontSet(getBaseDisplay().getXDisplay(), - fontname, &missing, &nmissing, &def); - if (fs && (! nmissing)) return fs; + // load window config + resource.wstyle.t_focus = + readDatabaseTexture("window.title.focus", "Window.Title.Focus", "white"); + resource.wstyle.t_unfocus = + readDatabaseTexture("window.title.unfocus", + "Window.Title.Unfocus", "black"); + resource.wstyle.l_focus = + readDatabaseTexture("window.label.focus", "Window.Label.Focus", "white" ); + resource.wstyle.l_unfocus = + readDatabaseTexture("window.label.unfocus", "Window.Label.Unfocus", + "black"); + resource.wstyle.h_focus = + readDatabaseTexture("window.handle.focus", "Window.Handle.Focus", "white"); + resource.wstyle.h_unfocus = + readDatabaseTexture("window.handle.unfocus", + "Window.Handle.Unfocus", "black"); + resource.wstyle.g_focus = + readDatabaseTexture("window.grip.focus", "Window.Grip.Focus", "white"); + resource.wstyle.g_unfocus = + readDatabaseTexture("window.grip.unfocus", "Window.Grip.Unfocus", "black"); + resource.wstyle.b_focus = + readDatabaseTexture("window.button.focus", "Window.Button.Focus", "white"); + resource.wstyle.b_unfocus = + readDatabaseTexture("window.button.unfocus", + "Window.Button.Unfocus", "black"); + resource.wstyle.b_pressed = + readDatabaseTexture("window.button.pressed", + "Window.Button.Pressed", "black"); + resource.wstyle.f_focus = + readDatabaseColor("window.frame.focusColor", + "Window.Frame.FocusColor", "white"); + resource.wstyle.f_unfocus = + readDatabaseColor("window.frame.unfocusColor", + "Window.Frame.UnfocusColor", "black"); + resource.wstyle.l_text_focus = + readDatabaseColor("window.label.focus.textColor", + "Window.Label.Focus.TextColor", "black"); + resource.wstyle.l_text_unfocus = + readDatabaseColor("window.label.unfocus.textColor", + "Window.Label.Unfocus.TextColor", "white"); + resource.wstyle.b_pic_focus = + readDatabaseColor("window.button.focus.picColor", + "Window.Button.Focus.PicColor", "black"); + resource.wstyle.b_pic_unfocus = + readDatabaseColor("window.button.unfocus.picColor", + "Window.Button.Unfocus.PicColor", "white"); + + resource.wstyle.justify = LeftJustify; + if (XrmGetResource(resource.stylerc, "window.justify", "Window.Justify", + &value_type, &value)) { + if (strstr(value.addr, "right") || strstr(value.addr, "Right")) + resource.wstyle.justify = RightJustify; + else if (strstr(value.addr, "center") || strstr(value.addr, "Center")) + resource.wstyle.justify = CenterJustify; + } -#ifdef HAVE_SETLOCALE - if (! fs) { - if (nmissing) XFreeStringList(missing); + // load toolbar config + resource.tstyle.toolbar = + readDatabaseTexture("toolbar", "Toolbar", "black"); + resource.tstyle.label = + readDatabaseTexture("toolbar.label", "Toolbar.Label", "black"); + resource.tstyle.window = + readDatabaseTexture("toolbar.windowLabel", "Toolbar.WindowLabel", "black"); + resource.tstyle.button = + readDatabaseTexture("toolbar.button", "Toolbar.Button", "white"); + resource.tstyle.pressed = + readDatabaseTexture("toolbar.button.pressed", + "Toolbar.Button.Pressed", "black"); + resource.tstyle.clock = + readDatabaseTexture("toolbar.clock", "Toolbar.Clock", "black"); + resource.tstyle.l_text = + readDatabaseColor("toolbar.label.textColor", + "Toolbar.Label.TextColor", "white"); + resource.tstyle.w_text = + readDatabaseColor("toolbar.windowLabel.textColor", + "Toolbar.WindowLabel.TextColor", "white"); + resource.tstyle.c_text = + readDatabaseColor("toolbar.clock.textColor", + "Toolbar.Clock.TextColor", "white"); + resource.tstyle.b_pic = + readDatabaseColor("toolbar.button.picColor", + "Toolbar.Button.PicColor", "black"); + + resource.tstyle.justify = LeftJustify; + if (XrmGetResource(resource.stylerc, "toolbar.justify", + "Toolbar.Justify", &value_type, &value)) { + if (strstr(value.addr, "right") || strstr(value.addr, "Right")) + resource.tstyle.justify = RightJustify; + else if (strstr(value.addr, "center") || strstr(value.addr, "Center")) + resource.tstyle.justify = CenterJustify; + } - setlocale(LC_CTYPE, "C"); - fs = XCreateFontSet(getBaseDisplay().getXDisplay(), fontname, - &missing, &nmissing, &def); - setlocale(LC_CTYPE, ""); + // load menu config + resource.mstyle.title = + readDatabaseTexture("menu.title", "Menu.Title", "white"); + resource.mstyle.frame = + readDatabaseTexture("menu.frame", "Menu.Frame", "black"); + resource.mstyle.hilite = + readDatabaseTexture("menu.hilite", "Menu.Hilite", "white"); + resource.mstyle.t_text = + readDatabaseColor("menu.title.textColor", "Menu.Title.TextColor", "black"); + resource.mstyle.f_text = + readDatabaseColor("menu.frame.textColor", "Menu.Frame.TextColor", "white"); + resource.mstyle.d_text = + readDatabaseColor("menu.frame.disableColor", + "Menu.Frame.DisableColor", "black"); + resource.mstyle.h_text = + readDatabaseColor("menu.hilite.textColor", + "Menu.Hilite.TextColor", "black"); + + resource.mstyle.t_justify = LeftJustify; + if (XrmGetResource(resource.stylerc, "menu.title.justify", + "Menu.Title.Justify", + &value_type, &value)) { + if (strstr(value.addr, "right") || strstr(value.addr, "Right")) + resource.mstyle.t_justify = RightJustify; + else if (strstr(value.addr, "center") || strstr(value.addr, "Center")) + resource.mstyle.t_justify = CenterJustify; } -#endif // HAVE_SETLOCALE - if (fs) { - XFontStruct **fontstructs; - char **fontnames; - XFontsOfFontSet(fs, &fontstructs, &fontnames); - fontname = fontnames[0]; + resource.mstyle.f_justify = LeftJustify; + if (XrmGetResource(resource.stylerc, "menu.frame.justify", + "Menu.Frame.Justify", + &value_type, &value)) { + if (strstr(value.addr, "right") || strstr(value.addr, "Right")) + resource.mstyle.f_justify = RightJustify; + else if (strstr(value.addr, "center") || strstr(value.addr, "Center")) + resource.mstyle.f_justify = CenterJustify; } - getFontElement(fontname, weight, FONT_ELEMENT_SIZE, - "-medium-", "-bold-", "-demibold-", "-regular-", NULL); - getFontElement(fontname, slant, FONT_ELEMENT_SIZE, - "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL); - getFontSize(fontname, &pixel_size); + resource.mstyle.bullet = Basemenu::Triangle; + if (XrmGetResource(resource.stylerc, "menu.bullet", "Menu.Bullet", + &value_type, &value)) { + if (! strncasecmp(value.addr, "empty", value.size)) + resource.mstyle.bullet = Basemenu::Empty; + else if (! strncasecmp(value.addr, "square", value.size)) + resource.mstyle.bullet = Basemenu::Square; + else if (! strncasecmp(value.addr, "diamond", value.size)) + resource.mstyle.bullet = Basemenu::Diamond; + } - if (! strcmp(weight, "*")) strncpy(weight, "medium", FONT_ELEMENT_SIZE); - if (! strcmp(slant, "*")) strncpy(slant, "r", FONT_ELEMENT_SIZE); - if (pixel_size < 3) pixel_size = 3; - else if (pixel_size > 97) pixel_size = 97; + resource.mstyle.bullet_pos = Basemenu::Left; + if (XrmGetResource(resource.stylerc, "menu.bullet.position", + "Menu.Bullet.Position", &value_type, &value)) { + if (! strncasecmp(value.addr, "right", value.size)) + resource.mstyle.bullet_pos = Basemenu::Right; + } - buf_size = strlen(fontname) + (FONT_ELEMENT_SIZE * 2) + 64; - char *pattern2 = new char[buf_size]; - snprintf(pattern2, buf_size - 1, - "%s," - "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*," - "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*", - fontname, weight, slant, pixel_size, pixel_size); - fontname = pattern2; + resource.border_color = + readDatabaseColor("borderColor", "BorderColor", "black"); - if (nmissing) XFreeStringList(missing); - if (fs) XFreeFontSet(getBaseDisplay().getXDisplay(), fs); + unsigned int uint_value; - fs = XCreateFontSet(getBaseDisplay().getXDisplay(), fontname, - &missing, &nmissing, &def); - delete [] pattern2; + // load bevel, border and handle widths + resource.handle_width = 6; + if (XrmGetResource(resource.stylerc, "handleWidth", "HandleWidth", + &value_type, &value) && + sscanf(value.addr, "%u", &uint_value) == 1 && + uint_value <= (getWidth() / 2) && uint_value != 0) { + resource.handle_width = uint_value; + } - return fs; -} + resource.border_width = 1; + if (XrmGetResource(resource.stylerc, "borderWidth", "BorderWidth", + &value_type, &value) && + sscanf(value.addr, "%u", &uint_value) == 1) { + resource.border_width = uint_value; + } + resource.bevel_width = 3; + if (XrmGetResource(resource.stylerc, "bevelWidth", "BevelWidth", + &value_type, &value) && + sscanf(value.addr, "%u", &uint_value) == 1 && + uint_value <= (getWidth() / 2) && uint_value != 0) { + resource.bevel_width = uint_value; + } -void BScreen::setSloppyFocus(bool b) { - resource.sloppy_focus = b; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".focusModel" << ends; - config.setValue(s.str(), - (resource.sloppy_focus ? - (resource.auto_raise ? "AutoRaiseSloppyFocus" : "SloppyFocus") - : "ClickToFocus")); - s.rdbuf()->freeze(0); -} + resource.frame_width = resource.bevel_width; + if (XrmGetResource(resource.stylerc, "frameWidth", "FrameWidth", + &value_type, &value) && + sscanf(value.addr, "%u", &uint_value) == 1 && + uint_value <= (getWidth() / 2)) { + resource.frame_width = uint_value; + } + if (XrmGetResource(resource.stylerc, "rootCommand", "RootCommand", + &value_type, &value)) { + bexec(value.addr, displayString()); + } -void BScreen::setAutoRaise(bool a) { - resource.auto_raise = a; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".focusModel" << ends; - config.setValue(s.str(), - (resource.sloppy_focus ? - (resource.auto_raise ? "AutoRaiseSloppyFocus" : "SloppyFocus") - : "ClickToFocus")); - s.rdbuf()->freeze(0); + XrmDestroyDatabase(resource.stylerc); } -void BScreen::setImageDither(bool d, bool reconfig) { - image_control->setDither(d); - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".imageDither" << ends; - config.setValue(s.str(), imageDither()); - if (reconfig) - reconfigure(); - s.rdbuf()->freeze(0); -} +void BScreen::addIcon(BlackboxWindow *w) { + if (! w) return; + w->setWorkspace(BSENTINEL); + w->setWindowNumber(iconList.size()); -void BScreen::setOpaqueMove(bool o) { - resource.opaque_move = o; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".opaqueMove" << ends; - config.setValue(s.str(), resource.opaque_move); - s.rdbuf()->freeze(0); + iconList.push_back(w); + + const char* title = w->getIconTitle(); + iconmenu->insert(title); + iconmenu->update(); } -void BScreen::setFullMax(bool f) { - resource.full_max = f; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".fullMaximization" << ends; - config.setValue(s.str(), resource.full_max); - s.rdbuf()->freeze(0); -} +void BScreen::removeIcon(BlackboxWindow *w) { + if (! w) return; + iconList.remove(w); -void BScreen::setFocusNew(bool f) { - resource.focus_new = f; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".focusNewWindows" << ends; - config.setValue(s.str(), resource.focus_new); - s.rdbuf()->freeze(0); + iconmenu->remove(w->getWindowNumber()); + iconmenu->update(); + + BlackboxWindowList::iterator it = iconList.begin(), + end = iconList.end(); + for (int i = 0; it != end; ++it) + (*it)->setWindowNumber(i++); } -void BScreen::setFocusLast(bool f) { - resource.focus_last = f; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".focusLastWindow" << ends; - config.setValue(s.str(), resource.focus_last); - s.rdbuf()->freeze(0); +BlackboxWindow *BScreen::getIcon(unsigned int index) { + if (index < iconList.size()) { + BlackboxWindowList::iterator it = iconList.begin(); + for (; index > 0; --index, ++it) ; /* increment to index */ + return *it; + } + + return (BlackboxWindow *) 0; } -void BScreen::setWindowZones(int z) { - resource.zones = z; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".windowZones" << ends; - config.setValue(s.str(), resource.zones); - s.rdbuf()->freeze(0); -} +unsigned int BScreen::addWorkspace(void) { + Workspace *wkspc = new Workspace(this, workspacesList.size()); + workspacesList.push_back(wkspc); + workspacemenu->insert(wkspc->getName(), wkspc->getMenu(), + wkspc->getID() + 2); + workspacemenu->update(); -void BScreen::setWorkspaceCount(int w) { - resource.workspaces = w; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".workspaces" << ends; - config.setValue(s.str(), resource.workspaces); - s.rdbuf()->freeze(0); -} + toolbar->reconfigure(); + updateNetizenWorkspaceCount(); -void BScreen::setPlacementPolicy(int p) { - resource.placement_policy = p; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".windowPlacement" << ends; - const char *placement; - switch (resource.placement_policy) { - case CascadePlacement: placement = "CascadePlacement"; break; - case BestFitPlacement: placement = "BestFitPlacement"; break; - case ColSmartPlacement: placement = "ColSmartPlacement"; break; - case UnderMousePlacement: placement = "UnderMousePlacement"; break; - case ClickMousePlacement: placement = "ClickMousePlacement"; break; - default: - case RowSmartPlacement: placement = "RowSmartPlacement"; break; - } - config.setValue(s.str(), placement); - s.rdbuf()->freeze(0); + return workspacesList.size(); } -void BScreen::setEdgeSnapThreshold(int t) { - resource.edge_snap_threshold = t; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".edgeSnapThreshold" << ends; - config.setValue(s.str(), resource.edge_snap_threshold); - s.rdbuf()->freeze(0); -} +unsigned int BScreen::removeLastWorkspace(void) { + if (workspacesList.size() == 1) + return 1; + Workspace *wkspc = workspacesList.back(); -void BScreen::setRowPlacementDirection(int d) { - resource.row_direction = d; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".rowPlacementDirection" << ends; - config.setValue(s.str(), - resource.row_direction == LeftRight ? - "LeftToRight" : "RightToLeft"); - s.rdbuf()->freeze(0); -} + if (current_workspace->getID() == wkspc->getID()) + changeWorkspaceID(current_workspace->getID() - 1); + wkspc->removeAll(); -void BScreen::setColPlacementDirection(int d) { - resource.col_direction = d; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".colPlacementDirection" << ends; - config.setValue(s.str(), - resource.col_direction == TopBottom ? - "TopToBottom" : "BottomToTop"); - s.rdbuf()->freeze(0); -} + workspacemenu->remove(wkspc->getID() + 2); + workspacemenu->update(); + workspacesList.pop_back(); + delete wkspc; -void BScreen::setRootCommand(const char *cmd) { - if (resource.root_command != NULL) - delete [] resource.root_command; - if (cmd != NULL) - resource.root_command = bstrdup(cmd); - else - resource.root_command = NULL; - // this doesn't save to the Resources config because it can't be changed - // inside Openbox, and this way we dont add an empty command which would over- - // ride the styles command when none has been specified -} + toolbar->reconfigure(); + updateNetizenWorkspaceCount(); -#ifdef HAVE_STRFTIME -void BScreen::setStrftimeFormat(const char *f) { - if (resource.strftime_format != NULL) - delete [] resource.strftime_format; - - resource.strftime_format = bstrdup(f); - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".strftimeFormat" << ends; - config.setValue(s.str(), resource.strftime_format); - s.rdbuf()->freeze(0); + return workspacesList.size(); } -#else // !HAVE_STRFTIME -void BScreen::setDateFormat(int f) { - resource.date_format = f; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".dateFormat" << ends; - config.setValue(s.str(), resource.date_format == B_EuropeanDate ? - "European" : "American"); - s.rdbuf()->freeze(0); -} +void BScreen::changeWorkspaceID(unsigned int id) { + if (! current_workspace) return; + if (id != current_workspace->getID()) { + current_workspace->hideAll(); -void BScreen::setClock24Hour(Bool c) { - resource.clock24hour = c; - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".clockFormat" << ends; - config.setValue(s.str(), resource.clock24hour ? 24 : 12); - s.rdbuf()->freeze(0); -} -#endif // HAVE_STRFTIME + workspacemenu->setItemSelected(current_workspace->getID() + 2, False); + if (blackbox->getFocusedWindow() && + blackbox->getFocusedWindow()->getScreen() == this && + (! blackbox->getFocusedWindow()->isStuck())) { + current_workspace->setLastFocusedWindow(blackbox->getFocusedWindow()); + blackbox->setFocusedWindow((BlackboxWindow *) 0); + } -void BScreen::setHideToolbar(bool b) { - resource.hide_toolbar = b; - if (resource.hide_toolbar) - getToolbar()->unMapToolbar(); - else - getToolbar()->mapToolbar(); - std::ostrstream s; - s << "session.screen" << getScreenNumber() << ".hideToolbar" << ends; - config.setValue(s.str(), resource.hide_toolbar ? "True" : "False"); - s.rdbuf()->freeze(0); -} + current_workspace = getWorkspace(id); + workspacemenu->setItemSelected(current_workspace->getID() + 2, True); + toolbar->redrawWorkspaceLabel(True); -void BScreen::saveWorkspaceNames() { - std::ostrstream rc, names; + current_workspace->showAll(); - wkspList::iterator it; - wkspList::iterator last = workspacesList.end() - 1; - for (it = workspacesList.begin(); it != workspacesList.end(); ++it) { - names << (*it)->getName(); - if (it != last) - names << ","; + if (resource.focus_last && current_workspace->getLastFocusedWindow()) { + XSync(blackbox->getXDisplay(), False); + current_workspace->getLastFocusedWindow()->setInputFocus(); + } } - names << ends; - rc << "session.screen" << getScreenNumber() << ".workspaceNames" << ends; - config.setValue(rc.str(), names.str()); - rc.rdbuf()->freeze(0); - names.rdbuf()->freeze(0); + updateNetizenCurrentWorkspace(); } -void BScreen::save() { - setSloppyFocus(resource.sloppy_focus); - setAutoRaise(resource.auto_raise); - setImageDither(imageDither(), false); - setOpaqueMove(resource.opaque_move); - setFullMax(resource.full_max); - setFocusNew(resource.focus_new); - setFocusLast(resource.focus_last); - setWindowZones(resource.zones); - setWorkspaceCount(resource.workspaces); - setPlacementPolicy(resource.placement_policy); - setEdgeSnapThreshold(resource.edge_snap_threshold); - setRowPlacementDirection(resource.row_direction); - setColPlacementDirection(resource.col_direction); - setRootCommand(resource.root_command); -#ifdef HAVE_STRFTIME - // it deletes the current value before setting the new one, so we have to - // duplicate the current value. - std::string s = resource.strftime_format; - setStrftimeFormat(s.c_str()); -#else // !HAVE_STRFTIME - setDateFormat(resource.date_format); - setClock24Hour(resource.clock24hour); -#endif // HAVE_STRFTIME - setHideToolbar(resource.hide_toolbar); - - toolbar->save(); -#ifdef SLIT - slit->save(); -#endif // SLIT -} - - -void BScreen::load() { - std::ostrstream rscreen, rname, rclass; - std::string s; - bool b; - long l; - rscreen << "session.screen" << getScreenNumber() << '.' << ends; - - rname << rscreen.str() << "hideToolbar" << ends; - rclass << rscreen.str() << "HideToolbar" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - resource.hide_toolbar = b; - else - resource.hide_toolbar = false; - Toolbar *t = getToolbar(); - if (t != NULL) { - if (resource.hide_toolbar) - t->unMapToolbar(); - else - t->mapToolbar(); - } - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "fullMaximization" << ends; - rclass << rscreen.str() << "FullMaximization" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - resource.full_max = b; - else - resource.full_max = false; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "focusNewWindows" << ends; - rclass << rscreen.str() << "FocusNewWindows" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - resource.focus_new = b; - else - resource.focus_new = false; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "focusLastWindow" << ends; - rclass << rscreen.str() << "FocusLastWindow" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - resource.focus_last = b; - else - resource.focus_last = false; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "rowPlacementDirection" << ends; - rclass << rscreen.str() << "RowPlacementDirection" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - if (0 == strncasecmp(s.c_str(), "RightToLeft", s.length())) - resource.row_direction = RightLeft; - else //if (0 == strncasecmp(s.c_str(), "LeftToRight", s.length())) - resource.row_direction = LeftRight; - } else - resource.row_direction = LeftRight; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "colPlacementDirection" << ends; - rclass << rscreen.str() << "ColPlacementDirection" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - if (0 == strncasecmp(s.c_str(), "BottomToTop", s.length())) - resource.col_direction = BottomTop; - else //if (0 == strncasecmp(s.c_str(), "TopToBottom", s.length())) - resource.col_direction = TopBottom; - } else - resource.col_direction = TopBottom; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "workspaces" << ends; - rclass << rscreen.str() << "Workspaces" << ends; - if (config.getValue(rname.str(), rclass.str(), l)) { - resource.workspaces = l; - } else - resource.workspaces = 1; - - removeWorkspaceNames(); - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "workspaceNames" << ends; - rclass << rscreen.str() << "WorkspaceNames" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - std::string::const_iterator it = s.begin(), end = s.end(); - while(1) { - std::string::const_iterator tmp = it;// current string.begin() - it = std::find(tmp, end, ','); // look for comma between tmp and end - std::string name(tmp, it); // name = s[tmp:it] - addWorkspaceName(name.c_str()); - if (it == end) - break; - ++it; - } - } - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "focusModel" << ends; - rclass << rscreen.str() << "FocusModel" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - if (0 == strncasecmp(s.c_str(), "ClickToFocus", s.length())) { - resource.auto_raise = false; - resource.sloppy_focus = false; - } else if (0 == strncasecmp(s.c_str(), "AutoRaiseSloppyFocus", - s.length())) { - resource.sloppy_focus = true; - resource.auto_raise = true; - } else { //if (0 == strncasecmp(s.c_str(), "SloppyFocus", s.length())) { - resource.sloppy_focus = true; - resource.auto_raise = false; - } - } else { - resource.sloppy_focus = true; - resource.auto_raise = false; - } - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "windowZones" << ends; - rclass << rscreen.str() << "WindowZones" << ends; - if (config.getValue(rname.str(), rclass.str(), l)) - resource.zones = (l == 1 || l == 2 || l == 4) ? l : 1; - else - resource.zones = 4; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "windowPlacement" << ends; - rclass << rscreen.str() << "WindowPlacement" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - if (0 == strncasecmp(s.c_str(), "RowSmartPlacement", s.length())) - resource.placement_policy = RowSmartPlacement; - else if (0 == strncasecmp(s.c_str(), "ColSmartPlacement", s.length())) - resource.placement_policy = ColSmartPlacement; - else if (0 == strncasecmp(s.c_str(), "BestFitPlacement", s.length())) - resource.placement_policy = BestFitPlacement; - else if (0 == strncasecmp(s.c_str(), "UnderMousePlacement", s.length())) - resource.placement_policy = UnderMousePlacement; - else if (0 == strncasecmp(s.c_str(), "ClickMousePlacement", s.length())) - resource.placement_policy = ClickMousePlacement; - else //if (0 == strncasecmp(s.c_str(), "CascadePlacement", s.length())) - resource.placement_policy = CascadePlacement; - } else - resource.placement_policy = CascadePlacement; - -#ifdef HAVE_STRFTIME - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "strftimeFormat" << ends; - rclass << rscreen.str() << "StrftimeFormat" << ends; - - if (resource.strftime_format != NULL) - delete [] resource.strftime_format; - - if (config.getValue(rname.str(), rclass.str(), s)) - resource.strftime_format = bstrdup(s.c_str()); - else - resource.strftime_format = bstrdup("%I:%M %p"); -#else // !HAVE_STRFTIME - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "dateFormat" << ends; - rclass << rscreen.str() << "DateFormat" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - if (strncasecmp(s.c_str(), "European", s.length())) - resource.date_format = B_EuropeanDate; - else //if (strncasecmp(s.c_str(), "American", s.length())) - resource.date_format = B_AmericanDate; - } else - resource.date_format = B_AmericanDate; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "clockFormat" << ends; - rclass << rscreen.str() << "ClockFormat" << ends; - if (config.getValue(rname.str(), rclass.str(), l)) { - if (clock == 24) - resource.clock24hour = true; - else if (clock == 12) - resource.clock24hour = false; - } else - resource.clock24hour = false; -#endif // HAVE_STRFTIME - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "edgeSnapThreshold" << ends; - rclass << rscreen.str() << "EdgeSnapThreshold" << ends; - if (config.getValue(rname.str(), rclass.str(), l)) - resource.edge_snap_threshold = l; - else - resource.edge_snap_threshold = 4; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "imageDither" << ends; - rclass << rscreen.str() << "ImageDither" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - image_control->setDither(b); - else - image_control->setDither(true); - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "rootCommand" << ends; - rclass << rscreen.str() << "RootCommand" << ends; - - if (resource.root_command != NULL) - delete [] resource.root_command; - - if (config.getValue(rname.str(), rclass.str(), s)) - resource.root_command = bstrdup(s.c_str()); - else - resource.root_command = NULL; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "opaqueMove" << ends; - rclass << rscreen.str() << "OpaqueMove" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - resource.opaque_move = b; - else - resource.opaque_move = false; - - rscreen.rdbuf()->freeze(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - } - - void BScreen::reconfigure(void) { - load(); - toolbar->load(); -#ifdef SLIT - slit->load(); -#endif // SLIT - LoadStyle(); - - XGCValues gcv; - unsigned long gc_value_mask = GCForeground; - if (! i18n.multibyte()) gc_value_mask |= GCFont; - - gcv.foreground = WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber()); - gcv.function = GXinvert; - gcv.subwindow_mode = IncludeInferiors; - XChangeGC(getBaseDisplay().getXDisplay(), opGC, - GCForeground | GCFunction | GCSubwindowMode, &gcv); - - gcv.foreground = resource.wstyle.l_text_focus.getPixel(); - if (resource.wstyle.font) - gcv.font = resource.wstyle.font->fid; - XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.l_text_focus_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.wstyle.l_text_unfocus.getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.l_text_unfocus_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.wstyle.b_pic_focus.getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.b_pic_focus_gc, - GCForeground, &gcv); - - gcv.foreground = resource.wstyle.b_pic_unfocus.getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.wstyle.b_pic_unfocus_gc, - GCForeground, &gcv); - - gcv.foreground = resource.mstyle.t_text.getPixel(); - if (resource.mstyle.t_font) - gcv.font = resource.mstyle.t_font->fid; - XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.t_text_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.mstyle.f_text.getPixel(); - if (resource.mstyle.f_font) - gcv.font = resource.mstyle.f_font->fid; - XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.f_text_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.mstyle.h_text.getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.h_text_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.mstyle.d_text.getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.d_text_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.mstyle.hilite.getColor()->getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.mstyle.hilite_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.tstyle.l_text.getPixel(); - if (resource.tstyle.font) - gcv.font = resource.tstyle.font->fid; - XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.l_text_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.tstyle.w_text.getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.w_text_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.tstyle.c_text.getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.c_text_gc, - gc_value_mask, &gcv); - - gcv.foreground = resource.tstyle.b_pic.getPixel(); - XChangeGC(getBaseDisplay().getXDisplay(), resource.tstyle.b_pic_gc, - gc_value_mask, &gcv); - - const char *s = i18n(ScreenSet, ScreenPositionLength, - "0: 0000 x 0: 0000"); - int l = strlen(s); - - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(resource.wstyle.fontset, s, l, &ink, &logical); - geom_w = logical.width; - - geom_h = resource.wstyle.fontset_extents->max_ink_extent.height; - } else { - geom_w = XTextWidth(resource.wstyle.font, s, l); - geom_h = resource.wstyle.font->ascent + - resource.wstyle.font->descent; - } - - geom_w += (resource.bevel_width * 2); - geom_h += (resource.bevel_width * 2); +void BScreen::manageWindow(Window w) { + new BlackboxWindow(blackbox, w, this); - Pixmap tmp = geom_pixmap; - if (resource.wstyle.l_focus.getTexture() & BImage_ParentRelative) { - if (resource.wstyle.t_focus.getTexture() == - (BImage_Flat | BImage_Solid)) { - geom_pixmap = None; - XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window, - resource.wstyle.t_focus.getColor()->getPixel()); - } else { - geom_pixmap = image_control->renderImage(geom_w, geom_h, - &resource.wstyle.t_focus); - XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(), - geom_window, geom_pixmap); - } - } else { - if (resource.wstyle.l_focus.getTexture() == - (BImage_Flat | BImage_Solid)) { - geom_pixmap = None; - XSetWindowBackground(getBaseDisplay().getXDisplay(), geom_window, - resource.wstyle.l_focus.getColor()->getPixel()); - } else { - geom_pixmap = image_control->renderImage(geom_w, geom_h, - &resource.wstyle.l_focus); - XSetWindowBackgroundPixmap(getBaseDisplay().getXDisplay(), - geom_window, geom_pixmap); - } - } - if (tmp) image_control->removeImage(tmp); - - XSetWindowBorderWidth(getBaseDisplay().getXDisplay(), geom_window, - resource.border_width); - XSetWindowBorder(getBaseDisplay().getXDisplay(), geom_window, - resource.border_color.getPixel()); - - workspacemenu->reconfigure(); - iconmenu->reconfigure(); - - { - int remember_sub = rootmenu->getCurrentSubmenu(); - InitMenu(); - raiseWindows(0, 0); - rootmenu->reconfigure(); - rootmenu->drawSubmenu(remember_sub); - } + BlackboxWindow *win = blackbox->searchWindow(w); + if (! win) + return; - configmenu->reconfigure(); + windowList.push_back(win); - toolbar->reconfigure(); + XMapRequestEvent mre; + mre.window = w; + win->restoreAttributes(); + win->mapRequestEvent(&mre); +} -#ifdef SLIT - slit->reconfigure(); -#endif // SLIT - std::for_each(workspacesList.begin(), workspacesList.end(), - std::mem_fun(&Workspace::reconfigure)); +void BScreen::unmanageWindow(BlackboxWindow *w, bool remap) { + w->restore(remap); - for (winList::iterator it = iconList.begin(); it != iconList.end(); ++it) - if ((*it)->validateClient()) - (*it)->reconfigure(); + if (w->getWorkspaceNumber() != BSENTINEL && + w->getWindowNumber() != BSENTINEL) + getWorkspace(w->getWorkspaceNumber())->removeWindow(w); + else if (w->isIconic()) + removeIcon(w); - image_control->timeout(); - } + windowList.remove(w); + if (blackbox->getFocusedWindow() == w) + blackbox->setFocusedWindow((BlackboxWindow *) 0); - void BScreen::rereadMenu(void) { - InitMenu(); - raiseWindows(0, 0); + removeNetizen(w->getClientWindow()); - rootmenu->reconfigure(); - } + delete w; +} - void BScreen::removeWorkspaceNames(void) { - workspaceNames.clear(); - } +void BScreen::addNetizen(Netizen *n) { + netizenList.push_back(n); + n->sendWorkspaceCount(); + n->sendCurrentWorkspace(); - void BScreen::LoadStyle(void) { - Resource &conf = resource.styleconfig; + WorkspaceList::iterator it = workspacesList.begin(); + const WorkspaceList::iterator end = workspacesList.end(); + for (; it != end; ++it) + (*it)->sendWindowList(*n); - const char *sfile = openbox.getStyleFilename(); - bool loaded = false; - if (sfile != NULL) { - conf.setFile(sfile); - loaded = conf.load(); - } - if (!loaded) { - conf.setFile(DEFAULTSTYLE); - if (!conf.load()) { - fprintf(stderr, i18n(ScreenSet, ScreenDefaultStyleLoadFail, - "BScreen::LoadStyle(): couldn't load " - "default style.\n")); - exit(2); - } - } + Window f = ((blackbox->getFocusedWindow()) ? + blackbox->getFocusedWindow()->getClientWindow() : None); + n->sendWindowFocus(f); +} - std::string s; - long l; - - // load fonts/fontsets - - if (i18n.multibyte()) { - readDatabaseFontSet("window.font", "Window.Font", - &resource.wstyle.fontset); - readDatabaseFontSet("toolbar.font", "Toolbar.Font", - &resource.tstyle.fontset); - readDatabaseFontSet("menu.title.font", "Menu.Title.Font", - &resource.mstyle.t_fontset); - readDatabaseFontSet("menu.frame.font", "Menu.Frame.Font", - &resource.mstyle.f_fontset); - - resource.mstyle.t_fontset_extents = - XExtentsOfFontSet(resource.mstyle.t_fontset); - resource.mstyle.f_fontset_extents = - XExtentsOfFontSet(resource.mstyle.f_fontset); - resource.tstyle.fontset_extents = - XExtentsOfFontSet(resource.tstyle.fontset); - resource.wstyle.fontset_extents = - XExtentsOfFontSet(resource.wstyle.fontset); - } else { - readDatabaseFont("window.font", "Window.Font", - &resource.wstyle.font); - readDatabaseFont("menu.title.font", "Menu.Title.Font", - &resource.mstyle.t_font); - readDatabaseFont("menu.frame.font", "Menu.Frame.Font", - &resource.mstyle.f_font); - readDatabaseFont("toolbar.font", "Toolbar.Font", - &resource.tstyle.font); - } - // load window config - readDatabaseTexture("window.title.focus", "Window.Title.Focus", - &resource.wstyle.t_focus, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.title.unfocus", "Window.Title.Unfocus", - &resource.wstyle.t_unfocus, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.label.focus", "Window.Label.Focus", - &resource.wstyle.l_focus, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.label.unfocus", "Window.Label.Unfocus", - &resource.wstyle.l_unfocus, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.handle.focus", "Window.Handle.Focus", - &resource.wstyle.h_focus, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.handle.unfocus", "Window.Handle.Unfocus", - &resource.wstyle.h_unfocus, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.grip.focus", "Window.Grip.Focus", - &resource.wstyle.g_focus, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.grip.unfocus", "Window.Grip.Unfocus", - &resource.wstyle.g_unfocus, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.button.focus", "Window.Button.Focus", - &resource.wstyle.b_focus, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.button.unfocus", "Window.Button.Unfocus", - &resource.wstyle.b_unfocus, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("window.button.pressed", "Window.Button.Pressed", - &resource.wstyle.b_pressed, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("window.frame.focusColor", - "Window.Frame.FocusColor", - &resource.wstyle.f_focus, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("window.frame.unfocusColor", - "Window.Frame.UnfocusColor", - &resource.wstyle.f_unfocus, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("window.label.focus.textColor", - "Window.Label.Focus.TextColor", - &resource.wstyle.l_text_focus, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("window.label.unfocus.textColor", - "Window.Label.Unfocus.TextColor", - &resource.wstyle.l_text_unfocus, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("window.button.focus.picColor", - "Window.Button.Focus.PicColor", - &resource.wstyle.b_pic_focus, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("window.button.unfocus.picColor", - "Window.Button.Unfocus.PicColor", - &resource.wstyle.b_pic_unfocus, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - - if (conf.getValue("window.justify", "Window.Justify", s)) { - if (0 == strncasecmp(s.c_str(), "right", s.length())) - resource.wstyle.justify = BScreen::RightJustify; - else if (0 == strncasecmp(s.c_str(), "center", s.length())) - resource.wstyle.justify = BScreen::CenterJustify; - else - resource.wstyle.justify = BScreen::LeftJustify; - } else - resource.wstyle.justify = BScreen::LeftJustify; - - // load toolbar config - readDatabaseTexture("toolbar", "Toolbar", - &resource.tstyle.toolbar, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("toolbar.label", "Toolbar.Label", - &resource.tstyle.label, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("toolbar.windowLabel", "Toolbar.WindowLabel", - &resource.tstyle.window, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("toolbar.button", "Toolbar.Button", - &resource.tstyle.button, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("toolbar.button.pressed", "Toolbar.Button.Pressed", - &resource.tstyle.pressed, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("toolbar.clock", "Toolbar.Clock", - &resource.tstyle.clock, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("toolbar.label.textColor", "Toolbar.Label.TextColor", - &resource.tstyle.l_text, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("toolbar.windowLabel.textColor", - "Toolbar.WindowLabel.TextColor", - &resource.tstyle.w_text, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("toolbar.clock.textColor", "Toolbar.Clock.TextColor", - &resource.tstyle.c_text, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("toolbar.button.picColor", "Toolbar.Button.PicColor", - &resource.tstyle.b_pic, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - - if (conf.getValue("toolbar.justify", "Toolbar.Justify", s)) { - if (0 == strncasecmp(s.c_str(), "right", s.length())) - resource.tstyle.justify = BScreen::RightJustify; - else if (0 == strncasecmp(s.c_str(), "center", s.length())) - resource.tstyle.justify = BScreen::CenterJustify; - else - resource.tstyle.justify = BScreen::LeftJustify; - } else - resource.tstyle.justify = BScreen::LeftJustify; - - // load menu config - readDatabaseTexture("menu.title", "Menu.Title", - &resource.mstyle.title, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("menu.frame", "Menu.Frame", - &resource.mstyle.frame, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseTexture("menu.hilite", "Menu.Hilite", - &resource.mstyle.hilite, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("menu.title.textColor", "Menu.Title.TextColor", - &resource.mstyle.t_text, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("menu.frame.textColor", "Menu.Frame.TextColor", - &resource.mstyle.f_text, - WhitePixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("menu.frame.disableColor", "Menu.Frame.DisableColor", - &resource.mstyle.d_text, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - readDatabaseColor("menu.hilite.textColor", "Menu.Hilite.TextColor", - &resource.mstyle.h_text, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - - if (conf.getValue("menu.title.justify", "Menu.Title.Justify", s)) { - if (0 == strncasecmp(s.c_str(), "right", s.length())) - resource.mstyle.t_justify = BScreen::RightJustify; - else if (0 == strncasecmp(s.c_str(), "center", s.length())) - resource.mstyle.t_justify = BScreen::CenterJustify; - else - resource.mstyle.t_justify = BScreen::LeftJustify; - } else - resource.mstyle.t_justify = BScreen::LeftJustify; - - if (conf.getValue("menu.frame.justify", "Menu.Frame.Justify", s)) { - if (0 == strncasecmp(s.c_str(), "right", s.length())) - resource.mstyle.f_justify = BScreen::RightJustify; - else if (0 == strncasecmp(s.c_str(), "center", s.length())) - resource.mstyle.f_justify = BScreen::CenterJustify; - else - resource.mstyle.f_justify = BScreen::LeftJustify; - } else - resource.mstyle.f_justify = BScreen::LeftJustify; - - if (conf.getValue("menu.bullet", "Menu.Bullet", s)) { - if (0 == strncasecmp(s.c_str(), "empty", s.length())) - resource.mstyle.bullet = Basemenu::Empty; - else if (0 == strncasecmp(s.c_str(), "square", s.length())) - resource.mstyle.bullet = Basemenu::Square; - else if (0 == strncasecmp(s.c_str(), "diamond", s.length())) - resource.mstyle.bullet = Basemenu::Diamond; - else - resource.mstyle.bullet = Basemenu::Triangle; - } else - resource.mstyle.bullet = Basemenu::Triangle; - - if (conf.getValue("menu.bullet.position", "Menu.Bullet.Position", s)) { - if (0 == strncasecmp(s.c_str(), "right", s.length())) - resource.mstyle.bullet_pos = Basemenu::Right; - else - resource.mstyle.bullet_pos = Basemenu::Left; - } else - resource.mstyle.bullet_pos = Basemenu::Left; - - readDatabaseColor("borderColor", "BorderColor", &resource.border_color, - BlackPixel(getBaseDisplay().getXDisplay(), - getScreenNumber())); - - // load bevel, border and handle widths - if (conf.getValue("handleWidth", "HandleWidth", l)) { - if (l <= (signed)size().w() / 2 && l != 0) - resource.handle_width = l; - else - resource.handle_width = 6; - } else - resource.handle_width = 6; - - if (conf.getValue("borderWidth", "BorderWidth", l)) - resource.border_width = l; - else - resource.border_width = 1; - - if (conf.getValue("bevelWidth", "BevelWidth", l)) { - if (l <= (signed)size().w() / 2 && l != 0) - resource.bevel_width = l; - else - resource.bevel_width = 3; - } else - resource.bevel_width = 3; - - if (conf.getValue("frameWidth", "FrameWidth", l)) { - if (l <= (signed)size().w() / 2) - resource.frame_width = l; - else - resource.frame_width = resource.bevel_width; - } else - resource.frame_width = resource.bevel_width; - - const char *cmd = resource.root_command; - if (cmd != NULL || conf.getValue("rootCommand", "RootCommand", s)) { - if (cmd == NULL) - cmd = s.c_str(); // not specified by the screen, so use the one from the - // style file -#ifndef __EMX__ - char displaystring[MAXPATHLEN]; - sprintf(displaystring, "DISPLAY=%s", - DisplayString(getBaseDisplay().getXDisplay())); - sprintf(displaystring + strlen(displaystring) - 1, "%d", - getScreenNumber()); - - bexec(cmd, displaystring); -#else // __EMX__ - spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", cmd, NULL); -#endif // !__EMX__ +void BScreen::removeNetizen(Window w) { + NetizenList::iterator it = netizenList.begin(); + for (; it != netizenList.end(); ++it) { + if ((*it)->getWindowID() == w) { + delete *it; + netizenList.erase(it); + break; } } +} - void BScreen::addIcon(OpenboxWindow *w) { - if (! w) return; - - w->setWorkspace(-1); - w->setWindowNumber(iconList.size()); - - iconList.push_back(w); - - iconmenu->insert((const char **) w->getIconTitle()); - iconmenu->update(); - } - - - void BScreen::removeIcon(OpenboxWindow *w) { - if (! w) return; - - iconList.remove(w); - - iconmenu->remove(w->getWindowNumber()); - iconmenu->update(); - - winList::iterator it = iconList.begin(); - for (int i = 0; it != iconList.end(); ++it, ++i) - (*it)->setWindowNumber(i); - } - - - OpenboxWindow *BScreen::getIcon(int index) { - if (index < 0 || index >= (signed)iconList.size()) - return (OpenboxWindow *) 0; - - winList::iterator it = iconList.begin(); - for (; index > 0; --index, ++it); // increment to index - return *it; - } +void BScreen::updateNetizenCurrentWorkspace(void) { + std::for_each(netizenList.begin(), netizenList.end(), + std::mem_fun(&Netizen::sendCurrentWorkspace)); +} - int BScreen::addWorkspace(void) { - Workspace *wkspc = new Workspace(*this, workspacesList.size()); - workspacesList.push_back(wkspc); - setWorkspaceCount(workspaceCount()+1); - saveWorkspaceNames(); +void BScreen::updateNetizenWorkspaceCount(void) { + std::for_each(netizenList.begin(), netizenList.end(), + std::mem_fun(&Netizen::sendWorkspaceCount)); +} - workspacemenu->insert(wkspc->getName(), wkspc->getMenu(), - wkspc->getWorkspaceID() + 2); - workspacemenu->update(); - toolbar->reconfigure(); +void BScreen::updateNetizenWindowFocus(void) { + Window f = ((blackbox->getFocusedWindow()) ? + blackbox->getFocusedWindow()->getClientWindow() : None); + NetizenList::iterator it = netizenList.begin(); + for (; it != netizenList.end(); ++it) + (*it)->sendWindowFocus(f); +} - updateNetizenWorkspaceCount(); - return workspacesList.size(); +void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) { + NetizenList::iterator it = netizenList.begin(); + for (; it != netizenList.end(); ++it) { + (*it)->sendWindowAdd(w, p); } +} - int BScreen::removeLastWorkspace(void) { - if (workspacesList.size() == 1) - return 0; - - Workspace *wkspc = workspacesList.back(); - - if (current_workspace->getWorkspaceID() == wkspc->getWorkspaceID()) - changeWorkspaceID(current_workspace->getWorkspaceID() - 1); - - wkspc->removeAll(); - - workspacemenu->remove(wkspc->getWorkspaceID() + 2); - workspacemenu->update(); - - workspacesList.pop_back(); - delete wkspc; - - setWorkspaceCount(workspaceCount()-1); - saveWorkspaceNames(); - - toolbar->reconfigure(); +void BScreen::updateNetizenWindowDel(Window w) { + NetizenList::iterator it = netizenList.begin(); + for (; it != netizenList.end(); ++it) + (*it)->sendWindowDel(w); +} - updateNetizenWorkspaceCount(); - - return workspacesList.size(); - } +void BScreen::updateNetizenWindowRaise(Window w) { + NetizenList::iterator it = netizenList.begin(); + for (; it != netizenList.end(); ++it) + (*it)->sendWindowRaise(w); +} - void BScreen::changeWorkspaceID(int id) { - if (! current_workspace) return; - if (id != current_workspace->getWorkspaceID()) { - current_workspace->hideAll(); +void BScreen::updateNetizenWindowLower(Window w) { + NetizenList::iterator it = netizenList.begin(); + for (; it != netizenList.end(); ++it) + (*it)->sendWindowLower(w); +} - workspacemenu->setItemSelected(current_workspace->getWorkspaceID() + 2, - False); - OpenboxWindow *fw = openbox.focusedWindow(); - if (fw && fw->getScreen() == this) - openbox.focusWindow(0); +void BScreen::updateNetizenConfigNotify(XEvent *e) { + NetizenList::iterator it = netizenList.begin(); + for (; it != netizenList.end(); ++it) + (*it)->sendConfigNotify(e); +} - current_workspace = getWorkspace(id); - workspacemenu->setItemSelected(current_workspace->getWorkspaceID() + 2, - True); - toolbar->redrawWorkspaceLabel(True); +void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) { + // XXX: why 13?? + Window *session_stack = new + Window[(num + workspacesList.size() + rootmenuList.size() + 13)]; + unsigned int i = 0, k = num; - current_workspace->showAll(); + XRaiseWindow(blackbox->getXDisplay(), iconmenu->getWindowID()); + *(session_stack + i++) = iconmenu->getWindowID(); - if (resource.focus_last && current_workspace->lastFocusedWindow()) { - XSync(openbox.getXDisplay(), False); - current_workspace->lastFocusedWindow()->setInputFocus(); - } - } + WorkspaceList::iterator wit = workspacesList.begin(); + const WorkspaceList::iterator w_end = workspacesList.end(); + for (; wit != w_end; ++wit) + *(session_stack + i++) = (*wit)->getMenu()->getWindowID(); - updateNetizenCurrentWorkspace(); - } + *(session_stack + i++) = workspacemenu->getWindowID(); + *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID(); + *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID(); + *(session_stack + i++) = configmenu->getWindowID(); - void BScreen::addNetizen(Netizen *n) { - netizenList.push_back(n); + *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID(); + *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID(); + *(session_stack + i++) = slit->getMenu()->getWindowID(); - n->sendWorkspaceCount(); - n->sendCurrentWorkspace(); + *(session_stack + i++) = + toolbar->getMenu()->getPlacementmenu()->getWindowID(); + *(session_stack + i++) = toolbar->getMenu()->getWindowID(); - wkspList::iterator it; - for (it = workspacesList.begin(); it != workspacesList.end(); ++it) { - for (int i = 0; i < (*it)->getCount(); i++) - n->sendWindowAdd((*it)->getWindow(i)->getClientWindow(), - (*it)->getWorkspaceID()); - } + RootmenuList::iterator rit = rootmenuList.begin(); + for (; rit != rootmenuList.end(); ++rit) + *(session_stack + i++) = (*rit)->getWindowID(); + *(session_stack + i++) = rootmenu->getWindowID(); - Window f = ((openbox.focusedWindow()) ? - openbox.focusedWindow()->getClientWindow() : None); - n->sendWindowFocus(f); - } + if (toolbar->isOnTop()) + *(session_stack + i++) = toolbar->getWindowID(); + if (slit->isOnTop()) + *(session_stack + i++) = slit->getWindowID(); - void BScreen::removeNetizen(Window w) { - netList::iterator it; + while (k--) + *(session_stack + i++) = *(workspace_stack + k); - for (it = netizenList.begin(); it != netizenList.end(); ++it) - if ((*it)->getWindowID() == w) { - Netizen *tmp = *it; - netizenList.erase(it); - delete tmp; - break; - } - } + XRestackWindows(blackbox->getXDisplay(), session_stack, i); + delete [] session_stack; +} - void BScreen::updateNetizenCurrentWorkspace(void) { - netList::iterator it; - for (it = netizenList.begin(); it != netizenList.end(); ++it) - (*it)->sendCurrentWorkspace(); - } +#ifdef HAVE_STRFTIME +void BScreen::saveStrftimeFormat(const string& format) { + resource.strftime_format = format; +} +#endif // HAVE_STRFTIME - void BScreen::updateNetizenWorkspaceCount(void) { - netList::iterator it; - for (it = netizenList.begin(); it != netizenList.end(); ++it) - (*it)->sendWorkspaceCount(); - } +void BScreen::addWorkspaceName(const string& name) { + workspaceNames.push_back(name); +} - void BScreen::updateNetizenWindowFocus(void) { - Window f = ((openbox.focusedWindow()) ? - openbox.focusedWindow()->getClientWindow() : None); - netList::iterator it; - for (it = netizenList.begin(); it != netizenList.end(); ++it) - (*it)->sendWindowFocus(f); - } +/* + * I would love to kill this function and the accompanying workspaceNames + * list. However, we have a chicken and egg situation. The names are read + * in during load_rc() which happens before the workspaces are created. + * The current solution is to read the names into a list, then use the list + * later for constructing the workspaces. It is only used during initial + * BScreen creation. + */ +const string BScreen::getNameOfWorkspace(unsigned int id) { + if (id < workspaceNames.size()) + return workspaceNames[id]; + return string(""); +} - void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) { - netList::iterator it; - for (it = netizenList.begin(); it != netizenList.end(); ++it) - (*it)->sendWindowAdd(w, p); - } +void BScreen::reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id, + bool ignore_sticky) { + if (! w) return; - void BScreen::updateNetizenWindowDel(Window w) { - netList::iterator it; - for (it = netizenList.begin(); it != netizenList.end(); ++it) - (*it)->sendWindowDel(w); - } + if (wkspc_id == BSENTINEL) + wkspc_id = current_workspace->getID(); + if (w->getWorkspaceNumber() == wkspc_id) + return; - void BScreen::updateNetizenWindowRaise(Window w) { - netList::iterator it; - for (it = netizenList.begin(); it != netizenList.end(); ++it) - (*it)->sendWindowRaise(w); + if (w->isIconic()) { + removeIcon(w); + getWorkspace(wkspc_id)->addWindow(w); + } else if (ignore_sticky || ! w->isStuck()) { + getWorkspace(w->getWorkspaceNumber())->removeWindow(w); + getWorkspace(wkspc_id)->addWindow(w); } +} - void BScreen::updateNetizenWindowLower(Window w) { - netList::iterator it; - for (it = netizenList.begin(); it != netizenList.end(); ++it) - (*it)->sendWindowLower(w); +void BScreen::propagateWindowName(const BlackboxWindow *bw) { + if (bw->isIconic()) { + iconmenu->changeItemLabel(bw->getWindowNumber(), bw->getIconTitle()); + iconmenu->update(); } + else { + Clientmenu *clientmenu = getWorkspace(bw->getWorkspaceNumber())->getMenu(); + clientmenu->changeItemLabel(bw->getWindowNumber(), bw->getTitle()); + clientmenu->update(); - - void BScreen::updateNetizenConfigNotify(XEvent *e) { - netList::iterator it; - for (it = netizenList.begin(); it != netizenList.end(); ++it) - (*it)->sendConfigNotify(e); + if (blackbox->getFocusedWindow() == bw) + toolbar->redrawWindowLabel(True); } +} - void BScreen::raiseWindows(Window *workspace_stack, int num) { - Window *session_stack = new - Window[(num + workspacesList.size() + rootmenuList.size() + 13)]; - int i = 0, k = num; - - XRaiseWindow(getBaseDisplay().getXDisplay(), iconmenu->getWindowID()); - *(session_stack + i++) = iconmenu->getWindowID(); - - wkspList::iterator it; - for (it = workspacesList.begin(); it != workspacesList.end(); ++it) - *(session_stack + i++) = (*it)->getMenu()->getWindowID(); - - *(session_stack + i++) = workspacemenu->getWindowID(); - - *(session_stack + i++) = configmenu->getFocusmenu()->getWindowID(); - *(session_stack + i++) = configmenu->getPlacementmenu()->getWindowID(); - *(session_stack + i++) = configmenu->getWindowID(); - -#ifdef SLIT - *(session_stack + i++) = slit->getMenu()->getDirectionmenu()->getWindowID(); - *(session_stack + i++) = slit->getMenu()->getPlacementmenu()->getWindowID(); - *(session_stack + i++) = slit->getMenu()->getWindowID(); -#endif // SLIT - - *(session_stack + i++) = - toolbar->getMenu()->getPlacementmenu()->getWindowID(); - *(session_stack + i++) = toolbar->getMenu()->getWindowID(); - - menuList::iterator rit; - for (rit = rootmenuList.begin(); rit != rootmenuList.end(); ++rit) - *(session_stack + i++) = (*rit)->getWindowID(); - *(session_stack + i++) = rootmenu->getWindowID(); - - if (toolbar->onTop()) - *(session_stack + i++) = toolbar->getWindowID(); - -#ifdef SLIT - if (slit->onTop()) - *(session_stack + i++) = slit->getWindowID(); -#endif // SLIT - - while (k--) - *(session_stack + i++) = *(workspace_stack + k); - - XRestackWindows(getBaseDisplay().getXDisplay(), session_stack, i); +void BScreen::nextFocus(void) { + BlackboxWindow *focused = blackbox->getFocusedWindow(), + *next = focused; - delete [] session_stack; + if (focused) { + // if window is not on this screen, ignore it + if (focused->getScreen()->getScreenNumber() != getScreenNumber()) + focused = (BlackboxWindow*) 0; } + if (focused && current_workspace->getCount() > 1) { + // next is the next window to recieve focus, current is a place holder + BlackboxWindow *current; + do { + current = next; + next = current_workspace->getNextWindowInList(current); + } while(!next->setInputFocus() && next != focused); - void BScreen::addWorkspaceName(const char *name) { - workspaceNames.push_back(name); - } - + if (next != focused) + current_workspace->raiseWindow(next); + } else if (current_workspace->getCount() >= 1) { + next = current_workspace->getTopWindowOnStack(); - const char *BScreen::getNameOfWorkspace(int id) { - if (id < 0 || id >= (signed)workspaceNames.size()) - return (const char *) 0; - return workspaceNames[id].c_str(); + current_workspace->raiseWindow(next); + next->setInputFocus(); } +} - void BScreen::reassociateWindow(OpenboxWindow *w, int wkspc_id, Bool ignore_sticky) { - if (! w) return; - - if (wkspc_id == -1) - wkspc_id = current_workspace->getWorkspaceID(); - - if (w->getWorkspaceNumber() == wkspc_id) - return; +void BScreen::prevFocus(void) { + BlackboxWindow *focused = blackbox->getFocusedWindow(), + *next = focused; - if (w->isIconic()) { - removeIcon(w); - getWorkspace(wkspc_id)->addWindow(w); - } else if (ignore_sticky || ! w->isStuck()) { - getWorkspace(w->getWorkspaceNumber())->removeWindow(w); - getWorkspace(wkspc_id)->addWindow(w); - } + if (focused) { + // if window is not on this screen, ignore it + if (focused->getScreen()->getScreenNumber() != getScreenNumber()) + focused = (BlackboxWindow*) 0; } + if (focused && current_workspace->getCount() > 1) { + // next is the next window to recieve focus, current is a place holder + BlackboxWindow *current; + do { + current = next; + next = current_workspace->getPrevWindowInList(current); + } while(!next->setInputFocus() && next != focused); - void BScreen::nextFocus(void) { - Bool have_focused = False; - int focused_window_number = -1; - OpenboxWindow *next; - - if (openbox.focusedWindow()) { - if (openbox.focusedWindow()->getScreen()->getScreenNumber() == - getScreenNumber()) { - have_focused = True; - focused_window_number = openbox.focusedWindow()->getWindowNumber(); - } - } - - if ((getCurrentWorkspace()->getCount() > 1) && have_focused) { - int next_window_number = focused_window_number; - do { - if ((++next_window_number) >= getCurrentWorkspace()->getCount()) - next_window_number = 0; - - next = getCurrentWorkspace()->getWindow(next_window_number); - } while ((! next->setInputFocus()) && (next_window_number != - focused_window_number)); - - if (next_window_number != focused_window_number) - getCurrentWorkspace()->raiseWindow(next); - } else if (getCurrentWorkspace()->getCount() >= 1) { - next = current_workspace->getWindow(0); - + if (next != focused) current_workspace->raiseWindow(next); - next->setInputFocus(); - } - } - + } else if (current_workspace->getCount() >= 1) { + next = current_workspace->getTopWindowOnStack(); - void BScreen::prevFocus(void) { - Bool have_focused = False; - int focused_window_number = -1; - OpenboxWindow *prev; - - if (openbox.focusedWindow()) { - if (openbox.focusedWindow()->getScreen()->getScreenNumber() == - getScreenNumber()) { - have_focused = True; - focused_window_number = openbox.focusedWindow()->getWindowNumber(); - } - } - - if ((getCurrentWorkspace()->getCount() > 1) && have_focused) { - int prev_window_number = focused_window_number; - do { - if ((--prev_window_number) < 0) - prev_window_number = getCurrentWorkspace()->getCount() - 1; + current_workspace->raiseWindow(next); + next->setInputFocus(); + } +} - prev = getCurrentWorkspace()->getWindow(prev_window_number); - } while ((! prev->setInputFocus()) && (prev_window_number != - focused_window_number)); - if (prev_window_number != focused_window_number) - getCurrentWorkspace()->raiseWindow(prev); - } else if (getCurrentWorkspace()->getCount() >= 1) { - prev = current_workspace->getWindow(0); +void BScreen::raiseFocus(void) { + BlackboxWindow *focused = blackbox->getFocusedWindow(); + if (! focused) + return; - current_workspace->raiseWindow(prev); - prev->setInputFocus(); - } + // if on this Screen, raise it + if (focused->getScreen()->getScreenNumber() == getScreenNumber()) { + Workspace *workspace = getWorkspace(focused->getWorkspaceNumber()); + workspace->raiseWindow(focused); } +} - void BScreen::raiseFocus(void) { - Bool have_focused = False; - int focused_window_number = -1; +void BScreen::InitMenu(void) { + if (rootmenu) { + rootmenuList.clear(); - if (openbox.focusedWindow()) { - if (openbox.focusedWindow()->getScreen()->getScreenNumber() == - getScreenNumber()) { - have_focused = True; - focused_window_number = openbox.focusedWindow()->getWindowNumber(); - } - } - - if ((getCurrentWorkspace()->getCount() > 1) && have_focused) - getWorkspace(openbox.focusedWindow()->getWorkspaceNumber())-> - raiseWindow(openbox.focusedWindow()); + while (rootmenu->getCount()) + rootmenu->remove(0); + } else { + rootmenu = new Rootmenu(this); } + bool defaultMenu = True; + if (blackbox->getMenuFilename()) { + FILE *menu_file = fopen(blackbox->getMenuFilename(), "r"); - void BScreen::InitMenu(void) { - if (rootmenu) { - rootmenuList.clear(); - while (rootmenu->getCount()) - rootmenu->remove(0); + if (!menu_file) { + perror(blackbox->getMenuFilename()); } else { - rootmenu = new Rootmenu(*this); - } - bool defaultMenu = true; - - FILE *menu_file; - const char *menu_filename = openbox.getMenuFilename(); - - if (!(menu_file = fopen(menu_filename, "r"))) { - perror(menu_filename); - menu_filename = (char *) 0; - } - if (menu_filename == (char *) 0) { - // opening the menu file failed, try the DEFAULTMENU - menu_filename = DEFAULTMENU; - if (!(menu_file = fopen(menu_filename, "r"))) { - perror(menu_filename); - menu_filename = (char *) 0; - } - } - - if (menu_filename) { if (feof(menu_file)) { fprintf(stderr, i18n(ScreenSet, ScreenEmptyMenuFile, - "%s: Empty menu file"), menu_filename); - menu_filename = (char *) 0; + "%s: Empty menu file"), + blackbox->getMenuFilename()); } else { - // successsfully opened a menu file char line[1024], label[1024]; memset(line, 0, 1024); memset(label, 0, 1024); @@ -2296,7 +1137,6 @@ void BScreen::load() { if (line[0] != '#') { int i, key = 0, index = -1, len = strlen(line); - key = 0; for (i = 0; i < len; i++) { if (line[i] == '[') index = 0; else if (line[i] == ']') break; @@ -2305,7 +1145,7 @@ void BScreen::load() { key += tolower(line[i]); } - if (key == 517) { + if (key == 517) { // [begin] index = -1; for (i = index; i < len; i++) { if (line[i] == '(') index = 0; @@ -2321,8 +1161,6 @@ void BScreen::load() { rootmenu->setLabel(label); defaultMenu = parseMenuFile(menu_file, rootmenu); - if (!defaultMenu) - openbox.addMenuTimestamp(menu_filename); break; } } @@ -2330,504 +1168,815 @@ void BScreen::load() { } fclose(menu_file); } + } - if (defaultMenu) { - rootmenu->setInternalMenu(); - rootmenu->insert(i18n(ScreenSet, Screenxterm, "xterm"), - BScreen::Execute, - i18n(ScreenSet, Screenxterm, "xterm")); - rootmenu->insert(i18n(ScreenSet, ScreenRestart, "Restart"), - BScreen::Restart); - rootmenu->insert(i18n(ScreenSet, ScreenExit, "Exit"), - BScreen::Exit); - } + if (defaultMenu) { + rootmenu->setInternalMenu(); + rootmenu->insert(i18n(ScreenSet, Screenxterm, "xterm"), + BScreen::Execute, + i18n(ScreenSet, Screenxterm, "xterm")); + rootmenu->insert(i18n(ScreenSet, ScreenRestart, "Restart"), + BScreen::Restart); + rootmenu->insert(i18n(ScreenSet, ScreenExit, "Exit"), + BScreen::Exit); + rootmenu->setLabel(i18n(BasemenuSet, BasemenuBlackboxMenu, + "Blackbox Menu")); + } else { + blackbox->saveMenuFilename(blackbox->getMenuFilename()); } +} + + +bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) { + char line[1024], label[1024], command[1024]; + while (! feof(file)) { + memset(line, 0, 1024); + memset(label, 0, 1024); + memset(command, 0, 1024); - Bool BScreen::parseMenuFile(FILE *file, Rootmenu *menu) { - char line[1024], label[1024], command[1024]; - - while (! feof(file)) { - memset(line, 0, 1024); - memset(label, 0, 1024); - memset(command, 0, 1024); - - if (fgets(line, 1024, file)) { - if (line[0] != '#') { - register int i, key = 0, parse = 0, index = -1, - line_length = strlen(line), - label_length = 0, command_length = 0; - - // determine the keyword - key = 0; - for (i = 0; i < line_length; i++) { - if (line[i] == '[') parse = 1; - else if (line[i] == ']') break; - else if (line[i] != ' ') - if (parse) - key += tolower(line[i]); + if (fgets(line, 1024, file)) { + if (line[0] != '#') { + int i, key = 0, parse = 0, index = -1, line_length = strlen(line); + + // determine the keyword + for (i = 0; i < line_length; i++) { + if (line[i] == '[') parse = 1; + else if (line[i] == ']') break; + else if (line[i] != ' ') + if (parse) + key += tolower(line[i]); + } + + // get the label enclosed in ()'s + parse = 0; + + for (i = 0; i < line_length; i++) { + if (line[i] == '(') { + index = 0; + parse = 1; + } else if (line[i] == ')') break; + else if (index++ >= 0) { + if (line[i] == '\\' && i < line_length - 1) i++; + label[index - 1] = line[i]; } + } - // get the label enclosed in ()'s - parse = 0; - - for (i = 0; i < line_length; i++) { - if (line[i] == '(') { - index = 0; - parse = 1; - } else if (line[i] == ')') break; - else if (index++ >= 0) { - if (line[i] == '\\' && i < line_length - 1) i++; - label[index - 1] = line[i]; - } + if (parse) { + label[index] = '\0'; + } else { + label[0] = '\0'; + } + + // get the command enclosed in {}'s + parse = 0; + index = -1; + for (i = 0; i < line_length; i++) { + if (line[i] == '{') { + index = 0; + parse = 1; + } else if (line[i] == '}') break; + else if (index++ >= 0) { + if (line[i] == '\\' && i < line_length - 1) i++; + command[index - 1] = line[i]; } + } + + if (parse) { + command[index] = '\0'; + } else { + command[0] = '\0'; + } + + switch (key) { + case 311: // end + return ((menu->getCount() == 0) ? True : False); - if (parse) { - label[index] = '\0'; - label_length = index; - } else { + break; + + case 333: // nop + if (! *label) label[0] = '\0'; - label_length = 0; + menu->insert(label); + + break; + + case 421: // exec + if ((! *label) && (! *command)) { + fprintf(stderr, i18n(ScreenSet, ScreenEXECError, + "BScreen::parseMenuFile: [exec] error, " + "no menu label and/or command defined\n")); + continue; } - // get the command enclosed in {}'s - parse = 0; - index = -1; - for (i = 0; i < line_length; i++) { - if (line[i] == '{') { - index = 0; - parse = 1; - } else if (line[i] == '}') break; - else if (index++ >= 0) { - if (line[i] == '\\' && i < line_length - 1) i++; - command[index - 1] = line[i]; - } + menu->insert(label, BScreen::Execute, command); + + break; + + case 442: // exit + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenEXITError, + "BScreen::parseMenuFile: [exit] error, " + "no menu label defined\n")); + continue; } - if (parse) { - command[index] = '\0'; - command_length = index; - } else { - command[0] = '\0'; - command_length = 0; + menu->insert(label, BScreen::Exit); + + break; + + case 561: // style + { + if ((! *label) || (! *command)) { + fprintf(stderr, + i18n(ScreenSet, ScreenSTYLEError, + "BScreen::parseMenuFile: [style] error, " + "no menu label and/or filename defined\n")); + continue; + } + + string style = expandTilde(command); + + menu->insert(label, BScreen::SetStyle, style.c_str()); } - switch (key) { - case 311: //end - return ((menu->getCount() == 0) ? True : False); + break; - break; + case 630: // config + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError, + "BScreen::parseMenufile: [config] error, " + "no label defined")); + continue; + } - case 333: // nop - menu->insert(label); + menu->insert(label, configmenu); - break; + break; - case 421: // exec - if ((! *label) && (! *command)) { - fprintf(stderr, i18n(ScreenSet, ScreenEXECError, - "BScreen::parseMenuFile: [exec] error, " - "no menu label and/or command defined\n")); + case 740: // include + { + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError, + "BScreen::parseMenuFile: [include] error, " + "no filename defined\n")); continue; } - menu->insert(label, BScreen::Execute, command); + string newfile = expandTilde(label); + FILE *submenufile = fopen(newfile.c_str(), "r"); - break; + if (submenufile) { + struct stat buf; + if (fstat(fileno(submenufile), &buf) || + (! S_ISREG(buf.st_mode))) { + fprintf(stderr, + i18n(ScreenSet, ScreenINCLUDEErrorReg, + "BScreen::parseMenuFile: [include] error: " + "'%s' is not a regular file\n"), newfile.c_str()); + break; + } + + if (! feof(submenufile)) { + if (! parseMenuFile(submenufile, menu)) + blackbox->saveMenuFilename(newfile); + + fclose(submenufile); + } + } else { + perror(newfile.c_str()); + } + } - case 442: // exit + break; + + case 767: // submenu + { if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenEXITError, - "BScreen::parseMenuFile: [exit] error, " + fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError, + "BScreen::parseMenuFile: [submenu] error, " "no menu label defined\n")); continue; } - menu->insert(label, BScreen::Exit); + Rootmenu *submenu = new Rootmenu(this); - break; + if (*command) + submenu->setLabel(command); + else + submenu->setLabel(label); - case 561: // style - { - if ((! *label) || (! *command)) { - fprintf(stderr, i18n(ScreenSet, ScreenSTYLEError, - "BScreen::parseMenuFile: [style] error, " - "no menu label and/or filename defined\n")); - continue; - } + parseMenuFile(file, submenu); + submenu->update(); + menu->insert(label, submenu); + rootmenuList.push_back(submenu); + } - char style[MAXPATHLEN]; + break; - // perform shell style ~ home directory expansion - char *homedir = 0; - int homedir_len = 0; - if (*command == '~' && *(command + 1) == '/') { - homedir = getenv("HOME"); - homedir_len = strlen(homedir); - } + case 773: // restart + { + if (! *label) { + fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError, + "BScreen::parseMenuFile: [restart] error, " + "no menu label defined\n")); + continue; + } - if (homedir && homedir_len != 0) { - strncpy(style, homedir, homedir_len); + if (*command) + menu->insert(label, BScreen::RestartOther, command); + else + menu->insert(label, BScreen::Restart); + } - strncpy(style + homedir_len, command + 1, - command_length - 1); - *(style + command_length + homedir_len - 1) = '\0'; - } else { - strncpy(style, command, command_length); - *(style + command_length) = '\0'; - } + break; - menu->insert(label, BScreen::SetStyle, style); + case 845: // reconfig + { + if (! *label) { + fprintf(stderr, + i18n(ScreenSet, ScreenRECONFIGError, + "BScreen::parseMenuFile: [reconfig] error, " + "no menu label defined\n")); + continue; } - break; + menu->insert(label, BScreen::Reconfigure); + } - case 630: // config - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenCONFIGError, - "BScreen::parseMenufile: [config] error, " - "no label defined")); + break; + + case 995: // stylesdir + case 1113: // stylesmenu + { + bool newmenu = ((key == 1113) ? True : False); + + if ((! *label) || ((! *command) && newmenu)) { + fprintf(stderr, + i18n(ScreenSet, ScreenSTYLESDIRError, + "BScreen::parseMenuFile: [stylesdir/stylesmenu]" + " error, no directory defined\n")); continue; } - menu->insert(label, configmenu); + char *directory = ((newmenu) ? command : label); - break; + string stylesdir = expandTilde(directory); - case 740: // include - { - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenINCLUDEError, - "BScreen::parseMenuFile: [include] error, " - "no filename defined\n")); - continue; - } + struct stat statbuf; - char newfile[MAXPATHLEN]; + if (! stat(stylesdir.c_str(), &statbuf)) { + if (S_ISDIR(statbuf.st_mode)) { + Rootmenu *stylesmenu; - // perform shell style ~ home directory expansion - char *homedir = 0; - int homedir_len = 0; - if (*label == '~' && *(label + 1) == '/') { - homedir = getenv("HOME"); - homedir_len = strlen(homedir); - } + if (newmenu) + stylesmenu = new Rootmenu(this); + else + stylesmenu = menu; + + DIR *d = opendir(stylesdir.c_str()); + struct dirent *p; + std::vector ls; + + while((p = readdir(d))) + ls.push_back(p->d_name); + + closedir(d); - if (homedir && homedir_len != 0) { - strncpy(newfile, homedir, homedir_len); + std::sort(ls.begin(), ls.end()); - strncpy(newfile + homedir_len, label + 1, - label_length - 1); - *(newfile + label_length + homedir_len - 1) = '\0'; + std::vector::iterator it = ls.begin(), + end = ls.end(); + for (; it != end; ++it) { + const string& fname = *it; + + if (fname[fname.size()-1] == '~') + continue; + + string style = stylesdir; + style += '/'; + style += fname; + + if ((! stat(style.c_str(), &statbuf)) && + S_ISREG(statbuf.st_mode)) + stylesmenu->insert(fname, BScreen::SetStyle, style); + } + + stylesmenu->update(); + + if (newmenu) { + stylesmenu->setLabel(label); + menu->insert(label, stylesmenu); + rootmenuList.push_back(stylesmenu); + } + + blackbox->saveMenuFilename(stylesdir); } else { - strncpy(newfile, label, label_length); - *(newfile + label_length) = '\0'; + fprintf(stderr, + i18n(ScreenSet, ScreenSTYLESDIRErrorNotDir, + "BScreen::parseMenuFile:" + " [stylesdir/stylesmenu] error, %s is not a" + " directory\n"), stylesdir.c_str()); } + } else { + fprintf(stderr, + i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist, + "BScreen::parseMenuFile: [stylesdir/stylesmenu]" + " error, %s does not exist\n"), stylesdir.c_str()); + } + break; + } - if (newfile) { - FILE *submenufile = fopen(newfile, "r"); - - if (submenufile) { - struct stat buf; - if (fstat(fileno(submenufile), &buf) || - (! S_ISREG(buf.st_mode))) { - fprintf(stderr, - i18n(ScreenSet, ScreenINCLUDEErrorReg, - "BScreen::parseMenuFile: [include] error: " - "'%s' is not a regular file\n"), newfile); - break; - } - - if (! feof(submenufile)) { - if (!parseMenuFile(submenufile, menu)) - openbox.addMenuTimestamp(newfile); - fclose(submenufile); - } - } else - perror(newfile); - } + case 1090: // workspaces + { + if (! *label) { + fprintf(stderr, + i18n(ScreenSet, ScreenWORKSPACESError, + "BScreen:parseMenuFile: [workspaces] error, " + "no menu label defined\n")); + continue; } + menu->insert(label, workspacemenu); + break; + } + } + } + } + } - case 767: // submenu - { - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenSUBMENUError, - "BScreen::parseMenuFile: [submenu] error, " - "no menu label defined\n")); - continue; - } + return ((menu->getCount() == 0) ? True : False); +} - Rootmenu *submenu = new Rootmenu(*this); - if (*command) - submenu->setLabel(command); - else - submenu->setLabel(label); +void BScreen::shutdown(void) { + XSelectInput(blackbox->getXDisplay(), getRootWindow(), NoEventMask); + XSync(blackbox->getXDisplay(), False); - parseMenuFile(file, submenu); - submenu->update(); - menu->insert(label, submenu); - rootmenuList.push_back(submenu); - } + while(! windowList.empty()) + unmanageWindow(windowList.front(), True); - break; + slit->shutdown(); +} - case 773: // restart - { - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenRESTARTError, - "BScreen::parseMenuFile: [restart] error, " - "no menu label defined\n")); - continue; - } - if (*command) - menu->insert(label, BScreen::RestartOther, command); - else - menu->insert(label, BScreen::Restart); - } +void BScreen::showPosition(int x, int y) { + if (! geom_visible) { + XMoveResizeWindow(blackbox->getXDisplay(), geom_window, + (getWidth() - geom_w) / 2, + (getHeight() - geom_h) / 2, geom_w, geom_h); + XMapWindow(blackbox->getXDisplay(), geom_window); + XRaiseWindow(blackbox->getXDisplay(), geom_window); - break; + geom_visible = True; + } - case 845: // reconfig - { - if (! *label) { - fprintf(stderr, i18n(ScreenSet, ScreenRECONFIGError, - "BScreen::parseMenuFile: [reconfig] error, " - "no menu label defined\n")); - continue; - } + char label[1024]; - menu->insert(label, BScreen::Reconfigure); - } + sprintf(label, i18n(ScreenSet, ScreenPositionFormat, + "X: %4d x Y: %4d"), x, y); - break; + XClearWindow(blackbox->getXDisplay(), geom_window); - case 995: // stylesdir - case 1113: // stylesmenu - { - Bool newmenu = ((key == 1113) ? True : False); + BPen pen(resource.wstyle.l_text_focus, resource.wstyle.font); + if (i18n.multibyte()) { + XmbDrawString(blackbox->getXDisplay(), geom_window, + resource.wstyle.fontset, pen.gc(), + resource.bevel_width, resource.bevel_width - + resource.wstyle.fontset_extents->max_ink_extent.y, + label, strlen(label)); + } else { + XDrawString(blackbox->getXDisplay(), geom_window, + pen.gc(), resource.bevel_width, + resource.wstyle.font->ascent + resource.bevel_width, + label, strlen(label)); + } +} - if ((! *label) || ((! *command) && newmenu)) { - fprintf(stderr, - i18n(ScreenSet, ScreenSTYLESDIRError, - "BScreen::parseMenuFile: [stylesdir/stylesmenu]" - " error, no directory defined\n")); - continue; - } - char stylesdir[MAXPATHLEN]; +void BScreen::showGeometry(unsigned int gx, unsigned int gy) { + if (! geom_visible) { + XMoveResizeWindow(blackbox->getXDisplay(), geom_window, + (getWidth() - geom_w) / 2, + (getHeight() - geom_h) / 2, geom_w, geom_h); + XMapWindow(blackbox->getXDisplay(), geom_window); + XRaiseWindow(blackbox->getXDisplay(), geom_window); - char *directory = ((newmenu) ? command : label); - int directory_length = ((newmenu) ? command_length : label_length); + geom_visible = True; + } - // perform shell style ~ home directory expansion - char *homedir = 0; - int homedir_len = 0; + char label[1024]; - if (*directory == '~' && *(directory + 1) == '/') { - homedir = getenv("HOME"); - homedir_len = strlen(homedir); - } + sprintf(label, i18n(ScreenSet, ScreenGeometryFormat, + "W: %4d x H: %4d"), gx, gy); - if (homedir && homedir_len != 0) { - strncpy(stylesdir, homedir, homedir_len); + XClearWindow(blackbox->getXDisplay(), geom_window); - strncpy(stylesdir + homedir_len, directory + 1, - directory_length - 1); - *(stylesdir + directory_length + homedir_len - 1) = '\0'; - } else { - strncpy(stylesdir, directory, directory_length); - *(stylesdir + directory_length) = '\0'; - } + BPen pen(resource.wstyle.l_text_focus, resource.wstyle.font); + if (i18n.multibyte()) { + XmbDrawString(blackbox->getXDisplay(), geom_window, + resource.wstyle.fontset, pen.gc(), + resource.bevel_width, resource.bevel_width - + resource.wstyle.fontset_extents->max_ink_extent.y, + label, strlen(label)); + } else { + XDrawString(blackbox->getXDisplay(), geom_window, + pen.gc(), resource.bevel_width, + resource.wstyle.font->ascent + + resource.bevel_width, label, strlen(label)); + } +} - struct stat statbuf; - if (! stat(stylesdir, &statbuf)) { - if (S_ISDIR(statbuf.st_mode)) { - Rootmenu *stylesmenu; +void BScreen::hideGeometry(void) { + if (geom_visible) { + XUnmapWindow(blackbox->getXDisplay(), geom_window); + geom_visible = False; + } +} - if (newmenu) - stylesmenu = new Rootmenu(*this); - else - stylesmenu = menu; - DIR *d = opendir(stylesdir); - int entries = 0; - struct dirent *p; +void BScreen::addStrut(Strut *strut) { + strutList.push_back(strut); +} - // get the total number of directory entries - while ((p = readdir(d))) entries++; - rewinddir(d); - char **ls = new char* [entries]; - int index = 0; - while ((p = readdir(d))) - ls[index++] = bstrdup(p->d_name); +void BScreen::removeStrut(Strut *strut) { + strutList.remove(strut); +} - closedir(d); - std::sort(ls, ls + entries, dcmp()); +const Rect& BScreen::availableArea(void) const { + if (doFullMax()) + return getRect(); // return the full screen + return usableArea; +} - int n, slen = strlen(stylesdir); - for (n = 0; n < entries; n++) { - if (ls[n][strlen(ls[n])-1] != '~') { - int nlen = strlen(ls[n]); - char style[MAXPATHLEN + 1]; - strncpy(style, stylesdir, slen); - *(style + slen) = '/'; - strncpy(style + slen + 1, ls[n], nlen + 1); +void BScreen::updateAvailableArea(void) { + Rect old_area = usableArea; + usableArea = getRect(); // reset to full screen + + /* these values represent offsets from the screen edge + * we look for the biggest offset on each edge and then apply them + * all at once + * do not be confused by the similarity to the names of Rect's members + */ + unsigned int current_left = 0, current_right = 0, current_top = 0, + current_bottom = 0; + + StrutList::const_iterator it = strutList.begin(), end = strutList.end(); + + for(; it != end; ++it) { + Strut *strut = *it; + if (strut->left > current_left) + current_left = strut->left; + if (strut->top > current_top) + current_top = strut->top; + if (strut->right > current_right) + current_right = strut->right; + if (strut->bottom > current_bottom) + current_bottom = strut->bottom; + } - if ((! stat(style, &statbuf)) && S_ISREG(statbuf.st_mode)) - stylesmenu->insert(ls[n], BScreen::SetStyle, style); - } + usableArea.setPos(current_left, current_top); + usableArea.setSize(usableArea.width() - (current_left + current_right), + usableArea.height() - (current_top + current_bottom)); - delete [] ls[n]; - } + if (old_area != usableArea) { + BlackboxWindowList::iterator it = windowList.begin(), + end = windowList.end(); + for (; it != end; ++it) + if ((*it)->isMaximized()) (*it)->remaximize(); + } +} - delete [] ls; - stylesmenu->update(); +Workspace* BScreen::getWorkspace(unsigned int index) { + assert(index < workspacesList.size()); + return workspacesList[index]; +} - if (newmenu) { - stylesmenu->setLabel(label); - menu->insert(label, stylesmenu); - rootmenuList.push_back(stylesmenu); - } - openbox.addMenuTimestamp(stylesdir); - } else { - fprintf(stderr, i18n(ScreenSet, - ScreenSTYLESDIRErrorNotDir, - "BScreen::parseMenuFile:" - " [stylesdir/stylesmenu] error, %s is not a" - " directory\n"), stylesdir); - } - } else { - fprintf(stderr, - i18n(ScreenSet, ScreenSTYLESDIRErrorNoExist, - "BScreen::parseMenuFile: [stylesdir/stylesmenu]" - " error, %s does not exist\n"), stylesdir); - } - break; - } +void BScreen::buttonPressEvent(XButtonEvent *xbutton) { + if (xbutton->button == 1) { + if (! isRootColormapInstalled()) + image_control->installRootColormap(); - case 1090: // workspaces - { - if (! *label) { - fprintf(stderr, - i18n(ScreenSet, ScreenWORKSPACESError, - "BScreen:parseMenuFile: [workspaces] error, " - "no menu label defined\n")); - continue; - } + if (workspacemenu->isVisible()) + workspacemenu->hide(); - menu->insert(label, workspacemenu); + if (rootmenu->isVisible()) + rootmenu->hide(); + } else if (xbutton->button == 2) { + int mx = xbutton->x_root - (workspacemenu->getWidth() / 2); + int my = xbutton->y_root - (workspacemenu->getTitleHeight() / 2); - break; - } - } - } - } + if (mx < 0) mx = 0; + if (my < 0) my = 0; + + if (mx + workspacemenu->getWidth() > getWidth()) + mx = getWidth() - workspacemenu->getWidth() - getBorderWidth(); + + if (my + workspacemenu->getHeight() > getHeight()) + my = getHeight() - workspacemenu->getHeight() - getBorderWidth(); + + workspacemenu->move(mx, my); + + if (! workspacemenu->isVisible()) { + workspacemenu->removeParent(); + workspacemenu->show(); } + } else if (xbutton->button == 3) { + int mx = xbutton->x_root - (rootmenu->getWidth() / 2); + int my = xbutton->y_root - (rootmenu->getTitleHeight() / 2); + + if (mx < 0) mx = 0; + if (my < 0) my = 0; - return ((menu->getCount() == 0) ? True : False); + if (mx + rootmenu->getWidth() > getWidth()) + mx = getWidth() - rootmenu->getWidth() - getBorderWidth(); + + if (my + rootmenu->getHeight() > getHeight()) + my = getHeight() - rootmenu->getHeight() - getBorderWidth(); + + rootmenu->move(mx, my); + + if (! rootmenu->isVisible()) { + blackbox->checkMenu(); + rootmenu->show(); + } } +} + +void BScreen::toggleFocusModel(FocusModel model) { + if (model == SloppyFocus) { + saveSloppyFocus(True); + } else { + saveSloppyFocus(False); + saveAutoRaise(False); + saveClickRaise(False); + } - void BScreen::shutdown(void) { - openbox.grab(); + updateFocusModel(); +} - XSelectInput(getBaseDisplay().getXDisplay(), getRootWindow(), NoEventMask); - XSync(getBaseDisplay().getXDisplay(), False); - std::for_each(workspacesList.begin(), workspacesList.end(), - std::mem_fun(&Workspace::shutdown)); +void BScreen::updateFocusModel() +{ + std::for_each(workspacesList.begin(), workspacesList.end(), + std::mem_fun(&Workspace::updateFocusModel)); +} - while (!iconList.empty()) - iconList.front()->restore(); -#ifdef SLIT - slit->shutdown(); -#endif // SLIT +BTexture BScreen::readDatabaseTexture(const string &rname, + const string &rclass, + const string &default_color) { + BTexture texture; + XrmValue value; + char *value_type; - openbox.ungrab(); + if (XrmGetResource(resource.stylerc, rname.c_str(), rclass.c_str(), + &value_type, &value)) + texture = BTexture(value.addr); + else + texture.setTexture(BTexture::Solid | BTexture::Flat); + + // associate this texture with this screen + texture.setDisplay(getBaseDisplay(), getScreenNumber()); + texture.setImageControl(image_control); + + if (texture.texture() & BTexture::Solid) { + texture.setColor(readDatabaseColor(rname + ".color", + rclass + ".Color", + default_color)); + texture.setColorTo(readDatabaseColor(rname + ".colorTo", + rclass + ".ColorTo", + default_color)); + } else if (texture.texture() & BTexture::Gradient) { + texture.setColor(readDatabaseColor(rname + ".color", + rclass + ".Color", + default_color)); + texture.setColorTo(readDatabaseColor(rname + ".colorTo", + rclass + ".ColorTo", + default_color)); } + return texture; +} + + +BColor BScreen::readDatabaseColor(const string &rname, const string &rclass, + const string &default_color) { + BColor color; + XrmValue value; + char *value_type; + if (XrmGetResource(resource.stylerc, rname.c_str(), rclass.c_str(), + &value_type, &value)) + color = BColor(value.addr, getBaseDisplay(), getScreenNumber()); + else + color = BColor(default_color, getBaseDisplay(), getScreenNumber()); + return color; +} + - void BScreen::showPosition(int x, int y) { - if (! geom_visible) { - XMoveResizeWindow(getBaseDisplay().getXDisplay(), geom_window, - (size().w() - geom_w) / 2, - (size().h() - geom_h) / 2, geom_w, geom_h); - XMapWindow(getBaseDisplay().getXDisplay(), geom_window); - XRaiseWindow(getBaseDisplay().getXDisplay(), geom_window); +XFontSet BScreen::readDatabaseFontSet(const string &rname, + const string &rclass) { + char *defaultFont = "fixed"; - geom_visible = True; + bool load_default = True; + XrmValue value; + char *value_type; + XFontSet fontset = 0; + if (XrmGetResource(resource.stylerc, rname.c_str(), rclass.c_str(), + &value_type, &value) && + (fontset = createFontSet(value.addr))) { + load_default = False; + } + + if (load_default) { + fontset = createFontSet(defaultFont); + + if (! fontset) { + fprintf(stderr, + i18n(ScreenSet, ScreenDefaultFontLoadFail, + "BScreen::setCurrentStyle(): couldn't load default font.\n")); + exit(2); } + } + + return fontset; +} - char label[1024]; - sprintf(label, i18n(ScreenSet, ScreenPositionFormat, - "X: %4d x Y: %4d"), x, y); +XFontStruct *BScreen::readDatabaseFont(const string &rname, + const string &rclass) { + char *defaultFont = "fixed"; - XClearWindow(getBaseDisplay().getXDisplay(), geom_window); + bool load_default = False; + XrmValue value; + char *value_type; + XFontStruct *font = 0; + if (XrmGetResource(resource.stylerc, rname.c_str(), rclass.c_str(), + &value_type, &value)) { + if ((font = XLoadQueryFont(blackbox->getXDisplay(), value.addr)) == NULL) { + fprintf(stderr, + i18n(ScreenSet, ScreenFontLoadFail, + "BScreen::setCurrentStyle(): couldn't load font '%s'\n"), + value.addr); - if (i18n.multibyte()) { - XmbDrawString(getBaseDisplay().getXDisplay(), geom_window, - resource.wstyle.fontset, resource.wstyle.l_text_focus_gc, - resource.bevel_width, resource.bevel_width - - resource.wstyle.fontset_extents->max_ink_extent.y, - label, strlen(label)); - } else { - XDrawString(getBaseDisplay().getXDisplay(), geom_window, - resource.wstyle.l_text_focus_gc, - resource.bevel_width, - resource.wstyle.font->ascent + - resource.bevel_width, label, strlen(label)); + load_default = True; } + } else { + load_default = True; } + if (load_default) { + font = XLoadQueryFont(blackbox->getXDisplay(), defaultFont); + if (font == NULL) { + fprintf(stderr, + i18n(ScreenSet, ScreenDefaultFontLoadFail, + "BScreen::setCurrentStyle(): couldn't load default font.\n")); + exit(2); + } + } + + return font; +} - void BScreen::showGeometry(unsigned int gx, unsigned int gy) { - if (! geom_visible) { - XMoveResizeWindow(getBaseDisplay().getXDisplay(), geom_window, - (size().w() - geom_w) / 2, - (size().h() - geom_h) / 2, geom_w, geom_h); - XMapWindow(getBaseDisplay().getXDisplay(), geom_window); - XRaiseWindow(getBaseDisplay().getXDisplay(), geom_window); - geom_visible = True; +#ifndef HAVE_STRCASESTR +static const char * strcasestr(const char *str, const char *ptn) { + const char *s2, *p2; + for(; *str; str++) { + for(s2=str,p2=ptn; ; s2++,p2++) { + if (!*p2) return str; + if (toupper(*s2) != toupper(*p2)) break; } + } + return NULL; +} +#endif // HAVE_STRCASESTR - char label[1024]; - sprintf(label, i18n(ScreenSet, ScreenGeometryFormat, - "W: %4d x H: %4d"), gx, gy); +static const char *getFontElement(const char *pattern, char *buf, + int bufsiz, ...) { + const char *p, *v; + char *p2; + va_list va; + + va_start(va, bufsiz); + buf[bufsiz-1] = 0; + buf[bufsiz-2] = '*'; + while((v = va_arg(va, char *)) != NULL) { + p = strcasestr(pattern, v); + if (p) { + strncpy(buf, p+1, bufsiz-2); + p2 = strchr(buf, '-'); + if (p2) *p2=0; + va_end(va); + return p; + } + } + va_end(va); + strncpy(buf, "*", bufsiz); + return NULL; +} - XClearWindow(getBaseDisplay().getXDisplay(), geom_window); - if (i18n.multibyte()) { - XmbDrawString(getBaseDisplay().getXDisplay(), geom_window, - resource.wstyle.fontset, resource.wstyle.l_text_focus_gc, - resource.bevel_width, resource.bevel_width - - resource.wstyle.fontset_extents->max_ink_extent.y, - label, strlen(label)); +static const char *getFontSize(const char *pattern, int *size) { + const char *p; + const char *p2=NULL; + int n=0; + + for (p=pattern; 1; p++) { + if (!*p) { + if (p2!=NULL && n>1 && n<72) { + *size = n; return p2+1; + } else { + *size = 16; return NULL; + } + } else if (*p=='-') { + if (n>1 && n<72 && p2!=NULL) { + *size = n; + return p2+1; + } + p2=p; n=0; + } else if (*p>='0' && *p<='9' && p2!=NULL) { + n *= 10; + n += *p-'0'; } else { - XDrawString(getBaseDisplay().getXDisplay(), geom_window, - resource.wstyle.l_text_focus_gc, - resource.bevel_width, - resource.wstyle.font->ascent + - resource.bevel_width, label, strlen(label)); + p2=NULL; n=0; } } +} - void BScreen::hideGeometry(void) { - if (geom_visible) { - XUnmapWindow(getBaseDisplay().getXDisplay(), geom_window); - geom_visible = False; - } + +XFontSet BScreen::createFontSet(const string &fontname) { + XFontSet fs; + char **missing, *def = "-"; + int nmissing, pixel_size = 0, buf_size = 0; + char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE]; + + fs = XCreateFontSet(blackbox->getXDisplay(), + fontname.c_str(), &missing, &nmissing, &def); + if (fs && (! nmissing)) + return fs; + + const char *nfontname = fontname.c_str(); +#ifdef HAVE_SETLOCALE + if (! fs) { + if (nmissing) XFreeStringList(missing); + + setlocale(LC_CTYPE, "C"); + fs = XCreateFontSet(blackbox->getXDisplay(), fontname.c_str(), + &missing, &nmissing, &def); + setlocale(LC_CTYPE, ""); } +#endif // HAVE_SETLOCALE + + if (fs) { + XFontStruct **fontstructs; + char **fontnames; + XFontsOfFontSet(fs, &fontstructs, &fontnames); + nfontname = fontnames[0]; + } + + getFontElement(nfontname, weight, FONT_ELEMENT_SIZE, + "-medium-", "-bold-", "-demibold-", "-regular-", NULL); + getFontElement(nfontname, slant, FONT_ELEMENT_SIZE, + "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL); + getFontSize(nfontname, &pixel_size); + + if (! strcmp(weight, "*")) + strncpy(weight, "medium", FONT_ELEMENT_SIZE); + if (! strcmp(slant, "*")) + strncpy(slant, "r", FONT_ELEMENT_SIZE); + if (pixel_size < 3) + pixel_size = 3; + else if (pixel_size > 97) + pixel_size = 97; + + buf_size = strlen(nfontname) + (FONT_ELEMENT_SIZE * 2) + 64; + char *pattern2 = new char[buf_size]; + sprintf(pattern2, + "%s," + "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*," + "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*", + nfontname, weight, slant, pixel_size, pixel_size); + nfontname = pattern2; + + if (nmissing) + XFreeStringList(missing); + if (fs) + XFreeFontSet(blackbox->getXDisplay(), fs); + + fs = XCreateFontSet(blackbox->getXDisplay(), nfontname, &missing, + &nmissing, &def); + + delete [] pattern2; + + return fs; +} diff --git a/src/Screen.h b/src/Screen.h deleted file mode 100644 index 24baba1f..00000000 --- a/src/Screen.h +++ /dev/null @@ -1,336 +0,0 @@ -// Screen.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Screen_hh -#define __Screen_hh - -#include -#include - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else // !TIME_WITH_SYS_TIME -# ifdef HAVE_SYS_TIME_H -# include -# else // !HAVE_SYS_TIME_H -# include -# endif // HAVE_SYS_TIME_H -#endif // TIME_WITH_SYS_TIME - -#include "BaseDisplay.h" -#include "Configmenu.h" -#include "Iconmenu.h" -#include "Netizen.h" -#include "Rootmenu.h" -#include "Timer.h" -#include "Workspace.h" -#include "Workspacemenu.h" -#include "openbox.h" -#ifdef SLIT -# include "Slit.h" -#endif // SLIT -#include "Image.h" -#include "Resource.h" -#include "Util.h" - -#include -#include - -// forward declaration -class BScreen; - -struct WindowStyle { - BColor f_focus, f_unfocus, l_text_focus, l_text_unfocus, b_pic_focus, - b_pic_unfocus; - BTexture t_focus, t_unfocus, l_focus, l_unfocus, h_focus, h_unfocus, - b_focus, b_unfocus, b_pressed, g_focus, g_unfocus; - GC l_text_focus_gc, l_text_unfocus_gc, b_pic_focus_gc, b_pic_unfocus_gc; - - XFontSet fontset; - XFontSetExtents *fontset_extents; - XFontStruct *font; - - int justify; -}; - -struct ToolbarStyle { - BColor l_text, w_text, c_text, b_pic; - BTexture toolbar, label, window, button, pressed, clock; - GC l_text_gc, w_text_gc, c_text_gc, b_pic_gc; - - XFontSet fontset; - XFontSetExtents *fontset_extents; - XFontStruct *font; - - int justify; -}; - -struct MenuStyle { - BColor t_text, f_text, h_text, d_text; - BTexture title, frame, hilite; - GC t_text_gc, f_text_gc, h_text_gc, d_text_gc, hilite_gc; - - XFontSet t_fontset, f_fontset; - XFontSetExtents *t_fontset_extents, *f_fontset_extents; - XFontStruct *t_font, *f_font; - - int t_justify, f_justify, bullet, bullet_pos; -}; - - -class BScreen : public ScreenInfo { -private: - Bool root_colormap_installed, managed, geom_visible; - GC opGC; - Pixmap geom_pixmap; - Window geom_window; - - Openbox &openbox; - Resource &config; - BImageControl *image_control; - Configmenu *configmenu; - Iconmenu *iconmenu; - Rootmenu *rootmenu; - - typedef std::list menuList; - menuList rootmenuList; - typedef std::list netList; - netList netizenList; - typedef std::list winList; - winList iconList; // winList is declared in Workspace.h - -#ifdef SLIT - Slit *slit; -#endif // SLIT - - Toolbar *toolbar; - Workspace *current_workspace; - Workspacemenu *workspacemenu; - - unsigned int geom_w, geom_h; - unsigned long event_mask; - - typedef std::vector wkspNameList; - wkspNameList workspaceNames; - typedef std::vector wkspList; - wkspList workspacesList; - - struct resource { - WindowStyle wstyle; - ToolbarStyle tstyle; - MenuStyle mstyle; - - bool sloppy_focus, auto_raise, auto_edge_balance, focus_last, - ordered_dither, opaque_move, hide_toolbar, full_max, focus_new; - BColor border_color; - Resource styleconfig; - - int workspaces, placement_policy, edge_snap_threshold, row_direction, - col_direction; - - unsigned int handle_width, bevel_width, frame_width, border_width; - int zones; // number of zones to be used when alt-resizing a window - -#ifdef HAVE_STRFTIME - char *strftime_format; -#else // !HAVE_STRFTIME - bool clock24hour; - int date_format; -#endif // HAVE_STRFTIME - - char *root_command; - } resource; - - -protected: - Bool parseMenuFile(FILE *, Rootmenu *); - - void readDatabaseTexture(const char *, const char *, BTexture *, - unsigned long); - void readDatabaseColor(const char *, const char *, BColor *, unsigned long); - - void readDatabaseFontSet(const char *, const char *, XFontSet *); - XFontSet createFontSet(const char *); - void readDatabaseFont(const char *, const char *, XFontStruct **); - - void InitMenu(); - void LoadStyle(); - - -public: - BScreen(Openbox &, int, Resource &); - ~BScreen(); - - inline const Bool &isScreenManaged() const { return managed; } - inline const GC &getOpGC() const { return opGC; } - - inline Openbox &getOpenbox() { return openbox; } - inline BColor *getBorderColor() { return &resource.border_color; } - inline BImageControl *getImageControl() { return image_control; } - inline Rootmenu *getRootmenu() { return rootmenu; } - -#ifdef SLIT - inline Slit *getSlit() { return slit; } -#endif // SLIT - - inline Toolbar *getToolbar() { return toolbar; } - - Rect availableArea() const; - - inline Workspace *getWorkspace(unsigned int w) { - ASSERT(w < workspacesList.size()); - return workspacesList[w]; - } - inline Workspace *getCurrentWorkspace() { return current_workspace; } - - inline Workspacemenu *getWorkspacemenu() { return workspacemenu; } - - inline void iconUpdate() { iconmenu->update(); } - - inline const unsigned int &getHandleWidth() const - { return resource.handle_width; } - inline const unsigned int &getBevelWidth() const - { return resource.bevel_width; } - inline const unsigned int &getFrameWidth() const - { return resource.frame_width; } - inline const unsigned int &getBorderWidth() const - { return resource.border_width; } - - inline const int getCurrentWorkspaceID() - { return current_workspace->getWorkspaceID(); } - inline const int getWorkspaceCount() { return workspacesList.size(); } - inline const int getIconCount() { return iconList.size(); } - - inline const Bool &isRootColormapInstalled() const - { return root_colormap_installed; } - inline void setRootColormapInstalled(Bool r) { root_colormap_installed = r; } - - inline bool sloppyFocus() const { return resource.sloppy_focus; } - void setSloppyFocus(bool s); - - inline bool autoRaise() const { return resource.auto_raise; } - void setAutoRaise(bool a); - - inline bool imageDither() const { return image_control->doDither(); } - void setImageDither(bool d, bool reconfig = true); - - inline bool orderedDither() const { return resource.ordered_dither; } - - inline bool opaqueMove() const { return resource.opaque_move; } - void setOpaqueMove(bool o); - - inline bool fullMax() const { return resource.full_max; } - void setFullMax(bool f); - - inline bool focusNew() const { return resource.focus_new; } - void setFocusNew(bool f); - - inline bool focusLast() const { return resource.focus_last; } - void setFocusLast(bool f); - - inline int getWindowZones() const { return resource.zones; } - void setWindowZones(int z); - - inline int workspaceCount() const { return resource.workspaces; } - void setWorkspaceCount(int w); - - inline int placementPolicy() const { return resource.placement_policy; } - void setPlacementPolicy(int p); - - inline int edgeSnapThreshold() const { return resource.edge_snap_threshold; } - void setEdgeSnapThreshold(int t); - - inline int rowPlacementDirection() const { return resource.row_direction; } - void setRowPlacementDirection(int d); - - inline int colPlacementDirection() const { return resource.col_direction; } - void setColPlacementDirection(int d); - - inline char *rootCommand() const { return resource.root_command; } - inline void setRootCommand(const char *cmd); - -#ifdef HAVE_STRFTIME - inline char *strftimeFormat() { return resource.strftime_format; } - void setStrftimeFormat(const char *); -#else // !HAVE_STRFTIME - inline int dateFormat() { return resource.date_format; } - void setDateFormat(int f); - inline bool clock24Hour() { return resource.clock24hour; } - void setClock24Hour(Bool c); -#endif // HAVE_STRFTIME - - inline bool hideToolbar() const { return resource.hide_toolbar; } - void setHideToolbar(bool); - - inline WindowStyle *getWindowStyle() { return &resource.wstyle; } - inline MenuStyle *getMenuStyle() { return &resource.mstyle; } - inline ToolbarStyle *getToolbarStyle() { return &resource.tstyle; } - - OpenboxWindow *getIcon(int); - - int addWorkspace(); - int removeLastWorkspace(); - - void removeWorkspaceNames(); - void addWorkspaceName(const char *); - void saveWorkspaceNames(); - void addNetizen(Netizen *); - void removeNetizen(Window); - void addIcon(OpenboxWindow *); - void removeIcon(OpenboxWindow *); - const char *getNameOfWorkspace(int); - void changeWorkspaceID(int); - void raiseWindows(Window *, int); - void reassociateWindow(OpenboxWindow *, int, Bool); - void prevFocus(); - void nextFocus(); - void raiseFocus(); - void reconfigure(); - void load(); - void save(); - void rereadMenu(); - void shutdown(); - void showPosition(int, int); - void showGeometry(unsigned int, unsigned int); - void hideGeometry(); - void updateNetizenCurrentWorkspace(); - void updateNetizenWorkspaceCount(); - void updateNetizenWindowFocus(); - void updateNetizenWindowAdd(Window, unsigned long); - void updateNetizenWindowDel(Window); - void updateNetizenConfigNotify(XEvent *); - void updateNetizenWindowRaise(Window); - void updateNetizenWindowLower(Window); - - enum { RowSmartPlacement = 1, ColSmartPlacement, CascadePlacement, - BestFitPlacement, UnderMousePlacement, ClickMousePlacement, - LeftRight, RightLeft, TopBottom, BottomTop }; - enum { LeftJustify = 1, RightJustify, CenterJustify }; - enum { RoundBullet = 1, TriangleBullet, SquareBullet, NoBullet }; - enum { Restart = 1, RestartOther, Exit, Shutdown, Execute, Reconfigure, - WindowShade, WindowIconify, WindowMaximize, WindowClose, WindowRaise, - WindowLower, WindowStick, WindowKill, SetStyle }; -}; - - -#endif // __Screen_hh diff --git a/src/Screen.hh b/src/Screen.hh new file mode 100644 index 00000000..7a75ac62 --- /dev/null +++ b/src/Screen.hh @@ -0,0 +1,372 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Screen.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef __Screen_hh +#define __Screen_hh + +extern "C" { +#include +#include + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else // !TIME_WITH_SYS_TIME +# ifdef HAVE_SYS_TIME_H +# include +# else // !HAVE_SYS_TIME_H +# include +# endif // HAVE_SYS_TIME_H +#endif // TIME_WITH_SYS_TIME +} + +#include +#include + +#include "Color.hh" +#include "Texture.hh" +#include "Configmenu.hh" +#include "Iconmenu.hh" +#include "Netizen.hh" +#include "Rootmenu.hh" +#include "Timer.hh" +#include "Workspace.hh" +#include "Workspacemenu.hh" +#include "blackbox.hh" +class Slit; // forward reference + +enum TextJustify { LeftJustify = 1, RightJustify, CenterJustify }; + +struct WindowStyle { + BColor f_focus, f_unfocus, l_text_focus, l_text_unfocus, b_pic_focus, + b_pic_unfocus; + BTexture t_focus, t_unfocus, l_focus, l_unfocus, h_focus, h_unfocus, + b_focus, b_unfocus, b_pressed, g_focus, g_unfocus; + + XFontSet fontset; + XFontSetExtents *fontset_extents; + XFontStruct *font; + + TextJustify justify; + + int doJustify(const char *text, int &start_pos, unsigned int max_length, + unsigned int modifier, bool multibyte) const; +}; + +struct ToolbarStyle { + BColor l_text, w_text, c_text, b_pic; + BTexture toolbar, label, window, button, pressed, clock; + + XFontSet fontset; + XFontSetExtents *fontset_extents; + XFontStruct *font; + + TextJustify justify; + + int doJustify(const char *text, int &start_pos, unsigned int max_length, + unsigned int modifier, bool multibyte) const; +}; + +struct MenuStyle { + BColor t_text, f_text, h_text, d_text; + BTexture title, frame, hilite; + + XFontSet t_fontset, f_fontset; + XFontSetExtents *t_fontset_extents, *f_fontset_extents; + XFontStruct *t_font, *f_font; + + TextJustify t_justify, f_justify; + int bullet, bullet_pos; +}; + +struct Strut { + unsigned int top, bottom, left, right; + + Strut(void): top(0), bottom(0), left(0), right(0) {} +}; + +class BScreen : public ScreenInfo { +private: + bool root_colormap_installed, managed, geom_visible; + GC opGC; + Pixmap geom_pixmap; + Window geom_window; + + Blackbox *blackbox; + BImageControl *image_control; + Configmenu *configmenu; + Iconmenu *iconmenu; + Rootmenu *rootmenu; + + typedef std::list RootmenuList; + RootmenuList rootmenuList; + + typedef std::list NetizenList; + NetizenList netizenList; + BlackboxWindowList iconList, windowList; + + Slit *slit; + Toolbar *toolbar; + Workspace *current_workspace; + Workspacemenu *workspacemenu; + + unsigned int geom_w, geom_h; + unsigned long event_mask; + + Rect usableArea; + + typedef std::list StrutList; + StrutList strutList; + typedef std::vector WorkspaceNamesList; + WorkspaceNamesList workspaceNames; + typedef std::vector WorkspaceList; + WorkspaceList workspacesList; + + struct screen_resource { + WindowStyle wstyle; + ToolbarStyle tstyle; + MenuStyle mstyle; + + bool toolbar_on_top, toolbar_auto_hide, sloppy_focus, auto_raise, + auto_edge_balance, image_dither, ordered_dither, opaque_move, full_max, + focus_new, focus_last, click_raise; + BColor border_color; + XrmDatabase stylerc; + + unsigned int workspaces; + int toolbar_placement, toolbar_width_percent, placement_policy, + edge_snap_threshold, row_direction, col_direction; + + bool slit_on_top, slit_auto_hide; + int slit_placement, slit_direction; + + unsigned int handle_width, bevel_width, frame_width, border_width; + +#ifdef HAVE_STRFTIME + std::string strftime_format; +#else // !HAVE_STRFTIME + bool clock24hour; + int date_format; +#endif // HAVE_STRFTIME + + } resource; + + BScreen(const BScreen&); + BScreen& operator=(const BScreen&); + + bool parseMenuFile(FILE *file, Rootmenu *menu); + + BTexture readDatabaseTexture(const std::string &rname, + const std::string &rclass, + const std::string &default_color); + BColor readDatabaseColor(const std::string &rname, + const std::string &rclass, + const std::string &default_color); + XFontSet readDatabaseFontSet(const std::string &rname, + const std::string &rclass); + XFontStruct *readDatabaseFont(const std::string &rname, + const std::string &rclass); + XFontSet createFontSet(const std::string &fontname); + + void InitMenu(void); + void LoadStyle(void); + + +public: + enum { RowSmartPlacement = 1, ColSmartPlacement, CascadePlacement, LeftRight, + RightLeft, TopBottom, BottomTop }; + enum { RoundBullet = 1, TriangleBullet, SquareBullet, NoBullet }; + enum { Restart = 1, RestartOther, Exit, Shutdown, Execute, Reconfigure, + WindowShade, WindowIconify, WindowMaximize, WindowClose, WindowRaise, + WindowLower, WindowStick, WindowKill, SetStyle }; + enum FocusModel { SloppyFocus, ClickToFocus }; + + BScreen(Blackbox *bb, unsigned int scrn); + ~BScreen(void); + + inline bool isToolbarOnTop(void) const + { return resource.toolbar_on_top; } + inline bool doToolbarAutoHide(void) const + { return resource.toolbar_auto_hide; } + inline bool isSloppyFocus(void) const + { return resource.sloppy_focus; } + inline bool isRootColormapInstalled(void) const + { return root_colormap_installed; } + inline bool doAutoRaise(void) const { return resource.auto_raise; } + inline bool doClickRaise(void) const { return resource.click_raise; } + inline bool isScreenManaged(void) const { return managed; } + inline bool doImageDither(void) const + { return resource.image_dither; } + inline bool doOrderedDither(void) const + { return resource.ordered_dither; } + inline bool doOpaqueMove(void) const { return resource.opaque_move; } + inline bool doFullMax(void) const { return resource.full_max; } + inline bool doFocusNew(void) const { return resource.focus_new; } + inline bool doFocusLast(void) const { return resource.focus_last; } + + inline const GC &getOpGC(void) const { return opGC; } + + inline Blackbox *getBlackbox(void) { return blackbox; } + inline BColor *getBorderColor(void) { return &resource.border_color; } + inline BImageControl *getImageControl(void) { return image_control; } + inline Rootmenu *getRootmenu(void) { return rootmenu; } + + inline bool isSlitOnTop(void) const { return resource.slit_on_top; } + inline bool doSlitAutoHide(void) const + { return resource.slit_auto_hide; } + inline Slit *getSlit(void) { return slit; } + inline int getSlitPlacement(void) const + { return resource.slit_placement; } + inline int getSlitDirection(void) const + { return resource.slit_direction; } + inline void saveSlitPlacement(int p) { resource.slit_placement = p; } + inline void saveSlitDirection(int d) { resource.slit_direction = d; } + inline void saveSlitOnTop(bool t) { resource.slit_on_top = t; } + inline void saveSlitAutoHide(bool t) { resource.slit_auto_hide = t; } + + inline Toolbar *getToolbar(void) { return toolbar; } + + Workspace *getWorkspace(unsigned int index); + + inline Workspace *getCurrentWorkspace(void) { return current_workspace; } + + inline Workspacemenu *getWorkspacemenu(void) { return workspacemenu; } + + inline unsigned int getHandleWidth(void) const + { return resource.handle_width; } + inline unsigned int getBevelWidth(void) const + { return resource.bevel_width; } + inline unsigned int getFrameWidth(void) const + { return resource.frame_width; } + inline unsigned int getBorderWidth(void) const + { return resource.border_width; } + + inline unsigned int getCurrentWorkspaceID(void) + { return current_workspace->getID(); } + inline unsigned int getWorkspaceCount(void) + { return workspacesList.size(); } + inline unsigned int getIconCount(void) { return iconList.size(); } + inline unsigned int getNumberOfWorkspaces(void) const + { return resource.workspaces; } + inline int getToolbarPlacement(void) const + { return resource.toolbar_placement; } + inline int getToolbarWidthPercent(void) const + { return resource.toolbar_width_percent; } + inline int getPlacementPolicy(void) const + { return resource.placement_policy; } + inline int getEdgeSnapThreshold(void) const + { return resource.edge_snap_threshold; } + inline int getRowPlacementDirection(void) const + { return resource.row_direction; } + inline int getColPlacementDirection(void) const + { return resource.col_direction; } + + inline void setRootColormapInstalled(bool r) { root_colormap_installed = r; } + inline void saveSloppyFocus(bool s) { resource.sloppy_focus = s; } + inline void saveAutoRaise(bool a) { resource.auto_raise = a; } + inline void saveClickRaise(bool c) { resource.click_raise = c; } + inline void saveWorkspaces(unsigned int w) { resource.workspaces = w; } + inline void saveToolbarOnTop(bool r) { resource.toolbar_on_top = r; } + inline void saveToolbarAutoHide(bool r) { resource.toolbar_auto_hide = r; } + inline void saveToolbarWidthPercent(int w) + { resource.toolbar_width_percent = w; } + inline void saveToolbarPlacement(int p) { resource.toolbar_placement = p; } + inline void savePlacementPolicy(int p) { resource.placement_policy = p; } + inline void saveRowPlacementDirection(int d) { resource.row_direction = d; } + inline void saveColPlacementDirection(int d) { resource.col_direction = d; } + inline void saveEdgeSnapThreshold(int t) + { resource.edge_snap_threshold = t; } + inline void saveImageDither(bool d) { resource.image_dither = d; } + inline void saveOpaqueMove(bool o) { resource.opaque_move = o; } + inline void saveFullMax(bool f) { resource.full_max = f; } + inline void saveFocusNew(bool f) { resource.focus_new = f; } + inline void saveFocusLast(bool f) { resource.focus_last = f; } + inline void iconUpdate(void) { iconmenu->update(); } + +#ifdef HAVE_STRFTIME + inline const char *getStrftimeFormat(void) + { return resource.strftime_format.c_str(); } + void saveStrftimeFormat(const std::string& format); +#else // !HAVE_STRFTIME + inline int getDateFormat(void) { return resource.date_format; } + inline void saveDateFormat(int f) { resource.date_format = f; } + inline bool isClock24Hour(void) { return resource.clock24hour; } + inline void saveClock24Hour(bool c) { resource.clock24hour = c; } +#endif // HAVE_STRFTIME + + inline WindowStyle *getWindowStyle(void) { return &resource.wstyle; } + inline MenuStyle *getMenuStyle(void) { return &resource.mstyle; } + inline ToolbarStyle *getToolbarStyle(void) { return &resource.tstyle; } + + BlackboxWindow *getIcon(unsigned int index); + + const Rect& availableArea(void) const; + void updateAvailableArea(void); + void addStrut(Strut *strut); + void removeStrut(Strut *strut); + + unsigned int addWorkspace(void); + unsigned int removeLastWorkspace(void); + void removeWorkspaceNames(void); + void addWorkspaceName(const std::string& name); + const std::string getNameOfWorkspace(unsigned int id); + void changeWorkspaceID(unsigned int id); + + void addNetizen(Netizen *n); + void removeNetizen(Window w); + + void addIcon(BlackboxWindow *w); + void removeIcon(BlackboxWindow *w); + + void manageWindow(Window w); + void unmanageWindow(BlackboxWindow *w, bool remap); + void raiseWindows(Window *workspace_stack, unsigned int num); + void reassociateWindow(BlackboxWindow *w, unsigned int wkspc_id, + bool ignore_sticky); + void propagateWindowName(const BlackboxWindow *bw); + void prevFocus(void); + void nextFocus(void); + void raiseFocus(void); + void reconfigure(void); + void toggleFocusModel(FocusModel model); + void updateFocusModel(void); + void rereadMenu(void); + void shutdown(void); + void showPosition(int x, int y); + void showGeometry(unsigned int gx, unsigned int gy); + void hideGeometry(void); + + void buttonPressEvent(XButtonEvent *xbutton); + + void updateNetizenCurrentWorkspace(void); + void updateNetizenWorkspaceCount(void); + void updateNetizenWindowFocus(void); + void updateNetizenWindowAdd(Window w, unsigned long p); + void updateNetizenWindowDel(Window w); + void updateNetizenConfigNotify(XEvent *e); + void updateNetizenWindowRaise(Window w); + void updateNetizenWindowLower(Window w); +}; + + +#endif // __Screen_hh diff --git a/src/Slit.cc b/src/Slit.cc index 0b199394..08767400 100644 --- a/src/Slit.cc +++ b/src/Slit.cc @@ -1,5 +1,6 @@ -// Slit.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Slit.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,170 +21,154 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#ifdef SLIT - +extern "C" { #include +} + +#include "i18n.hh" +#include "blackbox.hh" +#include "Image.hh" +#include "Screen.hh" +#include "Slit.hh" +#include "Toolbar.hh" -#include "i18n.h" -#include "openbox.h" -#include "Image.h" -#include "Screen.h" -#include "Slit.h" -#include "Toolbar.h" -#include -#include -using std::ends; +Slit::Slit(BScreen *scr) { + screen = scr; + blackbox = screen->getBlackbox(); -Slit::Slit(BScreen &scr, Resource &conf) : openbox(scr.getOpenbox()), -screen(scr), config(conf) -{ - load(); + on_top = screen->isSlitOnTop(); + hidden = do_auto_hide = screen->doSlitAutoHide(); - display = screen.getBaseDisplay().getXDisplay(); + display = screen->getBaseDisplay()->getXDisplay(); frame.window = frame.pixmap = None; - timer = new BTimer(openbox, *this); - // the time out is set in ::reconfigure() - timer->fireOnce(True); + timer = new BTimer(blackbox, this); + timer->setTimeout(blackbox->getAutoRaiseDelay()); - slitmenu = new Slitmenu(*this); + slitmenu = new Slitmenu(this); XSetWindowAttributes attrib; unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel | - CWColormap | CWOverrideRedirect | CWEventMask; + CWColormap | CWOverrideRedirect | CWEventMask; attrib.background_pixmap = None; attrib.background_pixel = attrib.border_pixel = - screen.getBorderColor()->getPixel(); - attrib.colormap = screen.getColormap(); + screen->getBorderColor()->pixel(); + attrib.colormap = screen->getColormap(); attrib.override_redirect = True; attrib.event_mask = SubstructureRedirectMask | ButtonPressMask | - EnterWindowMask | LeaveWindowMask; + EnterWindowMask | LeaveWindowMask; - frame.area = Rect(0, 0, 1, 1); + frame.rect.setSize(1, 1); frame.window = - XCreateWindow(display, screen.getRootWindow(), - frame.area.x(), frame.area.y(), - frame.area.w(), frame.area.h(), screen.getBorderWidth(), - screen.getDepth(), InputOutput, screen.getVisual(), - create_mask, &attrib); - openbox.saveSlitSearch(frame.window, this); + XCreateWindow(display, screen->getRootWindow(), + frame.rect.x(), frame.rect.y(), + frame.rect.width(), frame.rect.height(), + screen->getBorderWidth(), screen->getDepth(), InputOutput, + screen->getVisual(), create_mask, &attrib); + blackbox->saveSlitSearch(frame.window, this); + + screen->addStrut(&strut); reconfigure(); } -Slit::~Slit() { - openbox.grab(); - - if (timer->isTiming()) timer->stop(); +Slit::~Slit(void) { delete timer; - clientList.clear(); - delete slitmenu; - screen.getImageControl()->removeImage(frame.pixmap); + screen->getImageControl()->removeImage(frame.pixmap); - openbox.removeSlitSearch(frame.window); + blackbox->removeSlitSearch(frame.window); XDestroyWindow(display, frame.window); - - openbox.ungrab(); } void Slit::addClient(Window w) { - openbox.grab(); - - if (openbox.validateWindow(w)) { - SlitClient *client = new SlitClient; - client->client_window = w; - - XWMHints *wmhints = XGetWMHints(display, w); - - if (wmhints) { - if ((wmhints->flags & IconWindowHint) && - (wmhints->icon_window != None)) { - XMoveWindow(display, client->client_window, screen.size().w() + 10, - screen.size().h() + 10); - XMapWindow(display, client->client_window); - - client->icon_window = wmhints->icon_window; - client->window = client->icon_window; - } else { - client->icon_window = None; - client->window = client->client_window; - } + if (! blackbox->validateWindow(w)) + return; + + SlitClient *client = new SlitClient; + client->client_window = w; + + XWMHints *wmhints = XGetWMHints(display, w); - XFree(wmhints); + if (wmhints) { + if ((wmhints->flags & IconWindowHint) && + (wmhints->icon_window != None)) { + // some dock apps use separate windows, we need to hide these + XMoveWindow(display, client->client_window, screen->getWidth() + 10, + screen->getHeight() + 10); + XMapWindow(display, client->client_window); + + client->icon_window = wmhints->icon_window; + client->window = client->icon_window; } else { client->icon_window = None; client->window = client->client_window; } - XWindowAttributes attrib; - if (XGetWindowAttributes(display, client->window, &attrib)) { - client->width = attrib.width; - client->height = attrib.height; - } else { - client->width = client->height = 64; - } - - XSetWindowBorderWidth(display, client->window, 0); + XFree(wmhints); + } else { + client->icon_window = None; + client->window = client->client_window; + } - XSelectInput(display, frame.window, NoEventMask); - XSelectInput(display, client->window, NoEventMask); + XWindowAttributes attrib; + if (XGetWindowAttributes(display, client->window, &attrib)) { + client->rect.setSize(attrib.width, attrib.height); + } else { + client->rect.setSize(64, 64); + } - XReparentWindow(display, client->window, frame.window, 0, 0); - XMapRaised(display, client->window); - XChangeSaveSet(display, client->window, SetModeInsert); + XSetWindowBorderWidth(display, client->window, 0); - XSelectInput(display, frame.window, SubstructureRedirectMask | - ButtonPressMask | EnterWindowMask | LeaveWindowMask); - XSelectInput(display, client->window, StructureNotifyMask | - SubstructureNotifyMask | EnterWindowMask); - XFlush(display); + XGrabServer(display); + XSelectInput(display, frame.window, NoEventMask); + XSelectInput(display, client->window, NoEventMask); + XReparentWindow(display, client->window, frame.window, 0, 0); + XMapRaised(display, client->window); + XChangeSaveSet(display, client->window, SetModeInsert); + XSelectInput(display, frame.window, SubstructureRedirectMask | + ButtonPressMask | EnterWindowMask | LeaveWindowMask); + XSelectInput(display, client->window, StructureNotifyMask | + SubstructureNotifyMask | EnterWindowMask); - clientList.push_back(client); + XUngrabServer(display); - openbox.saveSlitSearch(client->client_window, this); - openbox.saveSlitSearch(client->icon_window, this); - reconfigure(); - } + clientList.push_back(client); - openbox.ungrab(); + blackbox->saveSlitSearch(client->client_window, this); + blackbox->saveSlitSearch(client->icon_window, this); + reconfigure(); } -void Slit::removeClient(SlitClient *client, Bool remap) { - openbox.removeSlitSearch(client->client_window); - openbox.removeSlitSearch(client->icon_window); - +void Slit::removeClient(SlitClient *client, bool remap) { + blackbox->removeSlitSearch(client->client_window); + blackbox->removeSlitSearch(client->icon_window); clientList.remove(client); - screen.removeNetizen(client->window); + screen->removeNetizen(client->window); - if (remap && openbox.validateWindow(client->window)) { + if (remap && blackbox->validateWindow(client->window)) { + XGrabServer(display); XSelectInput(display, frame.window, NoEventMask); XSelectInput(display, client->window, NoEventMask); - XReparentWindow(display, client->window, screen.getRootWindow(), - client->x, client->y); + XReparentWindow(display, client->window, screen->getRootWindow(), + client->rect.x(), client->rect.y()); XChangeSaveSet(display, client->window, SetModeDelete); XSelectInput(display, frame.window, SubstructureRedirectMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask); - XFlush(display); + XUngrabServer(display); } delete client; @@ -191,287 +176,174 @@ void Slit::removeClient(SlitClient *client, Bool remap) { } -void Slit::removeClient(Window w, Bool remap) { - openbox.grab(); +struct SlitClientMatch { + Window window; + SlitClientMatch(Window w): window(w) {} + inline bool operator()(const Slit::SlitClient* client) const { + return (client->window == window); + } +}; - Bool reconf = False; - slitClientList::iterator it; - for (it = clientList.begin(); it != clientList.end(); it++) - if ((*it)->window == w) { - removeClient(*it, remap); - reconf = True; - break; - } +void Slit::removeClient(Window w, bool remap) { + SlitClientList::iterator it = clientList.begin(); + const SlitClientList::iterator end = clientList.end(); - if (reconf) + it = std::find_if(it, end, SlitClientMatch(w)); + if (it != end) { + removeClient(*it, remap); reconfigure(); - - openbox.ungrab(); -} - -void Slit::setOnTop(bool b) { - m_ontop = b; - std::ostrstream s; - s << "session.screen" << screen.getScreenNumber() << ".slit.onTop" << ends; - config.setValue(s.str(), m_ontop ? "True" : "False"); - s.rdbuf()->freeze(0); -} - -void Slit::setAutoHide(bool b) { - m_autohide = b; - std::ostrstream s; - s << "session.screen" << screen.getScreenNumber() << ".slit.autoHide" << ends; - config.setValue(s.str(), m_autohide ? "True" : "False"); - s.rdbuf()->freeze(0); -} - -void Slit::setPlacement(int p) { - m_placement = p; - std::ostrstream s; - s << "session.screen" << screen.getScreenNumber() << ".slit.placement" - << ends; - const char *placement; - switch (m_placement) { - case TopLeft: placement = "TopLeft"; break; - case CenterLeft: placement = "CenterLeft"; break; - case BottomLeft: placement = "BottomLeft"; break; - case TopCenter: placement = "TopCenter"; break; - case BottomCenter: placement = "BottomCenter"; break; - case TopRight: placement = "TopRight"; break; - case BottomRight: placement = "BottomRight"; break; - case CenterRight: default: placement = "CenterRight"; break; } - config.setValue(s.str(), placement); - s.rdbuf()->freeze(0); -} - -void Slit::setDirection(int d) { - m_direction = d; - std::ostrstream s; - s << "session.screen" << screen.getScreenNumber() << ".slit.direction" - << ends; - config.setValue(s.str(), - m_direction == Horizontal ? "Horizontal" : "Vertical"); - s.rdbuf()->freeze(0); } -void Slit::save() { - setOnTop(m_ontop); - setAutoHide(m_autohide); - setPlacement(m_placement); - setDirection(m_direction); -} - -void Slit::load() { - std::ostrstream rscreen, rname, rclass; - std::string s; - bool b; - rscreen << "session.screen" << screen.getScreenNumber() << '.' << ends; - - rname << rscreen.str() << "slit.placement" << ends; - rclass << rscreen.str() << "Slit.Placement" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - if (0 == strncasecmp(s.c_str(), "TopLeft", s.length())) - m_placement = TopLeft; - else if (0 == strncasecmp(s.c_str(), "CenterLeft", s.length())) - m_placement = CenterLeft; - else if (0 == strncasecmp(s.c_str(), "BottomLeft", s.length())) - m_placement = BottomLeft; - else if (0 == strncasecmp(s.c_str(), "TopCenter", s.length())) - m_placement = TopCenter; - else if (0 == strncasecmp(s.c_str(), "BottomCenter", s.length())) - m_placement = BottomCenter; - else if (0 == strncasecmp(s.c_str(), "TopRight", s.length())) - m_placement = TopRight; - else if (0 == strncasecmp(s.c_str(), "BottomRight", s.length())) - m_placement = BottomRight; - else if (0 == strncasecmp(s.c_str(), "CenterRight", s.length())) - m_placement = CenterRight; - } else - m_placement = CenterRight; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "slit.direction" << ends; - rclass << rscreen.str() << "Slit.Direction" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - if (0 == strncasecmp(s.c_str(), "Horizontal", s.length())) - m_direction = Horizontal; - else if (0 == strncasecmp(s.c_str(), "Vertical", s.length())) - m_direction = Vertical; - } else - m_direction = Vertical; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "slit.onTop" << ends; - rclass << rscreen.str() << "Slit.OnTop" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - m_ontop = b; - else - m_ontop = false; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "slit.autoHide" << ends; - rclass << rscreen.str() << "Slit.AutoHide" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - m_hidden = m_autohide = b; - else - m_hidden = m_autohide = false; - - rscreen.rdbuf()->freeze(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); -} void Slit::reconfigure(void) { - timer->setTimeout(openbox.getAutoRaiseDelay()); + SlitClientList::iterator it = clientList.begin(); + const SlitClientList::iterator end = clientList.end(); + SlitClient *client; - frame.area.setSize(0, 0); - slitClientList::const_iterator it; + unsigned int width = 0, height = 0; - switch (m_direction) { + switch (screen->getSlitDirection()) { case Vertical: - for (it = clientList.begin(); it != clientList.end(); it++) { - frame.area.setH(frame.area.h() + (*it)->height + screen.getBevelWidth()); + for (; it != end; ++it) { + client = *it; + height += client->rect.height() + screen->getBevelWidth(); - if (frame.area.w() < (*it)->width) - frame.area.setW((*it)->width); + if (width < client->rect.width()) + width = client->rect.width(); } - if (frame.area.w() < 1) - frame.area.setW(1); + if (width < 1) + width = 1; else - frame.area.setW(frame.area.w() + (screen.getBevelWidth() * 2)); + width += (screen->getBevelWidth() * 2); - if (frame.area.h() < 1) - frame.area.setH(1); + if (height < 1) + height = 1; else - frame.area.setH(frame.area.h() + screen.getBevelWidth()); + height += screen->getBevelWidth(); break; case Horizontal: - for (it = clientList.begin(); it != clientList.end(); it++) { - frame.area.setW(frame.area.w() + (*it)->width + screen.getBevelWidth()); + for (; it != end; ++it) { + client = *it; + width += client->rect.width() + screen->getBevelWidth(); - if (frame.area.h() < (*it)->height) - frame.area.setH((*it)->height); + if (height < client->rect.height()) + height = client->rect.height(); } - if (frame.area.w() < 1) - frame.area.setW(1); + if (width < 1) + width = 1; else - frame.area.setW(frame.area.w() + screen.getBevelWidth()); + width += screen->getBevelWidth(); - if (frame.area.h() < 1) - frame.area.setH(1); + if (height < 1) + height = 1; else - frame.area.setH(frame.area.h() + (screen.getBevelWidth() * 2)); + height += (screen->getBevelWidth() * 2); break; } + frame.rect.setSize(width, height); reposition(); - XSetWindowBorderWidth(display ,frame.window, screen.getBorderWidth()); + XSetWindowBorderWidth(display ,frame.window, screen->getBorderWidth()); XSetWindowBorder(display, frame.window, - screen.getBorderColor()->getPixel()); + screen->getBorderColor()->pixel()); - if (! clientList.size()) + if (clientList.empty()) XUnmapWindow(display, frame.window); else XMapWindow(display, frame.window); - Pixmap tmp = frame.pixmap; - BImageControl *image_ctrl = screen.getImageControl(); - BTexture *texture = &(screen.getToolbarStyle()->toolbar); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.pixmap = None; - XSetWindowBackground(display, frame.window, - texture->getColor()->getPixel()); - } else { - frame.pixmap = image_ctrl->renderImage(frame.area.w(), frame.area.h(), - texture); + BTexture *texture = &(screen->getToolbarStyle()->toolbar); + frame.pixmap = texture->render(frame.rect.width(), frame.rect.height(), + frame.pixmap); + if (! frame.pixmap) + XSetWindowBackground(display, frame.window, texture->color().pixel()); + else XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap); - } - if (tmp) image_ctrl->removeImage(tmp); + XClearWindow(display, frame.window); + it = clientList.begin(); + int x, y; - switch (m_direction) { + switch (screen->getSlitDirection()) { case Vertical: x = 0; - y = screen.getBevelWidth(); + y = screen->getBevelWidth(); - for (it = clientList.begin(); it != clientList.end(); it++) { - x = (frame.area.w() - (*it)->width) / 2; + for (; it != end; ++it) { + client = *it; + x = (frame.rect.width() - client->rect.width()) / 2; - XMoveResizeWindow(display, (*it)->window, x, y, - (*it)->width, (*it)->height); - XMapWindow(display, (*it)->window); + XMoveResizeWindow(display, client->window, x, y, + client->rect.width(), client->rect.height()); + XMapWindow(display, client->window); // for ICCCM compliance - (*it)->x = x; - (*it)->y = y; + client->rect.setPos(x, y); XEvent event; event.type = ConfigureNotify; event.xconfigure.display = display; - event.xconfigure.event = (*it)->window; - event.xconfigure.window = (*it)->window; + event.xconfigure.event = client->window; + event.xconfigure.window = client->window; event.xconfigure.x = x; event.xconfigure.y = y; - event.xconfigure.width = (*it)->width; - event.xconfigure.height = (*it)->height; + event.xconfigure.width = client->rect.width(); + event.xconfigure.height = client->rect.height(); event.xconfigure.border_width = 0; event.xconfigure.above = frame.window; event.xconfigure.override_redirect = False; - XSendEvent(display, (*it)->window, False, StructureNotifyMask, &event); + XSendEvent(display, client->window, False, StructureNotifyMask, &event); - y += (*it)->height + screen.getBevelWidth(); + y += client->rect.height() + screen->getBevelWidth(); } break; case Horizontal: - x = screen.getBevelWidth(); + x = screen->getBevelWidth(); y = 0; - for (it = clientList.begin(); it != clientList.end(); it++) { - y = (frame.area.h() - (*it)->height) / 2; + for (; it != end; ++it) { + client = *it; + y = (frame.rect.height() - client->rect.height()) / 2; - XMoveResizeWindow(display, (*it)->window, x, y, - (*it)->width, (*it)->height); - XMapWindow(display, (*it)->window); + XMoveResizeWindow(display, client->window, x, y, + client->rect.width(), client->rect.height()); + XMapWindow(display, client->window); // for ICCCM compliance - (*it)->x = x; - (*it)->y = y; + client->rect.setPos(x, y); XEvent event; event.type = ConfigureNotify; event.xconfigure.display = display; - event.xconfigure.event = (*it)->window; - event.xconfigure.window = (*it)->window; + event.xconfigure.event = client->window; + event.xconfigure.window = client->window; event.xconfigure.x = x; event.xconfigure.y = y; - event.xconfigure.width = (*it)->width; - event.xconfigure.height = (*it)->height; + event.xconfigure.width = client->rect.width(); + event.xconfigure.height = client->rect.height(); event.xconfigure.border_width = 0; event.xconfigure.above = frame.window; event.xconfigure.override_redirect = False; - XSendEvent(display, (*it)->window, False, StructureNotifyMask, &event); + XSendEvent(display, client->window, False, StructureNotifyMask, &event); - x += (*it)->width + screen.getBevelWidth(); + x += client->rect.width() + screen->getBevelWidth(); } - break; } @@ -479,121 +351,195 @@ void Slit::reconfigure(void) { } +void Slit::updateStrut(void) { + strut.top = strut.bottom = strut.left = strut.right = 0; + + if (! clientList.empty()) { + switch (screen->getSlitDirection()) { + case Vertical: + switch (screen->getSlitPlacement()) { + case TopCenter: + strut.top = getY() + getExposedHeight() + + (screen->getBorderWidth() * 2); + break; + case BottomCenter: + strut.bottom = screen->getHeight() - getY(); + break; + case TopLeft: + case CenterLeft: + case BottomLeft: + strut.left = getExposedWidth() + (screen->getBorderWidth() * 2); + break; + case TopRight: + case CenterRight: + case BottomRight: + strut.right = getExposedWidth() + (screen->getBorderWidth() * 2); + break; + } + break; + case Horizontal: + switch (screen->getSlitPlacement()) { + case TopCenter: + case TopLeft: + case TopRight: + strut.top = getY() + getExposedHeight() + + (screen->getBorderWidth() * 2); + break; + case BottomCenter: + case BottomLeft: + case BottomRight: + strut.bottom = screen->getHeight() - getY(); + break; + case CenterLeft: + strut.left = getExposedWidth() + (screen->getBorderWidth() * 2); + break; + case CenterRight: + strut.right = getExposedWidth() + (screen->getBorderWidth() * 2); + break; + } + break; + } + } + + // update area with new Strut info + screen->updateAvailableArea(); +} + + void Slit::reposition(void) { // place the slit in the appropriate place - switch (m_placement) { + switch (screen->getSlitPlacement()) { case TopLeft: - frame.area.setOrigin(0, 0); - if (m_direction == Vertical) { - frame.hidden = Point(screen.getBevelWidth() - screen.getBorderWidth() - - frame.area.w(), 0); + frame.rect.setPos(0, 0); + + if (screen->getSlitDirection() == Vertical) { + frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth() + - frame.rect.width(); + frame.y_hidden = 0; } else { - frame.hidden = Point(0, screen.getBevelWidth() - screen.getBorderWidth() - - frame.area.h()); + frame.x_hidden = 0; + frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth() + - frame.rect.height(); } break; case CenterLeft: - frame.area.setOrigin(0, (screen.size().h() - frame.area.h()) / 2); - frame.hidden = Point(screen.getBevelWidth() - screen.getBorderWidth() - - frame.area.w(), frame.area.y()); + frame.rect.setPos(0, (screen->getHeight() - frame.rect.height()) / 2); + + frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth() + - frame.rect.width(); + frame.y_hidden = frame.rect.y(); break; case BottomLeft: - frame.area.setOrigin(0, screen.size().h() - frame.area.h() - - (screen.getBorderWidth() * 2)); - if (m_direction == Vertical) - frame.hidden = Point(screen.getBevelWidth() - screen.getBorderWidth() - - frame.area.w(), frame.area.y()); - else - frame.hidden = Point(0, screen.size().h() - screen.getBevelWidth() - - screen.getBorderWidth()); + frame.rect.setPos(0, (screen->getHeight() - frame.rect.height() + - (screen->getBorderWidth() * 2))); + + if (screen->getSlitDirection() == Vertical) { + frame.x_hidden = screen->getBevelWidth() - screen->getBorderWidth() + - frame.rect.width(); + frame.y_hidden = frame.rect.y(); + } else { + frame.x_hidden = 0; + frame.y_hidden = screen->getHeight() - screen->getBevelWidth() + - screen->getBorderWidth(); + } break; case TopCenter: - frame.area.setOrigin((screen.size().w() - frame.area.w()) / 2, 0); - frame.hidden = Point(frame.area.x(), screen.getBevelWidth() - - screen.getBorderWidth() - frame.area.h()); + frame.rect.setPos((screen->getWidth() - frame.rect.width()) / 2, 0); + + frame.x_hidden = frame.rect.x(); + frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth() + - frame.rect.height(); break; case BottomCenter: - frame.area.setOrigin((screen.size().w() - frame.area.w()) / 2, - screen.size().h() - frame.area.h() - - (screen.getBorderWidth() * 2)); - frame.hidden = Point(frame.area.x(), screen.size().h() - - screen.getBevelWidth() - screen.getBorderWidth()); + frame.rect.setPos((screen->getWidth() - frame.rect.width()) / 2, + (screen->getHeight() - frame.rect.height() + - (screen->getBorderWidth() * 2))); + frame.x_hidden = frame.rect.x(); + frame.y_hidden = screen->getHeight() - screen->getBevelWidth() + - screen->getBorderWidth(); break; case TopRight: - frame.area.setOrigin(screen.size().w() - frame.area.w() - - (screen.getBorderWidth() * 2), 0); - if (m_direction == Vertical) - frame.hidden = Point(screen.size().w() - screen.getBevelWidth() - - screen.getBorderWidth(), 0); - else - frame.hidden = Point(frame.area.x(), screen.getBevelWidth() - - screen.getBorderWidth() - frame.area.h()); + frame.rect.setPos((screen->getWidth() - frame.rect.width() + - (screen->getBorderWidth() * 2)), 0); + + if (screen->getSlitDirection() == Vertical) { + frame.x_hidden = screen->getWidth() - screen->getBevelWidth() + - screen->getBorderWidth(); + frame.y_hidden = 0; + } else { + frame.x_hidden = frame.rect.x(); + frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth() + - frame.rect.height(); + } break; case CenterRight: default: - frame.area.setOrigin(screen.size().w() - frame.area.w() - - (screen.getBorderWidth() * 2), - (screen.size().h() - frame.area.h()) / 2); - frame.hidden = Point(screen.size().w() - screen.getBevelWidth() - - screen.getBorderWidth(), frame.area.y()); + frame.rect.setPos((screen->getWidth() - frame.rect.width() + - (screen->getBorderWidth() * 2)), + (screen->getHeight() - frame.rect.height()) / 2); + + frame.x_hidden = screen->getWidth() - screen->getBevelWidth() + - screen->getBorderWidth(); + frame.y_hidden = frame.rect.y(); break; case BottomRight: - frame.area.setOrigin(screen.size().w() - frame.area.w() - - (screen.getBorderWidth() * 2), - screen.size().h() - frame.area.h() - - (screen.getBorderWidth() * 2)); - if (m_direction == Vertical) - frame.hidden = Point(screen.size().w() - screen.getBevelWidth() - - screen.getBorderWidth(), frame.area.y()); - else - frame.hidden = Point(frame.area.x(), screen.size().h() - - screen.getBevelWidth() - screen.getBorderWidth()); + frame.rect.setPos((screen->getWidth() - frame.rect.width() + - (screen->getBorderWidth() * 2)), + (screen->getHeight() - frame.rect.height() + - (screen->getBorderWidth() * 2))); + + if (screen->getSlitDirection() == Vertical) { + frame.x_hidden = screen->getWidth() - screen->getBevelWidth() + - screen->getBorderWidth(); + frame.y_hidden = frame.rect.y(); + } else { + frame.x_hidden = frame.rect.x(); + frame.y_hidden = screen->getHeight() - screen->getBevelWidth() + - screen->getBorderWidth(); + } break; } - Toolbar *tbar = screen.getToolbar(); - int sw = frame.area.w() + (screen.getBorderWidth() * 2), - sh = frame.area.h() + (screen.getBorderWidth() * 2), - tw = tbar->area().w() + screen.getBorderWidth(), - th = tbar->area().h() + screen.getBorderWidth(); - - if (tbar->area().x() < frame.area.x() + sw && - tbar->area().x() + tw > frame.area.x() && - tbar->area().y() < frame.area.y() + sh && - tbar->area().y() + th > frame.area.y()) { - if (frame.area.y() < th) { - frame.area.setY(frame.area.y() + tbar->getExposedHeight()); - if (m_direction == Vertical) - frame.hidden.setY(frame.hidden.y() + tbar->getExposedHeight()); - else - frame.hidden.setY(frame.area.y()); - } else { - frame.area.setY(frame.area.y() - tbar->getExposedHeight()); - if (m_direction == Vertical) - frame.hidden.setY(frame.area.y() - tbar->getExposedHeight()); - else - frame.hidden.setY(frame.area.y()); + Rect tbar_rect = screen->getToolbar()->getRect(); + tbar_rect.setSize(tbar_rect.width() + (screen->getBorderWidth() * 2), + tbar_rect.height() + (screen->getBorderWidth() * 2)); + Rect slit_rect = frame.rect; + slit_rect.setSize(slit_rect.width() + (screen->getBorderWidth() * 2), + slit_rect.height() + (screen->getBorderWidth() * 2)); + + if (slit_rect.intersects(tbar_rect)) { + Toolbar *tbar = screen->getToolbar(); + frame.y_hidden = frame.rect.y(); + + int delta = tbar->getExposedHeight() + (screen->getBorderWidth() * 2); + if (frame.rect.bottom() <= tbar_rect.bottom()) { + delta = -delta; } + frame.rect.setY(frame.rect.y() + delta); + if (screen->getSlitDirection() == Vertical) + frame.y_hidden += delta; } - if (m_hidden) - XMoveResizeWindow(display, frame.window, frame.hidden.x(), - frame.hidden.y(), frame.area.w(), frame.area.h()); + updateStrut(); + + if (hidden) + XMoveResizeWindow(display, frame.window, frame.x_hidden, + frame.y_hidden, frame.rect.width(), frame.rect.height()); else - XMoveResizeWindow(display, frame.window, frame.area.x(), - frame.area.y(), frame.area.w(), frame.area.h()); + XMoveResizeWindow(display, frame.window, frame.rect.x(), frame.rect.y(), + frame.rect.width(), frame.rect.height()); } void Slit::shutdown(void) { - while (clientList.size()) + while (! clientList.empty()) removeClient(clientList.front()); } @@ -601,10 +547,10 @@ void Slit::shutdown(void) { void Slit::buttonPressEvent(XButtonEvent *e) { if (e->window != frame.window) return; - if (e->button == Button1 && !m_ontop) { + if (e->button == Button1 && (! on_top)) { Window w[1] = { frame.window }; - screen.raiseWindows(w, 1); - } else if (e->button == Button2 && !m_ontop) { + screen->raiseWindows(w, 1); + } else if (e->button == Button2 && (! on_top)) { XLowerWindow(display, frame.window); } else if (e->button == Button3) { if (! slitmenu->isVisible()) { @@ -615,13 +561,13 @@ void Slit::buttonPressEvent(XButtonEvent *e) { if (x < 0) x = 0; - else if (x + slitmenu->getWidth() > screen.size().w()) - x = screen.size().w() - slitmenu->getWidth(); + else if (x + slitmenu->getWidth() > screen->getWidth()) + x = screen->getWidth() - slitmenu->getWidth(); if (y < 0) y = 0; - else if (y + slitmenu->getHeight() > screen.size().h()) - y = screen.size().h() - slitmenu->getHeight(); + else if (y + slitmenu->getHeight() > screen->getHeight()) + y = screen->getHeight() - slitmenu->getHeight(); slitmenu->move(x, y); slitmenu->show(); @@ -633,10 +579,10 @@ void Slit::buttonPressEvent(XButtonEvent *e) { void Slit::enterNotifyEvent(XCrossingEvent *) { - if (!m_autohide) + if (! do_auto_hide) return; - if (m_hidden) { + if (hidden) { if (! timer->isTiming()) timer->start(); } else { if (timer->isTiming()) timer->stop(); @@ -645,69 +591,84 @@ void Slit::enterNotifyEvent(XCrossingEvent *) { void Slit::leaveNotifyEvent(XCrossingEvent *) { - if (!m_autohide) + if (! do_auto_hide) return; - if (m_hidden) { + if (hidden) { if (timer->isTiming()) timer->stop(); } else if (! slitmenu->isVisible()) { - if (!timer->isTiming()) timer->start(); + if (! timer->isTiming()) timer->start(); } } void Slit::configureRequestEvent(XConfigureRequestEvent *e) { - openbox.grab(); - - if (openbox.validateWindow(e->window)) { - Bool reconf = False; - XWindowChanges xwc; - - xwc.x = e->x; - xwc.y = e->y; - xwc.width = e->width; - xwc.height = e->height; - xwc.border_width = 0; - xwc.sibling = e->above; - xwc.stack_mode = e->detail; - - XConfigureWindow(display, e->window, e->value_mask, &xwc); - - slitClientList::iterator it = clientList.begin(); - for (; it != clientList.end(); it++) { - SlitClient *client = *it; - if (client->window == e->window) - if (client->width != ((unsigned) e->width) || - client->height != ((unsigned) e->height)) { - client->width = (unsigned) e->width; - client->height = (unsigned) e->height; - reconf = True; - break; - } - } + if (! blackbox->validateWindow(e->window)) + return; + + XWindowChanges xwc; + + xwc.x = e->x; + xwc.y = e->y; + xwc.width = e->width; + xwc.height = e->height; + xwc.border_width = 0; + xwc.sibling = e->above; + xwc.stack_mode = e->detail; + + XConfigureWindow(display, e->window, e->value_mask, &xwc); + + SlitClientList::iterator it = clientList.begin(); + const SlitClientList::iterator end = clientList.end(); + for (; it != end; ++it) { + SlitClient *client = *it; + if (client->window == e->window && + (static_cast(client->rect.width()) != e->width || + static_cast(client->rect.height()) != e->height)) { + client->rect.setSize(e->width, e->height); - if (reconf) reconfigure(); + return; + } } - openbox.ungrab(); } void Slit::timeout(void) { - m_hidden = !m_hidden; - if (m_hidden) - XMoveWindow(display, frame.window, frame.hidden.x(), frame.hidden.y()); + hidden = ! hidden; + if (hidden) + XMoveWindow(display, frame.window, frame.x_hidden, frame.y_hidden); else - XMoveWindow(display, frame.window, frame.area.x(), frame.area.y()); + XMoveWindow(display, frame.window, frame.rect.x(), frame.rect.y()); } -Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen), slit(sl) { +void Slit::toggleAutoHide(void) { + do_auto_hide = (do_auto_hide) ? False : True; + + updateStrut(); + + if (do_auto_hide == False && hidden) { + // force the slit to be visible + if (timer->isTiming()) timer->stop(); + timeout(); + } +} + + +void Slit::unmapNotifyEvent(XUnmapEvent *e) { + removeClient(e->window); +} + + +Slitmenu::Slitmenu(Slit *sl) : Basemenu(sl->screen) { + slit = sl; + setLabel(i18n(SlitSet, SlitSlitTitle, "Slit")); setInternalMenu(); - directionmenu = new Directionmenu(*this); - placementmenu = new Placementmenu(*this); + directionmenu = new Directionmenu(this); + placementmenu = new Placementmenu(this); insert(i18n(CommonSet, CommonDirectionTitle, "Direction"), directionmenu); @@ -718,12 +679,8 @@ Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen), slit(sl) { update(); - setValues(); -} - -void Slitmenu::setValues() { - setItemSelected(2, slit.onTop()); - setItemSelected(3, slit.autoHide()); + if (slit->isOnTop()) setItemSelected(2, True); + if (slit->doAutoHide()) setItemSelected(3, True); } @@ -733,7 +690,7 @@ Slitmenu::~Slitmenu(void) { } -void Slitmenu::itemSelected(int button, int index) { +void Slitmenu::itemSelected(int button, unsigned int index) { if (button != 1) return; @@ -742,18 +699,16 @@ void Slitmenu::itemSelected(int button, int index) { switch (item->function()) { case 1: { // always on top - bool change = ((slit.onTop()) ? false : true); - slit.setOnTop(change); - setItemSelected(2, change); + slit->on_top = ((slit->isOnTop()) ? False : True); + setItemSelected(2, slit->on_top); - if (slit.onTop()) slit.screen.raiseWindows((Window *) 0, 0); + if (slit->isOnTop()) slit->screen->raiseWindows((Window *) 0, 0); break; } case 2: { // auto hide - Bool change = ((slit.autoHide()) ? false : true); - slit.setAutoHide(change); - setItemSelected(3, change); + slit->toggleAutoHide(); + setItemSelected(3, slit->do_auto_hide); break; } @@ -763,13 +718,12 @@ void Slitmenu::itemSelected(int button, int index) { void Slitmenu::internal_hide(void) { Basemenu::internal_hide(); - if (slit.autoHide()) - slit.timeout(); + if (slit->doAutoHide()) + slit->timeout(); } void Slitmenu::reconfigure(void) { - setValues(); directionmenu->reconfigure(); placementmenu->reconfigure(); @@ -777,43 +731,34 @@ void Slitmenu::reconfigure(void) { } -Slitmenu::Directionmenu::Directionmenu(Slitmenu &sm) - : Basemenu(sm.slit.screen), slitmenu(sm) { - setLabel(i18n(SlitSet, SlitSlitDirection, "Slit Direction")); - setInternalMenu(); +Slitmenu::Directionmenu::Directionmenu(Slitmenu *sm) + : Basemenu(sm->slit->screen) { - insert(i18n(CommonSet, CommonDirectionHoriz, "Horizontal"), - Slit::Horizontal); - insert(i18n(CommonSet, CommonDirectionVert, "Vertical"), - Slit::Vertical); - - update(); + setLabel(i18n(SlitSet, SlitSlitDirection, "Slit Direction")); + setInternalMenu(); - setValues(); - } + insert(i18n(CommonSet, CommonDirectionHoriz, "Horizontal"), + Slit::Horizontal); + insert(i18n(CommonSet, CommonDirectionVert, "Vertical"), + Slit::Vertical); + update(); -void Slitmenu::Directionmenu::setValues() { - if (slitmenu.slit.direction() == Slit::Horizontal) + if (getScreen()->getSlitDirection() == Slit::Horizontal) setItemSelected(0, True); else setItemSelected(1, True); } -void Slitmenu::Directionmenu::reconfigure() { - setValues(); - Basemenu::reconfigure(); -} - -void Slitmenu::Directionmenu::itemSelected(int button, int index) { +void Slitmenu::Directionmenu::itemSelected(int button, unsigned int index) { if (button != 1) return; BasemenuItem *item = find(index); if (! item) return; - slitmenu.slit.setDirection(item->function()); + getScreen()->saveSlitDirection(item->function()); if (item->function() == Slit::Horizontal) { setItemSelected(0, True); @@ -824,52 +769,48 @@ void Slitmenu::Directionmenu::itemSelected(int button, int index) { } hide(); - slitmenu.slit.reconfigure(); + getScreen()->getSlit()->reconfigure(); } -Slitmenu::Placementmenu::Placementmenu(Slitmenu &sm) - : Basemenu(sm.slit.screen), slitmenu(sm) { - - setLabel(i18n(SlitSet, SlitSlitPlacement, "Slit Placement")); - setMinimumSublevels(3); - setInternalMenu(); - - insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"), - Slit::TopLeft); - insert(i18n(CommonSet, CommonPlacementCenterLeft, "Center Left"), - Slit::CenterLeft); - insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"), - Slit::BottomLeft); - insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"), - Slit::TopCenter); - insert(""); - insert(i18n(CommonSet, CommonPlacementBottomCenter, - "Bottom Center"), - Slit::BottomCenter); - insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"), - Slit::TopRight); - insert(i18n(CommonSet, CommonPlacementCenterRight, - "Center Right"), - Slit::CenterRight); - insert(i18n(CommonSet, CommonPlacementBottomRight, - "Bottom Right"), - Slit::BottomRight); - - update(); - } +Slitmenu::Placementmenu::Placementmenu(Slitmenu *sm) + : Basemenu(sm->slit->screen) { + + setLabel(i18n(SlitSet, SlitSlitPlacement, "Slit Placement")); + setMinimumSublevels(3); + setInternalMenu(); + + insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"), + Slit::TopLeft); + insert(i18n(CommonSet, CommonPlacementCenterLeft, "Center Left"), + Slit::CenterLeft); + insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"), + Slit::BottomLeft); + insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"), + Slit::TopCenter); + insert(""); + insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"), + Slit::BottomCenter); + insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"), + Slit::TopRight); + insert(i18n(CommonSet, CommonPlacementCenterRight, "Center Right"), + Slit::CenterRight); + insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"), + Slit::BottomRight); + + update(); +} -void Slitmenu::Placementmenu::itemSelected(int button, int index) { +void Slitmenu::Placementmenu::itemSelected(int button, unsigned int index) { if (button != 1) return; BasemenuItem *item = find(index); if (! (item && item->function())) return; - slitmenu.slit.setPlacement(item->function()); + getScreen()->saveSlitPlacement(item->function()); hide(); - slitmenu.slit.reconfigure(); + getScreen()->getSlit()->reconfigure(); } -#endif // SLIT diff --git a/src/Slit.h b/src/Slit.h deleted file mode 100644 index b07d9c6c..00000000 --- a/src/Slit.h +++ /dev/null @@ -1,175 +0,0 @@ -// Slit.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Slit_hh -#define __Slit_hh - -#include -#include - -#include "Basemenu.h" -#include "Geometry.h" -#include - -// forward declaration -class Slit; -class Slitmenu; - -class Slitmenu : public Basemenu { -private: - class Directionmenu : public Basemenu { - private: - Slitmenu &slitmenu; - - protected: - virtual void itemSelected(int, int); - virtual void setValues(); - - public: - Directionmenu(Slitmenu &); - void reconfigure(); - }; - - class Placementmenu : public Basemenu { - private: - Slitmenu &slitmenu; - - protected: - virtual void itemSelected(int, int); - - public: - Placementmenu(Slitmenu &); - }; - - Directionmenu *directionmenu; - Placementmenu *placementmenu; - - Slit &slit; - - friend class Directionmenu; - friend class Placementmenu; - friend class Slit; - - -protected: - virtual void itemSelected(int, int); - virtual void internal_hide(); - virtual void setValues(); - -public: - Slitmenu(Slit &); - virtual ~Slitmenu(); - - inline Basemenu *getDirectionmenu() { return directionmenu; } - inline Basemenu *getPlacementmenu() { return placementmenu; } - - void reconfigure(); -}; - - -class Slit : public TimeoutHandler { -private: - class SlitClient { - public: - Window window, client_window, icon_window; - - int x, y; - unsigned int width, height; - }; - - bool m_ontop, m_autohide, m_hidden; - int m_direction, m_placement; - Display *display; - - Openbox &openbox; - BScreen &screen; - Resource &config; - BTimer *timer; - - typedef std::list slitClientList; - slitClientList clientList; - Slitmenu *slitmenu; - - struct frame { - Pixmap pixmap; - Window window; - - Rect area; - Point hidden; - } frame; - - - friend class Slitmenu; - friend class Slitmenu::Directionmenu; - friend class Slitmenu::Placementmenu; - - -public: - Slit(BScreen &, Resource &); - virtual ~Slit(); - - inline Slitmenu *getMenu() { return slitmenu; } - - inline const Window &getWindowID() const { return frame.window; } - - inline const Point &origin() const { return frame.area.origin(); } - inline const Size &size() const { return frame.area.size(); } - inline const Rect &area() const { return frame.area; } - inline const Point &hiddenOrigin() const { return frame.hidden; } - - void addClient(Window); - void removeClient(SlitClient *, Bool = True); - void removeClient(Window, Bool = True); - void reconfigure(); - void load(); - void save(); - void reposition(); - void shutdown(); - - void buttonPressEvent(XButtonEvent *); - void enterNotifyEvent(XCrossingEvent *); - void leaveNotifyEvent(XCrossingEvent *); - void configureRequestEvent(XConfigureRequestEvent *); - - virtual void timeout(); - - inline bool isHidden() const { return m_hidden; } - - inline bool onTop() const { return m_ontop; } - void setOnTop(bool); - - inline bool autoHide() const { return m_autohide; } - void setAutoHide(bool); - - inline int placement() const { return m_placement; } - void setPlacement(int); - - inline int direction() const { return m_direction; } - void setDirection(int); - - enum { Vertical = 1, Horizontal }; - enum { TopLeft = 1, CenterLeft, BottomLeft, TopCenter, BottomCenter, - TopRight, CenterRight, BottomRight }; -}; - - -#endif // __Slit_hh diff --git a/src/Texture.cc b/src/Texture.cc new file mode 100644 index 00000000..716522f6 --- /dev/null +++ b/src/Texture.cc @@ -0,0 +1,200 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Texture.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif // HAVE_CONFIG_H + +extern "C" { +#include +#ifdef HAVE_CTYPE_H +#include +#endif +} + +#include "Texture.hh" +#include "BaseDisplay.hh" +#include "Image.hh" +#include "Screen.hh" +#include "blackbox.hh" + +using std::string; + + +BTexture::BTexture(const BaseDisplay * const _display, + unsigned int _screen, BImageControl* _ctrl) + : c(_display, _screen), ct(_display, _screen), + lc(_display, _screen), sc(_display, _screen), t(0), + dpy(_display), ctrl(_ctrl), scrn(_screen) { } + + +BTexture::BTexture(const string &d, const BaseDisplay * const _display, + unsigned int _screen, BImageControl* _ctrl) + : c(_display, _screen), ct(_display, _screen), + lc(_display, _screen), sc(_display, _screen), t(0), + dpy(_display), ctrl(_ctrl), scrn(_screen) { + setDescription(d); +} + + +void BTexture::setColor(const BColor &cc) { + c = cc; + c.setDisplay(display(), screen()); + + unsigned char r, g, b, rr, gg, bb; + + // calculate the light color + r = c.red(); + g = c.green(); + b = c.blue(); + rr = r + (r >> 1); + gg = g + (g >> 1); + bb = b + (b >> 1); + if (rr < r) rr = ~0; + if (gg < g) gg = ~0; + if (bb < b) bb = ~0; + lc = BColor(rr, gg, bb, display(), screen()); + + // calculate the shadow color + r = c.red(); + g = c.green(); + b = c.blue(); + rr = (r >> 2) + (r >> 1); + gg = (g >> 2) + (g >> 1); + bb = (b >> 2) + (b >> 1); + if (rr > r) rr = 0; + if (gg > g) gg = 0; + if (bb > b) bb = 0; + sc = BColor(rr, gg, bb, display(), screen()); +} + + +void BTexture::setDescription(const string &d) { + descr.erase(); + descr.reserve(d.length()); + + string::const_iterator it = d.begin(), end = d.end(); + for (; it != end; ++it) + descr += tolower(*it); + + if (descr.find("parentrelative") != string::npos) { + setTexture(BTexture::Parent_Relative); + } else { + setTexture(0); + + if (descr.find("gradient") != string::npos) { + addTexture(BTexture::Gradient); + if (descr.find("crossdiagonal") != string::npos) + addTexture(BTexture::CrossDiagonal); + else if (descr.find("rectangle") != string::npos) + addTexture(BTexture::Rectangle); + else if (descr.find("pyramid") != string::npos) + addTexture(BTexture::Pyramid); + else if (descr.find("pipecross") != string::npos) + addTexture(BTexture::PipeCross); + else if (descr.find("elliptic") != string::npos) + addTexture(BTexture::Elliptic); + else if (descr.find("diagonal") != string::npos) + addTexture(BTexture::Diagonal); + else if (descr.find("horizontal") != string::npos) + addTexture(BTexture::Horizontal); + else if (descr.find("vertical") != string::npos) + addTexture(BTexture::Vertical); + else + addTexture(BTexture::Diagonal); + } else { + addTexture(BTexture::Solid); + } + + if (descr.find("raised") != string::npos) + addTexture(BTexture::Raised); + else if (descr.find("sunken") != string::npos) + addTexture(BTexture::Sunken); + else if (descr.find("flat") != string::npos) + addTexture(BTexture::Flat); + else + addTexture(BTexture::Raised); + + if (! (texture() & BTexture::Flat)) { + if (descr.find("bevel2") != string::npos) + addTexture(BTexture::Bevel2); + else + addTexture(BTexture::Bevel1); + } + + if (descr.find("interlaced") != string::npos) + addTexture(BTexture::Interlaced); + } +} + +void BTexture::setDisplay(const BaseDisplay * const _display, + const unsigned int _screen) { + if (_display == display() && _screen == screen()) { + // nothing to do + return; + } + + dpy = _display; + scrn = _screen; + c.setDisplay(_display, _screen); + ct.setDisplay(_display, _screen); + lc.setDisplay(_display, _screen); + sc.setDisplay(_display, _screen); +} + + +BTexture& BTexture::operator=(const BTexture &tt) { + c = tt.c; + ct = tt.ct; + lc = tt.lc; + sc = tt.sc; + descr = tt.descr; + t = tt.t; + dpy = tt.dpy; + scrn = tt.scrn; + ctrl = tt.ctrl; + + return *this; +} + + +Pixmap BTexture::render(const unsigned int width, const unsigned int height, + const Pixmap old) { + assert(display() != 0); + + if (texture() == (BTexture::Flat | BTexture::Solid)) + return None; + if (texture() == BTexture::Parent_Relative) + return ParentRelative; + + if (screen() == ~(0u)) + scrn = DefaultScreen(display()->getXDisplay()); + + assert(ctrl != 0); + Pixmap ret = ctrl->renderImage(width, height, *this); + + if (old) + ctrl->removeImage(old); + + return ret; +} diff --git a/src/Texture.hh b/src/Texture.hh new file mode 100644 index 00000000..1eed2c42 --- /dev/null +++ b/src/Texture.hh @@ -0,0 +1,108 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Texture.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef TEXTURE_HH +#define TEXTURE_HH + +#include "Color.hh" +#include "Util.hh" +class BImageControl; + +#include + +class BTexture { +public: + enum Type { + // bevel options + Flat = (1l<<0), + Sunken = (1l<<1), + Raised = (1l<<2), + // textures + Solid = (1l<<3), + Gradient = (1l<<4), + // gradients + Horizontal = (1l<<5), + Vertical = (1l<<6), + Diagonal = (1l<<7), + CrossDiagonal = (1l<<8), + Rectangle = (1l<<9), + Pyramid = (1l<<10), + PipeCross = (1l<<11), + Elliptic = (1l<<12), + // bevel types + Bevel1 = (1l<<13), + Bevel2 = (1l<<14), + // inverted image + Invert = (1l<<15), + // parent relative image + Parent_Relative = (1l<<16), + // fake interlaced image + Interlaced = (1l<<17) + }; + + BTexture(const BaseDisplay * const _display = 0, + unsigned int _screen = ~(0u), BImageControl* _ctrl = 0); + BTexture(const std::string &_description, + const BaseDisplay * const _display = 0, + unsigned int _screen = ~(0u), BImageControl* _ctrl = 0); + + void setColor(const BColor &_color); + void setColorTo(const BColor &_colorTo) { ct = _colorTo; } + + const BColor &color(void) const { return c; } + const BColor &colorTo(void) const { return ct; } + const BColor &lightColor(void) const { return lc; } + const BColor &shadowColor(void) const { return sc; } + + unsigned long texture(void) const { return t; } + void setTexture(const unsigned long _texture) { t = _texture; } + void addTexture(const unsigned long _texture) { t |= _texture; } + + BTexture &operator=(const BTexture &tt); + inline bool operator==(const BTexture &tt) + { return (c == tt.c && ct == tt.ct && lc == tt.lc && + sc == tt.sc && t == tt.t); } + inline bool operator!=(const BTexture &tt) + { return (! operator==(tt)); } + + const BaseDisplay *display(void) const { return dpy; } + unsigned int screen(void) const { return scrn; } + void setDisplay(const BaseDisplay * const _display, + const unsigned int _screen); + void setImageControl(BImageControl* _ctrl) { ctrl = _ctrl; } + const std::string &description(void) const { return descr; } + void setDescription(const std::string &d); + + Pixmap render(const unsigned int width, const unsigned int height, + const Pixmap old = 0); + +private: + BColor c, ct, lc, sc; + std::string descr; + unsigned long t; + const BaseDisplay *dpy; + BImageControl *ctrl; + unsigned int scrn; +}; + +#endif // TEXTURE_HH diff --git a/src/Timer.cc b/src/Timer.cc index 8cd4714e..443a7c46 100644 --- a/src/Timer.cc +++ b/src/Timer.cc @@ -1,5 +1,6 @@ -// Timer.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Timer.cc for Blackbox - An X11 Window Manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,60 +21,91 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "BaseDisplay.h" -#include "Timer.h" +#include "BaseDisplay.hh" +#include "Timer.hh" +#include "Util.hh" + +BTimer::BTimer(TimerQueueManager *m, TimeoutHandler *h) { + manager = m; + handler = h; -BTimer::BTimer(BaseDisplay &d, TimeoutHandler &h) : display(d), handler(h) { - once = timing = False; + recur = timing = False; } + BTimer::~BTimer(void) { if (timing) stop(); } + void BTimer::setTimeout(long t) { _timeout.tv_sec = t / 1000; - _timeout.tv_usec = t; - _timeout.tv_usec -= (_timeout.tv_sec * 1000); + _timeout.tv_usec = t % 1000; _timeout.tv_usec *= 1000; - if (timing) { - display.removeTimer(this); - display.addTimer(this); // reorder the display - } } -void BTimer::setTimeout(timeval t) { + +void BTimer::setTimeout(const timeval &t) { _timeout.tv_sec = t.tv_sec; _timeout.tv_usec = t.tv_usec; } + void BTimer::start(void) { gettimeofday(&_start, 0); if (! timing) { timing = True; - display.addTimer(this); + manager->addTimer(this); } } + void BTimer::stop(void) { - if (timing) { - timing = False; + timing = False; - display.removeTimer(this); - } + manager->removeTimer(this); } + +void BTimer::halt(void) { + timing = False; +} + + void BTimer::fireTimeout(void) { - handler.timeout(); + if (handler) + handler->timeout(); +} + + +timeval BTimer::timeRemaining(const timeval &tm) const { + timeval ret = endpoint(); + + ret.tv_sec -= tm.tv_sec; + ret.tv_usec -= tm.tv_usec; + + return normalizeTimeval(ret); +} + + +timeval BTimer::endpoint(void) const { + timeval ret; + + ret.tv_sec = _start.tv_sec + _timeout.tv_sec; + ret.tv_usec = _start.tv_usec + _timeout.tv_usec; + + return normalizeTimeval(ret); +} + + +bool BTimer::shouldFire(const timeval &tm) const { + timeval end = endpoint(); + + return !((tm.tv_sec < end.tv_sec) || + (tm.tv_sec == end.tv_sec && tm.tv_usec < end.tv_usec)); } diff --git a/src/Timer.h b/src/Timer.h deleted file mode 100644 index c132b4f2..00000000 --- a/src/Timer.h +++ /dev/null @@ -1,78 +0,0 @@ -// Timer.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Timer_hh -#define __Timer_hh - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else // !TIME_WITH_SYS_TIME -# ifdef HAVE_SYS_TIME_H -# include -# else // !HAVE_SYS_TIME_H -# include -# endif // HAVE_SYS_TIME_H -#endif // TIME_WITH_SYS_TIME - -// forward declaration -class BTimer; -class TimeoutHandler; -class BaseDisplay; - -class TimeoutHandler { -public: - virtual void timeout(void) = 0; -}; - -class BTimer { - friend class BaseDisplay; -private: - BaseDisplay &display; - TimeoutHandler &handler; - int timing, once; - - timeval _start, _timeout; - -protected: - void fireTimeout(void); - -public: - BTimer(BaseDisplay &, TimeoutHandler &); - virtual ~BTimer(void); - - inline const int &isTiming(void) const { return timing; } - inline const int &doOnce(void) const { return once; } - - inline const timeval &getTimeout(void) const { return _timeout; } - inline const timeval &getStartTime(void) const { return _start; } - - inline void fireOnce(int o) { once = o; } - - void setTimeout(long); - void setTimeout(timeval); - void start(void); - void stop(void); -}; - -#endif // __Timer_hh - diff --git a/src/Timer.hh b/src/Timer.hh new file mode 100644 index 00000000..a4b04010 --- /dev/null +++ b/src/Timer.hh @@ -0,0 +1,131 @@ +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Timer.hh for Blackbox - An X11 Window Manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef _BLACKBOX_Timer_hh +#define _BLACKBOX_Timer_hh + +extern "C" { +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else // !TIME_WITH_SYS_TIME +# ifdef HAVE_SYS_TIME_H +# include +# else // !HAVE_SYS_TIME_H +# include +# endif // HAVE_SYS_TIME_H +#endif // TIME_WITH_SYS_TIME +} + +// forward declaration +class TimerQueueManager; + +class TimeoutHandler { +public: + virtual void timeout(void) = 0; +}; + +class BTimer { +private: + TimerQueueManager *manager; + TimeoutHandler *handler; + bool timing, recur; + + timeval _start, _timeout; + + BTimer(const BTimer&); + BTimer& operator=(const BTimer&); + +public: + BTimer(TimerQueueManager *m, TimeoutHandler *h); + virtual ~BTimer(void); + + void fireTimeout(void); + + inline bool isTiming(void) const { return timing; } + inline bool isRecurring(void) const { return recur; } + + inline const timeval &getTimeout(void) const { return _timeout; } + inline const timeval &getStartTime(void) const { return _start; } + + timeval timeRemaining(const timeval &tm) const; + bool shouldFire(const timeval &tm) const; + timeval endpoint(void) const; + + inline void recurring(bool b) { recur = b; } + + void setTimeout(long t); + void setTimeout(const timeval &t); + + void start(void); // manager acquires timer + void stop(void); // manager releases timer + void halt(void); // halts the timer + + bool operator<(const BTimer& other) const + { return shouldFire(other.endpoint()); } +}; + + +#include +#include + +template +class _timer_queue: protected std::priority_queue<_Tp, _Sequence, _Compare> { +public: + typedef std::priority_queue<_Tp, _Sequence, _Compare> _Base; + + _timer_queue(void): _Base() {} + ~_timer_queue(void) {} + + void release(const _Tp& value) { + c.erase(std::remove(c.begin(), c.end(), value), c.end()); + // after removing the item we need to make the heap again + std::make_heap(c.begin(), c.end(), comp); + } + bool empty(void) const { return _Base::empty(); } + size_t size(void) const { return _Base::size(); } + void push(const _Tp& value) { _Base::push(value); } + void pop(void) { _Base::pop(); } + const _Tp& top(void) const { return _Base::top(); } +private: + // no copying! + _timer_queue(const _timer_queue&) {} + _timer_queue& operator=(const _timer_queue&) {} +}; + +struct TimerLessThan { + bool operator()(const BTimer* const l, const BTimer* const r) const { + return *r < *l; + } +}; + +#include +typedef _timer_queue, TimerLessThan> TimerQueue; + +class TimerQueueManager { +public: + virtual void addTimer(BTimer* timer) = 0; + virtual void removeTimer(BTimer* timer) = 0; +}; + +#endif // _BLACKBOX_Timer_hh diff --git a/src/Toolbar.cc b/src/Toolbar.cc index b0f9d230..a51f949c 100644 --- a/src/Toolbar.cc +++ b/src/Toolbar.cc @@ -1,5 +1,6 @@ -// Toolbar.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Toolbar.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,30 +21,14 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "i18n.h" -#include "openbox.h" -#include "Clientmenu.h" -#include "Iconmenu.h" -#include "Rootmenu.h" -#include "Screen.h" -#include "Toolbar.h" -#include "Window.h" -#include "Workspace.h" -#include "Workspacemenu.h" - +extern "C" { #include -#ifdef HAVE_STRING_H +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H @@ -61,145 +46,143 @@ # include # endif // HAVE_SYS_TIME_H #endif // TIME_WITH_SYS_TIME +} -#include #include -using std::ends; +using std::string; + +#include "i18n.hh" +#include "blackbox.hh" +#include "Clientmenu.hh" +#include "GCCache.hh" +#include "Iconmenu.hh" +#include "Image.hh" +#include "Rootmenu.hh" +#include "Screen.hh" +#include "Toolbar.hh" +#include "Window.hh" +#include "Workspace.hh" +#include "Workspacemenu.hh" +#include "Slit.hh" + + +static long aMinuteFromNow(void) { + timeval now; + gettimeofday(&now, 0); + return ((60 - (now.tv_sec % 60)) * 1000); +} + -Toolbar::Toolbar(BScreen &scrn, Resource &conf) : openbox(scrn.getOpenbox()), -screen(scrn), config(conf) -{ - load(); +Toolbar::Toolbar(BScreen *scrn) { + screen = scrn; + blackbox = screen->getBlackbox(); // get the clock updating every minute - clock_timer = new BTimer(openbox, *this); - timeval now; - gettimeofday(&now, 0); - clock_timer->setTimeout((60 - (now.tv_sec % 60)) * 1000); + clock_timer = new BTimer(blackbox, this); + clock_timer->setTimeout(aMinuteFromNow()); + clock_timer->recurring(True); clock_timer->start(); + frame.minute = frame.hour = -1; hide_handler.toolbar = this; - hide_timer = new BTimer(openbox, hide_handler); - // the time out is set in ::reconfigure() - hide_timer->fireOnce(True); + hide_timer = new BTimer(blackbox, &hide_handler); + hide_timer->setTimeout(blackbox->getAutoRaiseDelay()); - image_ctrl = screen.getImageControl(); + on_top = screen->isToolbarOnTop(); + hidden = do_auto_hide = screen->doToolbarAutoHide(); - m_editing = False; - new_workspace_name = (char *) 0; + editing = False; new_name_pos = 0; frame.grab_x = frame.grab_y = 0; - toolbarmenu = new Toolbarmenu(*this); + toolbarmenu = new Toolbarmenu(this); - display = openbox.getXDisplay(); + display = blackbox->getXDisplay(); XSetWindowAttributes attrib; unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel | - CWColormap | CWOverrideRedirect | CWEventMask; + CWColormap | CWOverrideRedirect | CWEventMask; attrib.background_pixmap = None; attrib.background_pixel = attrib.border_pixel = - screen.getBorderColor()->getPixel(); - attrib.colormap = screen.getColormap(); + screen->getBorderColor()->pixel(); + attrib.colormap = screen->getColormap(); attrib.override_redirect = True; attrib.event_mask = ButtonPressMask | ButtonReleaseMask | - EnterWindowMask | LeaveWindowMask; + EnterWindowMask | LeaveWindowMask; frame.window = - XCreateWindow(display, screen.getRootWindow(), 0, 0, 1, 1, 0, - screen.getDepth(), InputOutput, screen.getVisual(), + XCreateWindow(display, screen->getRootWindow(), 0, 0, 1, 1, 0, + screen->getDepth(), InputOutput, screen->getVisual(), create_mask, &attrib); - openbox.saveToolbarSearch(frame.window, this); + blackbox->saveToolbarSearch(frame.window, this); attrib.event_mask = ButtonPressMask | ButtonReleaseMask | ExposureMask | - KeyPressMask | EnterWindowMask; + KeyPressMask | EnterWindowMask; frame.workspace_label = - XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(), - InputOutput, screen.getVisual(), create_mask, &attrib); - openbox.saveToolbarSearch(frame.workspace_label, this); + XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(), + InputOutput, screen->getVisual(), create_mask, &attrib); + blackbox->saveToolbarSearch(frame.workspace_label, this); frame.window_label = - XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(), - InputOutput, screen.getVisual(), create_mask, &attrib); - openbox.saveToolbarSearch(frame.window_label, this); + XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(), + InputOutput, screen->getVisual(), create_mask, &attrib); + blackbox->saveToolbarSearch(frame.window_label, this); frame.clock = - XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen.getDepth(), - InputOutput, screen.getVisual(), create_mask, &attrib); - openbox.saveToolbarSearch(frame.clock, this); + XCreateWindow(display, frame.window, 0, 0, 1, 1, 0, screen->getDepth(), + InputOutput, screen->getVisual(), create_mask, &attrib); + blackbox->saveToolbarSearch(frame.clock, this); frame.psbutton = - XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(), - InputOutput, screen.getVisual(), create_mask, &attrib); - openbox.saveToolbarSearch(frame.psbutton, this); + XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(), + InputOutput, screen->getVisual(), create_mask, &attrib); + blackbox->saveToolbarSearch(frame.psbutton, this); frame.nsbutton = - XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(), - InputOutput, screen.getVisual(), create_mask, &attrib); - openbox.saveToolbarSearch(frame.nsbutton, this); + XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(), + InputOutput, screen->getVisual(), create_mask, &attrib); + blackbox->saveToolbarSearch(frame.nsbutton, this); frame.pwbutton = - XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(), - InputOutput, screen.getVisual(), create_mask, &attrib); - openbox.saveToolbarSearch(frame.pwbutton, this); + XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(), + InputOutput, screen->getVisual(), create_mask, &attrib); + blackbox->saveToolbarSearch(frame.pwbutton, this); frame.nwbutton = - XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen.getDepth(), - InputOutput, screen.getVisual(), create_mask, &attrib); - openbox.saveToolbarSearch(frame.nwbutton, this); + XCreateWindow(display ,frame.window, 0, 0, 1, 1, 0, screen->getDepth(), + InputOutput, screen->getVisual(), create_mask, &attrib); + blackbox->saveToolbarSearch(frame.nwbutton, this); frame.base = frame.label = frame.wlabel = frame.clk = frame.button = frame.pbutton = None; - reconfigure(); - mapToolbar(); -} + screen->addStrut(&strut); -Rect Toolbar::area() const { - int x = ((m_hidden) ? frame.x_hidden : frame.x); - int y; - if (screen.hideToolbar()) y = screen.size().h(); - else if (m_hidden) y = frame.y_hidden; - else y = frame.y; - return Rect(x, y, frame.width, frame.height); -} + reconfigure(); -unsigned int Toolbar::getExposedHeight() const { - if (screen.hideToolbar()) return 0; - else if (m_autohide) return frame.bevel_w; - else return frame.height; + XMapSubwindows(display, frame.window); + XMapWindow(display, frame.window); } -void Toolbar::mapToolbar(){ - if (!screen.hideToolbar()) { - //not hidden, so windows should not maximize over the toolbar - XMapSubwindows(display, frame.window); - XMapWindow(display, frame.window); - } -} -void Toolbar::unMapToolbar(){ - //hidden so we can maximize over the toolbar +Toolbar::~Toolbar(void) { XUnmapWindow(display, frame.window); -} -Toolbar::~Toolbar() { - unMapToolbar(); - if (frame.base) image_ctrl->removeImage(frame.base); - if (frame.label) image_ctrl->removeImage(frame.label); - if (frame.wlabel) image_ctrl->removeImage(frame.wlabel); - if (frame.clk) image_ctrl->removeImage(frame.clk); - if (frame.button) image_ctrl->removeImage(frame.button); - if (frame.pbutton) image_ctrl->removeImage(frame.pbutton); - - openbox.removeToolbarSearch(frame.window); - openbox.removeToolbarSearch(frame.workspace_label); - openbox.removeToolbarSearch(frame.window_label); - openbox.removeToolbarSearch(frame.clock); - openbox.removeToolbarSearch(frame.psbutton); - openbox.removeToolbarSearch(frame.nsbutton); - openbox.removeToolbarSearch(frame.pwbutton); - openbox.removeToolbarSearch(frame.nwbutton); + if (frame.base) screen->getImageControl()->removeImage(frame.base); + if (frame.label) screen->getImageControl()->removeImage(frame.label); + if (frame.wlabel) screen->getImageControl()->removeImage(frame.wlabel); + if (frame.clk) screen->getImageControl()->removeImage(frame.clk); + if (frame.button) screen->getImageControl()->removeImage(frame.button); + if (frame.pbutton) screen->getImageControl()->removeImage(frame.pbutton); + + blackbox->removeToolbarSearch(frame.window); + blackbox->removeToolbarSearch(frame.workspace_label); + blackbox->removeToolbarSearch(frame.window_label); + blackbox->removeToolbarSearch(frame.clock); + blackbox->removeToolbarSearch(frame.psbutton); + blackbox->removeToolbarSearch(frame.nsbutton); + blackbox->removeToolbarSearch(frame.pwbutton); + blackbox->removeToolbarSearch(frame.nwbutton); XDestroyWindow(display, frame.workspace_label); XDestroyWindow(display, frame.window_label); @@ -213,1182 +196,939 @@ Toolbar::~Toolbar() { } -void Toolbar::setOnTop(bool b) { - m_ontop = b; - std::ostrstream s; - s << "session.screen" << screen.getScreenNumber() << ".toolbar.onTop" << ends; - config.setValue(s.str(), m_ontop ? "True" : "False"); - s.rdbuf()->freeze(0); -} - -void Toolbar::setAutoHide(bool b) { - m_autohide = b; - std::ostrstream s; - s << "session.screen" << screen.getScreenNumber() << ".toolbar.autoHide" - << ends; - config.setValue(s.str(), m_autohide ? "True" : "False"); - s.rdbuf()->freeze(0); -} +void Toolbar::reconfigure(void) { + unsigned int height = 0, + width = (screen->getWidth() * screen->getToolbarWidthPercent()) / 100; -void Toolbar::setWidthPercent(int w) { - m_width_percent = w; - std::ostrstream s; - s << "session.screen" << screen.getScreenNumber() << ".toolbar.widthPercent" - << ends; - config.setValue(s.str(), m_width_percent); - s.rdbuf()->freeze(0); -} - -void Toolbar::setPlacement(int p) { - m_placement = p; - std::ostrstream s; - s << "session.screen" << screen.getScreenNumber() << ".toolbar.placement" - << ends; - const char *placement; - switch (m_placement) { - case TopLeft: placement = "TopLeft"; break; - case BottomLeft: placement = "BottomLeft"; break; - case TopCenter: placement = "TopCenter"; break; - case TopRight: placement = "TopRight"; break; - case BottomRight: placement = "BottomRight"; break; - case BottomCenter: default: placement = "BottomCenter"; break; - } - config.setValue(s.str(), placement); - s.rdbuf()->freeze(0); -} - -void Toolbar::save() { - setOnTop(m_ontop); - setAutoHide(m_autohide); - setWidthPercent(m_width_percent); - setPlacement(m_placement); -} - -void Toolbar::load() { - std::ostrstream rscreen, rname, rclass; - std::string s; - bool b; - long l; - rscreen << "session.screen" << screen.getScreenNumber() << '.' << ends; - - rname << rscreen.str() << "toolbar.widthPercent" << ends; - rclass << rscreen.str() << "Toolbar.WidthPercent" << ends; - if (config.getValue(rname.str(), rclass.str(), l) && (l > 0 && l <= 100)) - m_width_percent = l; - else - m_width_percent =66; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "toolbar.placement" << ends; - rclass << rscreen.str() << "Toolbar.Placement" << ends; - if (config.getValue(rname.str(), rclass.str(), s)) { - if (0 == strncasecmp(s.c_str(), "TopLeft", s.length())) - m_placement = TopLeft; - else if (0 == strncasecmp(s.c_str(), "BottomLeft", s.length())) - m_placement = BottomLeft; - else if (0 == strncasecmp(s.c_str(), "TopCenter", s.length())) - m_placement = TopCenter; - else if (0 == strncasecmp(s.c_str(), "TopRight", s.length())) - m_placement = TopRight; - else if ( 0 == strncasecmp(s.c_str(), "BottomRight", s.length())) - m_placement = BottomRight; - else if ( 0 == strncasecmp(s.c_str(), "BottomCenter", s.length())) - m_placement = BottomCenter; - } else - m_placement = BottomCenter; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "toolbar.onTop" << ends; - rclass << rscreen.str() << "Toolbar.OnTop" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - m_ontop = b; - else - m_ontop = false; - - rname.seekp(0); rclass.seekp(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); - rname << rscreen.str() << "toolbar.autoHide" << ends; - rclass << rscreen.str() << "Toolbar.AutoHide" << ends; - if (config.getValue(rname.str(), rclass.str(), b)) - m_hidden = m_autohide = b; + if (i18n.multibyte()) + height = screen->getToolbarStyle()->fontset_extents->max_ink_extent.height; else - m_hidden = m_autohide = false; - - rscreen.rdbuf()->freeze(0); - rname.rdbuf()->freeze(0); rclass.rdbuf()->freeze(0); -} + height = screen->getToolbarStyle()->font->ascent + + screen->getToolbarStyle()->font->descent; -void Toolbar::reconfigure() { - hide_timer->setTimeout(openbox.getAutoRaiseDelay()); + frame.bevel_w = screen->getBevelWidth(); + frame.button_w = height; + height += 2; + frame.label_h = height; + height += (frame.bevel_w * 2); - frame.bevel_w = screen.getBevelWidth(); - frame.width = screen.size().w() * m_width_percent / 100; + frame.rect.setSize(width, height); - if (i18n.multibyte()) - frame.height = - screen.getToolbarStyle()->fontset_extents->max_ink_extent.height; - else - frame.height = screen.getToolbarStyle()->font->ascent + - screen.getToolbarStyle()->font->descent; - frame.button_w = frame.height; - frame.height += 2; - frame.label_h = frame.height; - frame.height += (frame.bevel_w * 2); - - switch (m_placement) { + int x, y; + switch (screen->getToolbarPlacement()) { case TopLeft: - frame.x = 0; - frame.y = 0; - frame.x_hidden = 0; - frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth() - - frame.height; - break; + case TopRight: + case TopCenter: + if (screen->getToolbarPlacement() == TopLeft) + x = 0; + else if (screen->getToolbarPlacement() == TopRight) + x = screen->getWidth() - frame.rect.width() + - (screen->getBorderWidth() * 2); + else + x = (screen->getWidth() - frame.rect.width()) / 2; - case BottomLeft: - frame.x = 0; - frame.y = screen.size().h() - frame.height - - (screen.getBorderWidth() * 2); - frame.x_hidden = 0; - frame.y_hidden = screen.size().h() - screen.getBevelWidth() - - screen.getBorderWidth(); - break; + y = 0; - case TopCenter: - frame.x = (screen.size().w() - frame.width) / 2; - frame.y = 0; - frame.x_hidden = frame.x; - frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth() - - frame.height; + frame.x_hidden = x; + frame.y_hidden = screen->getBevelWidth() - screen->getBorderWidth() + - frame.rect.height(); break; + case BottomLeft: + case BottomRight: case BottomCenter: default: - frame.x = (screen.size().w() - frame.width) / 2; - frame.y = screen.size().h() - frame.height - - (screen.getBorderWidth() * 2); - frame.x_hidden = frame.x; - frame.y_hidden = screen.size().h() - screen.getBevelWidth() - - screen.getBorderWidth(); - break; + if (screen->getToolbarPlacement() == BottomLeft) + x = 0; + else if (screen->getToolbarPlacement() == BottomRight) + x = screen->getWidth() - frame.rect.width() + - (screen->getBorderWidth() * 2); + else + x = (screen->getWidth() - frame.rect.width()) / 2; - case TopRight: - frame.x = screen.size().w() - frame.width - - (screen.getBorderWidth() * 2); - frame.y = 0; - frame.x_hidden = frame.x; - frame.y_hidden = screen.getBevelWidth() - screen.getBorderWidth() - - frame.height; - break; + y = screen->getHeight() - frame.rect.height() + - (screen->getBorderWidth() * 2); - case BottomRight: - frame.x = screen.size().w() - frame.width - - (screen.getBorderWidth() * 2); - frame.y = screen.size().h() - frame.height - - (screen.getBorderWidth() * 2); - frame.x_hidden = frame.x; - frame.y_hidden = screen.size().h() - screen.getBevelWidth() - - screen.getBorderWidth(); + frame.x_hidden = x; + frame.y_hidden = screen->getHeight() - screen->getBevelWidth() + - screen->getBorderWidth(); break; } + frame.rect.setPos(x, y); + + updateStrut(); + #ifdef HAVE_STRFTIME time_t ttmp = time(NULL); - struct tm *tt = 0; + frame.clock_w = 0; if (ttmp != -1) { - tt = localtime(&ttmp); + struct tm *tt = localtime(&ttmp); if (tt) { - char t[1025], *time_string = (char *) 0; - int len = strftime(t, 1024, screen.strftimeFormat(), tt); - t[len++] = 'A'; // add size to the string for padding - t[len++] = 'A'; // add size to the string for padding - t[len] = '\0'; - + char t[1024]; + int len = strftime(t, 1024, screen->getStrftimeFormat(), tt); + if (len == 0) { // invalid time format found + screen->saveStrftimeFormat("%I:%M %p"); // so use the default + len = strftime(t, 1024, screen->getStrftimeFormat(), tt); + } + // find the length of the rendered string and add room for two extra + // characters to it. This allows for variable width output of the fonts if (i18n.multibyte()) { XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, t, len, &ink, - &logical); - frame.clock_w = logical.width; - - // ben's additional solution to pad some space beside the numbers - //frame.clock_w += - // screen.getToolbarStyle()->fontset_extents->max_logical_extent.width * - // 4; - - // brad's solution, which is currently buggy, too big - //frame.clock_w = - // screen.getToolbarStyle()->fontset_extents->max_logical_extent.width - // * len; + XmbTextExtents(screen->getToolbarStyle()->fontset, t, len, + &ink, &logical); + XFontSetExtents* extents = screen->getToolbarStyle()->fontset_extents; + frame.clock_w = logical.width + + (extents->max_logical_extent.width * 2); } else { - frame.clock_w = XTextWidth(screen.getToolbarStyle()->font, t, len); - // ben's additional solution to pad some space beside the numbers - //frame.clock_w += screen.getToolbarStyle()->font->max_bounds.width * 4; - // brad's solution again, too big - //frame.clock_w = screen.getToolbarStyle()->font->max_bounds.width * len; + XFontStruct* font = screen->getToolbarStyle()->font; + frame.clock_w = XTextWidth(font, t, len) + + ((font->max_bounds.rbearing - font->min_bounds.lbearing) * 2); } - frame.clock_w += (frame.bevel_w * 4); - - delete [] time_string; - } else { - frame.clock_w = 0; } - } else { - frame.clock_w = 0; } #else // !HAVE_STRFTIME frame.clock_w = - XTextWidth(screen.getToolbarStyle()->font, - i18n(ToolbarSet, ToolbarNoStrftimeLength, - "00:00000"), + XTextWidth(screen->getToolbarStyle()->font, + i18n(ToolbarSet, ToolbarNoStrftimeLength, "00:00000"), strlen(i18n(ToolbarSet, ToolbarNoStrftimeLength, - "00:00000"))) + (frame.bevel_w * 4); + "00:00000"))); #endif // HAVE_STRFTIME - int i; - unsigned int w = 0; - frame.workspace_label_w = 0; - - for (i = 0; i < screen.getWorkspaceCount(); i++) { - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, - screen.getWorkspace(i)->getName(), - strlen(screen.getWorkspace(i)->getName()), - &ink, &logical); - w = logical.width; - } else { - w = XTextWidth(screen.getToolbarStyle()->font, - screen.getWorkspace(i)->getName(), - strlen(screen.getWorkspace(i)->getName())); - } - w += (frame.bevel_w * 4); - - if (w > frame.workspace_label_w) frame.workspace_label_w = w; - } - - if (frame.workspace_label_w < frame.clock_w) - frame.workspace_label_w = frame.clock_w; - else if (frame.workspace_label_w > frame.clock_w) - frame.clock_w = frame.workspace_label_w; - - frame.window_label_w = - (frame.width - (frame.clock_w + (frame.button_w * 4) + - frame.workspace_label_w + (frame.bevel_w * 8) + 6)); - - if (m_hidden) { - XMoveResizeWindow(display, frame.window, frame.x_hidden, frame.y_hidden, - frame.width, frame.height); - } else { - XMoveResizeWindow(display, frame.window, frame.x, frame.y, - frame.width, frame.height); - } - - XMoveResizeWindow(display, frame.workspace_label, frame.bevel_w, - frame.bevel_w, frame.workspace_label_w, - frame.label_h); - XMoveResizeWindow(display, frame.psbutton, (frame.bevel_w * 2) + - frame.workspace_label_w + 1, frame.bevel_w + 1, - frame.button_w, frame.button_w); - XMoveResizeWindow(display ,frame.nsbutton, (frame.bevel_w * 3) + - frame.workspace_label_w + frame.button_w + 2, - frame.bevel_w + 1, frame.button_w, frame.button_w); - XMoveResizeWindow(display, frame.window_label, (frame.bevel_w * 4) + - (frame.button_w * 2) + frame.workspace_label_w + 3, - frame.bevel_w, frame.window_label_w, frame.label_h); - XMoveResizeWindow(display, frame.pwbutton, (frame.bevel_w * 5) + - (frame.button_w * 2) + frame.workspace_label_w + - frame.window_label_w + 4, frame.bevel_w + 1, - frame.button_w, frame.button_w); - XMoveResizeWindow(display, frame.nwbutton, (frame.bevel_w * 6) + - (frame.button_w * 3) + frame.workspace_label_w + - frame.window_label_w + 5, frame.bevel_w + 1, - frame.button_w, frame.button_w); - XMoveResizeWindow(display, frame.clock, frame.width - frame.clock_w - - frame.bevel_w, frame.bevel_w, frame.clock_w, - frame.label_h); - - Pixmap tmp = frame.base; - BTexture *texture = &(screen.getToolbarStyle()->toolbar); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.base = None; - XSetWindowBackground(display, frame.window, - texture->getColor()->getPixel()); - } else { - frame.base = - image_ctrl->renderImage(frame.width, frame.height, texture); - XSetWindowBackgroundPixmap(display, frame.window, frame.base); - } - if (tmp) image_ctrl->removeImage(tmp); - - tmp = frame.label; - texture = &(screen.getToolbarStyle()->window); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.label = None; - XSetWindowBackground(display, frame.window_label, - texture->getColor()->getPixel()); - } else { - frame.label = - image_ctrl->renderImage(frame.window_label_w, frame.label_h, texture); - XSetWindowBackgroundPixmap(display, frame.window_label, frame.label); - } - if (tmp) image_ctrl->removeImage(tmp); - - tmp = frame.wlabel; - texture = &(screen.getToolbarStyle()->label); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.wlabel = None; - XSetWindowBackground(display, frame.workspace_label, - texture->getColor()->getPixel()); - } else { - frame.wlabel = - image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture); - XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel); - } - if (tmp) image_ctrl->removeImage(tmp); - - tmp = frame.clk; - texture = &(screen.getToolbarStyle()->clock); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.clk = None; - XSetWindowBackground(display, frame.clock, - texture->getColor()->getPixel()); - } else { - frame.clk = - image_ctrl->renderImage(frame.clock_w, frame.label_h, texture); - XSetWindowBackgroundPixmap(display, frame.clock, frame.clk); - } - if (tmp) image_ctrl->removeImage(tmp); - - tmp = frame.button; - texture = &(screen.getToolbarStyle()->button); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.button = None; - - frame.button_pixel = texture->getColor()->getPixel(); - XSetWindowBackground(display, frame.psbutton, frame.button_pixel); - XSetWindowBackground(display, frame.nsbutton, frame.button_pixel); - XSetWindowBackground(display, frame.pwbutton, frame.button_pixel); - XSetWindowBackground(display, frame.nwbutton, frame.button_pixel); - } else { - frame.button = - image_ctrl->renderImage(frame.button_w, frame.button_w, texture); - - XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button); - XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button); - XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button); - XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button); - } - if (tmp) image_ctrl->removeImage(tmp); - - tmp = frame.pbutton; - texture = &(screen.getToolbarStyle()->pressed); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.pbutton = None; - frame.pbutton_pixel = texture->getColor()->getPixel(); - } else { - frame.pbutton = - image_ctrl->renderImage(frame.button_w, frame.button_w, texture); - } - if (tmp) image_ctrl->removeImage(tmp); - - XSetWindowBorder(display, frame.window, - screen.getBorderColor()->getPixel()); - XSetWindowBorderWidth(display, frame.window, screen.getBorderWidth()); - - XClearWindow(display, frame.window); - XClearWindow(display, frame.workspace_label); - XClearWindow(display, frame.window_label); - XClearWindow(display, frame.clock); - XClearWindow(display, frame.psbutton); - XClearWindow(display, frame.nsbutton); - XClearWindow(display, frame.pwbutton); - XClearWindow(display, frame.nwbutton); - - redrawWindowLabel(); - redrawWorkspaceLabel(); - redrawPrevWorkspaceButton(); - redrawNextWorkspaceButton(); - redrawPrevWindowButton(); - redrawNextWindowButton(); - checkClock(True); - - toolbarmenu->reconfigure(); + frame.workspace_label_w = 0; + + for (unsigned int i = 0; i < screen->getWorkspaceCount(); i++) { + const string& workspace_name = screen->getWorkspace(i)->getName(); + if (i18n.multibyte()) { + XRectangle ink, logical; + XmbTextExtents(screen->getToolbarStyle()->fontset, + workspace_name.c_str(), workspace_name.length(), + &ink, &logical); + width = logical.width; + } else { + width = XTextWidth(screen->getToolbarStyle()->font, + workspace_name.c_str(), workspace_name.length()); + } + + if (width > frame.workspace_label_w) frame.workspace_label_w = width; + } + + frame.workspace_label_w = frame.clock_w = + std::max(frame.workspace_label_w, frame.clock_w) + (frame.bevel_w * 4); + + // XXX: where'd the +6 come from? + frame.window_label_w = + (frame.rect.width() - (frame.clock_w + (frame.button_w * 4) + + frame.workspace_label_w + (frame.bevel_w * 8) + 6)); + + if (hidden) { + XMoveResizeWindow(display, frame.window, frame.x_hidden, frame.y_hidden, + frame.rect.width(), frame.rect.height()); + } else { + XMoveResizeWindow(display, frame.window, frame.rect.x(), frame.rect.y(), + frame.rect.width(), frame.rect.height()); + } + + XMoveResizeWindow(display, frame.workspace_label, frame.bevel_w, + frame.bevel_w, frame.workspace_label_w, + frame.label_h); + XMoveResizeWindow(display, frame.psbutton, + ((frame.bevel_w * 2) + frame.workspace_label_w + 1), + frame.bevel_w + 1, frame.button_w, frame.button_w); + XMoveResizeWindow(display, frame.nsbutton, + ((frame.bevel_w * 3) + frame.workspace_label_w + + frame.button_w + 2), frame.bevel_w + 1, frame.button_w, + frame.button_w); + XMoveResizeWindow(display, frame.window_label, + ((frame.bevel_w * 4) + (frame.button_w * 2) + + frame.workspace_label_w + 3), frame.bevel_w, + frame.window_label_w, frame.label_h); + XMoveResizeWindow(display, frame.pwbutton, + ((frame.bevel_w * 5) + (frame.button_w * 2) + + frame.workspace_label_w + frame.window_label_w + 4), + frame.bevel_w + 1, frame.button_w, frame.button_w); + XMoveResizeWindow(display, frame.nwbutton, + ((frame.bevel_w * 6) + (frame.button_w * 3) + + frame.workspace_label_w + frame.window_label_w + 5), + frame.bevel_w + 1, frame.button_w, frame.button_w); + XMoveResizeWindow(display, frame.clock, + frame.rect.width() - frame.clock_w - (frame.bevel_w * 2), + frame.bevel_w, frame.clock_w, frame.label_h); + + ToolbarStyle *style = screen->getToolbarStyle(); + frame.base = style->toolbar.render(frame.rect.width(), frame.rect.height(), + frame.base); + if (! frame.base) + XSetWindowBackground(display, frame.window, + style->toolbar.color().pixel()); + else + XSetWindowBackgroundPixmap(display, frame.window, frame.base); + + frame.label = style->window.render(frame.window_label_w, frame.label_h, + frame.label); + if (! frame.label) + XSetWindowBackground(display, frame.window_label, + style->window.color().pixel()); + else + XSetWindowBackgroundPixmap(display, frame.window_label, frame.label); + + frame.wlabel = style->label.render(frame.workspace_label_w, frame.label_h, + frame.wlabel); + if (! frame.wlabel) + XSetWindowBackground(display, frame.workspace_label, + style->label.color().pixel()); + else + XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel); + + frame.clk = style->clock.render(frame.clock_w, frame.label_h, frame.clk); + if (! frame.clk) + XSetWindowBackground(display, frame.clock, style->clock.color().pixel()); + else + XSetWindowBackgroundPixmap(display, frame.clock, frame.clk); + + frame.button = style->button.render(frame.button_w, frame.button_w, + frame.button); + if (! frame.button) { + frame.button_pixel = style->button.color().pixel(); + XSetWindowBackground(display, frame.psbutton, frame.button_pixel); + XSetWindowBackground(display, frame.nsbutton, frame.button_pixel); + XSetWindowBackground(display, frame.pwbutton, frame.button_pixel); + XSetWindowBackground(display, frame.nwbutton, frame.button_pixel); + } else { + XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button); + XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button); + XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button); + XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button); + } + + frame.pbutton = style->pressed.render(frame.button_w, frame.button_w, + frame.pbutton); + if (! frame.pbutton) + frame.pbutton_pixel = style->pressed.color().pixel(); + + XSetWindowBorder(display, frame.window, + screen->getBorderColor()->pixel()); + XSetWindowBorderWidth(display, frame.window, screen->getBorderWidth()); + + XClearWindow(display, frame.window); + XClearWindow(display, frame.workspace_label); + XClearWindow(display, frame.window_label); + XClearWindow(display, frame.clock); + XClearWindow(display, frame.psbutton); + XClearWindow(display, frame.nsbutton); + XClearWindow(display, frame.pwbutton); + XClearWindow(display, frame.nwbutton); + + redrawWindowLabel(); + redrawWorkspaceLabel(); + redrawPrevWorkspaceButton(); + redrawNextWorkspaceButton(); + redrawPrevWindowButton(); + redrawNextWindowButton(); + checkClock(True); + + toolbarmenu->reconfigure(); +} + + +void Toolbar::updateStrut(void) { + // left and right are always 0 + strut.top = strut.bottom = 0; + + switch(screen->getToolbarPlacement()) { + case TopLeft: + case TopCenter: + case TopRight: + strut.top = getExposedHeight() + (screen->getBorderWidth() * 2); + break; + default: + strut.bottom = getExposedHeight() + (screen->getBorderWidth() * 2); + } + + screen->updateAvailableArea(); } #ifdef HAVE_STRFTIME -void Toolbar::checkClock(Bool redraw) { +void Toolbar::checkClock(bool redraw) { #else // !HAVE_STRFTIME - void Toolbar::checkClock(Bool redraw, Bool date) { +void Toolbar::checkClock(bool redraw, bool date) { #endif // HAVE_STRFTIME - time_t tmp = 0; - struct tm *tt = 0; - - if ((tmp = time(NULL)) != -1) { - if (! (tt = localtime(&tmp))) return; - if (tt->tm_min != frame.minute || tt->tm_hour != frame.hour) { - frame.hour = tt->tm_hour; - frame.minute = tt->tm_min; - XClearWindow(display, frame.clock); - redraw = True; - } + time_t tmp = 0; + struct tm *tt = 0; + + if ((tmp = time(NULL)) != -1) { + if (! (tt = localtime(&tmp))) return; + if (tt->tm_min != frame.minute || tt->tm_hour != frame.hour) { + frame.hour = tt->tm_hour; + frame.minute = tt->tm_min; + XClearWindow(display, frame.clock); + redraw = True; } + } - if (redraw) { + if (redraw) { #ifdef HAVE_STRFTIME - char t[1024]; - if (! strftime(t, 1024, screen.strftimeFormat(), tt)) - return; + char t[1024]; + if (! strftime(t, 1024, screen->getStrftimeFormat(), tt)) + return; #else // !HAVE_STRFTIME - char t[9]; - if (date) { - // format the date... with special consideration for y2k ;) - if (screen.getDateFormat() == Openbox::B_EuropeanDate) - sprintf(t, 18n->getMessage(ToolbarSet, ToolbarNoStrftimeDateFormatEu, - "%02d.%02d.%02d"), - tt->tm_mday, tt->tm_mon + 1, - (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year); - else - sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeDateFormat, - "%02d/%02d/%02d"), - tt->tm_mon + 1, tt->tm_mday, - (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year); - } else { - if (screen.isClock24Hour()) - sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat24, - " %02d:%02d "), - frame.hour, frame.minute); - else - sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat12, - "%02d:%02d %sm"), - ((frame.hour > 12) ? frame.hour - 12 : - ((frame.hour == 0) ? 12 : frame.hour)), frame.minute, - ((frame.hour >= 12) ? - i18n(ToolbarSet, - ToolbarNoStrftimeTimeFormatP, "p") : - i18n(ToolbarSet, - ToolbarNoStrftimeTimeFormatA, "a"))); - } + char t[9]; + if (date) { + // format the date... with special consideration for y2k ;) + if (screen->getDateFormat() == Blackbox::B_EuropeanDate) + sprintf(t, 18n(ToolbarSet, ToolbarNoStrftimeDateFormatEu, + "%02d.%02d.%02d"), + tt->tm_mday, tt->tm_mon + 1, + (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year); + else + sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeDateFormat, + "%02d/%02d/%02d"), + tt->tm_mon + 1, tt->tm_mday, + (tt->tm_year >= 100) ? tt->tm_year - 100 : tt->tm_year); + } else { + if (screen->isClock24Hour()) + sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat24, + " %02d:%02d "), + frame.hour, frame.minute); + else + sprintf(t, i18n(ToolbarSet, ToolbarNoStrftimeTimeFormat12, + "%02d:%02d %sm"), + ((frame.hour > 12) ? frame.hour - 12 : + ((frame.hour == 0) ? 12 : frame.hour)), frame.minute, + ((frame.hour >= 12) ? + i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatP, "p") : + i18n(ToolbarSet, ToolbarNoStrftimeTimeFormatA, "a"))); + } #endif // HAVE_STRFTIME - int dx = (frame.bevel_w * 2), dlen = strlen(t); - unsigned int l; + ToolbarStyle *style = screen->getToolbarStyle(); - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, - t, dlen, &ink, &logical); - l = logical.width; - } else { - l = XTextWidth(screen.getToolbarStyle()->font, t, dlen); - } + int pos = frame.bevel_w * 2, // this is modified by doJustify() + dlen = style->doJustify(t, pos, frame.clock_w, + frame.bevel_w * 4, i18n.multibyte()); + BPen pen(style->c_text, style->font); + if (i18n.multibyte()) + XmbDrawString(display, frame.clock, style->fontset, pen.gc(), + pos, (1 - style->fontset_extents->max_ink_extent.y), + t, dlen); + else + XDrawString(display, frame.clock, pen.gc(), pos, + (style->font->ascent + 1), t, dlen); + } +} - l += (frame.bevel_w * 4); - - if (l > frame.clock_w) { - for (; dlen >= 0; dlen--) { - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, - t, dlen, &ink, &logical); - l = logical.width; - } else { - l = XTextWidth(screen.getToolbarStyle()->font, t, dlen); - } - l+= (frame.bevel_w * 4); - - if (l < frame.clock_w) - break; - } - } - switch (screen.getToolbarStyle()->justify) { - case BScreen::RightJustify: - dx += frame.clock_w - l; - break; - - case BScreen::CenterJustify: - dx += (frame.clock_w - l) / 2; - break; - } - ToolbarStyle *style = screen.getToolbarStyle(); - if (i18n.multibyte()) - XmbDrawString(display, frame.clock, style->fontset, style->c_text_gc, - dx, (1 - style->fontset_extents->max_ink_extent.y), - t, dlen); - else - XDrawString(display, frame.clock, style->c_text_gc, dx, - (style->font->ascent + 1), t, dlen); - } +void Toolbar::redrawWindowLabel(bool redraw) { + BlackboxWindow *foc = screen->getBlackbox()->getFocusedWindow(); + if (! foc) { + XClearWindow(display, frame.window_label); + return; } + if (redraw) + XClearWindow(display, frame.window_label); - void Toolbar::redrawWindowLabel(Bool redraw) { - OpenboxWindow *foc = screen.getOpenbox().focusedWindow(); - if (foc == (OpenboxWindow *) 0) { - XClearWindow(display, frame.window_label); - } else { - if (redraw) - XClearWindow(display, frame.window_label); + if (foc->getScreen() != screen) return; - if (foc->getScreen() != &screen) return; + const char *title = foc->getTitle(); + ToolbarStyle *style = screen->getToolbarStyle(); - int dx = (frame.bevel_w * 2), dlen = strlen(*foc->getTitle()); - unsigned int l; + int pos = frame.bevel_w * 2, // modified by doJustify() + dlen = style->doJustify(title, pos, frame.window_label_w, + frame.bevel_w * 4, i18n.multibyte()); + BPen pen(style->w_text, style->font); + if (i18n.multibyte()) + XmbDrawString(display, frame.window_label, style->fontset, pen.gc(), pos, + (1 - style->fontset_extents->max_ink_extent.y), + title, dlen); + else + XDrawString(display, frame.window_label, pen.gc(), pos, + (style->font->ascent + 1), title, dlen); +} - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, *foc->getTitle(), - dlen, &ink, &logical); - l = logical.width; - } else { - l = XTextWidth(screen.getToolbarStyle()->font, *foc->getTitle(), dlen); - } - l += (frame.bevel_w * 4); - - if (l > frame.window_label_w) { - for (; dlen >= 0; dlen--) { - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, - *foc->getTitle(), dlen, &ink, &logical); - l = logical.width; - } else { - l = XTextWidth(screen.getToolbarStyle()->font, - *foc->getTitle(), dlen); - } - l += (frame.bevel_w * 4); - - if (l < frame.window_label_w) - break; - } - } - switch (screen.getToolbarStyle()->justify) { - case BScreen::RightJustify: - dx += frame.window_label_w - l; - break; - - case BScreen::CenterJustify: - dx += (frame.window_label_w - l) / 2; - break; - } - ToolbarStyle *style = screen.getToolbarStyle(); - if (i18n.multibyte()) - XmbDrawString(display, frame.window_label, style->fontset, - style->w_text_gc, dx, - (1 - style->fontset_extents->max_ink_extent.y), - *foc->getTitle(), dlen); - else - XDrawString(display, frame.window_label, style->w_text_gc, dx, - (style->font->ascent + 1), *foc->getTitle(), dlen); - } - } +void Toolbar::redrawWorkspaceLabel(bool redraw) { + const string& name = screen->getCurrentWorkspace()->getName(); + if (redraw) + XClearWindow(display, frame.workspace_label); - void Toolbar::redrawWorkspaceLabel(Bool redraw) { - if (screen.getCurrentWorkspace()->getName()) { - if (redraw) - XClearWindow(display, frame.workspace_label); + ToolbarStyle *style = screen->getToolbarStyle(); - int dx = (frame.bevel_w * 2), dlen = - strlen(screen.getCurrentWorkspace()->getName()); - unsigned int l; + int pos = frame.bevel_w * 2, + dlen = style->doJustify(name.c_str(), pos, frame.workspace_label_w, + frame.bevel_w * 4, i18n.multibyte()); + BPen pen(style->l_text, style->font); + if (i18n.multibyte()) + XmbDrawString(display, frame.workspace_label, style->fontset, pen.gc(), + pos, (1 - style->fontset_extents->max_ink_extent.y), + name.c_str(), dlen); + else + XDrawString(display, frame.workspace_label, pen.gc(), pos, + (style->font->ascent + 1), + name.c_str(), dlen); +} - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, - screen.getCurrentWorkspace()->getName(), dlen, - &ink, &logical); - l = logical.width; - } else { - l = XTextWidth(screen.getToolbarStyle()->font, - screen.getCurrentWorkspace()->getName(), dlen); - } - l += (frame.bevel_w * 4); - - if (l > frame.workspace_label_w) { - for (; dlen >= 0; dlen--) { - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, - screen.getCurrentWorkspace()->getName(), dlen, - &ink, &logical); - l = logical.width; - } else { - l = XTextWidth(screen.getWindowStyle()->font, - screen.getCurrentWorkspace()->getName(), dlen); - } - l += (frame.bevel_w * 4); - - if (l < frame.workspace_label_w) - break; - } - } - switch (screen.getToolbarStyle()->justify) { - case BScreen::RightJustify: - dx += frame.workspace_label_w - l; - break; - - case BScreen::CenterJustify: - dx += (frame.workspace_label_w - l) / 2; - break; - } - ToolbarStyle *style = screen.getToolbarStyle(); - if (i18n.multibyte()) - XmbDrawString(display, frame.workspace_label, style->fontset, - style->l_text_gc, dx, - (1 - style->fontset_extents->max_ink_extent.y), - (char *) screen.getCurrentWorkspace()->getName(), dlen); +void Toolbar::redrawPrevWorkspaceButton(bool pressed, bool redraw) { + if (redraw) { + if (pressed) { + if (frame.pbutton) + XSetWindowBackgroundPixmap(display, frame.psbutton, frame.pbutton); else - XDrawString(display, frame.workspace_label, style->l_text_gc, dx, - (style->font->ascent + 1), - (char *) screen.getCurrentWorkspace()->getName(), dlen); + XSetWindowBackground(display, frame.psbutton, frame.pbutton_pixel); + } else { + if (frame.button) + XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button); + else + XSetWindowBackground(display, frame.psbutton, frame.button_pixel); } + XClearWindow(display, frame.psbutton); } + int hh = frame.button_w / 2, hw = frame.button_w / 2; - void Toolbar::redrawPrevWorkspaceButton(Bool pressed, Bool redraw) { - if (redraw) { - if (pressed) { - if (frame.pbutton) - XSetWindowBackgroundPixmap(display, frame.psbutton, frame.pbutton); - else - XSetWindowBackground(display, frame.psbutton, frame.pbutton_pixel); - } else { - if (frame.button) - XSetWindowBackgroundPixmap(display, frame.psbutton, frame.button); - else - XSetWindowBackground(display, frame.psbutton, frame.button_pixel); - } - XClearWindow(display, frame.psbutton); - } - - int hh = frame.button_w / 2, hw = frame.button_w / 2; - - XPoint pts[3]; - pts[0].x = hw - 2; pts[0].y = hh; - pts[1].x = 4; pts[1].y = 2; - pts[2].x = 0; pts[2].y = -4; + XPoint pts[3]; + pts[0].x = hw - 2; pts[0].y = hh; + pts[1].x = 4; pts[1].y = 2; + pts[2].x = 0; pts[2].y = -4; - XFillPolygon(display, frame.psbutton, screen.getToolbarStyle()->b_pic_gc, - pts, 3, Convex, CoordModePrevious); - } + ToolbarStyle *style = screen->getToolbarStyle(); + BPen pen(style->b_pic, style->font); + XFillPolygon(display, frame.psbutton, pen.gc(), + pts, 3, Convex, CoordModePrevious); +} - void Toolbar::redrawNextWorkspaceButton(Bool pressed, Bool redraw) { - if (redraw) { - if (pressed) { - if (frame.pbutton) - XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.pbutton); - else - XSetWindowBackground(display, frame.nsbutton, frame.pbutton_pixel); - } else { - if (frame.button) - XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button); - else - XSetWindowBackground(display, frame.nsbutton, frame.button_pixel); - } - XClearWindow(display, frame.nsbutton); +void Toolbar::redrawNextWorkspaceButton(bool pressed, bool redraw) { + if (redraw) { + if (pressed) { + if (frame.pbutton) + XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.pbutton); + else + XSetWindowBackground(display, frame.nsbutton, frame.pbutton_pixel); + } else { + if (frame.button) + XSetWindowBackgroundPixmap(display, frame.nsbutton, frame.button); + else + XSetWindowBackground(display, frame.nsbutton, frame.button_pixel); } - - int hh = frame.button_w / 2, hw = frame.button_w / 2; - - XPoint pts[3]; - pts[0].x = hw - 2; pts[0].y = hh - 2; - pts[1].x = 4; pts[1].y = 2; - pts[2].x = -4; pts[2].y = 2; - - XFillPolygon(display, frame.nsbutton, screen.getToolbarStyle()->b_pic_gc, - pts, 3, Convex, CoordModePrevious); + XClearWindow(display, frame.nsbutton); } + int hh = frame.button_w / 2, hw = frame.button_w / 2; - void Toolbar::redrawPrevWindowButton(Bool pressed, Bool redraw) { - if (redraw) { - if (pressed) { - if (frame.pbutton) - XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.pbutton); - else - XSetWindowBackground(display, frame.pwbutton, frame.pbutton_pixel); - } else { - if (frame.button) - XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button); - else - XSetWindowBackground(display, frame.pwbutton, frame.button_pixel); - } - XClearWindow(display, frame.pwbutton); - } + XPoint pts[3]; + pts[0].x = hw - 2; pts[0].y = hh - 2; + pts[1].x = 4; pts[1].y = 2; + pts[2].x = -4; pts[2].y = 2; - int hh = frame.button_w / 2, hw = frame.button_w / 2; + ToolbarStyle *style = screen->getToolbarStyle(); + BPen pen(style->b_pic, style->font); + XFillPolygon(display, frame.nsbutton, pen.gc(), + pts, 3, Convex, CoordModePrevious); +} - XPoint pts[3]; - pts[0].x = hw - 2; pts[0].y = hh; - pts[1].x = 4; pts[1].y = 2; - pts[2].x = 0; pts[2].y = -4; - XFillPolygon(display, frame.pwbutton, screen.getToolbarStyle()->b_pic_gc, - pts, 3, Convex, CoordModePrevious); +void Toolbar::redrawPrevWindowButton(bool pressed, bool redraw) { + if (redraw) { + if (pressed) { + if (frame.pbutton) + XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.pbutton); + else + XSetWindowBackground(display, frame.pwbutton, frame.pbutton_pixel); + } else { + if (frame.button) + XSetWindowBackgroundPixmap(display, frame.pwbutton, frame.button); + else + XSetWindowBackground(display, frame.pwbutton, frame.button_pixel); + } + XClearWindow(display, frame.pwbutton); } + int hh = frame.button_w / 2, hw = frame.button_w / 2; - void Toolbar::redrawNextWindowButton(Bool pressed, Bool redraw) { - if (redraw) { - if (pressed) { - if (frame.pbutton) - XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.pbutton); - else - XSetWindowBackground(display, frame.nwbutton, frame.pbutton_pixel); - } else { - if (frame.button) - XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button); - else - XSetWindowBackground(display, frame.nwbutton, frame.button_pixel); - } - XClearWindow(display, frame.nwbutton); - } + XPoint pts[3]; + pts[0].x = hw - 2; pts[0].y = hh; + pts[1].x = 4; pts[1].y = 2; + pts[2].x = 0; pts[2].y = -4; - int hh = frame.button_w / 2, hw = frame.button_w / 2; + ToolbarStyle *style = screen->getToolbarStyle(); + BPen pen(style->b_pic, style->font); + XFillPolygon(display, frame.pwbutton, pen.gc(), + pts, 3, Convex, CoordModePrevious); +} - XPoint pts[3]; - pts[0].x = hw - 2; pts[0].y = hh - 2; - pts[1].x = 4; pts[1].y = 2; - pts[2].x = -4; pts[2].y = 2; - XFillPolygon(display, frame.nwbutton, screen.getToolbarStyle()->b_pic_gc, - pts, 3, Convex, CoordModePrevious); +void Toolbar::redrawNextWindowButton(bool pressed, bool redraw) { + if (redraw) { + if (pressed) { + if (frame.pbutton) + XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.pbutton); + else + XSetWindowBackground(display, frame.nwbutton, frame.pbutton_pixel); + } else { + if (frame.button) + XSetWindowBackgroundPixmap(display, frame.nwbutton, frame.button); + else + XSetWindowBackground(display, frame.nwbutton, frame.button_pixel); + } + XClearWindow(display, frame.nwbutton); } + int hh = frame.button_w / 2, hw = frame.button_w / 2; - void Toolbar::edit() { - Window window; - int foo; + XPoint pts[3]; + pts[0].x = hw - 2; pts[0].y = hh - 2; + pts[1].x = 4; pts[1].y = 2; + pts[2].x = -4; pts[2].y = 2; - m_editing = True; - if (XGetInputFocus(display, &window, &foo) && - window == frame.workspace_label) - return; + ToolbarStyle *style = screen->getToolbarStyle(); + BPen pen(style->b_pic, style->font); + XFillPolygon(display, frame.nwbutton, pen.gc(), pts, 3, Convex, + CoordModePrevious); +} - XSetInputFocus(display, frame.workspace_label, - RevertToPointerRoot, CurrentTime); - XClearWindow(display, frame.workspace_label); - openbox.setNoFocus(True); - if (openbox.focusedWindow()) - openbox.focusedWindow()->setFocusFlag(False); - - XDrawRectangle(display, frame.workspace_label, - screen.getWindowStyle()->l_text_focus_gc, - frame.workspace_label_w / 2, 0, 1, - frame.label_h - 1); - - // change the background of the window to that of an active window label - Pixmap tmp = frame.wlabel; - BTexture *texture = &(screen.getWindowStyle()->l_focus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.wlabel = None; - XSetWindowBackground(display, frame.workspace_label, - texture->getColor()->getPixel()); - } else { - frame.wlabel = - image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture); - XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel); - } - if (tmp) image_ctrl->removeImage(tmp); - } +void Toolbar::edit(void) { + Window window; + int foo; + + editing = True; + XGetInputFocus(display, &window, &foo); + if (window == frame.workspace_label) + return; + + XSetInputFocus(display, frame.workspace_label, + RevertToPointerRoot, CurrentTime); + XClearWindow(display, frame.workspace_label); + + blackbox->setNoFocus(True); + if (blackbox->getFocusedWindow()) + blackbox->getFocusedWindow()->setFocusFlag(False); + + ToolbarStyle *style = screen->getToolbarStyle(); + BPen pen(style->l_text, style->font); + XDrawRectangle(display, frame.workspace_label, pen.gc(), + frame.workspace_label_w / 2, 0, 1, + frame.label_h - 1); + // change the background of the window to that of an active window label + BTexture *texture = &(screen->getWindowStyle()->l_focus); + frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h, + frame.wlabel); + if (! frame.wlabel) + XSetWindowBackground(display, frame.workspace_label, + texture->color().pixel()); + else + XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel); +} - void Toolbar::buttonPressEvent(XButtonEvent *be) { - if (be->button == 1) { - if (be->window == frame.psbutton) - redrawPrevWorkspaceButton(True, True); - else if (be->window == frame.nsbutton) - redrawNextWorkspaceButton(True, True); - else if (be->window == frame.pwbutton) - redrawPrevWindowButton(True, True); - else if (be->window == frame.nwbutton) - redrawNextWindowButton(True, True); +void Toolbar::buttonPressEvent(XButtonEvent *be) { + if (be->button == 1) { + if (be->window == frame.psbutton) + redrawPrevWorkspaceButton(True, True); + else if (be->window == frame.nsbutton) + redrawNextWorkspaceButton(True, True); + else if (be->window == frame.pwbutton) + redrawPrevWindowButton(True, True); + else if (be->window == frame.nwbutton) + redrawNextWindowButton(True, True); #ifndef HAVE_STRFTIME - else if (be->window == frame.clock) { - XClearWindow(display, frame.clock); - checkClock(True, True); - } + else if (be->window == frame.clock) { + XClearWindow(display, frame.clock); + checkClock(True, True); + } #endif // HAVE_STRFTIME - else if (! m_ontop) { - Window w[1] = { frame.window }; - screen.raiseWindows(w, 1); - } - } else if (be->button == 2 && (! m_ontop)) { - XLowerWindow(display, frame.window); - } else if (be->button == 3) { - if (! toolbarmenu->isVisible()) { - int x, y; - - x = be->x_root - (toolbarmenu->getWidth() / 2); - y = be->y_root - (toolbarmenu->getHeight() / 2); - - if (x < 0) - x = 0; - else if (x + toolbarmenu->getWidth() > screen.size().w()) - x = screen.size().w() - toolbarmenu->getWidth(); - - if (y < 0) - y = 0; - else if (y + toolbarmenu->getHeight() > screen.size().h()) - y = screen.size().h() - toolbarmenu->getHeight(); - - toolbarmenu->move(x, y); - toolbarmenu->show(); - } else - toolbarmenu->hide(); + else if (! on_top) { + Window w[1] = { frame.window }; + screen->raiseWindows(w, 1); } - } + } else if (be->button == 2 && (! on_top)) { + XLowerWindow(display, frame.window); + } else if (be->button == 3) { + if (toolbarmenu->isVisible()) { + toolbarmenu->hide(); + } else { + int x, y; + x = be->x_root - (toolbarmenu->getWidth() / 2); + y = be->y_root - (toolbarmenu->getHeight() / 2); + if (x < 0) + x = 0; + else if (x + toolbarmenu->getWidth() > screen->getWidth()) + x = screen->getWidth() - toolbarmenu->getWidth(); - void Toolbar::buttonReleaseEvent(XButtonEvent *re) { - if (re->button == 1) { - if (re->window == frame.psbutton) { - redrawPrevWorkspaceButton(False, True); - - if (re->x >= 0 && re->x < (signed) frame.button_w && - re->y >= 0 && re->y < (signed) frame.button_w) - if (screen.getCurrentWorkspace()->getWorkspaceID() > 0) - screen.changeWorkspaceID(screen.getCurrentWorkspace()-> - getWorkspaceID() - 1); - else - screen.changeWorkspaceID(screen.getWorkspaceCount() - 1); - } else if (re->window == frame.nsbutton) { - redrawNextWorkspaceButton(False, True); - - if (re->x >= 0 && re->x < (signed) frame.button_w && - re->y >= 0 && re->y < (signed) frame.button_w) - if (screen.getCurrentWorkspace()->getWorkspaceID() < - screen.getWorkspaceCount() - 1) - screen.changeWorkspaceID(screen.getCurrentWorkspace()-> - getWorkspaceID() + 1); - else - screen.changeWorkspaceID(0); - } else if (re->window == frame.pwbutton) { - redrawPrevWindowButton(False, True); - - if (re->x >= 0 && re->x < (signed) frame.button_w && - re->y >= 0 && re->y < (signed) frame.button_w) - screen.prevFocus(); - } else if (re->window == frame.nwbutton) { - redrawNextWindowButton(False, True); - - if (re->x >= 0 && re->x < (signed) frame.button_w && - re->y >= 0 && re->y < (signed) frame.button_w) - screen.nextFocus(); - } else if (re->window == frame.window_label) - screen.raiseFocus(); -#ifndef HAVE_STRFTIME - else if (re->window == frame.clock) { - XClearWindow(display, frame.clock); - checkClock(True); - } -#endif // HAVE_STRFTIME + if (y < 0) + y = 0; + else if (y + toolbarmenu->getHeight() > screen->getHeight()) + y = screen->getHeight() - toolbarmenu->getHeight(); + + toolbarmenu->move(x, y); + toolbarmenu->show(); } } +} - void Toolbar::enterNotifyEvent(XCrossingEvent *) { - if (! m_autohide) - return; - if (m_hidden) { - if (! hide_timer->isTiming()) hide_timer->start(); - } else { - if (hide_timer->isTiming()) hide_timer->stop(); +void Toolbar::buttonReleaseEvent(XButtonEvent *re) { + if (re->button == 1) { + if (re->window == frame.psbutton) { + redrawPrevWorkspaceButton(False, True); + + if (re->x >= 0 && re->x < static_cast(frame.button_w) && + re->y >= 0 && re->y < static_cast(frame.button_w)) + if (screen->getCurrentWorkspace()->getID() > 0) + screen->changeWorkspaceID(screen->getCurrentWorkspace()-> + getID() - 1); + else + screen->changeWorkspaceID(screen->getWorkspaceCount() - 1); + } else if (re->window == frame.nsbutton) { + redrawNextWorkspaceButton(False, True); + + if (re->x >= 0 && re->x < static_cast(frame.button_w) && + re->y >= 0 && re->y < static_cast(frame.button_w)) + if (screen->getCurrentWorkspace()->getID() < + (screen->getWorkspaceCount() - 1)) + screen->changeWorkspaceID(screen->getCurrentWorkspace()-> + getID() + 1); + else + screen->changeWorkspaceID(0); + } else if (re->window == frame.pwbutton) { + redrawPrevWindowButton(False, True); + + if (re->x >= 0 && re->x < static_cast(frame.button_w) && + re->y >= 0 && re->y < static_cast(frame.button_w)) + screen->prevFocus(); + } else if (re->window == frame.nwbutton) { + redrawNextWindowButton(False, True); + + if (re->x >= 0 && re->x < static_cast(frame.button_w) && + re->y >= 0 && re->y < static_cast(frame.button_w)) + screen->nextFocus(); + } else if (re->window == frame.window_label) + screen->raiseFocus(); +#ifndef HAVE_STRFTIME + else if (re->window == frame.clock) { + XClearWindow(display, frame.clock); + checkClock(True); } +#endif // HAVE_STRFTIME } +} - void Toolbar::leaveNotifyEvent(XCrossingEvent *) { - if (! m_autohide) - return; - if (m_hidden) { - if (hide_timer->isTiming()) hide_timer->stop(); - } else if (! toolbarmenu->isVisible()) { - if (! hide_timer->isTiming()) hide_timer->start(); - } +void Toolbar::enterNotifyEvent(XCrossingEvent *) { + if (! do_auto_hide) + return; + + if (hidden) { + if (! hide_timer->isTiming()) hide_timer->start(); + } else { + if (hide_timer->isTiming()) hide_timer->stop(); } +} +void Toolbar::leaveNotifyEvent(XCrossingEvent *) { + if (! do_auto_hide) + return; - void Toolbar::exposeEvent(XExposeEvent *ee) { - if (ee->window == frame.clock) checkClock(True); - else if (ee->window == frame.workspace_label && (! m_editing)) - redrawWorkspaceLabel(); - else if (ee->window == frame.window_label) redrawWindowLabel(); - else if (ee->window == frame.psbutton) redrawPrevWorkspaceButton(); - else if (ee->window == frame.nsbutton) redrawNextWorkspaceButton(); - else if (ee->window == frame.pwbutton) redrawPrevWindowButton(); - else if (ee->window == frame.nwbutton) redrawNextWindowButton(); + if (hidden) { + if (hide_timer->isTiming()) hide_timer->stop(); + } else if (! toolbarmenu->isVisible()) { + if (! hide_timer->isTiming()) hide_timer->start(); } +} - void Toolbar::keyPressEvent(XKeyEvent *ke) { - if (ke->window == frame.workspace_label && m_editing) { - openbox.grab(); +void Toolbar::exposeEvent(XExposeEvent *ee) { + if (ee->window == frame.clock) checkClock(True); + else if (ee->window == frame.workspace_label && (! editing)) + redrawWorkspaceLabel(); + else if (ee->window == frame.window_label) redrawWindowLabel(); + else if (ee->window == frame.psbutton) redrawPrevWorkspaceButton(); + else if (ee->window == frame.nsbutton) redrawNextWorkspaceButton(); + else if (ee->window == frame.pwbutton) redrawPrevWindowButton(); + else if (ee->window == frame.nwbutton) redrawNextWindowButton(); +} - if (! new_workspace_name) { - new_workspace_name = new char[128]; - new_name_pos = 0; - if (! new_workspace_name) return; - } +void Toolbar::keyPressEvent(XKeyEvent *ke) { + if (ke->window == frame.workspace_label && editing) { + if (new_workspace_name.empty()) { + new_name_pos = 0; + } - KeySym ks; - char keychar[1]; - XLookupString(ke, keychar, 1, &ks, 0); - - // either we are told to end with a return or we hit the end of the buffer - if (ks == XK_Return || new_name_pos == 127) { - *(new_workspace_name + new_name_pos) = 0; - - m_editing = False; - - openbox.setNoFocus(False); - if (openbox.focusedWindow()) { - openbox.focusedWindow()->setInputFocus(); - openbox.focusedWindow()->setFocusFlag(True); - } else - openbox.focusWindow((OpenboxWindow *) 0); - - // check to make sure that new_name[0] != 0... otherwise we have a null - // workspace name which causes serious problems, especially for the - // Openbox::LoadRC() method. - if (*new_workspace_name) { - screen.getCurrentWorkspace()->setName(new_workspace_name); - screen.getCurrentWorkspace()->getMenu()->hide(); - screen.getWorkspacemenu()-> - remove(screen.getCurrentWorkspace()->getWorkspaceID() + 2); - screen.getWorkspacemenu()-> - insert(screen.getCurrentWorkspace()->getName(), - screen.getCurrentWorkspace()->getMenu(), - screen.getCurrentWorkspace()->getWorkspaceID() + 2); - screen.getWorkspacemenu()->update(); - } + KeySym ks; + char keychar[1]; + XLookupString(ke, keychar, 1, &ks, 0); - delete [] new_workspace_name; - new_workspace_name = (char *) 0; - new_name_pos = 0; - - // reset the background to that of the workspace label (its normal - // setting) - Pixmap tmp = frame.wlabel; - BTexture *texture = &(screen.getToolbarStyle()->label); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.wlabel = None; - XSetWindowBackground(display, frame.workspace_label, - texture->getColor()->getPixel()); - } else { - frame.wlabel = - image_ctrl->renderImage(frame.workspace_label_w, frame.label_h, texture); - XSetWindowBackgroundPixmap(display, frame.workspace_label, frame.wlabel); - } - if (tmp) image_ctrl->removeImage(tmp); - - reconfigure(); - } else if (! (ks == XK_Shift_L || ks == XK_Shift_R || - ks == XK_Control_L || ks == XK_Control_R || - ks == XK_Caps_Lock || ks == XK_Shift_Lock || - ks == XK_Meta_L || ks == XK_Meta_R || - ks == XK_Alt_L || ks == XK_Alt_R || - ks == XK_Super_L || ks == XK_Super_R || - ks == XK_Hyper_L || ks == XK_Hyper_R)) { - if (ks == XK_BackSpace) { - if (new_name_pos > 0) { - --new_name_pos; - *(new_workspace_name + new_name_pos) = '\0'; - } else { - *new_workspace_name = '\0'; - } - } else { - *(new_workspace_name + new_name_pos) = *keychar; - ++new_name_pos; - *(new_workspace_name + new_name_pos) = '\0'; - } + // either we are told to end with a return or we hit 127 chars + if (ks == XK_Return || new_name_pos == 127) { + editing = False; - XClearWindow(display, frame.workspace_label); - int l = strlen(new_workspace_name), tw, x; + blackbox->setNoFocus(False); + if (blackbox->getFocusedWindow()) { + blackbox->getFocusedWindow()->setInputFocus(); + } else { + blackbox->setFocusedWindow(0); + } - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen.getToolbarStyle()->fontset, - new_workspace_name, l, &ink, &logical); - tw = logical.width; + Workspace *wkspc = screen->getCurrentWorkspace(); + wkspc->setName(new_workspace_name); + wkspc->getMenu()->hide(); + + screen->getWorkspacemenu()->changeItemLabel(wkspc->getID() + 2, + wkspc->getName()); + screen->getWorkspacemenu()->update(); + + new_workspace_name.erase(); + new_name_pos = 0; + + // reset the background to that of the workspace label (its normal + // setting) + BTexture *texture = &(screen->getToolbarStyle()->label); + frame.wlabel = texture->render(frame.workspace_label_w, frame.label_h, + frame.wlabel); + if (! frame.wlabel) + XSetWindowBackground(display, frame.workspace_label, + texture->color().pixel()); + else + XSetWindowBackgroundPixmap(display, frame.workspace_label, + frame.wlabel); + reconfigure(); + } else if (! (ks == XK_Shift_L || ks == XK_Shift_R || + ks == XK_Control_L || ks == XK_Control_R || + ks == XK_Caps_Lock || ks == XK_Shift_Lock || + ks == XK_Meta_L || ks == XK_Meta_R || + ks == XK_Alt_L || ks == XK_Alt_R || + ks == XK_Super_L || ks == XK_Super_R || + ks == XK_Hyper_L || ks == XK_Hyper_R)) { + if (ks == XK_BackSpace) { + if (new_name_pos > 0) { + --new_name_pos; + new_workspace_name.erase(new_name_pos); } else { - tw = XTextWidth(screen.getToolbarStyle()->font, - new_workspace_name, l); + new_workspace_name.resize(0); } - x = (frame.workspace_label_w - tw) / 2; - - if (x < (signed) frame.bevel_w) x = frame.bevel_w; + } else { + new_workspace_name += (*keychar); + ++new_name_pos; + } - WindowStyle *style = screen.getWindowStyle(); - if (i18n.multibyte()) - XmbDrawString(display, frame.workspace_label, style->fontset, - style->l_text_focus_gc, x, - (1 - style->fontset_extents->max_ink_extent.y), - new_workspace_name, l); - else - XDrawString(display, frame.workspace_label, style->l_text_focus_gc, x, - (style->font->ascent + 1), - new_workspace_name, l); + XClearWindow(display, frame.workspace_label); + unsigned int l = new_workspace_name.length(), tw, x; - XDrawRectangle(display, frame.workspace_label, - screen.getWindowStyle()->l_text_focus_gc, x + tw, 0, 1, - frame.label_h - 1); + if (i18n.multibyte()) { + XRectangle ink, logical; + XmbTextExtents(screen->getToolbarStyle()->fontset, + new_workspace_name.c_str(), l, &ink, &logical); + tw = logical.width; + } else { + tw = XTextWidth(screen->getToolbarStyle()->font, + new_workspace_name.c_str(), l); } + x = (frame.workspace_label_w - tw) / 2; + + if (x < frame.bevel_w) x = frame.bevel_w; - openbox.ungrab(); + ToolbarStyle *style = screen->getToolbarStyle(); + BPen pen(style->l_text, style->font); + if (i18n.multibyte()) + XmbDrawString(display, frame.workspace_label, style->fontset, + pen.gc(), x, + (1 - style->fontset_extents->max_ink_extent.y), + new_workspace_name.c_str(), l); + else + XDrawString(display, frame.workspace_label, pen.gc(), x, + (style->font->ascent + 1), + new_workspace_name.c_str(), l); + XDrawRectangle(display, frame.workspace_label, pen.gc(), x + tw, 0, 1, + frame.label_h - 1); } } +} - void Toolbar::timeout() { - checkClock(True); +void Toolbar::timeout(void) { + checkClock(True); - timeval now; - gettimeofday(&now, 0); - clock_timer->setTimeout((60 - (now.tv_sec % 60)) * 1000); - } + clock_timer->setTimeout(aMinuteFromNow()); +} - void Toolbar::HideHandler::timeout() { - toolbar->m_hidden = !toolbar->m_hidden; - if (toolbar->m_hidden) - XMoveWindow(toolbar->display, toolbar->frame.window, - toolbar->frame.x_hidden, toolbar->frame.y_hidden); - else - XMoveWindow(toolbar->display, toolbar->frame.window, - toolbar->frame.x, toolbar->frame.y); +void Toolbar::HideHandler::timeout(void) { + toolbar->hidden = ! toolbar->hidden; + if (toolbar->hidden) + XMoveWindow(toolbar->display, toolbar->frame.window, + toolbar->frame.x_hidden, toolbar->frame.y_hidden); + else + XMoveWindow(toolbar->display, toolbar->frame.window, + toolbar->frame.rect.x(), toolbar->frame.rect.y()); +} + + +void Toolbar::toggleAutoHide(void) { + do_auto_hide = (do_auto_hide) ? False : True; + + updateStrut(); + screen->getSlit()->reposition(); + + if (do_auto_hide == False && hidden) { + // force the slit to be visible + if (hide_timer->isTiming()) hide_timer->stop(); + hide_handler.timeout(); } +} - Toolbarmenu::Toolbarmenu(Toolbar &tb) : Basemenu(tb.screen), toolbar(tb) { - setLabel(i18n(ToolbarSet, ToolbarToolbarTitle, "Toolbar")); - setInternalMenu(); +Toolbarmenu::Toolbarmenu(Toolbar *tb) : Basemenu(tb->screen) { + toolbar = tb; - placementmenu = new Placementmenu(*this); + setLabel(i18n(ToolbarSet, ToolbarToolbarTitle, "Toolbar")); + setInternalMenu(); - insert(i18n(CommonSet, CommonPlacementTitle, "Placement"), - placementmenu); - insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1); - insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2); - insert(i18n(ToolbarSet, ToolbarEditWkspcName, - "Edit current workspace name"), 3); + placementmenu = new Placementmenu(this); - update(); + insert(i18n(CommonSet, CommonPlacementTitle, "Placement"), + placementmenu); + insert(i18n(CommonSet, CommonAlwaysOnTop, "Always on top"), 1); + insert(i18n(CommonSet, CommonAutoHide, "Auto hide"), 2); + insert(i18n(ToolbarSet, ToolbarEditWkspcName, + "Edit current workspace name"), 3); - setValues(); - } + update(); - void Toolbarmenu::setValues() { - setItemSelected(1, toolbar.onTop()); - setItemSelected(2, toolbar.autoHide()); + if (toolbar->isOnTop()) setItemSelected(1, True); + if (toolbar->doAutoHide()) setItemSelected(2, True); +} + + +Toolbarmenu::~Toolbarmenu(void) { + delete placementmenu; +} + + +void Toolbarmenu::itemSelected(int button, unsigned int index) { + if (button != 1) + return; + + BasemenuItem *item = find(index); + if (! item) return; + + switch (item->function()) { + case 1: { // always on top + toolbar->on_top = ((toolbar->isOnTop()) ? False : True);; + setItemSelected(1, toolbar->on_top); + + if (toolbar->isOnTop()) getScreen()->raiseWindows((Window *) 0, 0); + break; } + case 2: { // auto hide + toolbar->toggleAutoHide(); + setItemSelected(2, toolbar->do_auto_hide); - Toolbarmenu::~Toolbarmenu() { - delete placementmenu; + break; } + case 3: { // edit current workspace name + toolbar->edit(); + hide(); - void Toolbarmenu::itemSelected(int button, int index) { - if (button != 1) - return; + break; + } + } // switch +} - BasemenuItem *item = find(index); - if (! item) return; - switch (item->function()) { - case 1: { // always on top - Bool change = ((toolbar.onTop()) ? False : True); - toolbar.setOnTop(change); - setItemSelected(1, change); +void Toolbarmenu::internal_hide(void) { + Basemenu::internal_hide(); + if (toolbar->doAutoHide() && ! toolbar->isEditing()) + toolbar->hide_handler.timeout(); +} - if (toolbar.onTop()) toolbar.screen.raiseWindows((Window *) 0, 0); - break; - } - case 2: { // auto hide - Bool change = ((toolbar.autoHide()) ? False : True); - toolbar.setAutoHide(change); - setItemSelected(2, change); +void Toolbarmenu::reconfigure(void) { + placementmenu->reconfigure(); -#ifdef SLIT - toolbar.screen.getSlit()->reposition(); -#endif // SLIT - break; - } + Basemenu::reconfigure(); +} - case 3: { // edit current workspace name - toolbar.edit(); - hide(); - break; - } - } // switch - } +Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu *tm) + : Basemenu(tm->toolbar->screen) { + setLabel(i18n(ToolbarSet, ToolbarToolbarPlacement, "Toolbar Placement")); + setInternalMenu(); + setMinimumSublevels(3); + + insert(i18n(CommonSet, CommonPlacementTopLeft, "Top Left"), + Toolbar::TopLeft); + insert(i18n(CommonSet, CommonPlacementBottomLeft, "Bottom Left"), + Toolbar::BottomLeft); + insert(i18n(CommonSet, CommonPlacementTopCenter, "Top Center"), + Toolbar::TopCenter); + insert(i18n(CommonSet, CommonPlacementBottomCenter, "Bottom Center"), + Toolbar::BottomCenter); + insert(i18n(CommonSet, CommonPlacementTopRight, "Top Right"), + Toolbar::TopRight); + insert(i18n(CommonSet, CommonPlacementBottomRight, "Bottom Right"), + Toolbar::BottomRight); + update(); +} - void Toolbarmenu::internal_hide() { - Basemenu::internal_hide(); - if (toolbar.autoHide() && ! toolbar.isEditing()) - toolbar.hide_handler.timeout(); - } +void Toolbarmenu::Placementmenu::itemSelected(int button, unsigned int index) { + if (button != 1) + return; + BasemenuItem *item = find(index); + if (! item) return; - void Toolbarmenu::reconfigure() { - setValues(); - placementmenu->reconfigure(); + getScreen()->saveToolbarPlacement(item->function()); + hide(); + getScreen()->getToolbar()->reconfigure(); - Basemenu::reconfigure(); - } + // reposition the slit as well to make sure it doesn't intersect the + // toolbar + getScreen()->getSlit()->reposition(); +} - Toolbarmenu::Placementmenu::Placementmenu(Toolbarmenu &tm) - : Basemenu(tm.toolbar.screen), toolbarmenu(tm) { - setLabel(i18n(ToolbarSet, ToolbarToolbarPlacement, - "Toolbar Placement")); - setInternalMenu(); - setMinimumSublevels(3); - - insert(i18n(CommonSet, CommonPlacementTopLeft, - "Top Left"), Toolbar::TopLeft); - insert(i18n(CommonSet, CommonPlacementBottomLeft, - "Bottom Left"), Toolbar::BottomLeft); - insert(i18n(CommonSet, CommonPlacementTopCenter, - "Top Center"), Toolbar::TopCenter); - insert(i18n(CommonSet, CommonPlacementBottomCenter, - "Bottom Center"), Toolbar::BottomCenter); - insert(i18n(CommonSet, CommonPlacementTopRight, - "Top Right"), Toolbar::TopRight); - insert(i18n(CommonSet, CommonPlacementBottomRight, - "Bottom Right"), Toolbar::BottomRight); - update(); - } +int ToolbarStyle::doJustify(const char *text, int &start_pos, + unsigned int max_length, unsigned int modifier, + bool multibyte) const { + size_t text_len = strlen(text); + unsigned int length; - void Toolbarmenu::Placementmenu::itemSelected(int button, int index) { - if (button != 1) - return; + do { + if (multibyte) { + XRectangle ink, logical; + XmbTextExtents(fontset, text, text_len, &ink, &logical); + length = logical.width; + } else { + length = XTextWidth(font, text, text_len); + } + length += modifier; + } while (length > max_length && text_len-- > 0); - BasemenuItem *item = find(index); - if (! item) return; + switch (justify) { + case RightJustify: + start_pos += max_length - length; + break; - toolbarmenu.toolbar.setPlacement(item->function()); - hide(); - toolbarmenu.toolbar.reconfigure(); + case CenterJustify: + start_pos += (max_length - length) / 2; + break; -#ifdef SLIT - // reposition the slit as well to make sure it doesn't intersect the - // toolbar - toolbarmenu.toolbar.screen.getSlit()->reposition(); -#endif // SLIT + case LeftJustify: + default: + break; } + + return text_len; +} diff --git a/src/Toolbar.h b/src/Toolbar.h deleted file mode 100644 index 93d92055..00000000 --- a/src/Toolbar.h +++ /dev/null @@ -1,176 +0,0 @@ -// Toolbar.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Toolbar_hh -#define __Toolbar_hh - -#include - -#include "Basemenu.h" -#include "Timer.h" -#include "Resource.h" -#include "Screen.h" -#include "Geometry.h" - -// forward declaration -class Toolbar; - -class Toolbarmenu : public Basemenu { -private: - class Placementmenu : public Basemenu { - private: - Toolbarmenu &toolbarmenu; - - protected: - virtual void itemSelected(int, int); - - public: - Placementmenu(Toolbarmenu &); - }; - - Toolbar &toolbar; - Placementmenu *placementmenu; - - friend class Placementmenu; - friend class Toolbar; - - -protected: - virtual void itemSelected(int, int); - virtual void internal_hide(); - virtual void setValues(); - -public: - Toolbarmenu(Toolbar &); - ~Toolbarmenu(); - - inline Basemenu *getPlacementmenu() { return placementmenu; } - - void reconfigure(); -}; - - -class Toolbar : public TimeoutHandler { -private: - bool m_ontop, m_editing, m_hidden, m_autohide; - int m_width_percent, m_placement; - Display *display; - - struct frame { - unsigned long button_pixel, pbutton_pixel; - Pixmap base, label, wlabel, clk, button, pbutton; - Window window, workspace_label, window_label, clock, psbutton, nsbutton, - pwbutton, nwbutton; - - int x, y, x_hidden, y_hidden, hour, minute, grab_x, grab_y; - unsigned int width, height, window_label_w, workspace_label_w, clock_w, - button_w, bevel_w, label_h; - } frame; - - class HideHandler : public TimeoutHandler { - public: - Toolbar *toolbar; - virtual void timeout(); - } hide_handler; - - Openbox &openbox; - BScreen &screen; - Resource &config; - BImageControl *image_ctrl; - BTimer *clock_timer, *hide_timer; - Toolbarmenu *toolbarmenu; - - char *new_workspace_name; - size_t new_name_pos; - - friend class HideHandler; - friend class Toolbarmenu; - friend class Toolbarmenu::Placementmenu; - - -public: - Toolbar(BScreen &, Resource &); - virtual ~Toolbar(); - - inline Toolbarmenu *getMenu() { return toolbarmenu; } - - inline const Window &getWindowID() const { return frame.window; } - - //inline unsigned int getWidth() const { return frame.width; } - //inline unsigned int getHeight() const { return frame.height; } - unsigned int getExposedHeight() const; - - //int getX() const; - //int getY() const; - - Rect area() const; - //Size size() const { return area().size(); } - //Point origin() const { return area().origin(); } - - void buttonPressEvent(XButtonEvent *); - void buttonReleaseEvent(XButtonEvent *); - void enterNotifyEvent(XCrossingEvent *); - void leaveNotifyEvent(XCrossingEvent *); - void exposeEvent(XExposeEvent *); - void keyPressEvent(XKeyEvent *); - - void redrawWindowLabel(Bool = False); - void redrawWorkspaceLabel(Bool = False); - void redrawPrevWorkspaceButton(Bool = False, Bool = False); - void redrawNextWorkspaceButton(Bool = False, Bool = False); - void redrawPrevWindowButton(Bool = False, Bool = False); - void redrawNextWindowButton(Bool = False, Bool = False); - void edit(); - void reconfigure(); - void load(); - void save(); - void mapToolbar(); - void unMapToolbar(); -#ifdef HAVE_STRFTIME - void checkClock(Bool = False); -#else // HAVE_STRFTIME - void checkClock(Bool = False, Bool = False); -#endif // HAVE_STRFTIME - - virtual void timeout(); - - inline bool onTop() const { return m_ontop; } - void setOnTop(bool); - - inline bool autoHide() const { return m_autohide; } - void setAutoHide(bool); - - inline int widthPercent() const { return m_width_percent; } - void setWidthPercent(int); - - inline int placement() const { return m_placement; } - void setPlacement(int); - - inline bool isEditing() const { return m_editing; } - inline bool isHidden() const { return m_hidden; } - - enum { TopLeft = 1, BottomLeft, TopCenter, - BottomCenter, TopRight, BottomRight }; -}; - - -#endif // __Toolbar_hh diff --git a/src/Toolbar.hh b/src/Toolbar.hh new file mode 100644 index 00000000..5ec3029c --- /dev/null +++ b/src/Toolbar.hh @@ -0,0 +1,173 @@ +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Toolbar.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef __Toolbar_hh +#define __Toolbar_hh + +extern "C" { +#include +} + +#include "Screen.hh" +#include "Basemenu.hh" +#include "Timer.hh" + +// forward declaration +class Toolbar; + +class Toolbarmenu : public Basemenu { +private: + class Placementmenu : public Basemenu { + private: + Placementmenu(const Placementmenu&); + Placementmenu& operator=(const Placementmenu&); + + protected: + virtual void itemSelected(int button, unsigned int index); + + public: + Placementmenu(Toolbarmenu *tm); + }; + + Toolbar *toolbar; + Placementmenu *placementmenu; + + friend class Placementmenu; + friend class Toolbar; + + Toolbarmenu(const Toolbarmenu&); + Toolbarmenu& operator=(const Toolbarmenu&); + +protected: + virtual void itemSelected(int button, unsigned int index); + virtual void internal_hide(void); + +public: + Toolbarmenu(Toolbar *tb); + ~Toolbarmenu(void); + + inline Basemenu *getPlacementmenu(void) { return placementmenu; } + + void reconfigure(void); +}; + + +class Toolbar : public TimeoutHandler { +private: + bool on_top, editing, hidden, do_auto_hide; + Display *display; + + struct ToolbarFrame { + unsigned long button_pixel, pbutton_pixel; + Pixmap base, label, wlabel, clk, button, pbutton; + Window window, workspace_label, window_label, clock, psbutton, nsbutton, + pwbutton, nwbutton; + + int x_hidden, y_hidden, hour, minute, grab_x, grab_y; + unsigned int window_label_w, workspace_label_w, clock_w, + button_w, bevel_w, label_h; + + Rect rect; + } frame; + + class HideHandler : public TimeoutHandler { + public: + Toolbar *toolbar; + + virtual void timeout(void); + } hide_handler; + + Blackbox *blackbox; + BScreen *screen; + BTimer *clock_timer, *hide_timer; + Toolbarmenu *toolbarmenu; + Strut strut; + + std::string new_workspace_name; + size_t new_name_pos; + + friend class HideHandler; + friend class Toolbarmenu; + friend class Toolbarmenu::Placementmenu; + + void redrawPrevWorkspaceButton(bool pressed = False, bool redraw = False); + void redrawNextWorkspaceButton(bool pressed = False, bool redraw = False); + void redrawPrevWindowButton(bool preseed = False, bool redraw = False); + void redrawNextWindowButton(bool preseed = False, bool redraw = False); + + void updateStrut(void); + +#ifdef HAVE_STRFTIME + void checkClock(bool redraw = False); +#else // HAVE_STRFTIME + void checkClock(bool redraw = False, bool date = False); +#endif // HAVE_STRFTIME + + Toolbar(const Toolbar&); + Toolbar& operator=(const Toolbar&); + +public: + Toolbar(BScreen *scrn); + virtual ~Toolbar(void); + + inline Toolbarmenu *getMenu(void) { return toolbarmenu; } + + inline bool isEditing(void) const { return editing; } + inline bool isOnTop(void) const { return on_top; } + inline bool isHidden(void) const { return hidden; } + inline bool doAutoHide(void) const { return do_auto_hide; } + + inline Window getWindowID(void) const { return frame.window; } + + inline const Rect& getRect(void) const { return frame.rect; } + inline unsigned int getWidth(void) const { return frame.rect.width(); } + inline unsigned int getHeight(void) const { return frame.rect.height(); } + inline unsigned int getExposedHeight(void) const + { return ((do_auto_hide) ? frame.bevel_w : frame.rect.height()); } + inline int getX(void) const + { return ((hidden) ? frame.x_hidden : frame.rect.x()); } + inline int getY(void) const + { return ((hidden) ? frame.y_hidden : frame.rect.y()); } + + void buttonPressEvent(XButtonEvent *be); + void buttonReleaseEvent(XButtonEvent *re); + void enterNotifyEvent(XCrossingEvent * /*unused*/); + void leaveNotifyEvent(XCrossingEvent * /*unused*/); + void exposeEvent(XExposeEvent *ee); + void keyPressEvent(XKeyEvent *ke); + + void edit(void); + void reconfigure(void); + void toggleAutoHide(void); + + void redrawWindowLabel(bool redraw = False); + void redrawWorkspaceLabel(bool redraw = False); + + virtual void timeout(void); + + enum { TopLeft = 1, BottomLeft, TopCenter, + BottomCenter, TopRight, BottomRight }; +}; + + +#endif // __Toolbar_hh diff --git a/src/Util.cc b/src/Util.cc index 14e0f32a..0300e52b 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -1,8 +1,7 @@ // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -// Util.cc for Openbox -// Copyright (c) 2002 - 2002 Ben Jansens (ben at orodu.net) -// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry (shaleh at debian.org) -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net) +// Util.cc for Blackbox - an X11 Window manager +// Copyright (c) 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000, 2002 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -22,47 +21,202 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -#include "../config.h" +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif // HAVE_CONFIG_H -#ifdef HAVE_SYS_TYPES_H -# include +extern "C" { +#ifdef HAVE_STRING_H +#include #endif - -#ifdef HAVE_UNISTD_H -# include -#endif - #ifdef HAVE_STDLIB_H -# include +#include #endif +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else // !TIME_WITH_SYS_TIME +# ifdef HAVE_SYS_TIME_H +# include +# else // !HAVE_SYS_TIME_H +# include +# endif // HAVE_SYS_TIME_H +#endif // TIME_WITH_SYS_TIME +#ifdef HAVE_UNISTD_H +#include +#endif // HAVE_UNISTD_H +#if defined(HAVE_PROCESS_H) && defined(__EMX__) +# include +#endif // HAVE_PROCESS_H __EMX__ +} + +#include + +#include + +#include "Util.hh" + +using std::string; + + +void Rect::setX(int __x) { + _x2 += __x - _x1; + _x1 = __x; +} + + +void Rect::setY(int __y) +{ + _y2 += __y - _y1; + _y1 = __y; +} + + +void Rect::setPos(int __x, int __y) { + _x2 += __x - _x1; + _x1 = __x; + _y2 += __y - _y1; + _y1 = __y; +} + + +void Rect::setWidth(unsigned int __w) { + _x2 = __w + _x1 - 1; +} + + +void Rect::setHeight(unsigned int __h) { + _y2 = __h + _y1 - 1; +} + + +void Rect::setSize(unsigned int __w, unsigned int __h) { + _x2 = __w + _x1 - 1; + _y2 = __h + _y1 - 1; +} + + +void Rect::setRect(int __x, int __y, unsigned int __w, unsigned int __h) { + *this = Rect(__x, __y, __w, __h); +} + + +void Rect::setCoords(int __l, int __t, int __r, int __b) { + _x1 = __l; + _y1 = __t; + _x2 = __r; + _y2 = __b; +} + +Rect Rect::operator|(const Rect &a) const { + Rect b; + b._x1 = std::min(_x1, a._x1); + b._y1 = std::min(_y1, a._y1); + b._x2 = std::max(_x2, a._x2); + b._y2 = std::max(_y2, a._y2); + + return b; +} + + +Rect Rect::operator&(const Rect &a) const { + Rect b; + + b._x1 = std::max(_x1, a._x1); + b._y1 = std::max(_y1, a._y1); + b._x2 = std::min(_x2, a._x2); + b._y2 = std::min(_y2, a._y2); + + return b; +} + + +bool Rect::intersects(const Rect &a) const { + return std::max(_x1, a._x1) <= std::min(_x2, a._x2) && + std::max(_y1, a._y1) <= std::min(_y2, a._y2); +} + + +string expandTilde(const string& s) { + if (s[0] != '~') return s; + + const char* const home = getenv("HOME"); + if (home == NULL) return s; + + return string(home + s.substr(s.find('/'))); +} + + +void bexec(const string& command, const string& displaystring) { #ifndef __EMX__ -void bexec(const char *command, char* displaystring) { if (! fork()) { setsid(); - putenv(displaystring); - execl("/bin/sh", "/bin/sh", "-c", command, NULL); + int ret = putenv(const_cast(displaystring.c_str())); + assert(ret != -1); + string cmd = "exec "; + cmd += command; + execl("/bin/sh", "/bin/sh", "-c", cmd.c_str(), NULL); exit(0); } -} +#else // __EMX__ + spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", command, NULL); #endif // !__EMX__ +} -char *bstrdup(const char *s) { - const int l = strlen(s) + 1; - char *n = new char[l]; - strncpy(n, s, l); - return n; +#ifndef HAVE_BASENAME +string basename (const string& path) { + string::size_type slash = path.rfind('/'); + if (slash == string::npos) + return path; + return path.substr(slash+1); } +#endif // HAVE_BASENAME -#ifndef HAVE_BASENAME -char *basename (char *s) { - char *save = s; +string textPropertyToString(Display *display, XTextProperty& text_prop) { + string ret; - while (*s) if (*s++ == '/') save = s; + if (text_prop.value && text_prop.nitems > 0) { + ret = (char *) text_prop.value; + if (text_prop.encoding != XA_STRING) { + text_prop.nitems = strlen((char *) text_prop.value); - return save; + char **list; + int num; + if (XmbTextPropertyToTextList(display, &text_prop, + &list, &num) == Success && + num > 0 && *list) { + ret = *list; + XFreeStringList(list); + } + } + } + + return ret; +} + + +timeval normalizeTimeval(const timeval &tm) { + timeval ret = tm; + + while (ret.tv_usec < 0) { + if (ret.tv_sec > 0) { + --ret.tv_sec; + ret.tv_usec += 1000000; + } else { + ret.tv_usec = 0; + } + } + + if (ret.tv_usec >= 1000000) { + ret.tv_sec += ret.tv_usec / 1000000; + ret.tv_usec %= 1000000; + } + + if (ret.tv_sec < 0) ret.tv_sec = 0; + + return ret; } -#endif // HAVE_BASENAME diff --git a/src/Util.h b/src/Util.h deleted file mode 100644 index ad45c403..00000000 --- a/src/Util.h +++ /dev/null @@ -1,39 +0,0 @@ -// Util.h for Openbox -// Copyright (c) 2002 - 2002 Ben Jansens (ben@orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Util_hh -#define __Util_hh - -#ifdef DEBUG -# include -# define ASSERT(x) assert(x) -#else // !DEBUG -# define ASSERT(x) -#endif // DEBUG - -struct PointerAssassin { - template - inline void operator()(const T ptr) const { - delete ptr; - } -}; - -#endif // __Util_hh diff --git a/src/Util.hh b/src/Util.hh new file mode 100644 index 00000000..1536226c --- /dev/null +++ b/src/Util.hh @@ -0,0 +1,102 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Util.cc for Blackbox - an X11 Window manager +// Copyright (c) 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef _BLACKBOX_UTIL_HH +#define _BLACKBOX_UTIL_HH + +#include +#include + +#include + +class Rect { +public: + inline Rect(void) : _x1(0), _y1(0), _x2(0), _y2(0) { } + inline Rect(int __x, int __y, unsigned int __w, unsigned int __h) + : _x1(__x), _y1(__y), _x2(__w + __x - 1), _y2(__h + __y - 1) { } + inline explicit Rect(const XRectangle& xrect) + : _x1(xrect.x), _y1(xrect.y), _x2(xrect.width + xrect.x - 1), + _y2(xrect.height + xrect.y - 1) { } + + inline int left(void) const { return _x1; } + inline int top(void) const { return _y1; } + inline int right(void) const { return _x2; } + inline int bottom(void) const { return _y2; } + + inline int x(void) const { return _x1; } + inline int y(void) const { return _y1; } + void setX(int __x); + void setY(int __y); + void setPos(int __x, int __y); + + inline unsigned int width(void) const { return _x2 - _x1 + 1; } + inline unsigned int height(void) const { return _y2 - _y1 + 1; } + void setWidth(unsigned int __w); + void setHeight(unsigned int __h); + void setSize(unsigned int __w, unsigned int __h); + + void setRect(int __x, int __y, unsigned int __w, unsigned int __h); + + void setCoords(int __l, int __t, int __r, int __b); + + inline bool operator==(const Rect &a) + { return _x1 == a._x1 && _y1 == a._y1 && _x2 == a._x2 && _y2 == a._y2; } + inline bool operator!=(const Rect &a) { return ! operator==(a); } + + Rect operator|(const Rect &a) const; + Rect operator&(const Rect &a) const; + inline Rect &operator|=(const Rect &a) { *this = *this | a; return *this; } + inline Rect &operator&=(const Rect &a) { *this = *this & a; return *this; } + + inline bool valid(void) const { return _x2 > _x1 && _y2 > _y1; } + + bool intersects(const Rect &a) const; + +private: + int _x1, _y1, _x2, _y2; +}; + +/* XXX: this needs autoconf help */ +const unsigned int BSENTINEL = 65535; + +std::string expandTilde(const std::string& s); + +void bexec(const std::string& command, const std::string& displaystring); + +#ifndef HAVE_BASENAME +std::string basename(const std::string& path); +#endif + +std::string textPropertyToString(Display *display, XTextProperty& text_prop); + +struct timeval; // forward declare to avoid the header +timeval normalizeTimeval(const timeval &tm); + +struct PointerAssassin { + template + inline void operator()(const T ptr) const { + delete ptr; + } +}; + +#endif diff --git a/src/Window.cc b/src/Window.cc index 342864c9..7ca881ac 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -1,7 +1,7 @@ -// Window.cc for Openbox -// Copyright (c) 2002 - 2002 Ben Jansens (ben at orodu.net) -// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry (shaleh at debian.org) -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net) +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Window.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000, 2002 Brad Hughes // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -21,20 +21,15 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H +extern "C" { #include #include -#ifdef HAVE_STRING_H +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H @@ -43,122 +38,118 @@ # include # endif // HAVE_STDIO_H #endif // DEBUG +} + +#include + +#include "i18n.hh" +#include "blackbox.hh" +#include "GCCache.hh" +#include "Iconmenu.hh" +#include "Image.hh" +#include "Screen.hh" +#include "Toolbar.hh" +#include "Util.hh" +#include "Window.hh" +#include "Windowmenu.hh" +#include "Workspace.hh" +#include "Slit.hh" -#include "i18n.h" -#include "openbox.h" -#include "Iconmenu.h" -#include "Screen.h" -#include "Toolbar.h" -#include "Window.h" -#include "Windowmenu.h" -#include "Workspace.h" -#ifdef SLIT -# include "Slit.h" -#endif // SLIT -#include "Util.h" /* * Initializes the class with default values/the window's set initial values. */ -OpenboxWindow::OpenboxWindow(Openbox &o, Window w, BScreen *s) : openbox(o) { +BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { + // fprintf(stderr, "BlackboxWindow size: %d bytes\n", + // sizeof(BlackboxWindow)); + #ifdef DEBUG - fprintf(stderr, i18n(WindowSet, WindowCreating, - "OpenboxWindow::OpenboxWindow(): creating 0x%lx\n"), - w); + 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; - display = openbox.getXDisplay(); + screen = s; + + if (! validateClient()) { + delete this; + return; + } - openbox.grab(); - if (! validateClient()) 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(blackbox->getXDisplay(), client.window, + CWEventMask|CWDontPropagate, &attrib_set); // fetch client size and placement XWindowAttributes wattrib; - if ((! XGetWindowAttributes(display, client.window, &wattrib)) || + if ((! XGetWindowAttributes(blackbox->getXDisplay(), + client.window, &wattrib)) || (! wattrib.screen) || wattrib.override_redirect) { #ifdef DEBUG fprintf(stderr, - i18n(WindowSet, WindowXGetWindowAttributesFail, - "OpenboxWindow::OpenboxWindow(): XGetWindowAttributes " - "failed\n")); + "BlackboxWindow::BlackboxWindow(): XGetWindowAttributes failed\n"); #endif // DEBUG - openbox.ungrab(); + delete this; return; } - if (s) { - screen = s; - } else { - screen = openbox.searchScreen(RootWindowOfScreen(wattrib.screen)); - if (! screen) { -#ifdef DEBUG - fprintf(stderr, i18n(WindowSet, WindowCannotFindScreen, - "OpenboxWindow::OpenboxWindow(): can't find screen\n" - "\tfor root window 0x%lx\n"), - RootWindowOfScreen(wattrib.screen)); -#endif // DEBUG - - openbox.ungrab(); - return; - } - } - flags.moving = flags.resizing = flags.shaded = flags.visible = - flags.iconic = flags.transient = flags.focused = - flags.stuck = flags.modal = flags.send_focus_message = - flags.shaped = flags.managed = False; + flags.iconic = flags.focused = flags.stuck = flags.modal = + flags.send_focus_message = flags.shaped = False; flags.maximized = 0; - openbox_attrib.workspace = workspace_number = window_number = -1; + blackbox_attrib.workspace = window_number = BSENTINEL; - openbox_attrib.flags = openbox_attrib.attrib = openbox_attrib.stack - = openbox_attrib.decoration = 0l; - openbox_attrib.premax_x = openbox_attrib.premax_y = 0; - openbox_attrib.premax_w = openbox_attrib.premax_h = 0; + blackbox_attrib.flags = blackbox_attrib.attrib = blackbox_attrib.stack + = blackbox_attrib.decoration = 0l; + 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 = 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.pbutton_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.pbutton = frame.ugrip = frame.fgrip = None; + frame.pbutton = frame.ugrip = frame.fgrip = decorations; - decorations.titlebar = decorations.border = decorations.handle = True; - decorations.iconify = decorations.maximize = decorations.menu = True; - functions.resize = functions.move = functions.iconify = - functions.maximize = True; - functions.close = decorations.close = False; + decorations = Decor_Titlebar | Decor_Border | Decor_Handle | + Decor_Iconify | Decor_Maximize; + functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize; client.wm_hint_flags = client.normal_hint_flags = 0; - client.transient_for = client.transient = 0; - client.title = 0; - client.title_len = 0; - client.icon_title = 0; - client.mwm_hint = (MwmHints *) 0; - client.openbox_hint = (OpenboxHints *) 0; + client.transient_for = 0; // get 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.x = wattrib.x; - client.y = wattrib.y; - client.width = wattrib.width; - client.height = wattrib.height; + client.rect.setRect(wattrib.x, wattrib.y, wattrib.width, wattrib.height); client.old_bw = wattrib.border_width; windowmenu = 0; lastButtonPressTime = 0; - image_ctrl = screen->getImageControl(); - timer = new BTimer(openbox, *this); - timer->setTimeout(openbox.getAutoRaiseDelay()); - timer->fireOnce(True); + timer = new BTimer(blackbox, this); + timer->setTimeout(blackbox->getAutoRaiseDelay()); - getOpenboxHints(); - if (! client.openbox_hint) + if (! getBlackboxHints()) getMWMHints(); // get size, aspect, minimum/maximum size and other hints set by the @@ -167,268 +158,170 @@ OpenboxWindow::OpenboxWindow(Openbox &o, Window w, BScreen *s) : openbox(o) { getWMHints(); getWMNormalHints(); -#ifdef SLIT if (client.initial_state == WithdrawnState) { screen->getSlit()->addClient(client.window); - openbox.ungrab(); delete this; return; } -#endif // SLIT - flags.managed = True; - openbox.saveWindowSearch(client.window, this); + frame.window = createToplevelWindow(); + frame.plate = createChildWindow(frame.window); + associateClientWindow(); - // determine if this is a transient window - Window win; - if (XGetTransientForHint(display, client.window, &win)) { - if (win && (win != client.window)) { - OpenboxWindow *tr; - if ((tr = openbox.searchWindow(win))) { - while (tr->client.transient) tr = tr->client.transient; - client.transient_for = tr; - tr->client.transient = this; - flags.stuck = client.transient_for->flags.stuck; - flags.transient = True; - } else if (win == client.window_group) { - if ((tr = openbox.searchGroup(win, this))) { - while (tr->client.transient) tr = tr->client.transient; - client.transient_for = tr; - tr->client.transient = this; - flags.stuck = client.transient_for->flags.stuck; - flags.transient = True; - } - } - } + blackbox->saveWindowSearch(frame.window, this); + blackbox->saveWindowSearch(frame.plate, this); + blackbox->saveWindowSearch(client.window, this); - if (win == screen->getRootWindow()) flags.modal = True; - } + // determine if this is a transient window + getTransientInfo(); // adjust the window decorations based on transience and window sizes - if (flags.transient) - decorations.maximize = decorations.handle = functions.maximize = False; + if (isTransient()) { + decorations &= ~(Decor_Maximize | Decor_Handle); + functions &= ~Func_Maximize; + } if ((client.normal_hint_flags & PMinSize) && (client.normal_hint_flags & PMaxSize) && client.max_width <= client.min_width && client.max_height <= client.min_height) { - decorations.maximize = decorations.handle = - functions.resize = functions.maximize = False; + decorations &= ~(Decor_Maximize | Decor_Handle); + functions &= ~(Func_Resize | Func_Maximize); } upsize(); - place_window = true; - if (openbox.isStartup() || flags.transient || + bool place_window = True; + if (blackbox->isStartup() || isTransient() || client.normal_hint_flags & (PPosition|USPosition)) { setGravityOffsets(); - if ((openbox.isStartup()) || - (frame.x >= 0 && - (signed) (frame.y + frame.y_border) >= 0 && - frame.x <= (signed) screen->size().w() && - frame.y <= (signed) screen->size().h())) - place_window = false; - } - - frame.window = createToplevelWindow(frame.x, frame.y, frame.width, - frame.height, - frame.border_w); - openbox.saveWindowSearch(frame.window, this); - - frame.plate = createChildWindow(frame.window); - openbox.saveWindowSearch(frame.plate, this); - if (decorations.titlebar) { - frame.title = createChildWindow(frame.window); - frame.label = createChildWindow(frame.title); - openbox.saveWindowSearch(frame.title, this); - openbox.saveWindowSearch(frame.label, this); + if (blackbox->isStartup() || + client.rect.intersects(screen->availableArea())) + place_window = False; } - if (decorations.handle) { - frame.handle = createChildWindow(frame.window); - openbox.saveWindowSearch(frame.handle, this); + if (decorations & Decor_Titlebar) + createTitlebar(); - frame.left_grip = - createChildWindow(frame.handle, openbox.getLowerLeftAngleCursor()); - openbox.saveWindowSearch(frame.left_grip, this); + if (decorations & Decor_Handle) + createHandle(); - frame.right_grip = - createChildWindow(frame.handle, openbox.getLowerRightAngleCursor()); - openbox.saveWindowSearch(frame.right_grip, this); +#ifdef SHAPE + if (blackbox->hasShapeExtensions() && flags.shaped) { + configureShape(); } +#endif // SHAPE - associateClientWindow(); - - if (! screen->sloppyFocus()) - openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask, - GrabModeSync, GrabModeSync, frame.plate, None); + if ((! screen->isSloppyFocus()) || screen->doClickRaise()) { + // grab button 1 for changing focus/raising + blackbox->grabButton(Button1, 0, frame.plate, True, ButtonPressMask, + GrabModeSync, GrabModeSync, frame.plate, None); + } - openbox.grabButton(Button1, Mod1Mask, frame.window, True, - ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, - GrabModeAsync, frame.window, openbox.getMoveCursor()); - openbox.grabButton(Button2, Mod1Mask, frame.window, True, - ButtonReleaseMask, GrabModeAsync, GrabModeAsync, frame.window, None); - openbox.grabButton(Button3, Mod1Mask, frame.window, True, - ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, - GrabModeAsync, frame.window, None); + blackbox->grabButton(Button1, Mod1Mask, frame.window, True, + ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, + GrabModeAsync, frame.window, blackbox->getMoveCursor()); + blackbox->grabButton(Button2, Mod1Mask, frame.window, True, + ButtonReleaseMask, GrabModeAsync, GrabModeAsync, + frame.window, None); + blackbox->grabButton(Button3, Mod1Mask, frame.window, True, + ButtonReleaseMask | ButtonMotionMask, GrabModeAsync, + GrabModeAsync, frame.window, + blackbox->getLowerRightAngleCursor()); positionWindows(); - XRaiseWindow(display, frame.plate); - XMapSubwindows(display, frame.plate); - if (decorations.titlebar) XMapSubwindows(display, frame.title); - XMapSubwindows(display, frame.window); + decorate(); - if (decorations.menu) - windowmenu = new Windowmenu(*this); + if (decorations & Decor_Titlebar) + XMapSubwindows(blackbox->getXDisplay(), frame.title); + XMapSubwindows(blackbox->getXDisplay(), frame.window); - decorate(); + windowmenu = new Windowmenu(this); - if (workspace_number < 0 || workspace_number >= screen->getWorkspaceCount()) + if (blackbox_attrib.workspace >= screen->getWorkspaceCount()) screen->getCurrentWorkspace()->addWindow(this, place_window); else - screen->getWorkspace(workspace_number)->addWindow(this, place_window); + screen->getWorkspace(blackbox_attrib.workspace)-> + addWindow(this, place_window); - configure(frame.x, frame.y, frame.width, frame.height); + 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()); + } if (flags.shaded) { flags.shaded = False; shade(); } - if (flags.maximized && functions.maximize) { - unsigned int button = flags.maximized; - flags.maximized = 0; - maximize(button); + if (flags.maximized && (functions & Func_Maximize)) { + remaximize(); } setFocusFlag(False); - - openbox.ungrab(); } -OpenboxWindow::~OpenboxWindow(void) { - if (flags.moving || flags.resizing) { - screen->hideGeometry(); - XUngrabPointer(display, CurrentTime); - } - - if (workspace_number != -1 && window_number != -1) { - if (flags.stuck) { - // make sure no other workspaces think that we're focused - for (int i=0; i < screen->getWorkspaceCount(); i++) - screen->getWorkspace(i)->removeWindow(this); - } else - screen->getWorkspace(workspace_number)->removeWindow(this); - } else if (flags.iconic) - screen->removeIcon(this); - - if (timer) { - if (timer->isTiming()) timer->stop(); - delete timer; - } - - if (windowmenu) delete windowmenu; - - if (client.title) - delete [] client.title; - - if (client.icon_title) - delete [] client.icon_title; - - if (client.mwm_hint) - XFree(client.mwm_hint); +BlackboxWindow::~BlackboxWindow(void) { - if (client.openbox_hint) - XFree(client.openbox_hint); - - if (client.window_group) - openbox.removeGroupSearch(client.window_group); - - if (flags.transient && client.transient_for) - client.transient_for->client.transient = client.transient; - if (client.transient) - client.transient->client.transient_for = client.transient_for; - - if (frame.close_button) { - openbox.removeWindowSearch(frame.close_button); - XDestroyWindow(display, frame.close_button); - } +#ifdef DEBUG + fprintf(stderr, "BlackboxWindow::~BlackboxWindow: destroying 0x%lx\n", + client.window); +#endif // DEBUG - if (frame.iconify_button) { - openbox.removeWindowSearch(frame.iconify_button); - XDestroyWindow(display, frame.iconify_button); - } + if (! timer) // window not managed... + return; - if (frame.maximize_button) { - openbox.removeWindowSearch(frame.maximize_button); - XDestroyWindow(display, frame.maximize_button); + if (flags.moving || flags.resizing) { + screen->hideGeometry(); + XUngrabPointer(blackbox->getXDisplay(), CurrentTime); } - if (frame.title) { - if (frame.ftitle) - image_ctrl->removeImage(frame.ftitle); - - if (frame.utitle) - image_ctrl->removeImage(frame.utitle); - - if (frame.flabel) - image_ctrl->removeImage(frame.flabel); + delete timer; - if( frame.ulabel) - image_ctrl->removeImage(frame.ulabel); + delete windowmenu; - openbox.removeWindowSearch(frame.label); - openbox.removeWindowSearch(frame.title); - XDestroyWindow(display, frame.label); - XDestroyWindow(display, frame.title); + if (client.window_group) { + BWindowGroup *group = blackbox->searchGroup(client.window_group); + if (group) group->removeWindow(this); } - if (frame.handle) { - if (frame.fhandle) - image_ctrl->removeImage(frame.fhandle); - - if (frame.uhandle) - image_ctrl->removeImage(frame.uhandle); - - if (frame.fgrip) - image_ctrl->removeImage(frame.fgrip); - - if (frame.ugrip) - image_ctrl->removeImage(frame.ugrip); - - openbox.removeWindowSearch(frame.handle); - openbox.removeWindowSearch(frame.right_grip); - openbox.removeWindowSearch(frame.left_grip); - XDestroyWindow(display, frame.right_grip); - XDestroyWindow(display, frame.left_grip); - XDestroyWindow(display, frame.handle); + // 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 (frame.fbutton) - image_ctrl->removeImage(frame.fbutton); + 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.ubutton) - image_ctrl->removeImage(frame.ubutton); + if (frame.title) + destroyTitlebar(); - if (frame.pbutton) - image_ctrl->removeImage(frame.pbutton); + if (frame.handle) + destroyHandle(); if (frame.plate) { - openbox.removeWindowSearch(frame.plate); - XDestroyWindow(display, frame.plate); + blackbox->removeWindowSearch(frame.plate); + XDestroyWindow(blackbox->getXDisplay(), frame.plate); } if (frame.window) { - openbox.removeWindowSearch(frame.window); - XDestroyWindow(display, frame.window); + blackbox->removeWindowSearch(frame.window); + XDestroyWindow(blackbox->getXDisplay(), frame.window); } - if (flags.managed) { - openbox.removeWindowSearch(client.window); - screen->removeNetizen(client.window); - } + blackbox->removeWindowSearch(client.window); } @@ -437,23 +330,20 @@ OpenboxWindow::~OpenboxWindow(void) { * width. * Returns: the newly created window */ -Window OpenboxWindow::createToplevelWindow(int x, int y, unsigned int width, - unsigned int height, - unsigned int borderwidth) -{ +Window BlackboxWindow::createToplevelWindow(void) { XSetWindowAttributes attrib_create; unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap | - CWOverrideRedirect | CWEventMask; + CWOverrideRedirect | CWEventMask; attrib_create.background_pixmap = None; attrib_create.colormap = screen->getColormap(); attrib_create.override_redirect = True; attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask | EnterWindowMask; + ButtonMotionMask | EnterWindowMask; - return XCreateWindow(display, screen->getRootWindow(), x, y, width, height, - borderwidth, screen->getDepth(), InputOutput, - screen->getVisual(), create_mask, + return XCreateWindow(blackbox->getXDisplay(), screen->getRootWindow(), + -1, -1, 1, 1, frame.border_w, screen->getDepth(), + InputOutput, screen->getVisual(), create_mask, &attrib_create); } @@ -462,522 +352,470 @@ Window OpenboxWindow::createToplevelWindow(int x, int y, unsigned int width, * Creates a child window, and optionally associates a given cursor with * the new window. */ -Window OpenboxWindow::createChildWindow(Window parent, Cursor cursor) { +Window BlackboxWindow::createChildWindow(Window parent, Cursor cursor) { XSetWindowAttributes attrib_create; unsigned long create_mask = CWBackPixmap | CWBorderPixel | - CWEventMask; + CWEventMask; attrib_create.background_pixmap = None; attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask | ExposureMask | - EnterWindowMask | LeaveWindowMask; + ButtonMotionMask | ExposureMask; if (cursor) { create_mask |= CWCursor; attrib_create.cursor = cursor; } - return XCreateWindow(display, parent, 0, 0, 1, 1, 0, screen->getDepth(), - InputOutput, screen->getVisual(), create_mask, - &attrib_create); + return XCreateWindow(blackbox->getXDisplay(), parent, 0, 0, 1, 1, 0, + screen->getDepth(), InputOutput, screen->getVisual(), + create_mask, &attrib_create); } -void OpenboxWindow::associateClientWindow(void) { - XSetWindowBorderWidth(display, client.window, 0); +void BlackboxWindow::associateClientWindow(void) { + XSetWindowBorderWidth(blackbox->getXDisplay(), client.window, 0); getWMName(); getWMIconName(); - XChangeSaveSet(display, client.window, SetModeInsert); - XSetWindowAttributes attrib_set; + XChangeSaveSet(blackbox->getXDisplay(), client.window, SetModeInsert); - XSelectInput(display, frame.plate, NoEventMask); - XReparentWindow(display, client.window, frame.plate, 0, 0); - XSelectInput(display, frame.plate, SubstructureRedirectMask); + XSelectInput(blackbox->getXDisplay(), frame.plate, SubstructureRedirectMask); - XFlush(display); + XGrabServer(blackbox->getXDisplay()); + XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask); + XReparentWindow(blackbox->getXDisplay(), client.window, frame.plate, 0, 0); + XSelectInput(blackbox->getXDisplay(), client.window, + PropertyChangeMask | FocusChangeMask | StructureNotifyMask); + XUngrabServer(blackbox->getXDisplay()); - attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask | - FocusChangeMask; - attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask; + XRaiseWindow(blackbox->getXDisplay(), frame.plate); + XMapSubwindows(blackbox->getXDisplay(), frame.plate); - XChangeWindowAttributes(display, client.window, CWEventMask|CWDontPropagate, - &attrib_set); #ifdef SHAPE - if (openbox.hasShapeExtensions()) { - XShapeSelectInput(display, client.window, ShapeNotifyMask); + if (blackbox->hasShapeExtensions()) { + XShapeSelectInput(blackbox->getXDisplay(), client.window, + ShapeNotifyMask); + Bool shaped = False; int foo; unsigned int ufoo; - XShapeQueryExtents(display, client.window, &flags.shaped, &foo, &foo, - &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo); - - if (flags.shaped) { - XShapeCombineShape(display, frame.window, ShapeBounding, - frame.mwm_border_w, frame.y_border + - frame.mwm_border_w, client.window, - ShapeBounding, ShapeSet); - - int num = 1; - XRectangle xrect[2]; - xrect[0].x = xrect[0].y = 0; - xrect[0].width = frame.width; - xrect[0].height = frame.y_border; - - if (decorations.handle) { - xrect[1].x = 0; - xrect[1].y = frame.y_handle; - xrect[1].width = frame.width; - xrect[1].height = frame.handle_h + frame.border_w; - num++; - } - - XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0, - xrect, num, ShapeUnion, Unsorted); - } + XShapeQueryExtents(blackbox->getXDisplay(), client.window, &shaped, + &foo, &foo, &ufoo, &ufoo, &foo, &foo, &foo, + &ufoo, &ufoo); + flags.shaped = shaped; } #endif // SHAPE - - if (decorations.iconify) createIconifyButton(); - if (decorations.maximize) createMaximizeButton(); - if (decorations.close) createCloseButton(); } -void OpenboxWindow::decorate(void) { - Pixmap tmp = frame.fbutton; - BTexture *texture = &(screen->getWindowStyle()->b_focus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.fbutton = None; - frame.fbutton_pixel = texture->getColor()->getPixel(); - } else { - frame.fbutton = - image_ctrl->renderImage(frame.button_w, frame.button_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); +void BlackboxWindow::decorate(void) { + 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(); - tmp = frame.ubutton; texture = &(screen->getWindowStyle()->b_unfocus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.ubutton = None; - frame.ubutton_pixel = texture->getColor()->getPixel(); - } else { - frame.ubutton = - image_ctrl->renderImage(frame.button_w, frame.button_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + frame.ubutton = texture->render(frame.button_w, frame.button_w, + frame.ubutton); + if (! frame.ubutton) + frame.ubutton_pixel = texture->color().pixel(); - tmp = frame.pbutton; texture = &(screen->getWindowStyle()->b_pressed); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.pbutton = None; - frame.pbutton_pixel = texture->getColor()->getPixel(); - } else { - frame.pbutton = - image_ctrl->renderImage(frame.button_w, frame.button_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + frame.pbutton = texture->render(frame.button_w, frame.button_w, + frame.pbutton); + if (! frame.pbutton) + frame.pbutton_pixel = texture->color().pixel(); - if (decorations.titlebar) { - tmp = frame.ftitle; + if (decorations & Decor_Titlebar) { texture = &(screen->getWindowStyle()->t_focus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.ftitle = None; - frame.ftitle_pixel = texture->getColor()->getPixel(); - } else { - frame.ftitle = - image_ctrl->renderImage(frame.width, frame.title_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + frame.ftitle = texture->render(frame.inside_w, frame.title_h, + frame.ftitle); + if (! frame.ftitle) + frame.ftitle_pixel = texture->color().pixel(); - tmp = frame.utitle; texture = &(screen->getWindowStyle()->t_unfocus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.utitle = None; - frame.utitle_pixel = texture->getColor()->getPixel(); - } else { - frame.utitle = - image_ctrl->renderImage(frame.width, frame.title_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + frame.utitle = texture->render(frame.inside_w, frame.title_h, + frame.utitle); + if (! frame.utitle) + frame.utitle_pixel = texture->color().pixel(); - XSetWindowBorder(display, frame.title, - screen->getBorderColor()->getPixel()); + XSetWindowBorder(blackbox->getXDisplay(), frame.title, + screen->getBorderColor()->pixel()); decorateLabel(); } - if (decorations.border) { - frame.fborder_pixel = screen->getWindowStyle()->f_focus.getPixel(); - frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.getPixel(); - openbox_attrib.flags |= AttribDecoration; - openbox_attrib.decoration = DecorNormal; + if (decorations & Decor_Border) { + frame.fborder_pixel = screen->getWindowStyle()->f_focus.pixel(); + frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.pixel(); + blackbox_attrib.flags |= AttribDecoration; + blackbox_attrib.decoration = DecorNormal; } else { - openbox_attrib.flags |= AttribDecoration; - openbox_attrib.decoration = DecorNone; + blackbox_attrib.flags |= AttribDecoration; + blackbox_attrib.decoration = DecorNone; } - if (decorations.handle) { - tmp = frame.fhandle; + if (decorations & Decor_Handle) { texture = &(screen->getWindowStyle()->h_focus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.fhandle = None; - frame.fhandle_pixel = texture->getColor()->getPixel(); - } else { - frame.fhandle = - image_ctrl->renderImage(frame.width, frame.handle_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + frame.fhandle = texture->render(frame.inside_w, frame.handle_h, + frame.fhandle); + if (! frame.fhandle) + frame.fhandle_pixel = texture->color().pixel(); - tmp = frame.uhandle; texture = &(screen->getWindowStyle()->h_unfocus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.uhandle = None; - frame.uhandle_pixel = texture->getColor()->getPixel(); - } else { - frame.uhandle = - image_ctrl->renderImage(frame.width, frame.handle_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + frame.uhandle = texture->render(frame.inside_w, frame.handle_h, + frame.uhandle); + if (! frame.uhandle) + frame.uhandle_pixel = texture->color().pixel(); - tmp = frame.fgrip; texture = &(screen->getWindowStyle()->g_focus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.fgrip = None; - frame.fgrip_pixel = texture->getColor()->getPixel(); - } else { - frame.fgrip = - image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + frame.fgrip = texture->render(frame.grip_w, frame.handle_h, frame.fgrip); + if (! frame.fgrip) + frame.fgrip_pixel = texture->color().pixel(); - tmp = frame.ugrip; texture = &(screen->getWindowStyle()->g_unfocus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.ugrip = None; - frame.ugrip_pixel = texture->getColor()->getPixel(); - } else { - frame.ugrip = - image_ctrl->renderImage(frame.grip_w, frame.grip_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + frame.ugrip = texture->render(frame.grip_w, frame.handle_h, frame.ugrip); + if (! frame.ugrip) + frame.ugrip_pixel = texture->color().pixel(); - XSetWindowBorder(display, frame.handle, - screen->getBorderColor()->getPixel()); - XSetWindowBorder(display, frame.left_grip, - screen->getBorderColor()->getPixel()); - XSetWindowBorder(display, frame.right_grip, - screen->getBorderColor()->getPixel()); + XSetWindowBorder(blackbox->getXDisplay(), frame.handle, + screen->getBorderColor()->pixel()); + XSetWindowBorder(blackbox->getXDisplay(), frame.left_grip, + screen->getBorderColor()->pixel()); + XSetWindowBorder(blackbox->getXDisplay(), frame.right_grip, + screen->getBorderColor()->pixel()); } - XSetWindowBorder(display, frame.window, - screen->getBorderColor()->getPixel()); + XSetWindowBorder(blackbox->getXDisplay(), frame.window, + screen->getBorderColor()->pixel()); } -void OpenboxWindow::decorateLabel(void) { - Pixmap tmp = frame.flabel; - BTexture *texture = &(screen->getWindowStyle()->l_focus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.flabel = None; - frame.flabel_pixel = texture->getColor()->getPixel(); - } else { - frame.flabel = - image_ctrl->renderImage(frame.label_w, frame.label_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); +void BlackboxWindow::decorateLabel(void) { + 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(); - tmp = frame.ulabel; texture = &(screen->getWindowStyle()->l_unfocus); - if (texture->getTexture() == (BImage_Flat | BImage_Solid)) { - frame.ulabel = None; - frame.ulabel_pixel = texture->getColor()->getPixel(); - } else { - frame.ulabel = - image_ctrl->renderImage(frame.label_w, frame.label_h, texture); - } - if (tmp) image_ctrl->removeImage(tmp); + 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); + blackbox->saveWindowSearch(frame.handle, this); + + frame.left_grip = + createChildWindow(frame.handle, blackbox->getLowerLeftAngleCursor()); + blackbox->saveWindowSearch(frame.left_grip, this); + + frame.right_grip = + createChildWindow(frame.handle, 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(blackbox->getXDisplay(), frame.left_grip); + XDestroyWindow(blackbox->getXDisplay(), frame.right_grip); + frame.left_grip = frame.right_grip = None; + + blackbox->removeWindowSearch(frame.handle); + XDestroyWindow(blackbox->getXDisplay(), frame.handle); + frame.handle = None; +} + + +void BlackboxWindow::createTitlebar(void) { + frame.title = createChildWindow(frame.window); + frame.label = createChildWindow(frame.title); + 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.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); + + if (frame.pbutton) + screen->getImageControl()->removeImage(frame.pbutton); + + blackbox->removeWindowSearch(frame.title); + blackbox->removeWindowSearch(frame.label); + + XDestroyWindow(blackbox->getXDisplay(), frame.label); + XDestroyWindow(blackbox->getXDisplay(), frame.title); + frame.title = frame.label = None; } -void OpenboxWindow::createCloseButton(void) { - if (decorations.close && frame.title != None) { +void BlackboxWindow::createCloseButton(void) { + if (frame.title != None) { frame.close_button = createChildWindow(frame.title); - openbox.saveWindowSearch(frame.close_button, this); + blackbox->saveWindowSearch(frame.close_button, this); } } -void OpenboxWindow::createIconifyButton(void) { - if (decorations.iconify && frame.title != None) { +void BlackboxWindow::destroyCloseButton(void) { + blackbox->removeWindowSearch(frame.close_button); + XDestroyWindow(blackbox->getXDisplay(), frame.close_button); + frame.close_button = None; +} + + +void BlackboxWindow::createIconifyButton(void) { + if (frame.title != None) { frame.iconify_button = createChildWindow(frame.title); - openbox.saveWindowSearch(frame.iconify_button, this); + blackbox->saveWindowSearch(frame.iconify_button, this); } } -void OpenboxWindow::createMaximizeButton(void) { - if (decorations.maximize && frame.title != None) { +void BlackboxWindow::destroyIconifyButton(void) { + blackbox->removeWindowSearch(frame.iconify_button); + XDestroyWindow(blackbox->getXDisplay(), frame.iconify_button); + frame.iconify_button = None; +} + + +void BlackboxWindow::createMaximizeButton(void) { + if (frame.title != None) { frame.maximize_button = createChildWindow(frame.title); - openbox.saveWindowSearch(frame.maximize_button, this); - } -} - - -void OpenboxWindow::positionButtons() { - const char *format = openbox.getTitleBarLayout(); - const unsigned int bw = frame.bevel_w + 1; - const unsigned int by = frame.bevel_w + 1; - unsigned int bx = frame.bevel_w + 1; - unsigned int bcount = strlen(format) - 1; - - if (!decorations.close) - bcount--; - if (!decorations.maximize) - bcount--; - if (!decorations.iconify) - bcount--; - frame.label_w = frame.width - bx * 2 - (frame.button_w + bw) * bcount; - - bool hasclose, hasiconify, hasmaximize; - hasclose = hasiconify = hasmaximize = false; - - for (int i = 0; format[i] != '\0' && i < 4; i++) { - switch(format[i]) { - case 'C': - if (decorations.close) { - if (frame.close_button == None) - createCloseButton(); - XMoveResizeWindow(display, frame.close_button, bx, by, - frame.button_w, frame.button_h); - XMapWindow(display, frame.close_button); - XClearWindow(display, frame.close_button); - bx += frame.button_w + bw; - hasclose = true; - } - break; - case 'I': - if (decorations.iconify) { - if (frame.iconify_button == None) - createIconifyButton(); - XMoveResizeWindow(display, frame.iconify_button, bx, by, - frame.button_w, frame.button_h); - XMapWindow(display, frame.iconify_button); - XClearWindow(display, frame.iconify_button); - bx += frame.button_w + bw; - hasiconify = true; - } - break; - case 'M': - if (decorations.maximize) { - if (frame.maximize_button == None) - createMaximizeButton(); - XMoveResizeWindow(display, frame.maximize_button, bx, by, - frame.button_w, frame.button_h); - XMapWindow(display, frame.maximize_button); - XClearWindow(display, frame.maximize_button); - bx += frame.button_w + bw; - hasmaximize = true; - } - break; - case 'L': - XMoveResizeWindow(display, frame.label, bx, by - 1, - frame.label_w, frame.label_h); - bx += frame.label_w + bw; - break; - } + blackbox->saveWindowSearch(frame.maximize_button, this); } +} + - if (!hasclose && frame.close_button) { - openbox.removeWindowSearch(frame.close_button); - XDestroyWindow(display, frame.close_button); - frame.close_button = None; +void BlackboxWindow::destroyMaximizeButton(void) { + blackbox->removeWindowSearch(frame.maximize_button); + XDestroyWindow(blackbox->getXDisplay(), frame.maximize_button); + frame.maximize_button = None; +} + + +void BlackboxWindow::positionButtons(bool redecorate_label) { + unsigned int bw = frame.button_w + frame.bevel_w + 1, + by = frame.bevel_w + 1, lx = by, lw = frame.inside_w - by; + + if (decorations & Decor_Iconify) { + if (frame.iconify_button == None) createIconifyButton(); + + XMoveResizeWindow(blackbox->getXDisplay(), frame.iconify_button, by, by, + frame.button_w, frame.button_w); + XMapWindow(blackbox->getXDisplay(), frame.iconify_button); + XClearWindow(blackbox->getXDisplay(), frame.iconify_button); + + lx += bw; + lw -= bw; + } else if (frame.iconify_button) { + destroyIconifyButton(); } - if (!hasiconify && frame.iconify_button) { - openbox.removeWindowSearch(frame.iconify_button); - XDestroyWindow(display, frame.iconify_button); - frame.iconify_button = None; + int bx = frame.inside_w - bw; + + if (decorations & Decor_Close) { + if (frame.close_button == None) createCloseButton(); + + XMoveResizeWindow(blackbox->getXDisplay(), frame.close_button, bx, by, + frame.button_w, frame.button_w); + XMapWindow(blackbox->getXDisplay(), frame.close_button); + XClearWindow(blackbox->getXDisplay(), frame.close_button); + + bx -= bw; + lw -= bw; + } else if (frame.close_button) { + destroyCloseButton(); } - if (!hasmaximize && frame.iconify_button) { - openbox.removeWindowSearch(frame.maximize_button); - XDestroyWindow(display, frame.maximize_button); - frame.maximize_button = None; + if (decorations & Decor_Maximize) { + if (frame.maximize_button == None) createMaximizeButton(); + + XMoveResizeWindow(blackbox->getXDisplay(), frame.maximize_button, bx, by, + frame.button_w, frame.button_w); + XMapWindow(blackbox->getXDisplay(), frame.maximize_button); + XClearWindow(blackbox->getXDisplay(), frame.maximize_button); + + lw -= bw; + } else if (frame.maximize_button) { + destroyMaximizeButton(); } + frame.label_w = lw - by; + XMoveResizeWindow(blackbox->getXDisplay(), frame.label, lx, frame.bevel_w, + frame.label_w, frame.label_h); + if (redecorate_label) decorateLabel(); redrawLabel(); redrawAllButtons(); } -void OpenboxWindow::reconfigure(void) { +void BlackboxWindow::reconfigure(void) { upsize(); - client.x = frame.x + frame.mwm_border_w + frame.border_w; - client.y = frame.y + frame.y_border + frame.mwm_border_w + - frame.border_w; - - if (client.title) { - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen->getWindowStyle()->fontset, - client.title, client.title_len, &ink, &logical); - client.title_text_w = logical.width; - } else { - client.title_text_w = XTextWidth(screen->getWindowStyle()->font, - client.title, client.title_len); - } - client.title_text_w += (frame.bevel_w * 4); - } + client.rect.setPos(frame.rect.left() + frame.margin.left, + frame.rect.top() + frame.margin.top); positionWindows(); decorate(); - XClearWindow(display, frame.window); + XClearWindow(blackbox->getXDisplay(), frame.window); setFocusFlag(flags.focused); - configure(frame.x, frame.y, frame.width, frame.height); - - if (! screen->sloppyFocus()) - openbox.grabButton(Button1, 0, frame.plate, True, ButtonPressMask, - GrabModeSync, GrabModeSync, None, None); - else - openbox.ungrabButton(Button1, 0, frame.plate); + configure(frame.rect.x(), frame.rect.y(), + frame.rect.width(), frame.rect.height()); if (windowmenu) { - windowmenu->move(windowmenu->getX(), frame.y + frame.title_h); + windowmenu->move(windowmenu->getX(), frame.rect.y() + frame.title_h); windowmenu->reconfigure(); } +} + - // re-get the timeout delay - timer->setTimeout(openbox.getAutoRaiseDelay()); +void BlackboxWindow::updateFocusModel(void) { + if ((! screen->isSloppyFocus()) || screen->doClickRaise()) { + // grab button 1 for changing focus/raising + blackbox->grabButton(Button1, 0, frame.plate, True, ButtonPressMask, + GrabModeSync, GrabModeSync, None, None); + } else { + blackbox->ungrabButton(Button1, 0, frame.plate); + } } -void OpenboxWindow::positionWindows(void) { - XResizeWindow(display, frame.window, frame.width, - ((flags.shaded) ? frame.title_h : frame.height)); - XSetWindowBorderWidth(display, frame.window, frame.border_w); - XSetWindowBorderWidth(display, frame.plate, frame.mwm_border_w); - XMoveResizeWindow(display, frame.plate, 0, frame.y_border, - client.width, client.height); - XMoveResizeWindow(display, client.window, 0, 0, client.width, client.height); +void BlackboxWindow::positionWindows(void) { + XMoveResizeWindow(blackbox->getXDisplay(), frame.window, + frame.rect.x(), frame.rect.y(), frame.inside_w, + (flags.shaded) ? frame.title_h : frame.inside_h); + XSetWindowBorderWidth(blackbox->getXDisplay(), frame.window, frame.border_w); + XSetWindowBorderWidth(blackbox->getXDisplay(), frame.plate, + frame.mwm_border_w); + XMoveResizeWindow(blackbox->getXDisplay(), 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(blackbox->getXDisplay(), client.window, + 0, 0, client.rect.width(), client.rect.height()); - if (decorations.titlebar) { - XSetWindowBorderWidth(display, frame.title, frame.border_w); - XMoveResizeWindow(display, frame.title, -frame.border_w, - -frame.border_w, frame.width, frame.title_h); + if (decorations & Decor_Titlebar) { + if (frame.title == None) createTitlebar(); + + XSetWindowBorderWidth(blackbox->getXDisplay(), frame.title, + frame.border_w); + XMoveResizeWindow(blackbox->getXDisplay(), frame.title, -frame.border_w, + -frame.border_w, frame.inside_w, frame.title_h); positionButtons(); + XMapSubwindows(blackbox->getXDisplay(), frame.title); + XMapWindow(blackbox->getXDisplay(), frame.title); } else if (frame.title) { - XUnmapWindow(display, frame.title); - } - if (decorations.handle) { - XSetWindowBorderWidth(display, frame.handle, frame.border_w); - XSetWindowBorderWidth(display, frame.left_grip, frame.border_w); - XSetWindowBorderWidth(display, frame.right_grip, frame.border_w); - - XMoveResizeWindow(display, frame.handle, -frame.border_w, - frame.y_handle - frame.border_w, - frame.width, frame.handle_h); - XMoveResizeWindow(display, frame.left_grip, -frame.border_w, - -frame.border_w, frame.grip_w, frame.grip_h); - XMoveResizeWindow(display, frame.right_grip, - frame.width - frame.grip_w - frame.border_w, - -frame.border_w, frame.grip_w, frame.grip_h); - XMapSubwindows(display, frame.handle); + destroyTitlebar(); + } + if (decorations & Decor_Handle) { + if (frame.handle == None) createHandle(); + XSetWindowBorderWidth(blackbox->getXDisplay(), frame.handle, + frame.border_w); + XSetWindowBorderWidth(blackbox->getXDisplay(), frame.left_grip, + frame.border_w); + XSetWindowBorderWidth(blackbox->getXDisplay(), frame.right_grip, + frame.border_w); + + XMoveResizeWindow(blackbox->getXDisplay(), frame.handle, + -frame.border_w, + frame.rect.height() - frame.margin.bottom + + frame.mwm_border_w - frame.border_w, + frame.inside_w, frame.handle_h); + XMoveResizeWindow(blackbox->getXDisplay(), frame.left_grip, + -frame.border_w, -frame.border_w, + frame.grip_w, frame.handle_h); + XMoveResizeWindow(blackbox->getXDisplay(), frame.right_grip, + frame.inside_w - frame.grip_w - frame.border_w, + -frame.border_w, frame.grip_w, frame.handle_h); + XMapSubwindows(blackbox->getXDisplay(), frame.handle); + XMapWindow(blackbox->getXDisplay(), frame.handle); } else if (frame.handle) { - XUnmapWindow(display, frame.handle); + destroyHandle(); } } -void OpenboxWindow::getWMName(void) { - if (client.title) { - delete [] client.title; - client.title = (char *) 0; - } - +void BlackboxWindow::getWMName(void) { XTextProperty text_prop; - char **list; - int num; - - if (XGetWMName(display, client.window, &text_prop)) { - if (text_prop.value && text_prop.nitems > 0) { - if (text_prop.encoding != XA_STRING) { - text_prop.nitems = strlen((char *) text_prop.value); - - if ((XmbTextPropertyToTextList(display, &text_prop, - &list, &num) == Success) && - (num > 0) && *list) { - client.title = bstrdup(*list); - XFreeStringList(list); - } else { - client.title = bstrdup((char *) text_prop.value); - } - } else { - client.title = bstrdup((char *) text_prop.value); - } - XFree((char *) text_prop.value); - } else { - client.title = bstrdup(i18n(WindowSet, WindowUnnamed, - "Unnamed")); - } - } else { - client.title = bstrdup(i18n(WindowSet, WindowUnnamed, - "Unnamed")); - } - client.title_len = strlen(client.title); - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen->getWindowStyle()->fontset, - client.title, client.title_len, &ink, &logical); - client.title_text_w = logical.width; + if (XGetWMName(blackbox->getXDisplay(), client.window, &text_prop)) { + client.title = textPropertyToString(blackbox->getXDisplay(), text_prop); + if (client.title.empty()) + client.title = i18n(WindowSet, WindowUnnamed, "Unnamed"); + XFree((char *) text_prop.value); } else { - client.title_len = strlen(client.title); - client.title_text_w = XTextWidth(screen->getWindowStyle()->font, - client.title, client.title_len); + client.title = i18n(WindowSet, WindowUnnamed, "Unnamed"); } - - client.title_text_w += (frame.bevel_w * 4); } -void OpenboxWindow::getWMIconName(void) { - if (client.icon_title) { - delete [] client.icon_title; - client.icon_title = (char *) 0; - } - +void BlackboxWindow::getWMIconName(void) { XTextProperty text_prop; - char **list; - int num; - - if (XGetWMIconName(display, client.window, &text_prop)) { - if (text_prop.value && text_prop.nitems > 0) { - if (text_prop.encoding != XA_STRING) { - text_prop.nitems = strlen((char *) text_prop.value); - - if ((XmbTextPropertyToTextList(display, &text_prop, - &list, &num) == Success) && - (num > 0) && *list) { - client.icon_title = bstrdup(*list); - XFreeStringList(list); - } else { - client.icon_title = bstrdup((char *) text_prop.value); - } - } else { - client.icon_title = bstrdup((char *) text_prop.value); - } - XFree((char *) text_prop.value); - } else { - client.icon_title = bstrdup(client.title); - } + + if (XGetWMIconName(blackbox->getXDisplay(), client.window, &text_prop)) { + client.icon_title = + textPropertyToString(blackbox->getXDisplay(), text_prop); + if (client.icon_title.empty()) + client.icon_title = client.title; + XFree((char *) text_prop.value); } else { - client.icon_title = bstrdup(client.title); + client.icon_title = client.title; } } @@ -989,18 +827,20 @@ void OpenboxWindow::getWMIconName(void) { * If the WM_TAKE_FOCUS protocol is supported, save a value that indicates * this. */ -void OpenboxWindow::getWMProtocols(void) { +void BlackboxWindow::getWMProtocols(void) { Atom *proto; int num_return = 0; - if (XGetWMProtocols(display, client.window, &proto, &num_return)) { + if (XGetWMProtocols(blackbox->getXDisplay(), client.window, + &proto, &num_return)) { for (int i = 0; i < num_return; ++i) { - if (proto[i] == openbox.getWMDeleteAtom()) - functions.close = decorations.close = True; - else if (proto[i] == openbox.getWMTakeFocusAtom()) + if (proto[i] == blackbox->getWMDeleteAtom()) { + decorations |= Decor_Close; + functions |= Func_Close; + } else if (proto[i] == blackbox->getWMTakeFocusAtom()) flags.send_focus_message = True; - else if (proto[i] == openbox.getOpenboxStructureMessagesAtom()) - screen->addNetizen(new Netizen(*screen, client.window)); + else if (proto[i] == blackbox->getBlackboxStructureMessagesAtom()) + screen->addNetizen(new Netizen(screen, client.window)); } XFree(proto); @@ -1012,46 +852,48 @@ void OpenboxWindow::getWMProtocols(void) { * Gets the value of the WM_HINTS property. * If the property is not set, then use a set of default values. */ -void OpenboxWindow::getWMHints(void) { - XWMHints *wmhint = XGetWMHints(display, client.window); +void BlackboxWindow::getWMHints(void) { + focus_mode = F_Passive; + client.initial_state = NormalState; + + // 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(blackbox->getXDisplay(), client.window); if (! wmhint) { - flags.visible = True; - flags.iconic = False; - focus_mode = F_Passive; - client.window_group = None; - client.initial_state = NormalState; return; } - client.wm_hint_flags = wmhint->flags; + if (wmhint->flags & InputHint) { if (wmhint->input == True) { if (flags.send_focus_message) focus_mode = F_LocallyActive; - else - focus_mode = F_Passive; } else { if (flags.send_focus_message) focus_mode = F_GloballyActive; else focus_mode = F_NoInput; } - } else { - focus_mode = F_Passive; } if (wmhint->flags & StateHint) client.initial_state = wmhint->initial_state; - else - client.initial_state = NormalState; if (wmhint->flags & WindowGroupHint) { - if (! client.window_group) { - client.window_group = wmhint->window_group; - openbox.saveGroupSearch(client.window_group, this); - } - } else { - client.window_group = None; + 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! + group = new BWindowGroup(blackbox, client.window_group); + group->addWindow(this); } + + client.wm_hint_flags = wmhint->flags; XFree(wmhint); } @@ -1060,20 +902,23 @@ void OpenboxWindow::getWMHints(void) { * Gets the value of the WM_NORMAL_HINTS property. * If the property is not set, then use a set of default values. */ -void OpenboxWindow::getWMNormalHints(void) { +void BlackboxWindow::getWMNormalHints(void) { long icccm_mask; XSizeHints sizehint; + const Rect& screen_area = screen->availableArea(); + client.min_width = client.min_height = - client.base_width = client.base_height = client.width_inc = client.height_inc = 1; - client.max_width = screen->size().w(); - client.max_height = screen->size().h(); + client.base_width = client.base_height = 0; + client.max_width = screen_area.width(); + client.max_height = screen_area.height(); client.min_aspect_x = client.min_aspect_y = client.max_aspect_x = client.max_aspect_y = 1; client.win_gravity = NorthWestGravity; - if (! XGetWMNormalHints(display, client.window, &sizehint, &icccm_mask)) + if (! XGetWMNormalHints(blackbox->getXDisplay(), client.window, + &sizehint, &icccm_mask)) return; client.normal_hint_flags = sizehint.flags; @@ -1114,641 +959,728 @@ void OpenboxWindow::getWMNormalHints(void) { * 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. + * Returns: true if the MWM hints are successfully retreived and applied; + * false if they are not. */ -void OpenboxWindow::getMWMHints(void) { +void BlackboxWindow::getMWMHints(void) { int format; Atom atom_return; unsigned long num, len; + MwmHints *mwm_hint = 0; - int ret = XGetWindowProperty(display, client.window, - openbox.getMotifWMHintsAtom(), 0, + int ret = XGetWindowProperty(blackbox->getXDisplay(), client.window, + blackbox->getMotifWMHintsAtom(), 0, PropMwmHintsElements, False, - openbox.getMotifWMHintsAtom(), &atom_return, + blackbox->getMotifWMHintsAtom(), &atom_return, &format, &num, &len, - (unsigned char **) &client.mwm_hint); + (unsigned char **) &mwm_hint); - if (ret != Success || !client.mwm_hint || num != PropMwmHintsElements) + if (ret != Success || ! mwm_hint || num != PropMwmHintsElements) return; - if (client.mwm_hint->flags & MwmHintsDecorations) { - if (client.mwm_hint->decorations & MwmDecorAll) { - decorations.titlebar = decorations.handle = decorations.border = - decorations.iconify = decorations.maximize = - decorations.close = decorations.menu = True; + if (mwm_hint->flags & MwmHintsDecorations) { + if (mwm_hint->decorations & MwmDecorAll) { + decorations = Decor_Titlebar | Decor_Handle | Decor_Border | + Decor_Iconify | Decor_Maximize | Decor_Close; } else { - decorations.titlebar = decorations.handle = decorations.border = - decorations.iconify = decorations.maximize = - decorations.close = decorations.menu = False; - - if (client.mwm_hint->decorations & MwmDecorBorder) - decorations.border = True; - if (client.mwm_hint->decorations & MwmDecorHandle) - decorations.handle = True; - if (client.mwm_hint->decorations & MwmDecorTitle) - decorations.titlebar = True; - if (client.mwm_hint->decorations & MwmDecorMenu) - decorations.menu = True; - if (client.mwm_hint->decorations & MwmDecorIconify) - decorations.iconify = True; - if (client.mwm_hint->decorations & MwmDecorMaximize) - decorations.maximize = True; + decorations = 0; + + if (mwm_hint->decorations & MwmDecorBorder) + decorations |= Decor_Border; + if (mwm_hint->decorations & MwmDecorHandle) + decorations |= Decor_Handle; + if (mwm_hint->decorations & MwmDecorTitle) + decorations |= Decor_Titlebar; + if (mwm_hint->decorations & MwmDecorIconify) + decorations |= Decor_Iconify; + if (mwm_hint->decorations & MwmDecorMaximize) + decorations |= Decor_Maximize; } } - if (client.mwm_hint->flags & MwmHintsFunctions) { - if (client.mwm_hint->functions & MwmFuncAll) { - functions.resize = functions.move = functions.iconify = - functions.maximize = functions.close = True; + if (mwm_hint->flags & MwmHintsFunctions) { + if (mwm_hint->functions & MwmFuncAll) { + functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize | + Func_Close; } else { - functions.resize = functions.move = functions.iconify = - functions.maximize = functions.close = False; - - if (client.mwm_hint->functions & MwmFuncResize) - functions.resize = True; - if (client.mwm_hint->functions & MwmFuncMove) - functions.move = True; - if (client.mwm_hint->functions & MwmFuncIconify) - functions.iconify = True; - if (client.mwm_hint->functions & MwmFuncMaximize) - functions.maximize = True; - if (client.mwm_hint->functions & MwmFuncClose) - functions.close = True; + 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; } } + XFree(mwm_hint); } /* - * Gets the openbox hints from the class' contained window. + * 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. */ -void OpenboxWindow::getOpenboxHints(void) { +bool BlackboxWindow::getBlackboxHints(void) { int format; Atom atom_return; unsigned long num, len; + BlackboxHints *blackbox_hint = 0; - int ret = XGetWindowProperty(display, client.window, - openbox.getOpenboxHintsAtom(), 0, - PropOpenboxHintsElements, False, - openbox.getOpenboxHintsAtom(), &atom_return, + int ret = XGetWindowProperty(blackbox->getXDisplay(), client.window, + blackbox->getBlackboxHintsAtom(), 0, + PropBlackboxHintsElements, False, + blackbox->getBlackboxHintsAtom(), &atom_return, &format, &num, &len, - (unsigned char **) &client.openbox_hint); - if (ret != Success || !client.openbox_hint || - num != PropOpenboxHintsElements) - return; + (unsigned char **) &blackbox_hint); + if (ret != Success || ! blackbox_hint || num != PropBlackboxHintsElements) + return False; - if (client.openbox_hint->flags & AttribShaded) - flags.shaded = (client.openbox_hint->attrib & AttribShaded); + if (blackbox_hint->flags & AttribShaded) + flags.shaded = (blackbox_hint->attrib & AttribShaded); - if ((client.openbox_hint->flags & AttribMaxHoriz) && - (client.openbox_hint->flags & AttribMaxVert)) - flags.maximized = (client.openbox_hint->attrib & + if ((blackbox_hint->flags & AttribMaxHoriz) && + (blackbox_hint->flags & AttribMaxVert)) + flags.maximized = (blackbox_hint->attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0; - else if (client.openbox_hint->flags & AttribMaxVert) - flags.maximized = (client.openbox_hint->attrib & AttribMaxVert) ? 2 : 0; - else if (client.openbox_hint->flags & AttribMaxHoriz) - flags.maximized = (client.openbox_hint->attrib & AttribMaxHoriz) ? 3 : 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 (client.openbox_hint->flags & AttribOmnipresent) - flags.stuck = (client.openbox_hint->attrib & AttribOmnipresent); + if (blackbox_hint->flags & AttribOmnipresent) + flags.stuck = (blackbox_hint->attrib & AttribOmnipresent); - if (client.openbox_hint->flags & AttribWorkspace) - workspace_number = client.openbox_hint->workspace; + if (blackbox_hint->flags & AttribWorkspace) + blackbox_attrib.workspace = blackbox_hint->workspace; - // if (client.openbox_hint->flags & AttribStack) - // don't yet have always on top/bottom for openbox yet... working + // if (blackbox_hint->flags & AttribStack) + // don't yet have always on top/bottom for blackbox yet... working // on that - if (client.openbox_hint->flags & AttribDecoration) { - switch (client.openbox_hint->decoration) { + if (blackbox_hint->flags & AttribDecoration) { + switch (blackbox_hint->decoration) { case DecorNone: - decorations.titlebar = decorations.border = decorations.handle = - decorations.iconify = decorations.maximize = - decorations.menu = False; - functions.resize = functions.move = functions.iconify = - functions.maximize = False; + // clear all decorations except close + decorations &= Decor_Close; + // clear all functions except close + functions &= Func_Close; break; case DecorTiny: - decorations.titlebar = decorations.iconify = decorations.menu = - functions.move = functions.iconify = True; - decorations.border = decorations.handle = decorations.maximize = - functions.resize = functions.maximize = False; + decorations |= Decor_Titlebar | Decor_Iconify; + decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize); + functions |= Func_Move | Func_Iconify; + functions &= ~(Func_Resize | Func_Maximize); break; case DecorTool: - decorations.titlebar = decorations.menu = functions.move = True; - decorations.iconify = decorations.border = decorations.handle = - decorations.maximize = functions.resize = functions.maximize = - functions.iconify = False; + decorations |= Decor_Titlebar; + decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle); + functions |= Func_Move; + functions &= ~(Func_Resize | Func_Maximize | Func_Iconify); break; case DecorNormal: default: - decorations.titlebar = decorations.border = decorations.handle = - decorations.iconify = decorations.maximize = - decorations.menu = True; - functions.resize = functions.move = functions.iconify = - functions.maximize = True; + decorations |= Decor_Titlebar | Decor_Border | Decor_Handle | + Decor_Iconify | Decor_Maximize; + functions |= Func_Resize | Func_Move | Func_Iconify | Func_Maximize; break; } reconfigure(); } + XFree(blackbox_hint); + return True; +} + + +void BlackboxWindow::getTransientInfo(void) { + if (client.transient_for && + client.transient_for != (BlackboxWindow *) ~0ul) { + // the transient for hint was removed, so we need to tell our + // previous transient_for that we are going away + client.transient_for->client.transientList.remove(this); + } + + // we have no transient_for until we find a new one + client.transient_for = 0; + + Window trans_for; + if (!XGetTransientForHint(blackbox->getXDisplay(), 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; + } + + // 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; } -void OpenboxWindow::configure(int dx, int dy, - unsigned int dw, unsigned int dh) { - Bool send_event = (frame.x != dx || frame.y != dy); +void BlackboxWindow::configure(int dx, int dy, + unsigned int dw, unsigned int dh) { + bool send_event = (frame.rect.x() != dx || frame.rect.y() != dy); - if ((dw != frame.width) || (dh != frame.height)) { - if ((((signed) frame.width) + dx) < 0) dx = 0; - if ((((signed) frame.height) + dy) < 0) dy = 0; + 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); - frame.x = dx; - frame.y = dy; - frame.width = dw; - frame.height = dh; + if (frame.rect.right() <= 0 || frame.rect.bottom() <= 0) + frame.rect.setPos(0, 0); - downsize(); + 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 (openbox.hasShapeExtensions() && flags.shaped) { - XShapeCombineShape(display, frame.window, ShapeBounding, - frame.mwm_border_w, frame.y_border + - frame.mwm_border_w, client.window, - ShapeBounding, ShapeSet); - - int num = 1; - XRectangle xrect[2]; - xrect[0].x = xrect[0].y = 0; - xrect[0].width = frame.width; - xrect[0].height = frame.y_border; - - if (decorations.handle) { - xrect[1].x = 0; - xrect[1].y = frame.y_handle; - xrect[1].width = frame.width; - xrect[1].height = frame.handle_h + frame.border_w; - num++; - } - - XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0, - xrect, num, ShapeUnion, Unsorted); + if (blackbox->hasShapeExtensions() && flags.shaped) { + configureShape(); } #endif // SHAPE - XMoveWindow(display, frame.window, frame.x, frame.y); - - setFocusFlag(flags.focused); positionWindows(); decorate(); + setFocusFlag(flags.focused); + redrawAllButtons(); } else { - frame.x = dx; - frame.y = dy; + frame.rect.setPos(dx, dy); - XMoveWindow(display, frame.window, frame.x, frame.y); + XMoveWindow(blackbox->getXDisplay(), frame.window, + frame.rect.x(), frame.rect.y()); if (! flags.moving) send_event = True; } if (send_event && ! flags.moving) { - client.x = dx + frame.mwm_border_w + frame.border_w; - client.y = dy + frame.y_border + frame.mwm_border_w + - frame.border_w; + client.rect.setPos(frame.rect.left() + frame.margin.left, + frame.rect.top() + frame.margin.top); XEvent event; event.type = ConfigureNotify; - event.xconfigure.display = display; + event.xconfigure.display = blackbox->getXDisplay(); event.xconfigure.event = client.window; event.xconfigure.window = client.window; - event.xconfigure.x = client.x; - event.xconfigure.y = client.y; - event.xconfigure.width = client.width; - event.xconfigure.height = client.height; + 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(display, client.window, True, NoEventMask, &event); + XSendEvent(blackbox->getXDisplay(), client.window, True, + NoEventMask, &event); screen->updateNetizenConfigNotify(&event); } } -bool OpenboxWindow::setInputFocus(void) { - if (((signed) (frame.x + frame.width)) < 0) { - if (((signed) (frame.y + frame.y_border)) < 0) - configure(frame.border_w, frame.border_w, frame.width, frame.height); - else if (frame.y > (signed) screen->size().h()) - configure(frame.border_w, screen->size().h() - frame.height, - frame.width, frame.height); - else - configure(frame.border_w, frame.y + frame.border_w, - frame.width, frame.height); - } else if (frame.x > (signed) screen->size().w()) { - if (((signed) (frame.y + frame.y_border)) < 0) - configure(screen->size().w() - frame.width, frame.border_w, - frame.width, frame.height); - else if (frame.y > (signed) screen->size().h()) - configure(screen->size().w() - frame.width, - screen->size().h() - frame.height, frame.width, frame.height); - else - configure(screen->size().w() - frame.width, - frame.y + frame.border_w, frame.width, frame.height); - } - - openbox.grab(); - if (! validateClient()) return False; - - bool ret = false; - - if (client.transient && flags.modal) { - ret = client.transient->setInputFocus(); - } else if (! flags.focused) { - if (focus_mode == F_LocallyActive || focus_mode == F_Passive) { - XSetInputFocus(display, client.window, - RevertToPointerRoot, CurrentTime); - openbox.focusWindow(this); - - if (flags.send_focus_message) { - XEvent ce; - ce.xclient.type = ClientMessage; - ce.xclient.message_type = openbox.getWMProtocolsAtom(); - ce.xclient.display = display; - ce.xclient.window = client.window; - ce.xclient.format = 32; - ce.xclient.data.l[0] = openbox.getWMTakeFocusAtom(); - ce.xclient.data.l[1] = openbox.getLastTime(); - ce.xclient.data.l[2] = 0l; - ce.xclient.data.l[3] = 0l; - ce.xclient.data.l[4] = 0l; - XSendEvent(display, client.window, False, NoEventMask, &ce); - } +#ifdef SHAPE +void BlackboxWindow::configureShape(void) { + XShapeCombineShape(blackbox->getXDisplay(), frame.window, ShapeBounding, + frame.margin.left - frame.border_w, + frame.margin.top - frame.border_w, + client.window, ShapeBounding, ShapeSet); - if (screen->sloppyFocus() && screen->autoRaise()) - timer->start(); + int num = 0; + XRectangle xrect[2]; - ret = true; - } + 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; } - openbox.ungrab(); + 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; + } - return ret; + XShapeCombineRectangles(blackbox->getXDisplay(), frame.window, + ShapeBounding, 0, 0, xrect, num, + ShapeUnion, Unsorted); } +#endif // SHAPE -void OpenboxWindow::iconify(void) { - if (flags.iconic) return; +bool BlackboxWindow::setInputFocus(void) { + if (flags.focused) return True; - if (flags.moving) - endMove(); + if (! client.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(blackbox->getXDisplay(), client.window, + RevertToPointerRoot, CurrentTime); + + blackbox->setFocusedWindow(this); + } 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 = blackbox->getWMProtocolsAtom(); + ce.xclient.display = blackbox->getXDisplay(); + ce.xclient.window = client.window; + ce.xclient.format = 32; + ce.xclient.data.l[0] = blackbox->getWMTakeFocusAtom(); + 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(blackbox->getXDisplay(), client.window, False, + NoEventMask, &ce); + } + + return ret; +} + + +void BlackboxWindow::iconify(void) { + if (flags.iconic) return; if (windowmenu) windowmenu->hide(); setState(IconicState); - XSelectInput(display, client.window, NoEventMask); - XUnmapWindow(display, client.window); - XSelectInput(display, client.window, - PropertyChangeMask | StructureNotifyMask | FocusChangeMask); - - XUnmapWindow(display, frame.window); + /* + * 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 + */ + XGrabServer(blackbox->getXDisplay()); + XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask); + XUnmapWindow(blackbox->getXDisplay(), client.window); + XSelectInput(blackbox->getXDisplay(), client.window, + PropertyChangeMask | FocusChangeMask | StructureNotifyMask); + XUngrabServer(blackbox->getXDisplay()); + + XUnmapWindow(blackbox->getXDisplay(), frame.window); flags.visible = False; flags.iconic = True; - screen->getWorkspace(workspace_number)->removeWindow(this); + screen->getWorkspace(blackbox_attrib.workspace)->removeWindow(this); - if (flags.transient && client.transient_for && - !client.transient_for->flags.iconic) { - client.transient_for->iconify(); + 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.transient && !client.transient->flags.iconic) { - client.transient->iconify(); + 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(); + } } } -void OpenboxWindow::deiconify(bool reassoc, bool raise, bool initial) { - if (flags.iconic || reassoc) - screen->reassociateWindow(this, -1, False); - else if (workspace_number != screen->getCurrentWorkspace()->getWorkspaceID()) - return; - +void BlackboxWindow::show(void) { setState(NormalState); - XSelectInput(display, client.window, NoEventMask); - XMapWindow(display, client.window); - XSelectInput(display, client.window, - PropertyChangeMask | StructureNotifyMask | FocusChangeMask); + XMapWindow(blackbox->getXDisplay(), client.window); + XMapSubwindows(blackbox->getXDisplay(), frame.window); + XMapWindow(blackbox->getXDisplay(), frame.window); - XMapSubwindows(display, frame.window); - XMapWindow(display, frame.window); + flags.visible = True; + flags.iconic = False; +} - // if we're using the click to place placement type, then immediately - // after the window is mapped, we need to start interactively moving it - if (initial && place_window && - screen->placementPolicy() == BScreen::ClickMousePlacement) { - int x, y, rx, ry; - Window c, r; - unsigned int m; - XQueryPointer(openbox.getXDisplay(), screen->getRootWindow(), - &r, &c, &rx, &ry, &x, &y, &m); - startMove(rx, ry); - } - if (flags.iconic && screen->focusNew()) setInputFocus(); +void BlackboxWindow::deiconify(bool reassoc, bool raise) { + if (flags.iconic || reassoc) + screen->reassociateWindow(this, BSENTINEL, False); + else if (blackbox_attrib.workspace != screen->getCurrentWorkspace()->getID()) + return; - flags.visible = True; - flags.iconic = False; + show(); - if (reassoc && client.transient) client.transient->deiconify(True, False); + // 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(workspace_number)->raiseWindow(this); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); } -void OpenboxWindow::close(void) { +void BlackboxWindow::close(void) { XEvent ce; ce.xclient.type = ClientMessage; - ce.xclient.message_type = openbox.getWMProtocolsAtom(); - ce.xclient.display = display; + ce.xclient.message_type = blackbox->getWMProtocolsAtom(); + ce.xclient.display = blackbox->getXDisplay(); ce.xclient.window = client.window; ce.xclient.format = 32; - ce.xclient.data.l[0] = openbox.getWMDeleteAtom(); + ce.xclient.data.l[0] = blackbox->getWMDeleteAtom(); 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(display, client.window, False, NoEventMask, &ce); + XSendEvent(blackbox->getXDisplay(), client.window, False, NoEventMask, &ce); } -void OpenboxWindow::withdraw(void) { - if (flags.moving) - endMove(); +void BlackboxWindow::withdraw(void) { + setState(current_state); flags.visible = False; flags.iconic = False; - XUnmapWindow(display, frame.window); + XUnmapWindow(blackbox->getXDisplay(), frame.window); - XSelectInput(display, client.window, NoEventMask); - XUnmapWindow(display, client.window); - XSelectInput(display, client.window, - PropertyChangeMask | StructureNotifyMask | FocusChangeMask); + XGrabServer(blackbox->getXDisplay()); + XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask); + XUnmapWindow(blackbox->getXDisplay(), client.window); + XSelectInput(blackbox->getXDisplay(), client.window, + PropertyChangeMask | FocusChangeMask | StructureNotifyMask); + XUngrabServer(blackbox->getXDisplay()); if (windowmenu) windowmenu->hide(); } -void OpenboxWindow::maximize(unsigned int button) { - if (flags.moving) - endMove(); - +void BlackboxWindow::maximize(unsigned int button) { // handle case where menu is open then the max button is used instead if (windowmenu && windowmenu->isVisible()) windowmenu->hide(); if (flags.maximized) { flags.maximized = 0; - openbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert); - openbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert); + blackbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert); + blackbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert); // when a resize is begun, 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(openbox_attrib.premax_x, openbox_attrib.premax_y, - openbox_attrib.premax_w, openbox_attrib.premax_h); + configure(blackbox_attrib.premax_x, blackbox_attrib.premax_y, + blackbox_attrib.premax_w, blackbox_attrib.premax_h); - openbox_attrib.premax_x = openbox_attrib.premax_y = 0; - openbox_attrib.premax_w = openbox_attrib.premax_h = 0; + blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0; + blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0; - redrawMaximizeButton(flags.maximized); + redrawAllButtons(); setState(current_state); return; } - openbox_attrib.premax_x = frame.x; - openbox_attrib.premax_y = frame.y; - openbox_attrib.premax_w = frame.width; - openbox_attrib.premax_h = frame.height; - - Rect space = screen->availableArea(); - unsigned int dw = space.w(), - dh = space.h(); - dw -= frame.border_w * 2; - dw -= frame.mwm_border_w * 2; - dw -= client.base_width; + blackbox_attrib.premax_x = frame.rect.x(); + blackbox_attrib.premax_y = frame.rect.y(); + blackbox_attrib.premax_w = frame.rect.width(); + blackbox_attrib.premax_h = frame.rect.height(); - dh -= frame.border_w * 2; - dh -= frame.mwm_border_w * 2; - dh -= ((frame.handle_h + frame.border_w) * decorations.handle); - dh -= client.base_height; - dh -= frame.y_border; - - 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; - - dw -= (dw % client.width_inc); - dw += client.base_width; - dw += frame.mwm_border_w * 2; - - dh -= (dh % client.height_inc); - dh += client.base_height; - dh += frame.y_border; - dh += ((frame.handle_h + frame.border_w) * decorations.handle); - dh += frame.mwm_border_w * 2; - - int dx = space.x() + ((space.w() - dw) / 2) - frame.border_w, - dy = space.y() + ((space.h() - dh) / 2) - frame.border_w; + const Rect &screen_area = screen->availableArea(); + frame.changing = screen_area; + constrain(TopLeft); switch(button) { case 1: - openbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert; - openbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert; + blackbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert; + blackbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert; break; case 2: - openbox_attrib.flags |= AttribMaxVert; - openbox_attrib.attrib |= AttribMaxVert; + blackbox_attrib.flags |= AttribMaxVert; + blackbox_attrib.attrib |= AttribMaxVert; - dw = frame.width; - dx = frame.x; + frame.changing.setX(frame.rect.x()); + frame.changing.setWidth(frame.rect.width()); break; case 3: - openbox_attrib.flags |= AttribMaxHoriz; - openbox_attrib.attrib |= AttribMaxHoriz; + blackbox_attrib.flags |= AttribMaxHoriz; + blackbox_attrib.attrib |= AttribMaxHoriz; - dh = frame.height; - dy = frame.y; + frame.changing.setY(frame.rect.y()); + frame.changing.setHeight(frame.rect.height()); break; } if (flags.shaded) { - openbox_attrib.flags ^= AttribShaded; - openbox_attrib.attrib ^= AttribShaded; + blackbox_attrib.flags ^= AttribShaded; + blackbox_attrib.attrib ^= AttribShaded; flags.shaded = False; } flags.maximized = button; - configure(dx, dy, dw, dh); - screen->getWorkspace(workspace_number)->raiseWindow(this); - redrawMaximizeButton(flags.maximized); + configure(frame.changing.x(), frame.changing.y(), + frame.changing.width(), frame.changing.height()); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); + redrawAllButtons(); setState(current_state); } -void OpenboxWindow::setWorkspace(int n) { - ASSERT(n < screen->getWorkspaceCount()); - workspace_number = n; +// re-maximizes the window to take into account availableArea changes +void BlackboxWindow::remaximize(void) { + // 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; - openbox_attrib.flags |= AttribWorkspace; - openbox_attrib.workspace = workspace_number; + 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 OpenboxWindow::shade(void) { - if (!decorations.titlebar) +void BlackboxWindow::setWorkspace(unsigned int n) { + blackbox_attrib.flags |= AttribWorkspace; + blackbox_attrib.workspace = n; +} + + +void BlackboxWindow::shade(void) { + if (! (decorations & Decor_Titlebar)) return; if (flags.shaded) { - XResizeWindow(display, frame.window, frame.width, frame.height); + XResizeWindow(blackbox->getXDisplay(), frame.window, + frame.inside_w, frame.inside_h); flags.shaded = False; - openbox_attrib.flags ^= AttribShaded; - openbox_attrib.attrib ^= AttribShaded; + 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 { - XResizeWindow(display, frame.window, frame.width, frame.title_h); + XResizeWindow(blackbox->getXDisplay(), frame.window, + frame.inside_w, frame.title_h); flags.shaded = True; - openbox_attrib.flags |= AttribShaded; - openbox_attrib.attrib |= AttribShaded; + 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)); } } -void OpenboxWindow::stick(void) { +void BlackboxWindow::stick(void) { if (flags.stuck) { - openbox_attrib.flags ^= AttribOmnipresent; - openbox_attrib.attrib ^= AttribOmnipresent; + blackbox_attrib.flags ^= AttribOmnipresent; + blackbox_attrib.attrib ^= AttribOmnipresent; flags.stuck = False; if (! flags.iconic) - screen->reassociateWindow(this, -1, True); + screen->reassociateWindow(this, BSENTINEL, True); setState(current_state); } else { flags.stuck = True; - openbox_attrib.flags |= AttribOmnipresent; - openbox_attrib.attrib |= AttribOmnipresent; + blackbox_attrib.flags |= AttribOmnipresent; + blackbox_attrib.attrib |= AttribOmnipresent; setState(current_state); } } -void OpenboxWindow::setFocusFlag(Bool focus) { +void BlackboxWindow::setFocusFlag(bool focus) { flags.focused = focus; - if (decorations.titlebar) { + if (decorations & Decor_Titlebar) { if (flags.focused) { if (frame.ftitle) - XSetWindowBackgroundPixmap(display, frame.title, frame.ftitle); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.title, frame.ftitle); else - XSetWindowBackground(display, frame.title, frame.ftitle_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.title, frame.ftitle_pixel); } else { if (frame.utitle) - XSetWindowBackgroundPixmap(display, frame.title, frame.utitle); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.title, frame.utitle); else - XSetWindowBackground(display, frame.title, frame.utitle_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.title, frame.utitle_pixel); } - XClearWindow(display, frame.title); + XClearWindow(blackbox->getXDisplay(), frame.title); redrawLabel(); redrawAllButtons(); } - if (decorations.handle) { + if (decorations & Decor_Handle) { if (flags.focused) { if (frame.fhandle) - XSetWindowBackgroundPixmap(display, frame.handle, frame.fhandle); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.handle, frame.fhandle); else - XSetWindowBackground(display, frame.handle, frame.fhandle_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.handle, frame.fhandle_pixel); if (frame.fgrip) { - XSetWindowBackgroundPixmap(display, frame.right_grip, frame.fgrip); - XSetWindowBackgroundPixmap(display, frame.left_grip, frame.fgrip); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.left_grip, frame.fgrip); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.right_grip, frame.fgrip); } else { - XSetWindowBackground(display, frame.right_grip, frame.fgrip_pixel); - XSetWindowBackground(display, frame.left_grip, frame.fgrip_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.left_grip, frame.fgrip_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.right_grip, frame.fgrip_pixel); } } else { if (frame.uhandle) - XSetWindowBackgroundPixmap(display, frame.handle, frame.uhandle); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.handle, frame.uhandle); else - XSetWindowBackground(display, frame.handle, frame.uhandle_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.handle, frame.uhandle_pixel); if (frame.ugrip) { - XSetWindowBackgroundPixmap(display, frame.right_grip, frame.ugrip); - XSetWindowBackgroundPixmap(display, frame.left_grip, frame.ugrip); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.left_grip, frame.ugrip); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.right_grip, frame.ugrip); } else { - XSetWindowBackground(display, frame.right_grip, frame.ugrip_pixel); - XSetWindowBackground(display, frame.left_grip, frame.ugrip_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.left_grip, frame.ugrip_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.right_grip, frame.ugrip_pixel); } } - XClearWindow(display, frame.handle); - XClearWindow(display, frame.right_grip); - XClearWindow(display, frame.left_grip); + XClearWindow(blackbox->getXDisplay(), frame.handle); + XClearWindow(blackbox->getXDisplay(), frame.left_grip); + XClearWindow(blackbox->getXDisplay(), frame.right_grip); } - if (decorations.border) { + if (decorations & Decor_Border) { if (flags.focused) - XSetWindowBorder(display, frame.plate, frame.fborder_pixel); + XSetWindowBorder(blackbox->getXDisplay(), + frame.plate, frame.fborder_pixel); else - XSetWindowBorder(display, frame.plate, frame.uborder_pixel); + XSetWindowBorder(blackbox->getXDisplay(), + frame.plate, frame.uborder_pixel); } - if (screen->sloppyFocus() && screen->autoRaise() && timer->isTiming()) - timer->stop(); + if (screen->isSloppyFocus() && screen->doAutoRaise()) { + if (isFocused()) timer->start(); + else timer->stop(); + } + if (isFocused()) + blackbox->setFocusedWindow(this); } -void OpenboxWindow::installColormap(Bool install) { - openbox.grab(); - if (! validateClient()) return; - +void BlackboxWindow::installColormap(bool install) { int i = 0, ncmap = 0; - Colormap *cmaps = XListInstalledColormaps(display, client.window, &ncmap); + Colormap *cmaps = XListInstalledColormaps(blackbox->getXDisplay(), + client.window, &ncmap); XWindowAttributes wattrib; if (cmaps) { - if (XGetWindowAttributes(display, client.window, &wattrib)) { + if (XGetWindowAttributes(blackbox->getXDisplay(), + client.window, &wattrib)) { if (install) { // install the window's colormap for (i = 0; i < ncmap; i++) { @@ -1758,61 +1690,59 @@ void OpenboxWindow::installColormap(Bool install) { } // otherwise, install the window's colormap if (install) - XInstallColormap(display, wattrib.colormap); + XInstallColormap(blackbox->getXDisplay(), 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(display, wattrib.colormap); + XUninstallColormap(blackbox->getXDisplay(), wattrib.colormap); } } } XFree(cmaps); } - - openbox.ungrab(); } -void OpenboxWindow::setState(unsigned long new_state) { +void BlackboxWindow::setState(unsigned long new_state) { current_state = new_state; unsigned long state[2]; - state[0] = (unsigned long) current_state; - state[1] = (unsigned long) None; - XChangeProperty(display, client.window, openbox.getWMStateAtom(), - openbox.getWMStateAtom(), 32, PropModeReplace, - (unsigned char *) state, 2); + state[0] = current_state; + state[1] = None; + XChangeProperty(blackbox->getXDisplay(), client.window, + blackbox->getWMStateAtom(), blackbox->getWMStateAtom(), 32, + PropModeReplace, (unsigned char *) state, 2); - XChangeProperty(display, client.window, - openbox.getOpenboxAttributesAtom(), - openbox.getOpenboxAttributesAtom(), 32, PropModeReplace, - (unsigned char *) &openbox_attrib, - PropOpenboxAttributesElements); + XChangeProperty(blackbox->getXDisplay(), client.window, + blackbox->getBlackboxAttributesAtom(), + blackbox->getBlackboxAttributesAtom(), 32, PropModeReplace, + (unsigned char *) &blackbox_attrib, + PropBlackboxAttributesElements); } -Bool OpenboxWindow::getState(void) { +bool BlackboxWindow::getState(void) { current_state = 0; Atom atom_return; - Bool ret = False; + bool ret = False; int foo; unsigned long *state, ulfoo, nitems; - if ((XGetWindowProperty(display, client.window, openbox.getWMStateAtom(), - 0l, 2l, False, openbox.getWMStateAtom(), + if ((XGetWindowProperty(blackbox->getXDisplay(), client.window, + blackbox->getWMStateAtom(), + 0l, 2l, False, blackbox->getWMStateAtom(), &atom_return, &foo, &nitems, &ulfoo, (unsigned char **) &state) != Success) || (! state)) { - openbox.ungrab(); return False; } if (nitems >= 1) { - current_state = (unsigned long) state[0]; + current_state = static_cast(state[0]); ret = True; } @@ -1823,94 +1753,25 @@ Bool OpenboxWindow::getState(void) { } -void OpenboxWindow::setGravityOffsets(void) { - // x coordinates for each gravity type - const int x_west = client.x; - const int x_east = client.x + client.width - frame.width; - const int x_center = client.x + client.width - frame.width/2; - // y coordinates for each gravity type - const int y_north = client.y; - const int y_south = client.y + client.height - frame.height; - const int y_center = client.y + client.height - frame.height/2; - - switch (client.win_gravity) { - case NorthWestGravity: - default: - frame.x = x_west; - frame.y = y_north; - break; - case NorthGravity: - frame.x = x_center; - frame.y = y_north; - break; - case NorthEastGravity: - frame.x = x_east; - frame.y = y_north; - break; - case SouthWestGravity: - frame.x = x_west; - frame.y = y_south; - break; - case SouthGravity: - frame.x = x_center; - frame.y = y_south; - break; - case SouthEastGravity: - frame.x = x_east; - frame.y = y_south; - break; - case WestGravity: - frame.x = x_west; - frame.y = y_center; - break; - case EastGravity: - frame.x = x_east; - frame.y = y_center; - break; - case CenterGravity: - frame.x = x_center; - frame.y = y_center; - break; - case ForgetGravity: - case StaticGravity: - frame.x = client.x - frame.mwm_border_w + frame.border_w; - frame.y = client.y - frame.y_border - frame.mwm_border_w - frame.border_w; - break; - } -} - - -void OpenboxWindow::restoreAttributes(void) { +void BlackboxWindow::restoreAttributes(void) { if (! getState()) current_state = NormalState; Atom atom_return; int foo; unsigned long ulfoo, nitems; - OpenboxAttributes *net; - int ret = XGetWindowProperty(display, client.window, - openbox.getOpenboxAttributesAtom(), 0l, - PropOpenboxAttributesElements, False, - openbox.getOpenboxAttributesAtom(), + BlackboxAttributes *net; + int ret = XGetWindowProperty(blackbox->getXDisplay(), client.window, + blackbox->getBlackboxAttributesAtom(), 0l, + PropBlackboxAttributesElements, False, + blackbox->getBlackboxAttributesAtom(), &atom_return, &foo, &nitems, &ulfoo, (unsigned char **) &net); - if (ret != Success || !net || nitems != PropOpenboxAttributesElements) + if (ret != Success || !net || nitems != PropBlackboxAttributesElements) return; - openbox_attrib.flags = net->flags; - openbox_attrib.attrib = net->attrib; - openbox_attrib.decoration = net->decoration; - openbox_attrib.workspace = net->workspace; - openbox_attrib.stack = net->stack; - openbox_attrib.premax_x = net->premax_x; - openbox_attrib.premax_y = net->premax_y; - openbox_attrib.premax_w = net->premax_w; - openbox_attrib.premax_h = net->premax_h; - - XFree((void *) net); - - if (openbox_attrib.flags & AttribShaded && - openbox_attrib.attrib & AttribShaded) { + if (net->flags & AttribShaded && + net->attrib & AttribShaded) { int save_state = ((current_state == IconicState) ? NormalState : current_state); @@ -1920,47 +1781,84 @@ void OpenboxWindow::restoreAttributes(void) { current_state = save_state; } - if (((int) openbox_attrib.workspace != screen->getCurrentWorkspaceID()) && - ((int) openbox_attrib.workspace < screen->getWorkspaceCount())) { - screen->reassociateWindow(this, openbox_attrib.workspace, True); + if ((net->workspace != screen->getCurrentWorkspaceID()) && + (net->workspace < screen->getWorkspaceCount())) { + screen->reassociateWindow(this, net->workspace, True); if (current_state == NormalState) current_state = WithdrawnState; } else if (current_state == WithdrawnState) { current_state = NormalState; } - if (openbox_attrib.flags & AttribOmnipresent && - openbox_attrib.attrib & AttribOmnipresent) { + if (net->flags & AttribOmnipresent && + net->attrib & AttribOmnipresent) { flags.stuck = False; stick(); current_state = NormalState; } - if ((openbox_attrib.flags & AttribMaxHoriz) || - (openbox_attrib.flags & AttribMaxVert)) { - int x = openbox_attrib.premax_x, y = openbox_attrib.premax_y; - unsigned int w = openbox_attrib.premax_w, h = openbox_attrib.premax_h; + 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 = False; - if ((openbox_attrib.flags & AttribMaxHoriz) && - (openbox_attrib.flags & AttribMaxVert)) - m = (openbox_attrib.attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0; - else if (openbox_attrib.flags & AttribMaxVert) - m = (openbox_attrib.attrib & AttribMaxVert) ? 2 : 0; - else if (openbox_attrib.flags & AttribMaxHoriz) - m = (openbox_attrib.attrib & AttribMaxHoriz) ? 3 : 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); - openbox_attrib.premax_x = x; - openbox_attrib.premax_y = y; - openbox_attrib.premax_w = w; - openbox_attrib.premax_h = h; + blackbox_attrib.premax_x = x; + blackbox_attrib.premax_y = y; + blackbox_attrib.premax_w = w; + blackbox_attrib.premax_h = h; } setState(current_state); + + XFree((void *) net); +} + + +/* + * Positions the frame according the the client window position and window + * gravity. + */ +void BlackboxWindow::setGravityOffsets(void) { + // x coordinates for each gravity type + const int x_west = client.rect.x(); + const int x_east = client.rect.right() - frame.inside_w + 1; + const int x_center = client.rect.right() - (frame.rect.width()/2) + 1; + // y coordinates for each gravity type + const int y_north = client.rect.y(); + const int y_south = client.rect.bottom() - frame.inside_h + 1; + const int y_center = client.rect.bottom() - (frame.rect.height()/2) + 1; + + switch (client.win_gravity) { + default: + case NorthWestGravity: frame.rect.setPos(x_west, y_north); break; + case NorthGravity: frame.rect.setPos(x_center, y_north); break; + case NorthEastGravity: frame.rect.setPos(x_east, y_north); break; + case SouthWestGravity: frame.rect.setPos(x_west, y_south); break; + case SouthGravity: frame.rect.setPos(x_center, y_south); break; + case SouthEastGravity: frame.rect.setPos(x_east, y_south); break; + case WestGravity: frame.rect.setPos(x_west, y_center); break; + case CenterGravity: frame.rect.setPos(x_center, y_center); break; + case EastGravity: frame.rect.setPos(x_east, y_center); break; + + case ForgetGravity: + case StaticGravity: + frame.rect.setPos(client.rect.x() - frame.margin.left, + client.rect.y() - frame.margin.top); + break; + } } @@ -1968,397 +1866,294 @@ void OpenboxWindow::restoreAttributes(void) { * The reverse of the setGravityOffsets function. Uses the frame window's * position to find the window's reference point. */ -void OpenboxWindow::restoreGravity(void) { +void BlackboxWindow::restoreGravity(void) { // x coordinates for each gravity type - const int x_west = frame.x; - const int x_east = frame.x + frame.width - client.width; - const int x_center = frame.x + (frame.width/2) - client.width; + const int x_west = frame.rect.x(); + const int x_east = frame.rect.x() + frame.inside_w - client.rect.width(); + const int x_center = frame.rect.x() + (frame.rect.width()/2) - + client.rect.width(); // y coordinates for each gravity type - const int y_north = frame.y; - const int y_south = frame.y + frame.height - client.height; - const int y_center = frame.y + (frame.height/2) - client.height; + const int y_north = frame.rect.y(); + const int y_south = frame.rect.y() + frame.inside_h - client.rect.height(); + const int y_center = frame.rect.y() + (frame.rect.height()/2) - + client.rect.height(); switch(client.win_gravity) { default: - case NorthWestGravity: - client.x = x_west; - client.y = y_north; - break; - case NorthGravity: - client.x = x_center; - client.y = y_north; - break; - case NorthEastGravity: - client.x = x_east; - client.y = y_north; - break; - case SouthWestGravity: - client.x = x_west; - client.y = y_south; - break; - case SouthGravity: - client.x = x_center; - client.y = y_south; - break; - case SouthEastGravity: - client.x = x_east; - client.y = y_south; - break; - case WestGravity: - client.x = x_west; - client.y = y_center; - break; - case EastGravity: - client.x = x_east; - client.y = y_center; - break; - case CenterGravity: - client.x = x_center; - client.y = y_center; - break; + case NorthWestGravity: client.rect.setPos(x_west, y_north); break; + case NorthGravity: client.rect.setPos(x_center, y_north); break; + case NorthEastGravity: client.rect.setPos(x_east, y_north); break; + case SouthWestGravity: client.rect.setPos(x_west, y_south); break; + case SouthGravity: client.rect.setPos(x_center, y_south); break; + case SouthEastGravity: client.rect.setPos(x_east, y_south); break; + case WestGravity: client.rect.setPos(x_west, y_center); break; + case CenterGravity: client.rect.setPos(x_center, y_center); break; + case EastGravity: client.rect.setPos(x_east, y_center); break; + case ForgetGravity: case StaticGravity: - client.x = frame.x + frame.mwm_border_w + frame.border_w; - client.y = frame.y + frame.y_border + frame.mwm_border_w + - frame.border_w; + client.rect.setPos(frame.rect.left() + frame.margin.left, + frame.rect.top() + frame.margin.top); break; } } -void OpenboxWindow::redrawLabel(void) { - int dx = frame.bevel_w * 2, dlen = client.title_len; - unsigned int l = client.title_text_w; - +void BlackboxWindow::redrawLabel(void) { if (flags.focused) { if (frame.flabel) - XSetWindowBackgroundPixmap(display, frame.label, frame.flabel); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.label, frame.flabel); else - XSetWindowBackground(display, frame.label, frame.flabel_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.label, frame.flabel_pixel); } else { if (frame.ulabel) - XSetWindowBackgroundPixmap(display, frame.label, frame.ulabel); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.label, frame.ulabel); else - XSetWindowBackground(display, frame.label, frame.ulabel_pixel); - } - XClearWindow(display, frame.label); - - if (client.title_text_w > frame.label_w) { - for (; dlen >= 0; dlen--) { - if (i18n.multibyte()) { - XRectangle ink, logical; - XmbTextExtents(screen->getWindowStyle()->fontset, client.title, dlen, - &ink, &logical); - l = logical.width; - } else { - l = XTextWidth(screen->getWindowStyle()->font, client.title, dlen); - } - l += (frame.bevel_w * 4); - - if (l < frame.label_w) - break; - } + XSetWindowBackground(blackbox->getXDisplay(), + frame.label, frame.ulabel_pixel); } + XClearWindow(blackbox->getXDisplay(), frame.label); - switch (screen->getWindowStyle()->justify) { - case BScreen::RightJustify: - dx += frame.label_w - l; - break; + WindowStyle *style = screen->getWindowStyle(); - case BScreen::CenterJustify: - dx += (frame.label_w - l) / 2; - break; - } + int pos = frame.bevel_w * 2, + dlen = style->doJustify(client.title.c_str(), pos, frame.label_w, + frame.bevel_w * 4, i18n.multibyte()); - WindowStyle *style = screen->getWindowStyle(); - GC text_gc = (flags.focused) ? style->l_text_focus_gc : - style->l_text_unfocus_gc; + BPen pen((flags.focused) ? style->l_text_focus : style->l_text_unfocus, + style->font); if (i18n.multibyte()) - XmbDrawString(display, frame.label, style->fontset, text_gc, dx, + XmbDrawString(blackbox->getXDisplay(), frame.label, style->fontset, + pen.gc(), pos, (1 - style->fontset_extents->max_ink_extent.y), - client.title, dlen); + client.title.c_str(), dlen); else - XDrawString(display, frame.label, text_gc, dx, - (style->font->ascent + 1), client.title, dlen); + XDrawString(blackbox->getXDisplay(), frame.label, pen.gc(), pos, + (style->font->ascent + 1), client.title.c_str(), dlen); } -void OpenboxWindow::redrawAllButtons(void) { +void BlackboxWindow::redrawAllButtons(void) { if (frame.iconify_button) redrawIconifyButton(False); if (frame.maximize_button) redrawMaximizeButton(flags.maximized); if (frame.close_button) redrawCloseButton(False); } -void OpenboxWindow::redrawIconifyButton(Bool pressed) { +void BlackboxWindow::redrawIconifyButton(bool pressed) { if (! pressed) { if (flags.focused) { if (frame.fbutton) - XSetWindowBackgroundPixmap(display, frame.iconify_button, - frame.fbutton); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.iconify_button, frame.fbutton); else - XSetWindowBackground(display, frame.iconify_button, - frame.fbutton_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.iconify_button, frame.fbutton_pixel); } else { if (frame.ubutton) - XSetWindowBackgroundPixmap(display, frame.iconify_button, - frame.ubutton); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.iconify_button, frame.ubutton); else - XSetWindowBackground(display, frame.iconify_button, + XSetWindowBackground(blackbox->getXDisplay(), frame.iconify_button, frame.ubutton_pixel); } } else { if (frame.pbutton) - XSetWindowBackgroundPixmap(display, frame.iconify_button, frame.pbutton); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.iconify_button, frame.pbutton); else - XSetWindowBackground(display, frame.iconify_button, frame.pbutton_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.iconify_button, frame.pbutton_pixel); } - XClearWindow(display, frame.iconify_button); + XClearWindow(blackbox->getXDisplay(), frame.iconify_button); - XDrawRectangle(display, frame.iconify_button, - ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc : - screen->getWindowStyle()->b_pic_unfocus_gc), - 2, (frame.button_h - 5), (frame.button_w - 5), 2); + BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : + screen->getWindowStyle()->b_pic_unfocus); + XDrawRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(), + 2, (frame.button_w - 5), (frame.button_w - 5), 2); } -void OpenboxWindow::redrawMaximizeButton(Bool pressed) { +void BlackboxWindow::redrawMaximizeButton(bool pressed) { if (! pressed) { if (flags.focused) { if (frame.fbutton) - XSetWindowBackgroundPixmap(display, frame.maximize_button, - frame.fbutton); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.maximize_button, frame.fbutton); else - XSetWindowBackground(display, frame.maximize_button, + XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button, frame.fbutton_pixel); } else { if (frame.ubutton) - XSetWindowBackgroundPixmap(display, frame.maximize_button, - frame.ubutton); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.maximize_button, frame.ubutton); else - XSetWindowBackground(display, frame.maximize_button, + XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button, frame.ubutton_pixel); } } else { if (frame.pbutton) - XSetWindowBackgroundPixmap(display, frame.maximize_button, - frame.pbutton); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.maximize_button, frame.pbutton); else - XSetWindowBackground(display, frame.maximize_button, + XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button, frame.pbutton_pixel); } - XClearWindow(display, frame.maximize_button); + XClearWindow(blackbox->getXDisplay(), frame.maximize_button); - XDrawRectangle(display, frame.maximize_button, - ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc : - screen->getWindowStyle()->b_pic_unfocus_gc), - 2, 2, (frame.button_w - 5), (frame.button_h - 5)); - XDrawLine(display, frame.maximize_button, - ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc : - screen->getWindowStyle()->b_pic_unfocus_gc), + BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : + screen->getWindowStyle()->b_pic_unfocus); + XDrawRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(), + 2, 2, (frame.button_w - 5), (frame.button_w - 5)); + XDrawLine(blackbox->getXDisplay(), frame.maximize_button, pen.gc(), 2, 3, (frame.button_w - 3), 3); } -void OpenboxWindow::redrawCloseButton(Bool pressed) { +void BlackboxWindow::redrawCloseButton(bool pressed) { if (! pressed) { if (flags.focused) { if (frame.fbutton) - XSetWindowBackgroundPixmap(display, frame.close_button, + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button, frame.fbutton); else - XSetWindowBackground(display, frame.close_button, + XSetWindowBackground(blackbox->getXDisplay(), frame.close_button, frame.fbutton_pixel); } else { if (frame.ubutton) - XSetWindowBackgroundPixmap(display, frame.close_button, + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button, frame.ubutton); else - XSetWindowBackground(display, frame.close_button, + XSetWindowBackground(blackbox->getXDisplay(), frame.close_button, frame.ubutton_pixel); } } else { if (frame.pbutton) - XSetWindowBackgroundPixmap(display, frame.close_button, frame.pbutton); + XSetWindowBackgroundPixmap(blackbox->getXDisplay(), + frame.close_button, frame.pbutton); else - XSetWindowBackground(display, frame.close_button, frame.pbutton_pixel); + XSetWindowBackground(blackbox->getXDisplay(), + frame.close_button, frame.pbutton_pixel); } - XClearWindow(display, frame.close_button); + XClearWindow(blackbox->getXDisplay(), frame.close_button); - XDrawLine(display, frame.close_button, - ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc : - screen->getWindowStyle()->b_pic_unfocus_gc), 2, 2, - (frame.button_w - 3), (frame.button_h - 3)); - XDrawLine(display, frame.close_button, - ((flags.focused) ? screen->getWindowStyle()->b_pic_focus_gc : - screen->getWindowStyle()->b_pic_unfocus_gc), 2, - (frame.button_h - 3), - (frame.button_w - 3), 2); + BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus : + screen->getWindowStyle()->b_pic_unfocus); + XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(), + 2, 2, (frame.button_w - 3), (frame.button_w - 3)); + XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(), + 2, (frame.button_w - 3), (frame.button_w - 3), 2); } -void OpenboxWindow::mapRequestEvent(XMapRequestEvent *re) { - if (re->window == client.window) { +void BlackboxWindow::mapRequestEvent(XMapRequestEvent *re) { + if (re->window != client.window) + return; + #ifdef DEBUG - fprintf(stderr, i18n(WindowSet, WindowMapRequest, - "OpenboxWindow::mapRequestEvent() for 0x%lx\n"), - client.window); + fprintf(stderr, "BlackboxWindow::mapRequestEvent() for 0x%lx\n", + client.window); #endif // DEBUG - openbox.grab(); - if (! validateClient()) return; - - Bool get_state_ret = getState(); - if (! (get_state_ret && openbox.isStartup())) { - if ((client.wm_hint_flags & StateHint) && - (! (current_state == NormalState || current_state == IconicState))) - current_state = client.initial_state; - else - current_state = NormalState; - } else if (flags.iconic) { + bool get_state_ret = getState(); + if (! (get_state_ret && blackbox->isStartup())) { + if ((client.wm_hint_flags & StateHint) && + (! (current_state == NormalState || current_state == IconicState))) + current_state = client.initial_state; + else current_state = NormalState; - } - - switch (current_state) { - case IconicState: - iconify(); - break; - - case WithdrawnState: - withdraw(); - break; - - case NormalState: - case InactiveState: - case ZoomState: - default: - deiconify(False, True, True); // specify that we're initializing the - // window - break; - } - - openbox.ungrab(); + } else if (flags.iconic) { + current_state = NormalState; } -} - -void OpenboxWindow::mapNotifyEvent(XMapEvent *ne) { - if ((ne->window == client.window) && (! ne->override_redirect) - && (flags.visible)) { - openbox.grab(); - if (! validateClient()) return; + switch (current_state) { + case IconicState: + iconify(); + break; - setState(NormalState); + case WithdrawnState: + withdraw(); + break; - if (flags.transient || screen->focusNew()) + case NormalState: + case InactiveState: + case ZoomState: + default: + show(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); + if (! blackbox->isStartup() && (isTransient() || screen->doFocusNew())) { + XSync(blackbox->getXDisplay(), False); // make sure the frame is mapped.. setInputFocus(); - else - setFocusFlag(False); - - flags.visible = True; - flags.iconic = False; - - openbox.ungrab(); + } + break; } } -void OpenboxWindow::unmapNotifyEvent(XUnmapEvent *ue) { - if (ue->window == client.window) { +void BlackboxWindow::unmapNotifyEvent(XUnmapEvent *ue) { + if (ue->window != client.window) + return; + #ifdef DEBUG - fprintf(stderr, i18n(WindowSet, WindowUnmapNotify, - "OpenboxWindow::unmapNotifyEvent() for 0x%lx\n"), - client.window); + fprintf(stderr, "BlackboxWindow::unmapNotifyEvent() for 0x%lx\n", + client.window); #endif // DEBUG - openbox.grab(); - if (! validateClient()) return; - - if (flags.moving) - endMove(); - - XChangeSaveSet(display, client.window, SetModeDelete); - XSelectInput(display, client.window, NoEventMask); + screen->unmanageWindow(this, False); +} - XDeleteProperty(display, client.window, openbox.getWMStateAtom()); - XDeleteProperty(display, client.window, - openbox.getOpenboxAttributesAtom()); - XUnmapWindow(display, frame.window); - XUnmapWindow(display, client.window); +void BlackboxWindow::destroyNotifyEvent(XDestroyWindowEvent *de) { + if (de->window != client.window) + return; - XEvent dummy; - if (! XCheckTypedWindowEvent(display, client.window, ReparentNotify, - &dummy)) { #ifdef DEBUG - fprintf(stderr, i18n(WindowSet, WindowUnmapNotifyReparent, - "OpenboxWindow::unmapNotifyEvent(): reparent 0x%lx to " - "root.\n"), client.window); + fprintf(stderr, "BlackboxWindow::destroyNotifyEvent() for 0x%lx\n", + client.window); #endif // DEBUG - restoreGravity(); - XReparentWindow(display, client.window, screen->getRootWindow(), - client.x, client.y); - } - - XFlush(display); - - openbox.ungrab(); - - delete this; - } + screen->unmanageWindow(this, False); } -void OpenboxWindow::destroyNotifyEvent(XDestroyWindowEvent *de) { - if (de->window == client.window) { - if (flags.moving) - endMove(); - XUnmapWindow(display, frame.window); +void BlackboxWindow::reparentNotifyEvent(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 - delete this; - } + XEvent ev; + ev.xreparent = *re; + XPutBackEvent(blackbox->getXDisplay(), &ev); + screen->unmanageWindow(this, True); } -void OpenboxWindow::propertyNotifyEvent(Atom atom) { - openbox.grab(); - if (! validateClient()) return; - +void BlackboxWindow::propertyNotifyEvent(Atom atom) { switch(atom) { case XA_WM_CLASS: case XA_WM_CLIENT_MACHINE: case XA_WM_COMMAND: break; - case XA_WM_TRANSIENT_FOR: + case XA_WM_TRANSIENT_FOR: { // determine if this is a transient window - Window win; - if (XGetTransientForHint(display, client.window, &win)) { - if (win && (win != client.window)) { - if ((client.transient_for = openbox.searchWindow(win))) { - client.transient_for->client.transient = this; - flags.stuck = client.transient_for->flags.stuck; - flags.transient = True; - } else if (win == client.window_group) { - //jr This doesn't look quite right... - if ((client.transient_for = openbox.searchGroup(win, this))) { - client.transient_for->client.transient = this; - flags.stuck = client.transient_for->flags.stuck; - flags.transient = True; - } - } - } - - if (win == screen->getRootWindow()) flags.modal = True; - } + getTransientInfo(); // adjust the window decorations based on transience - if (flags.transient) - decorations.maximize = decorations.handle = functions.maximize = False; + if (isTransient()) { + decorations &= ~(Decor_Maximize | Decor_Handle); + functions &= ~Func_Maximize; + } reconfigure(); - + } break; case XA_WM_HINTS: @@ -2367,18 +2162,16 @@ void OpenboxWindow::propertyNotifyEvent(Atom atom) { case XA_WM_ICON_NAME: getWMIconName(); - if (flags.iconic) screen->iconUpdate(); + if (flags.iconic) screen->propagateWindowName(this); break; case XA_WM_NAME: getWMName(); - if (decorations.titlebar) + if (decorations & Decor_Titlebar) redrawLabel(); - if (! flags.iconic) - screen->getWorkspace(workspace_number)->update(); - + screen->propagateWindowName(this); break; case XA_WM_NORMAL_HINTS: { @@ -2387,35 +2180,34 @@ void OpenboxWindow::propertyNotifyEvent(Atom atom) { if ((client.normal_hint_flags & PMinSize) && (client.normal_hint_flags & PMaxSize)) { if (client.max_width <= client.min_width && - client.max_height <= client.min_height) - decorations.maximize = decorations.handle = - functions.resize = functions.maximize = False; - else - decorations.maximize = decorations.handle = - functions.resize = functions.maximize = True; + client.max_height <= client.min_height) { + decorations &= ~(Decor_Maximize | Decor_Handle); + functions &= ~(Func_Resize | Func_Maximize); + } else { + decorations |= Decor_Maximize | Decor_Handle; + functions |= Func_Resize | Func_Maximize; + } } - int x = frame.x, y = frame.y; - unsigned int w = frame.width, h = frame.height; + Rect old_rect = frame.rect; upsize(); - if ((x != frame.x) || (y != frame.y) || - (w != frame.width) || (h != frame.height)) + if (old_rect != frame.rect) reconfigure(); break; } default: - if (atom == openbox.getWMProtocolsAtom()) { + if (atom == blackbox->getWMProtocolsAtom()) { getWMProtocols(); - if (decorations.close && (! frame.close_button)) { + if ((decorations & Decor_Close) && (! frame.close_button)) { createCloseButton(); - if (decorations.titlebar) { - positionButtons(); - decorateLabel(); + if (decorations & Decor_Titlebar) { + positionButtons(True); + XMapSubwindows(blackbox->getXDisplay(), frame.title); } if (windowmenu) windowmenu->reconfigure(); } @@ -2423,13 +2215,11 @@ void OpenboxWindow::propertyNotifyEvent(Atom atom) { break; } - - openbox.ungrab(); } -void OpenboxWindow::exposeEvent(XExposeEvent *ee) { - if (frame.label == ee->window && decorations.titlebar) +void BlackboxWindow::exposeEvent(XExposeEvent *ee) { + if (frame.label == ee->window && (decorations & Decor_Titlebar)) redrawLabel(); else if (frame.close_button == ee->window) redrawCloseButton(False); @@ -2440,623 +2230,444 @@ void OpenboxWindow::exposeEvent(XExposeEvent *ee) { } -void OpenboxWindow::configureRequestEvent(XConfigureRequestEvent *cr) { - if (cr->window == client.window) { - openbox.grab(); - if (! validateClient()) return; +void BlackboxWindow::configureRequestEvent(XConfigureRequestEvent *cr) { + if (cr->window != client.window || flags.iconic) + return; - int cx = frame.x, cy = frame.y; - unsigned int cw = frame.width, ch = frame.height; + int cx = frame.rect.x(), cy = frame.rect.y(); + unsigned int cw = frame.rect.width(), ch = frame.rect.height(); - if (cr->value_mask & CWBorderWidth) - client.old_bw = cr->border_width; + if (cr->value_mask & CWBorderWidth) + client.old_bw = cr->border_width; - if (cr->value_mask & CWX) - cx = cr->x - frame.mwm_border_w - frame.border_w; + if (cr->value_mask & CWX) + cx = cr->x - frame.margin.left; - if (cr->value_mask & CWY) - cy = cr->y - frame.y_border - frame.mwm_border_w - - frame.border_w; + if (cr->value_mask & CWY) + cy = cr->y - frame.margin.top; - if (cr->value_mask & CWWidth) - cw = cr->width + (frame.mwm_border_w * 2); + if (cr->value_mask & CWWidth) + cw = cr->width + frame.margin.left + frame.margin.right; - if (cr->value_mask & CWHeight) - ch = cr->height + frame.y_border + (frame.mwm_border_w * 2) + - (frame.border_w * decorations.handle) + frame.handle_h; + if (cr->value_mask & CWHeight) + ch = cr->height + frame.margin.top + frame.margin.bottom; - if (frame.x != cx || frame.y != cy || - frame.width != cw || frame.height != ch) - configure(cx, cy, cw, ch); + if (frame.rect != Rect(cx, cy, cw, ch)) + configure(cx, cy, cw, ch); - if (cr->value_mask & CWStackMode) { - switch (cr->detail) { - case Above: - case TopIf: - default: - if (flags.iconic) deiconify(); - screen->getWorkspace(workspace_number)->raiseWindow(this); - break; + if (cr->value_mask & CWStackMode) { + switch (cr->detail) { + case Below: + case BottomIf: + screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this); + break; - case Below: - case BottomIf: - if (flags.iconic) deiconify(); - screen->getWorkspace(workspace_number)->lowerWindow(this); - break; - } + case Above: + case TopIf: + default: + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); + break; } - - openbox.ungrab(); } } -void OpenboxWindow::buttonPressEvent(XButtonEvent *be) { - openbox.grab(); - if (! validateClient()) - return; +void BlackboxWindow::buttonPressEvent(XButtonEvent *be) { + if (frame.maximize_button == be->window) { + redrawMaximizeButton(True); + } else if (be->button == 1 || (be->button == 3 && be->state == Mod1Mask)) { + if (! flags.focused) + setInputFocus(); - int stack_change = 1; // < 0 means to lower the window - // > 0 means to raise the window - // 0 means to leave it where it is - - // alt + left/right click begins interactively moving/resizing the window - // when the mouse is moved - if (be->state == Mod1Mask && (be->button == 1 || be->button == 3)) { - if (be->button == 3) { - if (screen->getWindowZones() == 4 && - be->y < (signed) frame.height / 2) { - resize_zone = ZoneTop; - } else { - resize_zone = ZoneBottom; - } - if (screen->getWindowZones() >= 2 && - be->x < (signed) frame.width / 2) { - resize_zone |= ZoneLeft; - } else { - resize_zone |= ZoneRight; - } - } - // control + left click on the titlebar shades the window - } else if (be->state == ControlMask && be->button == 1) { - if (be->window == frame.title || - be->window == frame.label) - shade(); - // left click - } else if (be->state == 0 && be->button == 1) { - if (windowmenu && windowmenu->isVisible()) - windowmenu->hide(); - - if (be->window == frame.maximize_button) { - redrawMaximizeButton(True); - } else if (be->window == frame.iconify_button) { + if (frame.iconify_button == be->window) { redrawIconifyButton(True); - } else if (be->window == frame.close_button) { + } else if (frame.close_button == be->window) { redrawCloseButton(True); - } else if (be->window == frame.plate) { - XAllowEvents(display, ReplayPointer, be->time); - } else if (be->window == frame.title || - be->window == frame.label) { - // shade the window when the titlebar is double clicked - if ( (be->time - lastButtonPressTime) <= - openbox.getDoubleClickInterval()) { - lastButtonPressTime = 0; - shade(); - } else { - lastButtonPressTime = be->time; - } - // clicking and dragging on the titlebar moves the window, so on a click - // we need to save the coords of the click in case the user drags - frame.grab_x = be->x_root - frame.x - frame.border_w; - frame.grab_y = be->y_root - frame.y - frame.border_w; - } else if (be->window == frame.handle || - be->window == frame.left_grip || - be->window == frame.right_grip || - be->window == frame.window) { - // clicking and dragging on the window's frame moves the window, so on a - // click we need to save the coords of the click in case the user drags - frame.grab_x = be->x_root - frame.x - frame.border_w; - frame.grab_y = be->y_root - frame.y - frame.border_w; - if (be->window == frame.left_grip) - resize_zone = ZoneBottom | ZoneLeft; - else if (be->window == frame.right_grip) - resize_zone = ZoneBottom | ZoneRight; - } - // middle click - } else if (be->state == 0 && be->button == 2) { - if (be->window == frame.maximize_button) { - redrawMaximizeButton(True); - // a middle click anywhere on the window's frame except for on the buttons - // will lower the window - } else if (! (be->window == frame.iconify_button || - be->window == frame.close_button) ) { - stack_change = -1; - } - // right click - } else if (be->state == 0 && be->button == 3) { - if (be->window == frame.maximize_button) { - redrawMaximizeButton(True); - // a right click on the window's frame will show or hide the window's - // windowmenu - } else if (be->window == frame.title || - be->window == frame.label || - be->window == frame.handle || - be->window == frame.window) { - int mx, my; - if (windowmenu) { - if (windowmenu->isVisible()) { - windowmenu->hide(); + } else if (frame.plate == be->window) { + if (windowmenu && windowmenu->isVisible()) windowmenu->hide(); + + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); + + XAllowEvents(blackbox->getXDisplay(), 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 { - // get the coords for the menu - mx = be->x_root - windowmenu->getWidth() / 2; - if (be->window == frame.title || be->window == frame.label) { - my = frame.y + frame.title_h; - } else if (be->window == frame.handle) { - my = frame.y + frame.y_handle - windowmenu->getHeight(); - } else { // (be->window == frame.window) - if (be->y <= (signed) frame.bevel_w) { - my = frame.y + frame.y_border; - } else { - my = be->y_root - (windowmenu->getHeight() / 2); - } - } - - if (mx > (signed) (frame.x + frame.width - - windowmenu->getWidth())) { - mx = frame.x + frame.width - windowmenu->getWidth(); - } else if (mx < frame.x) { - mx = frame.x; - } - - if (my > (signed) (frame.y + frame.y_handle - - windowmenu->getHeight())) { - my = frame.y + frame.y_handle - windowmenu->getHeight(); - } else if (my < (signed) (frame.y + - ((decorations.titlebar) ? frame.title_h : frame.y_border))) { - my = frame.y + - ((decorations.titlebar) ? frame.title_h : frame.y_border); - } - - windowmenu->move(mx, my); - windowmenu->show(); - XRaiseWindow(display, windowmenu->getWindowID()); - XRaiseWindow(display, windowmenu->getSendToMenu()->getWindowID()); - stack_change = 0; // dont raise the window overtop of the menu + lastButtonPressTime = be->time; } } - } - // mouse wheel up - } else if (be->state == 0 && be->button == 4) { - if ((be->window == frame.label || - be->window == frame.title) && - !flags.shaded) - shade(); - // mouse wheel down - } else if (be->state == 0 && be->button == 5) { - if ((be->window == frame.label || - be->window == frame.title) && - flags.shaded) - shade(); - } - - if (! (flags.focused || screen->sloppyFocus()) ) { - setInputFocus(); // any click focus' the window in 'click to focus' - } - if (stack_change < 0) { - screen->getWorkspace(workspace_number)->lowerWindow(this); - } else if (stack_change > 0) { - screen->getWorkspace(workspace_number)->raiseWindow(this); - } - - openbox.ungrab(); -} + frame.grab_x = be->x_root - frame.rect.x() - frame.border_w; + frame.grab_y = be->y_root - frame.rect.y() - frame.border_w; -void OpenboxWindow::buttonReleaseEvent(XButtonEvent *re) { - openbox.grab(); - if (! validateClient()) - return; + if (windowmenu && windowmenu->isVisible()) windowmenu->hide(); - // alt + middle button released - if (re->state == (Mod1Mask & Button2Mask) && re->button == 2) { - if (re->window == frame.window) { - XUngrabPointer(display, CurrentTime); // why? i dont know - } - // left button released - } else if (re->button == 1) { - if (re->window == frame.maximize_button) { - if (re->state == Button1Mask && // only the left button was depressed - (re->x >= 0) && ((unsigned) re->x <= frame.button_w) && - (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) { - maximize(re->button); - } else { - redrawMaximizeButton(False); - } - } else if (re->window == frame.iconify_button) { - if (re->state == Button1Mask && // only the left button was depressed - (re->x >= 0) && ((unsigned) re->x <= frame.button_w) && - (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) { - iconify(); - } else { - redrawIconifyButton(False); - } - } else if (re->window == frame.close_button) { - if (re->state == Button1Mask && // only the left button was depressed - (re->x >= 0) && ((unsigned) re->x <= frame.button_w) && - (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) { - close(); - } - //we should always redraw the close button. some applications - //eg. acroread don't honour the close. - redrawCloseButton(False); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); } - // middle button released - } else if (re->button == 2) { - if (re->window == frame.maximize_button) { - if (re->state == Button2Mask && // only the middle button was depressed - (re->x >= 0) && ((unsigned) re->x <= frame.button_w) && - (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) { - maximize(re->button); - } else { - redrawMaximizeButton(False); - } + } else if (be->button == 2 && (be->window != frame.iconify_button) && + (be->window != frame.close_button)) { + screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this); + } else if (windowmenu && be->button == 3 && + (frame.title == be->window || frame.label == be->window || + frame.handle == be->window || frame.window == be->window)) { + int mx = 0, my = 0; + + if (frame.title == be->window || frame.label == be->window) { + mx = be->x_root - (windowmenu->getWidth() / 2); + my = frame.rect.y() + frame.title_h + frame.border_w; + } else if (frame.handle == be->window) { + mx = be->x_root - (windowmenu->getWidth() / 2); + my = frame.rect.bottom() - frame.handle_h - (frame.border_w * 3) - + windowmenu->getHeight(); + } else { + mx = be->x_root - (windowmenu->getWidth() / 2); + + if (be->y <= static_cast(frame.bevel_w)) + my = frame.rect.y() + frame.title_h; + else + my = be->y_root - (windowmenu->getHeight() / 2); } - // right button released - } else if (re->button == 3) { - if (re->window == frame.maximize_button) { - if (re->state == Button3Mask && // only the right button was depressed - (re->x >= 0) && ((unsigned) re->x <= frame.button_w) && - (re->y >= 0) && ((unsigned) re->y <= frame.button_h)) { - maximize(re->button); + + // snap the window menu into a corner if necessary - we check the + // position of the menu with the coordinates of the client to + // make the comparisions easier. + // ### this needs some work! + if (mx > client.rect.right() - + static_cast(windowmenu->getWidth())) + mx = frame.rect.right() - windowmenu->getWidth() - frame.border_w + 1; + if (mx < client.rect.left()) + mx = frame.rect.x(); + + if (my > client.rect.bottom() - + static_cast(windowmenu->getHeight())) + my = frame.rect.bottom() - windowmenu->getHeight() - frame.border_w + 1; + if (my < client.rect.top()) + my = frame.rect.y() + ((decorations & Decor_Titlebar) ? + frame.title_h : 0); + + if (windowmenu) { + if (! windowmenu->isVisible()) { + windowmenu->move(mx, my); + windowmenu->show(); + XRaiseWindow(blackbox->getXDisplay(), windowmenu->getWindowID()); + XRaiseWindow(blackbox->getXDisplay(), + windowmenu->getSendToMenu()->getWindowID()); } else { - redrawMaximizeButton(False); + windowmenu->hide(); } } } - - // when the window is being interactively moved, a button release stops the - // move where it is - if (flags.moving) { - endMove(); - // when the window is being interactively resized, a button release stops the - // resizing - } else if (flags.resizing) { - flags.resizing = False; - XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(), - frame.resize_x, frame.resize_y, - frame.resize_w - 1, frame.resize_h - 1); - screen->hideGeometry(); - if (resize_zone & ZoneLeft) { - left_fixsize(); - } else { // when resizing with "Alt+Button3", the resize is the same as if - // done with the right grip (the right side of the window is what - // moves) - right_fixsize(); - } - // unset maximized state when resized after fully maximized - if (flags.maximized == 1) { - maximize(0); - } - configure(frame.resize_x, frame.resize_y, - frame.resize_w - (frame.border_w * 2), - frame.resize_h - (frame.border_w * 2)); - openbox.ungrab(); - XUngrabPointer(display, CurrentTime); - resize_zone = 0; - } - - openbox.ungrab(); } -void OpenboxWindow::startMove(int x, int y) { - ASSERT(!flags.moving); - - // make sure only one window is moving at a time - OpenboxWindow *w = openbox.getMaskedWindow(); - if (w != (OpenboxWindow *) 0 && w->flags.moving) - w->endMove(); - - XGrabPointer(display, frame.window, False, PointerMotionMask | - ButtonReleaseMask, GrabModeAsync, GrabModeAsync, - None, openbox.getMoveCursor(), CurrentTime); - - if (windowmenu && windowmenu->isVisible()) - windowmenu->hide(); - - flags.moving = True; - - openbox.maskWindowEvents(client.window, this); +void BlackboxWindow::buttonReleaseEvent(XButtonEvent *re) { + if (re->window == frame.maximize_button) { + if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && + (re->y >= 0 && re->y <= static_cast(frame.button_w))) { + maximize(re->button); + } else { + redrawMaximizeButton(flags.maximized); + } + } else if (re->window == frame.iconify_button) { + if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && + (re->y >= 0 && re->y <= static_cast(frame.button_w))) { + iconify(); + } else { + redrawIconifyButton(False); + } + } else if (re->window == frame.close_button) { + if ((re->x >= 0 && re->x <= static_cast(frame.button_w)) && + (re->y >= 0 && re->y <= static_cast(frame.button_w))) + close(); + redrawCloseButton(False); + } else if (flags.moving) { + flags.moving = False; + + 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(blackbox->getXDisplay(), screen->getRootWindow(), + screen->getOpGC(), frame.changing.x(), frame.changing.y(), + frame.changing.width() - 1, frame.changing.height() - 1); + XUngrabServer(blackbox->getXDisplay()); + + 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(blackbox->getXDisplay(), CurrentTime); + } else if (flags.resizing) { + XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(), + screen->getOpGC(), frame.changing.x(), frame.changing.y(), + frame.changing.width() - 1, frame.changing.height() - 1); + XUngrabServer(blackbox->getXDisplay()); - if (! screen->opaqueMove()) { - openbox.grab(); + screen->hideGeometry(); - frame.move_x = frame.x; - frame.move_y = frame.y; - frame.resize_w = frame.width + (frame.border_w * 2); - frame.resize_h = ((flags.shaded) ? frame.title_h : frame.height) + - (frame.border_w * 2); + constrain((re->window == frame.left_grip) ? TopRight : TopLeft); - screen->showPosition(frame.x, frame.y); + // unset maximized state when resized after fully maximized + if (flags.maximized == 1) + maximize(0); + flags.resizing = False; + configure(frame.changing.x(), frame.changing.y(), + frame.changing.width(), frame.changing.height()); - XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(), - frame.move_x, frame.move_y, - frame.resize_w - 1, frame.resize_h - 1); + XUngrabPointer(blackbox->getXDisplay(), CurrentTime); + } else if (re->window == frame.window) { + if (re->button == 2 && re->state == Mod1Mask) + XUngrabPointer(blackbox->getXDisplay(), CurrentTime); } - frame.grab_x = x - frame.x - frame.border_w; - frame.grab_y = y - frame.y - frame.border_w; } -void OpenboxWindow::doMove(int x, int y) { - ASSERT(flags.moving); - - int dx = x - frame.grab_x, dy = y - frame.grab_y; - - dx -= frame.border_w; - dy -= frame.border_w; - - int snap_distance = screen->edgeSnapThreshold(); - // width/height of the snapping window - unsigned int snap_w = frame.width + (frame.border_w * 2); - unsigned int snap_h = area().h() + (frame.border_w * 2); - if (snap_distance) { - int drx = screen->size().w() - (dx + snap_w); - - if (dx < drx && (dx > 0 && dx < snap_distance) || - (dx < 0 && dx > -snap_distance) ) - dx = 0; - else if ( (drx > 0 && drx < snap_distance) || - (drx < 0 && drx > -snap_distance) ) - dx = screen->size().w() - snap_w; - - int dtty, dbby, dty, dby; - switch (screen->getToolbar()->placement()) { - case Toolbar::TopLeft: - case Toolbar::TopCenter: - case Toolbar::TopRight: - dtty = screen->getToolbar()->getExposedHeight() + - frame.border_w; - dbby = screen->size().h(); - break; - - default: - dtty = 0; - dbby = screen->getToolbar()->area().y(); - break; - } - - dty = dy - dtty; - dby = dbby - (dy + snap_h); - - if ( (dy > 0 && dty < snap_distance) || - (dy < 0 && dty > -snap_distance) ) - dy = dtty; - else if ( (dby > 0 && dby < snap_distance) || - (dby < 0 && dby > -snap_distance) ) - dy = dbby - snap_h; - } - - if (screen->opaqueMove()) { - configure(dx, dy, frame.width, frame.height); - } else { - XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(), - frame.move_x, frame.move_y, frame.resize_w - 1, - frame.resize_h - 1); - - frame.move_x = dx; - frame.move_y = dy; - - XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(), - frame.move_x, frame.move_y, frame.resize_w - 1, - frame.resize_h - 1); - } - - screen->showPosition(dx, dy); -} +void BlackboxWindow::motionNotifyEvent(XMotionEvent *me) { + if (!flags.resizing && (me->state & Button1Mask) && + (functions & Func_Move) && + (frame.title == me->window || frame.label == me->window || + frame.handle == me->window || frame.window == me->window)) { + if (! flags.moving) { + XGrabPointer(blackbox->getXDisplay(), me->window, False, + Button1MotionMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, + None, blackbox->getMoveCursor(), CurrentTime); + if (windowmenu && windowmenu->isVisible()) + windowmenu->hide(); -void OpenboxWindow::endMove() { - ASSERT(flags.moving); + flags.moving = True; - flags.moving = False; + if (! screen->doOpaqueMove()) { + XGrabServer(blackbox->getXDisplay()); - openbox.maskWindowEvents(0, (OpenboxWindow *) 0); - if (!screen->opaqueMove()) { - XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(), - frame.move_x, frame.move_y, frame.resize_w - 1, - frame.resize_h - 1); + frame.changing = frame.rect; + screen->showPosition(frame.changing.x(), frame.changing.y()); - configure(frame.move_x, frame.move_y, frame.width, frame.height); - openbox.ungrab(); - } else { - configure(frame.x, frame.y, frame.width, frame.height); - } - screen->hideGeometry(); - XUngrabPointer(display, CurrentTime); - // if there are any left over motions from the move, drop them now cuz they - // cause problems - XEvent e; - while (XCheckTypedWindowEvent(display, frame.window, MotionNotify, &e)); -} + XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(), + screen->getOpGC(), + frame.changing.x(), + frame.changing.y(), + frame.changing.width() - 1, + frame.changing.height() - 1); + } + } else { + int dx = me->x_root - frame.grab_x, dy = me->y_root - frame.grab_y; + dx -= frame.border_w; + dy -= frame.border_w; + + const int snap_distance = screen->getEdgeSnapThreshold(); + + if (snap_distance) { + Rect srect = screen->availableArea(); + // window corners + const int wleft = dx, + wright = dx + frame.rect.width() - 1, + wtop = dy, + wbottom = dy + frame.rect.height() - 1; + + int dleft = std::abs(wleft - srect.left()), + dright = std::abs(wright - srect.right()), + dtop = std::abs(wtop - srect.top()), + dbottom = std::abs(wbottom - srect.bottom()); + + // snap left? + if (dleft < snap_distance && dleft < dright) + dx = srect.left(); + // snap right? + else if (dright < snap_distance && dright < dleft) + dx = srect.right() - frame.rect.width() + 1; + + // snap top? + if (dtop < snap_distance && dtop < dbottom) + dy = srect.top(); + // snap bottom? + else if (dbottom < snap_distance && dbottom < dtop) + dy = srect.bottom() - frame.rect.height() + 1; + + srect = screen->getRect(); // now get the full screen + + dleft = std::abs(wleft - srect.left()), + dright = std::abs(wright - srect.right()), + dtop = std::abs(wtop - srect.top()), + dbottom = std::abs(wbottom - srect.bottom()); + + // snap left? + if (dleft < snap_distance && dleft < dright) + dx = srect.left(); + // snap right? + else if (dright < snap_distance && dright < dleft) + dx = srect.right() - frame.rect.width() + 1; + + // snap top? + if (dtop < snap_distance && dtop < dbottom) + dy = srect.top(); + // snap bottom? + else if (dbottom < snap_distance && dbottom < dtop) + dy = srect.bottom() - frame.rect.height() + 1; + } + if (screen->doOpaqueMove()) { + configure(dx, dy, frame.rect.width(), frame.rect.height()); + } else { + XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(), + screen->getOpGC(), + frame.changing.x(), + frame.changing.y(), + frame.changing.width() - 1, + frame.changing.height() - 1); + + frame.changing.setPos(dx, dy); + + XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(), + screen->getOpGC(), + frame.changing.x(), + frame.changing.y(), + frame.changing.width() - 1, + frame.changing.height() - 1); + } -void OpenboxWindow::motionNotifyEvent(XMotionEvent *me) { - if (flags.moving) - doMove(me->x_root, me->y_root); - else if (!flags.resizing && (me->state & Button1Mask) && functions.move && - (frame.title == me->window || frame.label == me->window || - frame.handle == me->window || frame.window == me->window)) - startMove(me->x_root, me->y_root); - else if (functions.resize && - (((me->state & Button1Mask) && (me->window == frame.right_grip || - me->window == frame.left_grip)) || - (me->state == (Mod1Mask | Button3Mask) && - me->window == frame.window))) { - Bool left = resize_zone & ZoneLeft; + screen->showPosition(dx, dy); + } + } else if ((functions & Func_Resize) && + (((me->state & Button1Mask) && + (me->window == frame.right_grip || + me->window == frame.left_grip)) || + (me->state & (Mod1Mask | Button3Mask) && + me->window == frame.window))) { + bool left = (me->window == frame.left_grip); if (! flags.resizing) { - Cursor cursor; - if (resize_zone & ZoneTop) - cursor = (resize_zone & ZoneLeft) ? - openbox.getUpperLeftAngleCursor() : - openbox.getUpperRightAngleCursor(); - else - cursor = (resize_zone & ZoneLeft) ? - openbox.getLowerLeftAngleCursor() : - openbox.getLowerRightAngleCursor(); - XGrabPointer(display, me->window, False, ButtonMotionMask | - ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, - cursor, CurrentTime); + XGrabServer(blackbox->getXDisplay()); + XGrabPointer(blackbox->getXDisplay(), me->window, False, + ButtonMotionMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + ((left) ? blackbox->getLowerLeftAngleCursor() : + blackbox->getLowerRightAngleCursor()), + CurrentTime); flags.resizing = True; - openbox.grab(); + int gw, gh; + frame.grab_x = me->x; + frame.grab_y = me->y; + frame.changing = frame.rect; - int gx, gy; - if (resize_zone & ZoneRight) - frame.grab_x = me->x - screen->getBorderWidth(); - else - frame.grab_x = me->x + screen->getBorderWidth(); - if (resize_zone & ZoneTop) - frame.grab_y = me->y + screen->getBorderWidth() * 2; - else - frame.grab_y = me->y - screen->getBorderWidth() * 2; - frame.resize_x = frame.x; - frame.resize_y = frame.y; - frame.resize_w = frame.width + (frame.border_w * 2); - frame.resize_h = frame.height + (frame.border_w * 2); - - if (left) - left_fixsize(&gx, &gy); - else - right_fixsize(&gx, &gy); + constrain((left) ? TopRight : TopLeft, &gw, &gh); - screen->showGeometry(gx, gy); + XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(), + screen->getOpGC(), frame.changing.x(), frame.changing.y(), + frame.changing.width() - 1, frame.changing.height() - 1); - XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(), - frame.resize_x, frame.resize_y, - frame.resize_w - 1, frame.resize_h - 1); + screen->showGeometry(gw, gh); } else { - XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(), - frame.resize_x, frame.resize_y, - frame.resize_w - 1, frame.resize_h - 1); + XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(), + screen->getOpGC(), frame.changing.x(), frame.changing.y(), + frame.changing.width() - 1, frame.changing.height() - 1); - int gx, gy; + int gw, gh; - if (resize_zone & ZoneTop) - frame.resize_h = frame.height - (me->y - frame.grab_y); - else - frame.resize_h = frame.height + (me->y - frame.grab_y); - if (frame.resize_h < 1) frame.resize_h = 1; + Corner anchor; if (left) { - frame.resize_x = me->x_root - frame.grab_x; - if (frame.resize_x > (signed) (frame.x + frame.width)) - frame.resize_x = frame.resize_x + frame.width - 1; - - left_fixsize(&gx, &gy); + anchor = TopRight; + frame.changing.setCoords(me->x_root - frame.grab_x, frame.rect.top(), + frame.rect.right(), frame.rect.bottom()); + frame.changing.setHeight(frame.rect.height() + (me->y - frame.grab_y)); } else { - frame.resize_w = frame.width + (me->x - frame.grab_x); - if (frame.resize_w < 1) frame.resize_w = 1; - - right_fixsize(&gx, &gy); + anchor = TopLeft; + frame.changing.setSize(frame.rect.width() + (me->x - frame.grab_x), + frame.rect.height() + (me->y - frame.grab_y)); } - XDrawRectangle(display, screen->getRootWindow(), screen->getOpGC(), - frame.resize_x, frame.resize_y, - frame.resize_w - 1, frame.resize_h - 1); + constrain(anchor, &gw, &gh); + + XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(), + screen->getOpGC(), frame.changing.x(), frame.changing.y(), + frame.changing.width() - 1, frame.changing.height() - 1); - screen->showGeometry(gx, gy); + screen->showGeometry(gw, gh); } } } #ifdef SHAPE -void OpenboxWindow::shapeEvent(XShapeEvent *) { - if (openbox.hasShapeExtensions()) { - if (flags.shaped) { - openbox.grab(); - if (! validateClient()) return; - XShapeCombineShape(display, frame.window, ShapeBounding, - frame.mwm_border_w, frame.y_border + - frame.mwm_border_w, client.window, - ShapeBounding, ShapeSet); - - int num = 1; - XRectangle xrect[2]; - xrect[0].x = xrect[0].y = 0; - xrect[0].width = frame.width; - xrect[0].height = frame.y_border; - - if (decorations.handle) { - xrect[1].x = 0; - xrect[1].y = frame.y_handle; - xrect[1].width = frame.width; - xrect[1].height = frame.handle_h + frame.border_w; - num++; - } - - XShapeCombineRectangles(display, frame.window, ShapeBounding, 0, 0, - xrect, num, ShapeUnion, Unsorted); - openbox.ungrab(); - } +void BlackboxWindow::shapeEvent(XShapeEvent *) { + if (blackbox->hasShapeExtensions() && flags.shaped) { + configureShape(); } } #endif // SHAPE -bool OpenboxWindow::validateClient(void) { - XSync(display, False); +bool BlackboxWindow::validateClient(void) { + XSync(blackbox->getXDisplay(), False); XEvent e; - if (XCheckTypedWindowEvent(display, client.window, DestroyNotify, &e) || - XCheckTypedWindowEvent(display, client.window, UnmapNotify, &e)) { - XPutBackEvent(display, &e); - openbox.ungrab(); + if (XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window, + DestroyNotify, &e) || + XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window, + UnmapNotify, &e)) { + XPutBackEvent(blackbox->getXDisplay(), &e); - return false; + return False; } - return true; + return True; } -void OpenboxWindow::restore(void) { - XChangeSaveSet(display, client.window, SetModeDelete); - XSelectInput(display, client.window, NoEventMask); +void BlackboxWindow::restore(bool remap) { + XChangeSaveSet(blackbox->getXDisplay(), client.window, SetModeDelete); + XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask); + XSelectInput(blackbox->getXDisplay(), frame.plate, NoEventMask); restoreGravity(); - XUnmapWindow(display, frame.window); - XUnmapWindow(display, client.window); + XUnmapWindow(blackbox->getXDisplay(), frame.window); + XUnmapWindow(blackbox->getXDisplay(), client.window); - XSetWindowBorderWidth(display, client.window, client.old_bw); - XReparentWindow(display, client.window, screen->getRootWindow(), - client.x, client.y); - XMapWindow(display, client.window); + XSetWindowBorderWidth(blackbox->getXDisplay(), client.window, client.old_bw); - XFlush(display); + XEvent ev; + if (! XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window, + ReparentNotify, &ev)) { + // according to the ICCCM - if the client doesn't reparent to + // root, then we have to do it for them + XReparentWindow(blackbox->getXDisplay(), client.window, + screen->getRootWindow(), + client.rect.x(), client.rect.y()); + } - delete this; + if (remap) XMapWindow(blackbox->getXDisplay(), client.window); } -void OpenboxWindow::timeout(void) { - screen->getWorkspace(workspace_number)->raiseWindow(this); +// timer for autoraise +void BlackboxWindow::timeout(void) { + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); } -void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) { +void BlackboxWindow::changeBlackboxHints(BlackboxHints *net) { if ((net->flags & AttribShaded) && - ((openbox_attrib.attrib & 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)) && - ((openbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) != + ((blackbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) != (net->attrib & (AttribMaxVert | AttribMaxHoriz)))) { if (flags.maximized) { maximize(0); @@ -3075,53 +2686,53 @@ void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) { } if ((net->flags & AttribOmnipresent) && - ((openbox_attrib.attrib & AttribOmnipresent) != + ((blackbox_attrib.attrib & AttribOmnipresent) != (net->attrib & AttribOmnipresent))) stick(); if ((net->flags & AttribWorkspace) && - (workspace_number != (signed) net->workspace)) { + (blackbox_attrib.workspace != net->workspace)) { screen->reassociateWindow(this, net->workspace, True); - if (screen->getCurrentWorkspaceID() != (signed) net->workspace) withdraw(); - else deiconify(); + if (screen->getCurrentWorkspaceID() != net->workspace) { + withdraw(); + } else { + show(); + screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this); + } } if (net->flags & AttribDecoration) { switch (net->decoration) { case DecorNone: - decorations.titlebar = decorations.border = decorations.handle = - decorations.iconify = decorations.maximize = decorations.menu = False; + // clear all decorations except close + decorations &= Decor_Close; break; default: case DecorNormal: - decorations.titlebar = decorations.iconify = decorations.menu = - decorations.border = True; - decorations.handle = (functions.resize && !flags.transient); - decorations.maximize = functions.maximize; + decorations |= Decor_Titlebar | Decor_Handle | Decor_Border | + Decor_Iconify | Decor_Maximize; break; case DecorTiny: - decorations.titlebar = decorations.iconify = decorations.menu = True; - decorations.border = decorations.border = decorations.handle = False; - decorations.maximize = functions.maximize; + decorations |= Decor_Titlebar | Decor_Iconify; + decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize); break; case DecorTool: - decorations.titlebar = decorations.menu = True; - decorations.iconify = decorations.border = False; - decorations.handle = (functions.resize && !flags.transient); - decorations.maximize = functions.maximize; + decorations |= Decor_Titlebar; + decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle); + functions |= Func_Move; break; } if (frame.window) { - XMapSubwindows(display, frame.window); - XMapWindow(display, frame.window); + XMapSubwindows(blackbox->getXDisplay(), frame.window); + XMapWindow(blackbox->getXDisplay(), frame.window); } reconfigure(); @@ -3134,14 +2745,14 @@ void OpenboxWindow::changeOpenboxHints(OpenboxHints *net) { * 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 dimentions. + * window's dimensions. */ -void OpenboxWindow::upsize(void) { +void BlackboxWindow::upsize(void) { frame.bevel_w = screen->getBevelWidth(); - if (decorations.border) { + if (decorations & Decor_Border) { frame.border_w = screen->getBorderWidth(); - if (!flags.transient) + if (!isTransient()) frame.mwm_border_w = screen->getFrameWidth(); else frame.mwm_border_w = 0; @@ -3149,7 +2760,7 @@ void OpenboxWindow::upsize(void) { frame.mwm_border_w = frame.border_w = 0; } - if (decorations.titlebar) { + 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 WindowStyle *style = screen->getWindowStyle(); @@ -3161,115 +2772,187 @@ void OpenboxWindow::upsize(void) { (frame.bevel_w * 2) + 2); frame.label_h = frame.title_h - (frame.bevel_w * 2); - frame.button_w = frame.button_h = (frame.label_h - 2); - frame.y_border = frame.title_h + frame.border_w; + 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 = frame.button_h = 0; - frame.y_border = 0; + frame.button_w = 0; + + // set the top frame margin + frame.margin.top = frame.border_w + frame.mwm_border_w; } - frame.border_h = client.height + frame.mwm_border_w * 2; + // set the left/right frame margin + frame.margin.left = frame.margin.right = frame.border_w + frame.mwm_border_w; - if (decorations.handle) { - frame.y_handle = frame.y_border + frame.border_h + frame.border_w; + if (decorations & Decor_Handle) { frame.grip_w = frame.button_w * 2; - frame.grip_h = frame.handle_h = screen->getHandleWidth(); + frame.handle_h = screen->getHandleWidth(); + + // set the bottom frame margin + frame.margin.bottom = frame.border_w + frame.handle_h + + frame.border_w + frame.mwm_border_w; } else { - frame.y_handle = frame.y_border + frame.border_h; frame.handle_h = 0; - frame.grip_w = frame.grip_h = 0; + frame.grip_w = 0; + + // set the bottom frame margin + frame.margin.bottom = frame.border_w + frame.mwm_border_w; } - frame.width = client.width + (frame.mwm_border_w * 2); - frame.height = frame.y_handle + frame.handle_h; + // set the frame rect + frame.rect.setSize(client.rect.width() + frame.margin.left + + frame.margin.right, + client.rect.height() + frame.margin.top + + frame.margin.bottom); + frame.inside_w = frame.rect.width() - (frame.border_w * 2); + frame.inside_h = frame.rect.height() - (frame.border_w * 2); } /* - * Set the size and position of the client window. - * These values are based upon the current style settings and the frame - * window's dimensions. + * 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 has resizes in cells, not in + * pixels). + * + * The physical geometry is placed into frame.changing_{x,y,width,height}. + * Physical geometry refers to the geometry of the window in pixels. */ -void OpenboxWindow::downsize(void) { - frame.y_handle = frame.height - frame.handle_h; - frame.border_h = frame.y_handle - frame.y_border - - (decorations.handle ? frame.border_w : 0); +void BlackboxWindow::constrain(Corner anchor, int *pw, 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); + + 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 + if (dw < static_cast(client.min_width)) dw = client.min_width; + if (dh < static_cast(client.min_height)) dh = client.min_height; + if (dw > static_cast(client.max_width)) dw = client.max_width; + if (dh > static_cast(client.max_height)) dh = client.max_height; + + dw -= base_width; + dw /= client.width_inc; + dh -= base_height; + dh /= client.height_inc; + + if (pw) *pw = dw; + if (ph) *ph = dh; + + dw *= client.width_inc; + dw += base_width; + 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 + switch (anchor) { + case TopLeft: + // nothing to do + break; - client.x = frame.x + frame.mwm_border_w + frame.border_w; - client.y = frame.y + frame.y_border + frame.mwm_border_w + frame.border_w; + case TopRight: + int dx = frame.rect.right() - frame.changing.right(); + frame.changing.setPos(frame.changing.x() + dx, frame.changing.y()); + break; + } +} - client.width = frame.width - (frame.mwm_border_w * 2); - client.height = frame.height - frame.y_border - (frame.mwm_border_w * 2) - - frame.handle_h - (decorations.handle ? frame.border_w : 0); - frame.y_handle = frame.border_h + frame.y_border + frame.border_w; -} +int WindowStyle::doJustify(const char *text, int &start_pos, + unsigned int max_length, unsigned int modifier, + bool multibyte) const { + size_t text_len = strlen(text); + unsigned int length; + do { + if (multibyte) { + XRectangle ink, logical; + XmbTextExtents(fontset, text, text_len, &ink, &logical); + length = logical.width; + } else { + length = XTextWidth(font, text, text_len); + } + length += modifier; + } while (length > max_length && text_len-- > 0); -void OpenboxWindow::right_fixsize(int *gx, int *gy) { - // calculate the size of the client window and conform it to the - // size specified by the size hints of the client window... - int dx = 1 + frame.resize_w - client.base_width - (frame.mwm_border_w * 2) - - (frame.border_w * 2) + (client.width_inc / 2); - int dy = 1 + frame.resize_h - frame.y_border - client.base_height - - frame.handle_h - (frame.border_w * 3) - (frame.mwm_border_w * 2) - + (client.height_inc / 2); + switch (justify) { + case RightJustify: + start_pos += max_length - length; + break; - if (dx < (signed) client.min_width) dx = client.min_width; - if (dy < (signed) client.min_height) dy = client.min_height; - if ((unsigned) dx > client.max_width) dx = client.max_width; - if ((unsigned) dy > client.max_height) dy = client.max_height; + case CenterJustify: + start_pos += (max_length - length) / 2; + break; - dx /= client.width_inc; - dy /= client.height_inc; + case LeftJustify: + default: + break; + } - if (gx) *gx = dx; - if (gy) *gy = dy; + return text_len; +} - dx = (dx * client.width_inc) + client.base_width; - dy = (dy * client.height_inc) + client.base_height; - frame.resize_w = dx + (frame.mwm_border_w * 2) + (frame.border_w * 2) - 1; - frame.resize_h = dy + frame.y_border + frame.handle_h + - (frame.mwm_border_w * 2) + (frame.border_w * 3) - 1; - if (resize_zone & ZoneTop) - frame.resize_y = frame.y + frame.height - frame.resize_h + - screen->getBorderWidth() * 2; +BWindowGroup::BWindowGroup(Blackbox *b, Window _group) + : blackbox(b), group(_group) { + // watch for destroy notify on the group window + XSelectInput(blackbox->getXDisplay(), group, StructureNotifyMask); + blackbox->saveGroupSearch(group, this); } -void OpenboxWindow::left_fixsize(int *gx, int *gy) { - // calculate the size of the client window and conform it to the - // size specified by the size hints of the client window... - int dx = 1 + frame.x + frame.width - frame.resize_x - client.base_width - - (frame.mwm_border_w * 2) + (client.width_inc / 2); - int dy = 1 + frame.resize_h - frame.y_border - client.base_height - - frame.handle_h - (frame.border_w * 3) - (frame.mwm_border_w * 2) - + (client.height_inc / 2); +BWindowGroup::~BWindowGroup(void) { + blackbox->removeGroupSearch(group); +} + - if (dx < (signed) client.min_width) dx = client.min_width; - if (dy < (signed) client.min_height) dy = client.min_height; - if ((unsigned) dx > client.max_width) dx = client.max_width; - if ((unsigned) dy > client.max_height) dy = client.max_height; +BlackboxWindow * +BWindowGroup::find(BScreen *screen, bool allow_transients) const { + BlackboxWindow *ret = blackbox->getFocusedWindow(); - dx /= client.width_inc; - dy /= client.height_inc; + // does the focus window match (or any transient_fors)? + while (ret) { + if (ret->getScreen() == screen && ret->getGroupWindow() == group) { + if (ret->isTransient() && allow_transients) break; + else if (! ret->isTransient()) break; + } - if (gx) *gx = dx; - if (gy) *gy = dy; + ret = ret->getTransientFor(); + } - dx = (dx * client.width_inc) + client.base_width; - dy = (dy * client.height_inc) + client.base_height; + if (ret) return ret; - frame.resize_w = dx + (frame.mwm_border_w * 2) + (frame.border_w * 2) - 1; - frame.resize_x = frame.x + frame.width - frame.resize_w + - (frame.border_w * 2); - frame.resize_h = dy + frame.y_border + frame.handle_h + - (frame.mwm_border_w * 2) + (frame.border_w * 3) - 1; - if (resize_zone & ZoneTop) - frame.resize_y = frame.y + frame.height - frame.resize_h + - screen->getBorderWidth() * 2; + // 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) { + if (ret->isTransient() && allow_transients) break; + else if (! ret->isTransient()) break; + } + } + return ret; } diff --git a/src/Window.h b/src/Window.h deleted file mode 100644 index b91a41fd..00000000 --- a/src/Window.h +++ /dev/null @@ -1,361 +0,0 @@ -// Window.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Window_hh -#define __Window_hh - -#include -#include -#ifdef SHAPE -# include -#endif // SHAPE - -#include "BaseDisplay.h" -#include "Timer.h" -#include "Windowmenu.h" -#include "Geometry.h" - -// forward declaration -class OpenboxWindow; - -#define MwmHintsFunctions (1l << 0) -#define MwmHintsDecorations (1l << 1) - -#define MwmFuncAll (1l << 0) -#define MwmFuncResize (1l << 1) -#define MwmFuncMove (1l << 2) -#define MwmFuncIconify (1l << 3) -#define MwmFuncMaximize (1l << 4) -#define MwmFuncClose (1l << 5) - -#define MwmDecorAll (1l << 0) -#define MwmDecorBorder (1l << 1) -#define MwmDecorHandle (1l << 2) -#define MwmDecorTitle (1l << 3) -#define MwmDecorMenu (1l << 4) -#define MwmDecorIconify (1l << 5) -#define MwmDecorMaximize (1l << 6) - -// this structure only contains 3 elements... the Motif 2.0 structure contains -// 5... we only need the first 3... so that is all we will define -typedef struct MwmHints { - unsigned long flags, functions, decorations; -} MwmHints; - -#define PropMwmHintsElements 3 - - -class OpenboxWindow : public TimeoutHandler { -private: - BImageControl *image_ctrl; - Openbox &openbox; - BScreen *screen; - Display *display; - BTimer *timer; - OpenboxAttributes openbox_attrib; - - Time lastButtonPressTime; // used for double clicks, when were we clicked - Windowmenu *windowmenu; - - int window_number, workspace_number; - unsigned long current_state; - bool place_window; // place the window ourselves when mapped - - enum FocusMode { F_NoInput = 0, F_Passive, - F_LocallyActive, F_GloballyActive }; - FocusMode focus_mode; - - enum ResizeZones { - ZoneTop = 1 << 0, - ZoneBottom = 1 << 1, - ZoneLeft = 1 << 2, - ZoneRight = 1 << 3 - }; - unsigned int resize_zone; // bitmask of ResizeZones values - - struct _flags { - Bool moving, // is moving? - resizing, // is resizing? - shaded, // is shaded? - visible, // is visible? - iconic, // is iconified? - transient, // is a transient window? - focused, // has focus? - stuck, // is omnipresent - modal, // is modal? (must be dismissed to continue) - send_focus_message, // should we send focus messages to our client? - shaped, // does the frame use the shape extension? - managed; // under openbox's control? - // maximize is special, the number corresponds - // with a mouse button - // if 0, not maximized - unsigned int maximized; // 1 = HorizVert, 2 = Vertical, 3 = Horizontal - } flags; - - struct _client { - OpenboxWindow *transient_for, // which window are we a transient for? - *transient; // which window is our transient? - - Window window, // the client's window - window_group; // the client's window group - - char *title, *icon_title; - size_t title_len; // strlen(title) - - int x, y, - old_bw; // client's borderwidth - - unsigned int width, height, - title_text_w, // width as rendered in the current font - min_width, min_height, // can not be resized smaller - max_width, max_height, // can not be resized larger - width_inc, height_inc, // increment step - min_aspect_x, min_aspect_y, // minimum aspect ratio - max_aspect_x, max_aspect_y, // maximum aspect ratio - base_width, base_height, - win_gravity; - - unsigned long initial_state, normal_hint_flags, wm_hint_flags; - - MwmHints *mwm_hint; - OpenboxHints *openbox_hint; - } client; - - struct _functions { - Bool resize, move, iconify, maximize, close; - } functions; - - /* - * client window = the application's window - * frame window = the window drawn around the outside of the client window - * by the window manager which contains items like the - * titlebar and close button - * title = the titlebar drawn above the client window, it displays the - * window's name and any buttons for interacting with the window, - * such as iconify, maximize, and close - * label = the window in the titlebar where the title is drawn - * buttons = maximize, iconify, close - * handle = the bar drawn at the bottom of the window, which contains the - * left and right grips used for resizing the window - * grips = the smaller reactangles in the handle, one of each side of it. - * When clicked and dragged, these resize the window interactively - * border = the line drawn around the outside edge of the frame window, - * between the title, the bordered client window, and the handle. - * Also drawn between the grips and the handle - */ - - /* - * what decorations do we have? - * this is based on the type of the client window as well as user input - * the menu is not really decor, but it goes hand in hand with the decor - */ - struct _decorations { - Bool titlebar, handle, border, iconify, maximize, close, menu; - } decorations; - - struct _frame { - // u -> unfocused, f -> has focus - unsigned long ulabel_pixel, flabel_pixel, utitle_pixel, - ftitle_pixel, uhandle_pixel, fhandle_pixel, ubutton_pixel, - fbutton_pixel, pbutton_pixel, uborder_pixel, fborder_pixel, - ugrip_pixel, fgrip_pixel; - Pixmap ulabel, flabel, utitle, ftitle, uhandle, fhandle, - ubutton, fbutton, pbutton, ugrip, fgrip; - - Window window, // the frame - plate, // holds the client - title, - label, - handle, - close_button, iconify_button, maximize_button, - right_grip, left_grip; - - - unsigned int resize_w, resize_h; - int resize_x, resize_y, // size and location of box drawn while resizing - move_x, move_y; // location of box drawn while moving - - int x, y, - grab_x, grab_y, // where was the window when it was grabbed? - y_border, y_handle; // where within frame is the border and handle - - unsigned int width, height, title_h, label_w, label_h, handle_h, - button_w, button_h, grip_w, grip_h, mwm_border_w, border_h, border_w, - bevel_w; - } frame; - -protected: - Bool getState(); - Window createToplevelWindow(int x, int y, unsigned int width, - unsigned int height, unsigned int borderwidth); - Window createChildWindow(Window parent, Cursor = None); - - void getWMName(); - void getWMIconName(); - void getWMNormalHints(); - void getWMProtocols(); - void getWMHints(); - void getMWMHints(); - void getOpenboxHints(); - void setNetWMAttributes(); - void associateClientWindow(); - void decorate(); - void decorateLabel(); - void positionButtons(); - void positionWindows(); - void createCloseButton(); - void createIconifyButton(); - void createMaximizeButton(); - void redrawLabel(); - void redrawAllButtons(); - void redrawCloseButton(Bool); - void redrawIconifyButton(Bool); - void redrawMaximizeButton(Bool); - void restoreGravity(); - void setGravityOffsets(); - void setState(unsigned long); - void upsize(); - void downsize(); - void right_fixsize(int *gx = 0, int *gy = 0); - void left_fixsize(int *gx = 0, int *gy = 0); - void doMove(int x, int y); - - -public: - OpenboxWindow(Openbox &b, Window w, BScreen *s = (BScreen *) 0); - virtual ~OpenboxWindow(); - - inline Bool isTransient() const { return flags.transient; } - inline Bool isFocused() const { return flags.focused; } - inline Bool isVisible() const { return flags.visible; } - inline Bool isIconic() const { return flags.iconic; } - inline Bool isShaded() const { return flags.shaded; } - inline Bool isMaximized() const { return flags.maximized; } - inline Bool isMaximizedFull() const { return flags.maximized == 1; } - inline Bool isStuck() const { return flags.stuck; } - inline Bool isIconifiable() const { return functions.iconify; } - inline Bool isMaximizable() const { return functions.maximize; } - inline Bool isResizable() const { return functions.resize; } - inline Bool isClosable() const { return functions.close; } - - inline Bool hasTitlebar() const { return decorations.titlebar; } - inline Bool hasTransient() const - { return ((client.transient) ? True : False); } - - inline OpenboxWindow *getTransient() { return client.transient; } - inline OpenboxWindow *getTransientFor() { return client.transient_for; } - - inline BScreen *getScreen() { return screen; } - - inline const Window &getFrameWindow() const { return frame.window; } - inline const Window &getClientWindow() const { return client.window; } - - inline Windowmenu * getWindowmenu() { return windowmenu; } - - inline char **getTitle() { return &client.title; } - inline char **getIconTitle() { return &client.icon_title; } - //inline const int &getXFrame() const { return frame.x; } - //inline const int &getYFrame() const { return frame.y; } - //inline const int &getXClient() const { return client.x; } - //inline const int &getYClient() const { return client.y; } - inline const int &getWorkspaceNumber() const { return workspace_number; } - inline const int &getWindowNumber() const { return window_number; } - - //inline const unsigned int &getWidth() const { return frame.width; } - //inline const unsigned int &getHeight() const { - // if (!flags.shaded) - // return frame.height; - // else - // return frame.title_h; - //} - //inline const unsigned int &getClientHeight() const - //{ return client.height; } - //inline const unsigned int &getClientWidth() const - //{ return client.width; } - inline const unsigned int &getTitleHeight() const - { return frame.title_h; } - - //inline const Point origin() const { - // return Point(frame.x, frame.y); - //} - //inline const Point clientOrigin() const { - // return Point(client.x, client.y); - //} - //inline const Size size() const { - // return Size(frame.width, flags.shaded ? frame.title_h : frame.height); - //} - //inline const Size clientSize() const { - // return Size(client.width, client.height); - //} - inline const Rect area() const { - return Rect(frame.x, frame.y, frame.width, - flags.shaded ? frame.title_h : frame.height); - } - inline const Rect clientArea() const { - return Rect(client.x, client.y, client.width, client.height); - } - - inline void setWindowNumber(int n) { window_number = n; } - - bool validateClient(); - bool setInputFocus(); - - void setFocusFlag(Bool); - void iconify(); - void deiconify(bool reassoc = true, bool raise = true, bool initial = false); - void close(); - void withdraw(); - void maximize(unsigned int button); - void shade(); - void stick(); - void unstick(); - void reconfigure(); - void installColormap(Bool); - void restore(); - void configure(int dx, int dy, unsigned int dw, unsigned int dh); - void setWorkspace(int n); - void changeOpenboxHints(OpenboxHints *); - void restoreAttributes(); - - void startMove(int x, int y); - void endMove(); - - void buttonPressEvent(XButtonEvent *); - void buttonReleaseEvent(XButtonEvent *); - void motionNotifyEvent(XMotionEvent *); - void destroyNotifyEvent(XDestroyWindowEvent *); - void mapRequestEvent(XMapRequestEvent *); - void mapNotifyEvent(XMapEvent *); - void unmapNotifyEvent(XUnmapEvent *); - void propertyNotifyEvent(Atom); - void exposeEvent(XExposeEvent *); - void configureRequestEvent(XConfigureRequestEvent *); - -#ifdef SHAPE - void shapeEvent(XShapeEvent *); -#endif // SHAPE - - virtual void timeout(); -}; - - -#endif // __Window_hh diff --git a/src/Window.hh b/src/Window.hh new file mode 100644 index 00000000..9bed2798 --- /dev/null +++ b/src/Window.hh @@ -0,0 +1,363 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Window.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef __Window_hh +#define __Window_hh + +extern "C" { +#include +#include +#ifdef SHAPE +# include +#endif // SHAPE +} + +#include + +#include "BaseDisplay.hh" +#include "Timer.hh" +#include "Util.hh" +#include "Windowmenu.hh" + +#define MwmHintsFunctions (1l << 0) +#define MwmHintsDecorations (1l << 1) + +#define MwmFuncAll (1l << 0) +#define MwmFuncResize (1l << 1) +#define MwmFuncMove (1l << 2) +#define MwmFuncIconify (1l << 3) +#define MwmFuncMaximize (1l << 4) +#define MwmFuncClose (1l << 5) + +#define MwmDecorAll (1l << 0) +#define MwmDecorBorder (1l << 1) +#define MwmDecorHandle (1l << 2) +#define MwmDecorTitle (1l << 3) +#define MwmDecorMenu (1l << 4) // not used +#define MwmDecorIconify (1l << 5) +#define MwmDecorMaximize (1l << 6) + +// this structure only contains 3 elements... the Motif 2.0 structure contains +// 5... we only need the first 3... so that is all we will define +typedef struct MwmHints { + unsigned long flags, functions, decorations; +} MwmHints; + +#define PropMwmHintsElements 3 + +class BWindowGroup { +private: + Blackbox *blackbox; + Window group; + BlackboxWindowList windowList; + +public: + BWindowGroup(Blackbox *b, Window _group); + ~BWindowGroup(void); + + inline Window groupWindow(void) const { return group; } + + inline bool empty(void) const { return windowList.empty(); } + + void addWindow(BlackboxWindow *w) { windowList.push_back(w); } + void removeWindow(BlackboxWindow *w) { windowList.remove(w); } + + /* + find a window on the specified screen. the focused window (if any) is + checked first, otherwise the first matching window found is returned. + transients are returned only if allow_transients is True. + */ + BlackboxWindow *find(BScreen *screen, bool allow_transients = False) const; +}; + + +class BlackboxWindow : public TimeoutHandler { +public: + enum Function { Func_Resize = (1l << 0), + Func_Move = (1l << 1), + Func_Iconify = (1l << 2), + Func_Maximize = (1l << 3), + Func_Close = (1l << 4) }; + typedef unsigned int FunctionFlags; + + enum Decoration { Decor_Titlebar = (1l << 0), + Decor_Handle = (1l << 1), + Decor_Border = (1l << 2), + Decor_Iconify = (1l << 3), + Decor_Maximize = (1l << 4), + Decor_Close = (1l << 5) }; + typedef unsigned int DecorationFlags; + +private: + Blackbox *blackbox; + BScreen *screen; + BTimer *timer; + BlackboxAttributes blackbox_attrib; + + Time lastButtonPressTime; // used for double clicks, when were we clicked + Windowmenu *windowmenu; + + unsigned int window_number; + unsigned long current_state; + + enum FocusMode { F_NoInput = 0, F_Passive, + F_LocallyActive, F_GloballyActive }; + FocusMode focus_mode; + + struct _flags { + bool moving, // is moving? + resizing, // is resizing? + shaded, // is shaded? + visible, // is visible? + iconic, // is iconified? + focused, // has focus? + stuck, // is omnipresent + modal, // is modal? (must be dismissed to continue) + send_focus_message, // should we send focus messages to our client? + shaped; // does the frame use the shape extension? + unsigned int maximized; // maximize is special, the number corresponds + // with a mouse button + // if 0, not maximized + // 1 = HorizVert, 2 = Vertical, 3 = Horizontal + } flags; + + struct _client { + Window window, // the client's window + window_group; + BlackboxWindow *transient_for; // which window are we a transient for? + BlackboxWindowList transientList; // which windows are our transients? + + std::string title, icon_title; + + Rect rect; + + int old_bw; // client's borderwidth + + unsigned int + min_width, min_height, // can not be resized smaller + max_width, max_height, // can not be resized larger + width_inc, height_inc, // increment step + min_aspect_x, min_aspect_y, // minimum aspect ratio + max_aspect_x, max_aspect_y, // maximum aspect ratio + base_width, base_height, + win_gravity; + + unsigned long initial_state, normal_hint_flags, wm_hint_flags; + } client; + + FunctionFlags functions; + /* + * what decorations do we have? + * this is based on the type of the client window as well as user input + * the menu is not really decor, but it goes hand in hand with the decor + */ + DecorationFlags decorations; + + /* + * client window = the application's window + * frame window = the window drawn around the outside of the client window + * by the window manager which contains items like the + * titlebar and close button + * title = the titlebar drawn above the client window, it displays the + * window's name and any buttons for interacting with the window, + * such as iconify, maximize, and close + * label = the window in the titlebar where the title is drawn + * buttons = maximize, iconify, close + * handle = the bar drawn at the bottom of the window, which contains the + * left and right grips used for resizing the window + * grips = the smaller reactangles in the handle, one of each side of it. + * When clicked and dragged, these resize the window interactively + * border = the line drawn around the outside edge of the frame window, + * between the title, the bordered client window, and the handle. + * Also drawn between the grips and the handle + */ + + struct _frame { + // u -> unfocused, f -> has focus + unsigned long ulabel_pixel, flabel_pixel, utitle_pixel, + ftitle_pixel, uhandle_pixel, fhandle_pixel, ubutton_pixel, + fbutton_pixel, pbutton_pixel, uborder_pixel, fborder_pixel, + ugrip_pixel, fgrip_pixel; + Pixmap ulabel, flabel, utitle, ftitle, uhandle, fhandle, + ubutton, fbutton, pbutton, ugrip, fgrip; + + Window window, // the frame + plate, // holds the client + title, + label, + handle, + close_button, iconify_button, maximize_button, + right_grip, left_grip; + + /* + * size and location of the box drawn while the window dimensions or + * location is being changed, ie. resized or moved + */ + Rect changing; + + Rect rect; // frame geometry + Strut margin; // margins between the frame and client + + int grab_x, grab_y; // where was the window when it was grabbed? + + unsigned int inside_w, inside_h, // window w/h without border_w + title_h, label_w, label_h, handle_h, + button_w, grip_w, mwm_border_w, border_w, + bevel_w; + } frame; + + BlackboxWindow(const BlackboxWindow&); + BlackboxWindow& operator=(const BlackboxWindow&); + + bool getState(void); + Window createToplevelWindow(); + Window createChildWindow(Window parent, Cursor = None); + + void getWMName(void); + void getWMIconName(void); + void getWMNormalHints(void); + void getWMProtocols(void); + void getWMHints(void); + void getMWMHints(void); + bool getBlackboxHints(void); + void getTransientInfo(void); + void setNetWMAttributes(void); + void associateClientWindow(void); + void decorate(void); + void decorateLabel(void); + void positionButtons(bool redecorate_label = False); + void positionWindows(void); + void createHandle(void); + void destroyHandle(void); + void createTitlebar(void); + void destroyTitlebar(void); + void createCloseButton(void); + void destroyCloseButton(void); + void createIconifyButton(void); + void destroyIconifyButton(void); + void createMaximizeButton(void); + void destroyMaximizeButton(void); + void redrawLabel(void); + void redrawAllButtons(void); + void redrawCloseButton(bool pressed); + void redrawIconifyButton(bool pressed); + void redrawMaximizeButton(bool pressed); + void restoreGravity(void); + void setGravityOffsets(void); + void setState(unsigned long new_state); + void upsize(void); + + enum Corner { TopLeft, TopRight }; + void constrain(Corner anchor, int *pw = 0, int *ph = 0); + +public: + BlackboxWindow(Blackbox *b, Window w, BScreen *s); + virtual ~BlackboxWindow(void); + + inline bool isTransient(void) const { return client.transient_for != 0; } + inline bool isFocused(void) const { return flags.focused; } + inline bool isVisible(void) const { return flags.visible; } + inline bool isIconic(void) const { return flags.iconic; } + inline bool isShaded(void) const { return flags.shaded; } + inline bool isMaximized(void) const { return flags.maximized; } + inline bool isStuck(void) const { return flags.stuck; } + inline bool isIconifiable(void) const { return functions & Func_Iconify; } + inline bool isMaximizable(void) const { return functions & Func_Maximize; } + inline bool isResizable(void) const { return functions & Func_Resize; } + inline bool isClosable(void) const { return functions & Func_Close; } + + inline bool hasTitlebar(void) const { return decorations & Decor_Titlebar; } + + inline const BlackboxWindowList &getTransients(void) const + { return client.transientList; } + BlackboxWindow *getTransientFor(void) const; + + inline BScreen *getScreen(void) { return screen; } + + inline Window getFrameWindow(void) const { return frame.window; } + inline Window getClientWindow(void) const { return client.window; } + inline Window getGroupWindow(void) const { return client.window_group; } + + inline Windowmenu * getWindowmenu(void) { return windowmenu; } + + inline const char *getTitle(void) const + { return client.title.c_str(); } + inline const char *getIconTitle(void) const + { return client.icon_title.c_str(); } + + inline unsigned int getWorkspaceNumber(void) const + { return blackbox_attrib.workspace; } + inline unsigned int getWindowNumber(void) const { return window_number; } + + inline const Rect &frameRect(void) const { return frame.rect; } + inline const Rect &clientRect(void) const { return client.rect; } + + inline unsigned int getTitleHeight(void) const + { return frame.title_h; } + + inline void setWindowNumber(int n) { window_number = n; } + + bool validateClient(void); + bool setInputFocus(void); + + void setFocusFlag(bool focus); + void iconify(void); + void deiconify(bool reassoc = True, bool raise = True); + void show(void); + void close(void); + void withdraw(void); + void maximize(unsigned int button); + void remaximize(void); + void shade(void); + void stick(void); + void unstick(void); + void reconfigure(void); + void updateFocusModel(void); + void installColormap(bool install); + void restore(bool remap); + void configure(int dx, int dy, unsigned int dw, unsigned int dh); + void setWorkspace(unsigned int n); + void changeBlackboxHints(BlackboxHints *net); + void restoreAttributes(void); + + void buttonPressEvent(XButtonEvent *be); + void buttonReleaseEvent(XButtonEvent *re); + void motionNotifyEvent(XMotionEvent *me); + void destroyNotifyEvent(XDestroyWindowEvent */*unused*/); + void mapRequestEvent(XMapRequestEvent *mre); + void unmapNotifyEvent(XUnmapEvent */*unused*/); + void reparentNotifyEvent(XReparentEvent */*unused*/); + void propertyNotifyEvent(Atom atom); + void exposeEvent(XExposeEvent *ee); + void configureRequestEvent(XConfigureRequestEvent *cr); + +#ifdef SHAPE + void configureShape(void); + void shapeEvent(XShapeEvent * /*unused*/); +#endif // SHAPE + + virtual void timeout(void); +}; + + +#endif // __Window_hh diff --git a/src/Windowmenu.cc b/src/Windowmenu.cc index 6f216e5c..f274a047 100644 --- a/src/Windowmenu.cc +++ b/src/Windowmenu.cc @@ -1,5 +1,6 @@ -// Windowmenu.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Windowmenu.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,37 +21,32 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "i18n.h" -#include "openbox.h" -#include "Screen.h" -#include "Window.h" -#include "Windowmenu.h" -#include "Workspace.h" - -#ifdef HAVE_STRING_H +extern "C" { +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H +} +#include "i18n.hh" +#include "blackbox.hh" +#include "Screen.hh" +#include "Window.hh" +#include "Windowmenu.hh" +#include "Workspace.hh" -Windowmenu::Windowmenu(OpenboxWindow &win) : Basemenu(*win.getScreen()), -window(win), screen(*win.getScreen()) -{ + +Windowmenu::Windowmenu(BlackboxWindow *win) : Basemenu(win->getScreen()) { + window = win; setTitleVisibility(False); setMovable(False); setInternalMenu(); - sendToMenu = new SendtoWorkspacemenu(*this); + sendToMenu = new SendtoWorkspacemenu(this); insert(i18n(WindowmenuSet, WindowmenuSendTo, "Send To ..."), sendToMenu); insert(i18n(WindowmenuSet, WindowmenuShade, "Shade"), @@ -72,10 +68,10 @@ window(win), screen(*win.getScreen()) update(); - setItemEnabled(1, window.hasTitlebar()); - setItemEnabled(2, window.isIconifiable()); - setItemEnabled(3, window.isMaximizable()); - setItemEnabled(8, window.isClosable()); + setItemEnabled(1, window->hasTitlebar()); + setItemEnabled(2, window->isIconifiable()); + setItemEnabled(3, window->isMaximizable()); + setItemEnabled(8, window->isClosable()); } @@ -85,71 +81,64 @@ Windowmenu::~Windowmenu(void) { void Windowmenu::show(void) { - if (isItemEnabled(1)) setItemSelected(1, window.isShaded()); - if (isItemEnabled(3)) setItemSelected(3, window.isMaximized()); - if (isItemEnabled(6)) setItemSelected(6, window.isStuck()); + if (isItemEnabled(1)) setItemSelected(1, window->isShaded()); + if (isItemEnabled(3)) setItemSelected(3, window->isMaximized()); + if (isItemEnabled(6)) setItemSelected(6, window->isStuck()); Basemenu::show(); } -void Windowmenu::itemSelected(int button, int index) { +void Windowmenu::itemSelected(int button, unsigned int index) { BasemenuItem *item = find(index); - /* Added by Scott Moynes, April 8, 2002 - Ignore the middle button for every item except the maximize - button in the window menu. Maximize needs it for - horizontal/vertical maximize, however, for the others it is - inconsistent with the rest of the window behaviour. - */ - if(button != 2) { - hide(); - switch (item->function()) { - case BScreen::WindowShade: - window.shade(); - break; - - case BScreen::WindowIconify: - window.iconify(); - break; - - case BScreen::WindowMaximize: - window.maximize((unsigned int) button); - break; - - case BScreen::WindowClose: - window.close(); - break; - - case BScreen::WindowRaise: - screen.getWorkspace(window.getWorkspaceNumber())->raiseWindow(&window); - break; - - case BScreen::WindowLower: - screen.getWorkspace(window.getWorkspaceNumber())->lowerWindow(&window); - break; - - case BScreen::WindowStick: - window.stick(); - break; - - case BScreen::WindowKill: - XKillClient(screen.getBaseDisplay().getXDisplay(), - window.getClientWindow()); - break; - } - } else if (item->function() == BScreen::WindowMaximize) { - hide(); - window.maximize((unsigned int) button); + hide(); + switch (item->function()) { + case BScreen::WindowShade: + window->shade(); + break; + + case BScreen::WindowIconify: + window->iconify(); + break; + + case BScreen::WindowMaximize: + window->maximize(button); + break; + + case BScreen::WindowClose: + window->close(); + break; + + case BScreen::WindowRaise: { + Workspace *wkspc = getScreen()->getWorkspace(window->getWorkspaceNumber()); + wkspc->raiseWindow(window); + } + break; + + case BScreen::WindowLower: { + Workspace *wkspc = getScreen()->getWorkspace(window->getWorkspaceNumber()); + wkspc->lowerWindow(window); + } + break; + + case BScreen::WindowStick: + window->stick(); + break; + + case BScreen::WindowKill: + XKillClient(getScreen()->getBaseDisplay()->getXDisplay(), + window->getClientWindow()); + break; } } void Windowmenu::reconfigure(void) { - setItemEnabled(1, window.hasTitlebar()); - setItemEnabled(2, window.isIconifiable()); - setItemEnabled(3, window.isMaximizable()); - setItemEnabled(8, window.isClosable()); + setItemEnabled(1, window->hasTitlebar()); + setItemEnabled(2, window->isIconifiable()); + setItemEnabled(3, window->isMaximizable()); + setItemEnabled(8, window->isClosable()); sendToMenu->reconfigure(); @@ -157,39 +146,51 @@ void Windowmenu::reconfigure(void) { } -Windowmenu::SendtoWorkspacemenu::SendtoWorkspacemenu(Windowmenu &w) - : Basemenu(w.screen), windowmenu(w) { - setTitleVisibility(False); - setMovable(False); - setInternalMenu(); - update(); - } +Windowmenu::SendtoWorkspacemenu::SendtoWorkspacemenu(Windowmenu *w) + : Basemenu(w->getScreen()) { + window = w->window; -void Windowmenu::SendtoWorkspacemenu::itemSelected(int button, int index) { + setTitleVisibility(False); + setMovable(False); + setInternalMenu(); + update(); +} + + +void Windowmenu::SendtoWorkspacemenu::itemSelected(int button, + unsigned int index) { if (button > 2) return; - if (index <= windowmenu.screen.getWorkspaceCount()) { - if (index == windowmenu.screen.getCurrentWorkspaceID()) return; - if (windowmenu.window.isStuck()) windowmenu.window.stick(); + if (index <= getScreen()->getWorkspaceCount()) { + if (index == getScreen()->getCurrentWorkspaceID()) return; + if (window->isStuck()) window->stick(); - if (button == 1) windowmenu.window.withdraw(); - windowmenu.screen.reassociateWindow(&(windowmenu.window), index, True); - if (button == 2) windowmenu.screen.changeWorkspaceID(index); + if (button == 1) window->withdraw(); + getScreen()->reassociateWindow(window, index, True); + if (button == 2) getScreen()->changeWorkspaceID(index); } hide(); } void Windowmenu::SendtoWorkspacemenu::update(void) { - int i, r = getCount(); - - if (r != 0) - for (i = 0; i < r; ++i) + unsigned int i, r = getCount(), + workspace_count = getScreen()->getWorkspaceCount(); + if (r > workspace_count) { + for (i = r; i < workspace_count; ++i) remove(0); + r = getCount(); + } - for (i = 0; i < windowmenu.screen.getWorkspaceCount(); ++i) - insert(windowmenu.screen.getWorkspace(i)->getName()); + for (i = 0; i < workspace_count; ++i) { + if (r < workspace_count) { + insert(getScreen()->getWorkspace(i)->getName()); + ++r; + } else { + changeItemLabel(i, getScreen()->getWorkspace(i)->getName()); + } + } Basemenu::update(); } diff --git a/src/Windowmenu.h b/src/Windowmenu.h deleted file mode 100644 index d892abc5..00000000 --- a/src/Windowmenu.h +++ /dev/null @@ -1,78 +0,0 @@ -// Windowmenu.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Windowmenu_hh -#define __Windowmenu_hh - -#include "Basemenu.h" - -// forward declaration -class Windowmenu; -class SendtoWorkspaceMenu; - -class Openbox; -class OpenboxWindow; -class Toolbar; - -class Windowmenu : public Basemenu { -private: - OpenboxWindow &window; - BScreen &screen; - - class SendtoWorkspacemenu : public Basemenu { - private: - Windowmenu &windowmenu; - - protected: - virtual void itemSelected(int, int); - - public: - SendtoWorkspacemenu(Windowmenu &); - - void update(void); - - virtual void show(void); - }; - - SendtoWorkspacemenu *sendToMenu; - - friend class SendtoWorkspacemenu; - - -protected: - virtual void itemSelected(int, int); - - -public: - Windowmenu(OpenboxWindow &); - virtual ~Windowmenu(void); - - inline Basemenu *getSendToMenu(void) { return (Basemenu *) sendToMenu; } - - void reconfigure(void); - void setClosable(void); - - virtual void show(void); -}; - - -#endif // __Windowmenu_hh diff --git a/src/Workspace.cc b/src/Workspace.cc index 47ad3827..3ef99ea7 100644 --- a/src/Workspace.cc +++ b/src/Workspace.cc @@ -1,6 +1,6 @@ -// Workspace.cc for Openbox -// Copyright (c) 2002 - 2002 Ben Jansens (ben@orodu.net) -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Workspace.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -21,594 +21,580 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H +extern "C" { +#include +#include + #ifdef HAVE_STDIO_H # include #endif // HAVE_STDIO_H -#ifdef HAVE_STDLIB_H -# include -#endif // HAVE_STDLIB_H - -#ifdef HAVE_STRING_H +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H +} -#include -#include +#include +#include -#include "i18n.h" -#include "openbox.h" -#include "Clientmenu.h" -#include "Screen.h" -#include "Toolbar.h" -#include "Window.h" -#include "Workspace.h" -#include "Windowmenu.h" -#include "Geometry.h" -#include "Util.h" - -#include -#include -typedef std::vector rectList; +using std::string; -Workspace::Workspace(BScreen &scrn, int i) : screen(scrn) { - cascade_x = cascade_y = 0; - _focused = _last = (OpenboxWindow *) 0; - id = i; +#include "i18n.hh" +#include "blackbox.hh" +#include "Clientmenu.hh" +#include "Netizen.hh" +#include "Screen.hh" +#include "Toolbar.hh" +#include "Util.hh" +#include "Window.hh" +#include "Workspace.hh" +#include "Windowmenu.hh" - clientmenu = new Clientmenu(*this); - name = (char *) 0; - setName(screen.getNameOfWorkspace(id)); -} +Workspace::Workspace(BScreen *scrn, unsigned int i) { + screen = scrn; + cascade_x = cascade_y = 32; -Workspace::~Workspace(void) { - delete clientmenu; + id = i; - if (name) - delete [] name; + clientmenu = new Clientmenu(this); + + lastfocus = (BlackboxWindow *) 0; + + setName(screen->getNameOfWorkspace(id)); } -int Workspace::addWindow(OpenboxWindow *w, bool place) { - if (! w) return -1; +void Workspace::addWindow(BlackboxWindow *w, bool place) { + assert(w != 0); - if (place) placeWindow(*w); + if (place) placeWindow(w); w->setWorkspace(id); - w->setWindowNumber(_windows.size()); + w->setWindowNumber(windowList.size()); - _zorder.push_front(w); - _windows.push_back(w); + stackingList.push_front(w); + windowList.push_back(w); - clientmenu->insert((const char **) w->getTitle()); + clientmenu->insert(w->getTitle()); clientmenu->update(); - screen.updateNetizenWindowAdd(w->getClientWindow(), id); + screen->updateNetizenWindowAdd(w->getClientWindow(), id); raiseWindow(w); - - return w->getWindowNumber(); } -int Workspace::removeWindow(OpenboxWindow *w) { - if (! w) return -1; +unsigned int Workspace::removeWindow(BlackboxWindow *w) { + assert(w != 0); - winVect::iterator winit = std::find(_windows.begin(), _windows.end(), w); + stackingList.remove(w); - if (winit == _windows.end()) { - if (w == _last) - _last = (OpenboxWindow *) 0; - if (w == _focused) - _focused = (OpenboxWindow *) 0; - return _windows.size(); + if (w->isFocused() && ! screen->getBlackbox()->doShutdown()) { + BlackboxWindow *newfocus = 0; + if (w->isTransient()) + newfocus = w->getTransientFor(); + if (! newfocus && ! stackingList.empty()) + newfocus = stackingList.front(); + if (! newfocus || ! newfocus->setInputFocus()) + screen->getBlackbox()->setFocusedWindow(0); } - - _zorder.remove(w); - - if (w == _last) - _last = (OpenboxWindow *) 0; - if (w == _focused) { - OpenboxWindow *fw = (OpenboxWindow *) 0; - if (w->isTransient() && w->getTransientFor() && - w->getTransientFor()->isVisible()) - fw = w->getTransientFor(); - else if (screen.sloppyFocus()) // sloppy focus - fw = (OpenboxWindow *) 0; - else if (!_zorder.empty()) // click focus - fw = _zorder.front(); - - if (!(fw != (OpenboxWindow *) 0 && fw->setInputFocus())) - screen.getOpenbox().focusWindow(0); - } - - _windows.erase(winit); + + if (lastfocus == w) + lastfocus = (BlackboxWindow *) 0; + + windowList.remove(w); clientmenu->remove(w->getWindowNumber()); clientmenu->update(); - screen.updateNetizenWindowDel(w->getClientWindow()); + screen->updateNetizenWindowDel(w->getClientWindow()); - winVect::iterator it = _windows.begin(); - for (int i=0; it != _windows.end(); ++it, ++i) + BlackboxWindowList::iterator it = windowList.begin(); + const BlackboxWindowList::iterator end = windowList.end(); + unsigned int i = 0; + for (; it != end; ++it, ++i) (*it)->setWindowNumber(i); - return _windows.size(); -} - + if (i == 0) + cascade_x = cascade_y = 32; -void Workspace::focusWindow(OpenboxWindow *win) { - if (_focused != (OpenboxWindow *) 0) - clientmenu->setItemSelected(_focused->getWindowNumber(), false); - _focused = win; - // make sure the focused window belongs to this workspace before highlighting - // it in the menu (sticky windows arent in this workspace's menu). - if (_focused != (OpenboxWindow *) 0 && _focused->getWorkspaceNumber() == id) - clientmenu->setItemSelected(_focused->getWindowNumber(), true); - if (win != (OpenboxWindow *) 0) - _last = win; + return i; } void Workspace::showAll(void) { - winList::iterator it; - for (it = _zorder.begin(); it != _zorder.end(); ++it) - (*it)->deiconify(false, false); + std::for_each(stackingList.begin(), stackingList.end(), + std::mem_fun(&BlackboxWindow::show)); } void Workspace::hideAll(void) { - winList::reverse_iterator it; - for (it = _zorder.rbegin(); it != _zorder.rend(); ++it) - if (!(*it)->isStuck()) - (*it)->withdraw(); -} + // withdraw in reverse order to minimize the number of Expose events + BlackboxWindowList lst(stackingList.rbegin(), stackingList.rend()); -void Workspace::removeAll(void) { - winVect::iterator it; - for (it = _windows.begin(); it != _windows.end(); ++it) - (*it)->iconify(); + BlackboxWindowList::iterator it = lst.begin(); + const BlackboxWindowList::iterator end = lst.end(); + for (; it != end; ++it) { + BlackboxWindow *bw = *it; + if (! bw->isStuck()) + bw->withdraw(); + } } -void Workspace::raiseWindow(OpenboxWindow *w) { - OpenboxWindow *win = (OpenboxWindow *) 0, *bottom = w; +void Workspace::removeAll(void) { + while (! windowList.empty()) + windowList.front()->iconify(); +} - while (bottom->isTransient() && bottom->getTransientFor()) - bottom = bottom->getTransientFor(); - int i = 1; - win = bottom; - while (win->hasTransient() && win->getTransient()) { - win = win->getTransient(); +/* + * returns the number of transients for win, plus the number of transients + * associated with each transient of win + */ +static int countTransients(const BlackboxWindow * const win) { + int ret = win->getTransients().size(); + if (ret > 0) { + BlackboxWindowList::const_iterator it, end = win->getTransients().end(); + for (it = win->getTransients().begin(); it != end; ++it) { + ret += countTransients(*it); + } + } + return ret; +} + + +/* + * puts the transients of win into the stack. windows are stacked above + * the window before it in the stackvector being iterated, meaning + * stack[0] is on bottom, stack[1] is above stack[0], stack[2] is above + * stack[1], etc... + */ +void Workspace::raiseTransients(const BlackboxWindow * const win, + StackVector::iterator &stack) { + if (win->getTransients().size() == 0) return; // nothing to do + + // put win's transients in the stack + BlackboxWindowList::const_iterator it, end = win->getTransients().end(); + for (it = win->getTransients().begin(); it != end; ++it) { + *stack++ = (*it)->getFrameWindow(); + screen->updateNetizenWindowRaise((*it)->getClientWindow()); + + if (! (*it)->isIconic()) { + Workspace *wkspc = screen->getWorkspace((*it)->getWorkspaceNumber()); + wkspc->stackingList.remove((*it)); + wkspc->stackingList.push_front((*it)); + } + } - i++; + // put transients of win's transients in the stack + for (it = win->getTransients().begin(); it != end; ++it) { + raiseTransients(*it, stack); } +} - Window *nstack = new Window[i], *curr = nstack; - Workspace *wkspc; - win = bottom; - while (true) { - *(curr++) = win->getFrameWindow(); - screen.updateNetizenWindowRaise(win->getClientWindow()); +void Workspace::lowerTransients(const BlackboxWindow * const win, + StackVector::iterator &stack) { + if (win->getTransients().size() == 0) return; // nothing to do - if (! win->isIconic()) { - wkspc = screen.getWorkspace(win->getWorkspaceNumber()); - wkspc->_zorder.remove(win); - wkspc->_zorder.push_front(win); - } + // put transients of win's transients in the stack + BlackboxWindowList::const_reverse_iterator it, + end = win->getTransients().rend(); + for (it = win->getTransients().rbegin(); it != end; ++it) { + lowerTransients(*it, stack); + } - if (! win->hasTransient() || ! win->getTransient()) - break; + // put win's transients in the stack + for (it = win->getTransients().rbegin(); it != end; ++it) { + *stack++ = (*it)->getFrameWindow(); + screen->updateNetizenWindowLower((*it)->getClientWindow()); - win = win->getTransient(); + if (! (*it)->isIconic()) { + Workspace *wkspc = screen->getWorkspace((*it)->getWorkspaceNumber()); + wkspc->stackingList.remove((*it)); + wkspc->stackingList.push_back((*it)); + } } - screen.raiseWindows(nstack, i); - - delete [] nstack; } -void Workspace::lowerWindow(OpenboxWindow *w) { - OpenboxWindow *win = (OpenboxWindow *) 0, *bottom = w; +void Workspace::raiseWindow(BlackboxWindow *w) { + BlackboxWindow *win = w; + + // walk up the transient_for's to the window that is not a transient + while (win->isTransient()) { + if (! win->getTransientFor()) break; + win = win->getTransientFor(); + } - while (bottom->isTransient() && bottom->getTransientFor()) - bottom = bottom->getTransientFor(); + // get the total window count (win and all transients) + unsigned int i = 1 + countTransients(win); - int i = 1; - win = bottom; - while (win->hasTransient() && win->getTransient()) { - win = win->getTransient(); + // stack the window with all transients above + StackVector stack_vector(i); + StackVector::iterator stack = stack_vector.begin(); - i++; + *(stack++) = win->getFrameWindow(); + screen->updateNetizenWindowRaise(win->getClientWindow()); + if (! win->isIconic()) { + Workspace *wkspc = screen->getWorkspace(win->getWorkspaceNumber()); + wkspc->stackingList.remove(win); + wkspc->stackingList.push_front(win); } - Window *nstack = new Window[i], *curr = nstack; - Workspace *wkspc; + raiseTransients(win, stack); - while (true) { - *(curr++) = win->getFrameWindow(); - screen.updateNetizenWindowLower(win->getClientWindow()); + screen->raiseWindows(&stack_vector[0], stack_vector.size()); +} - if (! win->isIconic()) { - wkspc = screen.getWorkspace(win->getWorkspaceNumber()); - wkspc->_zorder.remove(win); - wkspc->_zorder.push_back(win); - } - if (! win->getTransientFor()) - break; +void Workspace::lowerWindow(BlackboxWindow *w) { + BlackboxWindow *win = w; + // walk up the transient_for's to the window that is not a transient + while (win->isTransient()) { + if (! win->getTransientFor()) break; win = win->getTransientFor(); } - screen.getOpenbox().grab(); + // get the total window count (win and all transients) + unsigned int i = 1 + countTransients(win); + + // stack the window with all transients above + StackVector stack_vector(i); + StackVector::iterator stack = stack_vector.begin(); - XLowerWindow(screen.getBaseDisplay().getXDisplay(), *nstack); - XRestackWindows(screen.getBaseDisplay().getXDisplay(), nstack, i); + lowerTransients(win, stack); - screen.getOpenbox().ungrab(); + *(stack++) = win->getFrameWindow(); + screen->updateNetizenWindowLower(win->getClientWindow()); + if (! win->isIconic()) { + Workspace *wkspc = screen->getWorkspace(win->getWorkspaceNumber()); + wkspc->stackingList.remove(win); + wkspc->stackingList.push_back(win); + } - delete [] nstack; + XLowerWindow(screen->getBaseDisplay()->getXDisplay(), stack_vector.front()); + XRestackWindows(screen->getBaseDisplay()->getXDisplay(), + &stack_vector[0], stack_vector.size()); } void Workspace::reconfigure(void) { clientmenu->reconfigure(); + std::for_each(windowList.begin(), windowList.end(), + std::mem_fun(&BlackboxWindow::reconfigure)); +} + - winVect::iterator it; - for (it = _windows.begin(); it != _windows.end(); ++it) - if ((*it)->validateClient()) - (*it)->reconfigure(); +void Workspace::updateFocusModel(void) { + std::for_each(windowList.begin(), windowList.end(), + std::mem_fun(&BlackboxWindow::updateFocusModel)); } -OpenboxWindow *Workspace::getWindow(int index) { - if ((index >= 0) && (index < (signed)_windows.size())) - return _windows[index]; - else - return (OpenboxWindow *) 0; +BlackboxWindow *Workspace::getWindow(unsigned int index) { + if (index < windowList.size()) { + BlackboxWindowList::iterator it = windowList.begin(); + for(; index > 0; --index, ++it); /* increment to index */ + return *it; + } + return 0; } -int Workspace::getCount(void) { - return (signed)_windows.size(); +BlackboxWindow* +Workspace::getNextWindowInList(BlackboxWindow *w) { + BlackboxWindowList::iterator it = std::find(windowList.begin(), + windowList.end(), + w); + assert(it != windowList.end()); // window must be in list + ++it; // next window + if (it == windowList.end()) + return windowList.front(); // if we walked off the end, wrap around + + return *it; } -void Workspace::update(void) { - clientmenu->update(); - screen.getToolbar()->redrawWindowLabel(true); +BlackboxWindow* Workspace::getPrevWindowInList(BlackboxWindow *w) { + BlackboxWindowList::iterator it = std::find(windowList.begin(), + windowList.end(), + w); + assert(it != windowList.end()); // window must be in list + if (it == windowList.begin()) + return windowList.back(); // if we walked of the front, wrap around + + return *(--it); } -bool Workspace::isCurrent(void) { - return (id == screen.getCurrentWorkspaceID()); +BlackboxWindow* Workspace::getTopWindowOnStack(void) const { + return stackingList.front(); } -void Workspace::setCurrent(void) { - screen.changeWorkspaceID(id); +void Workspace::sendWindowList(Netizen &n) { + BlackboxWindowList::iterator it = windowList.begin(), + end = windowList.end(); + for(; it != end; ++it) + n.sendWindowAdd((*it)->getClientWindow(), getID()); +} + + +unsigned int Workspace::getCount(void) const { + return windowList.size(); +} + + +bool Workspace::isCurrent(void) const { + return (id == screen->getCurrentWorkspaceID()); } -void Workspace::setName(const char *new_name) { - if (name) - delete [] name; +bool Workspace::isLastWindow(const BlackboxWindow* const w) const { + return (w == windowList.back()); +} + +void Workspace::setCurrent(void) { + screen->changeWorkspaceID(id); +} + - if (new_name) { - name = bstrdup(new_name); +void Workspace::setName(const string& new_name) { + if (! new_name.empty()) { + name = new_name; } else { - name = new char[128]; - sprintf(name, i18n(WorkspaceSet, WorkspaceDefaultNameFormat, - "Workspace %d"), id + 1); + string tmp =i18n(WorkspaceSet, WorkspaceDefaultNameFormat, "Workspace %d"); + assert(tmp.length() < 32); + char default_name[32]; + sprintf(default_name, tmp.c_str(), id + 1); + name = default_name; } clientmenu->setLabel(name); clientmenu->update(); - screen.saveWorkspaceNames(); } -void Workspace::shutdown(void) { - while (!_windows.empty()) - _windows[0]->restore(); -} +/* + * Calculate free space available for window placement. + */ +typedef std::vector rectList; static rectList calcSpace(const Rect &win, const rectList &spaces) { + Rect isect, extra; rectList result; - rectList::const_iterator siter; - for(siter=spaces.begin(); siter!=spaces.end(); ++siter) { - if(win.Intersect(*siter)) { - //Check for space to the left of the window - if(win.x() > siter->x()) - result.push_back(Rect(siter->x(), siter->y(), - win.x() - siter->x() - 1, - siter->h())); - //Check for space above the window - if(win.y() > siter->y()) - result.push_back(Rect(siter->x(), siter->y(), - siter->w(), - win.y() - siter->y() - 1)); - //Check for space to the right of the window - if((win.x()+win.w()) < - (siter->x()+siter->w())) - result.push_back(Rect(win.x() + win.w() + 1, - siter->y(), - siter->x() + siter->w() - - win.x() - win.w() - 1, - siter->h())); - //Check for space below the window - if((win.y()+win.h()) < - (siter->y()+siter->h())) - result.push_back(Rect(siter->x(), - win.y() + win.h() + 1, - siter->w(), - siter->y() + siter->h()- - win.y() - win.h() - 1)); + rectList::const_iterator siter, end = spaces.end(); + for (siter = spaces.begin(); siter != end; ++siter) { + const Rect &curr = *siter; + if(! win.intersects(curr)) { + result.push_back(curr); + continue; } - else - result.push_back(*siter); + + /* Use an intersection of win and curr to determine the space around + * curr that we can use. + * + * NOTE: the spaces calculated can overlap. + */ + isect = curr & win; + + // left + extra.setCoords(curr.left(), curr.top(), + isect.left() - 1, curr.bottom()); + if (extra.valid()) result.push_back(extra); + + // top + extra.setCoords(curr.left(), curr.top(), + curr.right(), isect.top() - 1); + if (extra.valid()) result.push_back(extra); + + // right + extra.setCoords(isect.right() + 1, curr.top(), + curr.right(), curr.bottom()); + if (extra.valid()) result.push_back(extra); + + // bottom + extra.setCoords(curr.left(), isect.bottom() + 1, + curr.right(), curr.bottom()); + if (extra.valid()) result.push_back(extra); } return result; } -bool rowRLBT(const Rect &first, const Rect &second){ - if (first.y()+first.h()==second.y()+second.h()) - return first.x()+first.w()>second.x()+second.w(); - return first.y()+first.h()>second.y()+second.h(); + +static bool rowRLBT(const Rect &first, const Rect &second) { + if (first.bottom() == second.bottom()) + return first.right() > second.right(); + return first.bottom() > second.bottom(); } -bool rowRLTB(const Rect &first, const Rect &second){ - if (first.y()==second.y()) - return first.x()+first.w()>second.x()+second.w(); - return first.y() second.right(); + return first.y() < second.y(); } -bool rowLRBT(const Rect &first, const Rect &second){ - if (first.y()+first.h()==second.y()+second.h()) - return first.x()second.y()+second.h(); +static bool rowLRBT(const Rect &first, const Rect &second) { + if (first.bottom() == second.bottom()) + return first.x() < second.x(); + return first.bottom() > second.bottom(); } -bool rowLRTB(const Rect &first, const Rect &second){ - if (first.y()==second.y()) - return first.x()second.y()+second.h(); - return first.x() second.bottom(); + return first.x() < second.x(); } -bool colRLTB(const Rect &first, const Rect &second){ - if (first.x()+first.w()==second.x()+second.w()) - return first.y()second.x()+second.w(); +static bool colRLTB(const Rect &first, const Rect &second) { + if (first.right() == second.right()) + return first.y() < second.y(); + return first.right() > second.right(); } -bool colRLBT(const Rect &first, const Rect &second){ - if (first.x()+first.w()==second.x()+second.w()) - return first.y()+first.h()>second.y()+second.h(); - return first.x()+first.w()>second.x()+second.w(); +static bool colRLBT(const Rect &first, const Rect &second) { + if (first.right() == second.right()) + return first.bottom() > second.bottom(); + return first.right() > second.right(); } -//BestFitPlacement finds the smallest free space that fits the window -//to be placed. It currentl ignores whether placement is right to left or top -//to bottom. -Point *Workspace::bestFitPlacement(const Size &win_size, const Rect &space) { - const Rect *best; +bool Workspace::smartPlacement(Rect& win, const Rect& availableArea) { rectList spaces; - rectList::const_iterator siter; - spaces.push_back(space); //initially the entire screen is free + spaces.push_back(availableArea); //initially the entire screen is free //Find Free Spaces - winVect::iterator it; - for (it = _windows.begin(); it != _windows.end(); ++it) - spaces = calcSpace((*it)->area().Inflate(screen.getBorderWidth() * 4), - spaces); - - //Find first space that fits the window - best = NULL; - for (siter=spaces.begin(); siter!=spaces.end(); ++siter) { - if ((siter->w() >= win_size.w()) && (siter->h() >= win_size.h())) { - if (best==NULL) - best = &*siter; - else if(siter->w()*siter->h()h()*best->w()) - best = &*siter; - } + BlackboxWindowList::iterator wit = windowList.begin(), + end = windowList.end(); + Rect tmp; + for (; wit != end; ++wit) { + const BlackboxWindow* const curr = *wit; + tmp.setRect(curr->frameRect().x(), curr->frameRect().y(), + curr->frameRect().width() + screen->getBorderWidth(), + curr->frameRect().height() + screen->getBorderWidth()); + + spaces = calcSpace(tmp, spaces); } - if (best != NULL) { - Point *pt = new Point(best->origin()); - if (screen.colPlacementDirection() != BScreen::TopBottom) - pt->setY(pt->y() + (best->h() - win_size.h())); - if (screen.rowPlacementDirection() != BScreen::LeftRight) - pt->setX(pt->x() + (best->w() - win_size.w())); - return pt; - } else - return NULL; //fall back to cascade -} - -Point *Workspace::underMousePlacement(const Size &win_size, const Rect &space) { - Point *pt; - - int x, y, rx, ry; - Window c, r; - unsigned int m; - XQueryPointer(screen.getOpenbox().getXDisplay(), screen.getRootWindow(), - &r, &c, &rx, &ry, &x, &y, &m); - pt = new Point(rx - win_size.w() / 2, ry - win_size.h() / 2); - - if (pt->x() < space.x()) - pt->setX(space.x()); - if (pt->y() < space.y()) - pt->setY(space.y()); - if (pt->x() + win_size.w() > space.x() + space.w()) - pt->setX(space.x() + space.w() - win_size.w()); - if (pt->y() + win_size.h() > space.y() + space.h()) - pt->setY(space.y() + space.h() - win_size.h()); - return pt; -} - -Point *Workspace::rowSmartPlacement(const Size &win_size, const Rect &space) { - const Rect *best; - rectList spaces; - rectList::const_iterator siter; - spaces.push_back(space); //initially the entire screen is free + if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) { + if(screen->getRowPlacementDirection() == BScreen::LeftRight) { + if(screen->getColPlacementDirection() == BScreen::TopBottom) + sort(spaces.begin(), spaces.end(), rowLRTB); + else + sort(spaces.begin(), spaces.end(), rowLRBT); + } else { + if(screen->getColPlacementDirection() == BScreen::TopBottom) + sort(spaces.begin(), spaces.end(), rowRLTB); + else + sort(spaces.begin(), spaces.end(), rowRLBT); + } + } else { + if(screen->getColPlacementDirection() == BScreen::TopBottom) { + if(screen->getRowPlacementDirection() == BScreen::LeftRight) + sort(spaces.begin(), spaces.end(), colLRTB); + else + sort(spaces.begin(), spaces.end(), colRLTB); + } else { + if(screen->getRowPlacementDirection() == BScreen::LeftRight) + sort(spaces.begin(), spaces.end(), colLRBT); + else + sort(spaces.begin(), spaces.end(), colRLBT); + } + } - //Find Free Spaces - winVect::iterator it; - for (it = _windows.begin(); it != _windows.end(); ++it) - spaces = calcSpace((*it)->area().Inflate(screen.getBorderWidth() * 4), - spaces); - //Sort spaces by preference - if(screen.rowPlacementDirection() == BScreen::RightLeft) - if(screen.colPlacementDirection() == BScreen::TopBottom) - sort(spaces.begin(),spaces.end(),rowRLTB); - else - sort(spaces.begin(),spaces.end(),rowRLBT); - else - if(screen.colPlacementDirection() == BScreen::TopBottom) - sort(spaces.begin(),spaces.end(),rowLRTB); - else - sort(spaces.begin(),spaces.end(),rowLRBT); - best = NULL; - for (siter=spaces.begin(); siter!=spaces.end(); ++siter) - if ((siter->w() >= win_size.w()) && (siter->h() >= win_size.h())) { - best = &*siter; + rectList::const_iterator sit = spaces.begin(), spaces_end = spaces.end(); + for(; sit != spaces_end; ++sit) { + if (sit->width() >= win.width() && sit->height() >= win.height()) break; - } + } - if (best != NULL) { - Point *pt = new Point(best->origin()); - if (screen.colPlacementDirection() != BScreen::TopBottom) - pt->setY(best->y() + best->h() - win_size.h()); - if (screen.rowPlacementDirection() != BScreen::LeftRight) - pt->setX(best->x()+best->w()-win_size.w()); - return pt; - } else - return NULL; //fall back to cascade -} + if (sit == spaces_end) + return False; -Point *Workspace::colSmartPlacement(const Size &win_size, const Rect &space) { - const Rect *best; - rectList spaces; + //set new position based on the empty space found + const Rect& where = *sit; + win.setX(where.x()); + win.setY(where.y()); + + // adjust the location() based on left/right and top/bottom placement + if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) { + if (screen->getRowPlacementDirection() == BScreen::RightLeft) + win.setX(where.right() - win.width()); + if (screen->getColPlacementDirection() == BScreen::BottomTop) + win.setY(where.bottom() - win.height()); + } else { + if (screen->getColPlacementDirection() == BScreen::BottomTop) + win.setY(win.y() + where.height() - win.height()); + if (screen->getRowPlacementDirection() == BScreen::RightLeft) + win.setX(win.x() + where.width() - win.width()); + } + return True; +} - rectList::const_iterator siter; - spaces.push_back(space); //initially the entire screen is free - //Find Free Spaces - winVect::iterator it; - for (it = _windows.begin(); it != _windows.end(); ++it) - spaces = calcSpace((*it)->area().Inflate(screen.getBorderWidth() * 4), - spaces); - //Sort spaces by user preference - if(screen.colPlacementDirection() == BScreen::TopBottom) - if(screen.rowPlacementDirection() == BScreen::LeftRight) - sort(spaces.begin(),spaces.end(),colLRTB); - else - sort(spaces.begin(),spaces.end(),colRLTB); - else - if(screen.rowPlacementDirection() == BScreen::LeftRight) - sort(spaces.begin(),spaces.end(),colLRBT); - else - sort(spaces.begin(),spaces.end(),colRLBT); - - //Find first space that fits the window - best = NULL; - for (siter=spaces.begin(); siter!=spaces.end(); ++siter) - if ((siter->w() >= win_size.w()) && (siter->h() >= win_size.h())) { - best = &*siter; - break; - } +bool Workspace::cascadePlacement(Rect &win, const Rect &availableArea) { + if ((cascade_x > static_cast(availableArea.width() / 2)) || + (cascade_y > static_cast(availableArea.height() / 2))) + cascade_x = cascade_y = 32; - if (best != NULL) { - Point *pt = new Point(best->origin()); - if (screen.colPlacementDirection() != BScreen::TopBottom) - pt->setY(pt->y() + (best->h() - win_size.h())); - if (screen.rowPlacementDirection() != BScreen::LeftRight) - pt->setX(pt->x() + (best->w() - win_size.w())); - return pt; - } else - return NULL; //fall back to cascade -} - - -Point *const Workspace::cascadePlacement(const OpenboxWindow &win, - const Rect &space) { - if ((cascade_x + win.area().w() + screen.getBorderWidth() * 2 > - (space.x() + space.w())) || - (cascade_y + win.area().h() + screen.getBorderWidth() * 2 > - (space.y() + space.h()))) - cascade_x = cascade_y = 0; - if (cascade_x < space.x() || cascade_y < space.y()) { - cascade_x = space.x(); - cascade_y = space.y(); + if (cascade_x == 32) { + cascade_x += availableArea.x(); + cascade_y += availableArea.y(); } - Point *p = new Point(cascade_x, cascade_y); - cascade_x += win.getTitleHeight(); - cascade_y += win.getTitleHeight(); - return p; + win.setPos(cascade_x, cascade_y); + + return True; } -void Workspace::placeWindow(OpenboxWindow &win) { - Rect space = screen.availableArea(); - const Size window_size(win.area().w()+screen.getBorderWidth() * 2, - win.area().h()+screen.getBorderWidth() * 2); - Point *place = NULL; +void Workspace::placeWindow(BlackboxWindow *win) { + Rect availableArea(screen->availableArea()), + new_win(availableArea.x(), availableArea.y(), + win->frameRect().width(), win->frameRect().height()); + bool placed = False; - switch (screen.placementPolicy()) { - case BScreen::BestFitPlacement: - place = bestFitPlacement(window_size, space); - break; + switch (screen->getPlacementPolicy()) { case BScreen::RowSmartPlacement: - place = rowSmartPlacement(window_size, space); - break; case BScreen::ColSmartPlacement: - place = colSmartPlacement(window_size, space); - break; - case BScreen::UnderMousePlacement: - case BScreen::ClickMousePlacement: - place = underMousePlacement(window_size, space); + placed = smartPlacement(new_win, availableArea); break; + default: + break; // handled below } // switch - if (place == NULL) - place = cascadePlacement(win, space); - - ASSERT(place != NULL); - if (place->x() + window_size.w() > (signed) space.x() + space.w()) - place->setX(((signed) space.x() + space.w() - window_size.w()) / 2); - if (place->y() + window_size.h() > (signed) space.y() + space.h()) - place->setY(((signed) space.y() + space.h() - window_size.h()) / 2); + if (placed == False) { + cascadePlacement(new_win, availableArea); + cascade_x += win->getTitleHeight() + (screen->getBorderWidth() * 2); + cascade_y += win->getTitleHeight() + (screen->getBorderWidth() * 2); + } - win.configure(place->x(), place->y(), win.area().w(), win.area().h()); - delete place; + if (new_win.right() > availableArea.right()) + new_win.setX(availableArea.left()); + if (new_win.bottom() > availableArea.bottom()) + new_win.setY(availableArea.top()); + win->configure(new_win.x(), new_win.y(), new_win.width(), new_win.height()); } diff --git a/src/Workspace.h b/src/Workspace.h deleted file mode 100644 index 146e1d62..00000000 --- a/src/Workspace.h +++ /dev/null @@ -1,94 +0,0 @@ -// Workspace.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __Workspace_hh -#define __Workspace_hh - -#include - -#include -#include - -class BScreen; -class Clientmenu; -class Workspace; -class OpenboxWindow; -class Size; -class Rect; - -class Workspace { -private: - BScreen &screen; - Clientmenu *clientmenu; - - typedef std::vector winVect; - winVect _windows; - typedef std::list winList; - winList _zorder; - - char *name; - int id, cascade_x, cascade_y; - - OpenboxWindow *_focused, *_last; // last is the same as focused except - // that when focus is removed from all - // windows on the workspace, last doesnt - // change to NULL - -protected: - void placeWindow(OpenboxWindow &); - Point *bestFitPlacement(const Size &win_size, const Rect &space); - Point *underMousePlacement(const Size &win_size, const Rect &space); - Point *rowSmartPlacement(const Size &win_size, const Rect &space); - Point *colSmartPlacement(const Size &win_size, const Rect &space); - Point *const cascadePlacement(const OpenboxWindow &window, const Rect &space); - -public: - Workspace(BScreen &, int = 0); - ~Workspace(void); - - inline BScreen &getScreen(void) { return screen; } - inline Clientmenu *getMenu(void) { return clientmenu; } - inline const char *getName(void) const { return name; } - inline int getWorkspaceID(void) const { return id; } - inline OpenboxWindow *focusedWindow() { return _focused; } - inline OpenboxWindow *lastFocusedWindow() { return _last; } - void focusWindow(OpenboxWindow *win); - OpenboxWindow *getWindow(int); - bool isCurrent(void); - int addWindow(OpenboxWindow *, bool = false); - int removeWindow(OpenboxWindow *); - int getCount(void); - void showAll(void); - void hideAll(void); - void removeAll(void); - void raiseWindow(OpenboxWindow *); - void lowerWindow(OpenboxWindow *); - void reconfigure(); - void update(); - void setCurrent(void); - void setName(const char *); - void shutdown(void); -}; - - -#endif // __Workspace_hh - diff --git a/src/Workspace.hh b/src/Workspace.hh new file mode 100644 index 00000000..652e8cef --- /dev/null +++ b/src/Workspace.hh @@ -0,0 +1,109 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// Workspace.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef __Workspace_hh +#define __Workspace_hh + +extern "C" { +#include +} + +#include +#include +#include + +class BScreen; +class Clientmenu; +class Workspace; +class BlackboxWindow; +class Netizen; + +typedef std::list BlackboxWindowList; +typedef std::vector StackVector; + +class Workspace { +private: + BScreen *screen; + BlackboxWindow *lastfocus; + Clientmenu *clientmenu; + + BlackboxWindowList stackingList, windowList; + + std::string name; + unsigned int id; + int cascade_x, cascade_y; + + Workspace(const Workspace&); + Workspace& operator=(const Workspace&); + + void raiseTransients(const BlackboxWindow * const win, + StackVector::iterator &stack); + void lowerTransients(const BlackboxWindow * const win, + StackVector::iterator &stack); + + void placeWindow(BlackboxWindow *win); + bool cascadePlacement(Rect& win, const Rect& availableArea); + bool smartPlacement(Rect& win, const Rect& availableArea); + +public: + Workspace(BScreen *scrn, unsigned int i = 0); + + inline BScreen *getScreen(void) { return screen; } + + inline BlackboxWindow *getLastFocusedWindow(void) { return lastfocus; } + + inline Clientmenu *getMenu(void) { return clientmenu; } + + inline const std::string& getName(void) const { return name; } + + inline unsigned int getID(void) const { return id; } + + inline void setLastFocusedWindow(BlackboxWindow *w) { lastfocus = w; } + + BlackboxWindow* getWindow(unsigned int index); + BlackboxWindow* getNextWindowInList(BlackboxWindow *w); + BlackboxWindow* getPrevWindowInList(BlackboxWindow *w); + BlackboxWindow* getTopWindowOnStack(void) const; + void sendWindowList(Netizen &n); + + bool isCurrent(void) const; + bool isLastWindow(const BlackboxWindow* w) const; + + void addWindow(BlackboxWindow *w, bool place = False); + unsigned int removeWindow(BlackboxWindow *w); + unsigned int getCount(void) const; + + void showAll(void); + void hideAll(void); + void removeAll(void); + void raiseWindow(BlackboxWindow *w); + void lowerWindow(BlackboxWindow *w); + void reconfigure(void); + void updateFocusModel(void); + void setCurrent(void); + void setName(const std::string& new_name); +}; + + +#endif // __Workspace_hh + diff --git a/src/Workspacemenu.cc b/src/Workspacemenu.cc index a97bdfef..a63251ab 100644 --- a/src/Workspacemenu.cc +++ b/src/Workspacemenu.cc @@ -1,5 +1,6 @@ -// Workspacemenu.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// Workspacemenu.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,48 +21,41 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H -#include "i18n.h" -#include "openbox.h" -#include "Screen.h" -#include "Toolbar.h" -#include "Workspacemenu.h" -#include "Workspace.h" +#include "i18n.hh" +#include "blackbox.hh" +#include "Screen.hh" +#include "Toolbar.hh" +#include "Workspacemenu.hh" +#include "Workspace.hh" -Workspacemenu::Workspacemenu(BScreen &scrn) : Basemenu(scrn), screen(scrn) { +Workspacemenu::Workspacemenu(BScreen *scrn) : Basemenu(scrn) { setInternalMenu(); - setLabel(i18n(WorkspacemenuSet, WorkspacemenuWorkspacesTitle, - "Workspaces")); - insert(i18n(WorkspacemenuSet, WorkspacemenuNewWorkspace, - "New Workspace")); - insert(i18n(WorkspacemenuSet, WorkspacemenuRemoveLast, - "Remove Last")); + setLabel(i18n(WorkspacemenuSet, WorkspacemenuWorkspacesTitle, "Workspaces")); + insert(i18n(WorkspacemenuSet, WorkspacemenuNewWorkspace, "New Workspace")); + insert(i18n(WorkspacemenuSet, WorkspacemenuRemoveLast, "Remove Last")); } -void Workspacemenu::itemSelected(int button, int index) { +void Workspacemenu::itemSelected(int button, unsigned int index) { if (button != 1) return; - if (index == 0) - screen.addWorkspace(); - else if (index == 1) - screen.removeLastWorkspace(); - else if ((screen.getCurrentWorkspace()->getWorkspaceID() != - (index - 2)) && ((index - 2) < screen.getWorkspaceCount())) - screen.changeWorkspaceID(index - 2); - - if (! (screen.getWorkspacemenu()->isTorn() || isTorn())) + if (index == 0) { + getScreen()->addWorkspace(); + } else if (index == 1) { + getScreen()->removeLastWorkspace(); + } else { + index -= 2; + const Workspace* const wkspc = getScreen()->getCurrentWorkspace(); + if (wkspc->getID() != index && index < getScreen()->getWorkspaceCount()) + getScreen()->changeWorkspaceID(index); + } + if (! (getScreen()->getWorkspacemenu()->isTorn() || isTorn())) hide(); } diff --git a/src/Workspacemenu.h b/src/Workspacemenu.hh similarity index 78% rename from src/Workspacemenu.h rename to src/Workspacemenu.hh index fa25814e..28052a9f 100644 --- a/src/Workspacemenu.h +++ b/src/Workspacemenu.hh @@ -1,5 +1,6 @@ -// WorkspaceMenu.h for Openbox - an X11 Window manager -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// WorkspaceMenu.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -23,7 +24,7 @@ #ifndef __Workspacemenu_hh #define __Workspacemenu_hh -#include "Basemenu.h" +#include "Basemenu.hh" // forward declaration class Workspacemenu; @@ -31,13 +32,14 @@ class Toolbar; class Workspacemenu : public Basemenu { private: - BScreen &screen; + Workspacemenu(const Workspacemenu&); + Workspacemenu& operator=(const Workspacemenu&); protected: - virtual void itemSelected(int, int); + virtual void itemSelected(int button, unsigned int index); public: - Workspacemenu(BScreen &); + Workspacemenu(BScreen *scrn); }; diff --git a/src/XAtom.cc b/src/XAtom.cc deleted file mode 100644 index 9e590126..00000000 --- a/src/XAtom.cc +++ /dev/null @@ -1,348 +0,0 @@ -// XAtom.cc for Openbox -// Copyright (c) 2002 - 2002 Ben Jansens (xor at orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#include "XAtom.h" -#include "openbox.h" -#include "Screen.h" -#include "Util.h" - -XAtom::XAtom(Openbox &ob) { - _display = ob.getXDisplay(); - -#ifdef HAVE_GETPID - openbox_pid = getAtom("_BLACKBOX_PID"); -#endif // HAVE_GETPID - - wm_colormap_windows = getAtom("WM_COLORMAP_WINDOWS"); - wm_protocols = getAtom("WM_PROTOCOLS"); - wm_state = getAtom("WM_STATE"); - wm_change_state = getAtom("WM_CHANGE_STATE"); - wm_delete_window = getAtom("WM_DELETE_WINDOW"); - wm_take_focus = getAtom("WM_TAKE_FOCUS"); - motif_wm_hints = getAtom("_MOTIF_WM_HINTS"); - openbox_hints = getAtom("_BLACKBOX_HINTS"); - openbox_attributes = getAtom("_BLACKBOX_ATTRIBUTES"); - openbox_change_attributes = getAtom("_BLACKBOX_CHANGE_ATTRIBUTES"); - - openbox_structure_messages = getAtom("_BLACKBOX_STRUCTURE_MESSAGES"); - openbox_notify_startup = getAtom("_BLACKBOX_NOTIFY_STARTUP"); - openbox_notify_window_add = getAtom("_BLACKBOX_NOTIFY_WINDOW_ADD"); - openbox_notify_window_del = getAtom("_BLACKBOX_NOTIFY_WINDOW_DEL"); - openbox_notify_current_workspace = - getAtom("_BLACKBOX_NOTIFY_CURRENT_WORKSPACE"); - openbox_notify_workspace_count = getAtom("_BLACKBOX_NOTIFY_WORKSPACE_COUNT"); - openbox_notify_window_focus = getAtom("_BLACKBOX_NOTIFY_WINDOW_FOCUS"); - openbox_notify_window_raise = getAtom("_BLACKBOX_NOTIFY_WINDOW_RAISE"); - openbox_notify_window_lower = getAtom("_BLACKBOX_NOTIFY_WINDOW_LOWER"); - - openbox_change_workspace = getAtom("_BLACKBOX_CHANGE_WORKSPACE"); - openbox_change_window_focus = getAtom("_BLACKBOX_CHANGE_WINDOW_FOCUS"); - openbox_cycle_window_focus = getAtom("_BLACKBOX_CYCLE_WINDOW_FOCUS"); - - net_supported = getAtom("_NET_SUPPORTED"); - net_client_list = getAtom("_NET_CLIENT_LIST"); - net_client_list_stacking = getAtom("_NET_CLIENT_LIST_STACKING"); - net_number_of_desktops = getAtom("_NET_NUMBER_OF_DESKTOPS"); - net_desktop_geometry = getAtom("_NET_DESKTOP_GEOMETRY"); - net_desktop_viewport = getAtom("_NET_DESKTOP_VIEWPORT"); - net_current_desktop = getAtom("_NET_CURRENT_DESKTOP"); - net_desktop_names = getAtom("_NET_DESKTOP_NAMES"); - net_active_window = getAtom("_NET_ACTIVE_WINDOW"); - net_workarea = getAtom("_NET_WORKAREA"); - net_supporting_wm_check = getAtom("_NET_SUPPORTING_WM_CHECK"); - net_virtual_roots = getAtom("_NET_VIRTUAL_ROOTS"); - - net_close_window = getAtom("_NET_CLOSE_WINDOW"); - net_wm_moveresize = getAtom("_NET_WM_MOVERESIZE"); - - net_properties = getAtom("_NET_PROPERTIES"); - net_wm_name = getAtom("_NET_WM_NAME"); - net_wm_desktop = getAtom("_NET_WM_DESKTOP"); - net_wm_window_type = getAtom("_NET_WM_WINDOW_TYPE"); - net_wm_state = getAtom("_NET_WM_STATE"); - net_wm_strut = getAtom("_NET_WM_STRUT"); - net_wm_icon_geometry = getAtom("_NET_WM_ICON_GEOMETRY"); - net_wm_icon = getAtom("_NET_WM_ICON"); - net_wm_pid = getAtom("_NET_WM_PID"); - net_wm_handled_icons = getAtom("_NET_WM_HANDLED_ICONS"); - - net_wm_ping = getAtom("_NET_WM_PING"); - - for (unsigned int s = 0, c = ob.managedScreenCount(); s < c; ++s) - setSupported( static_cast(ob.getScreen(s)) ); -} - - -/* - * clean up the class' members - */ -XAtom::~XAtom() { - while (!_support_windows.empty()) { - // make sure we aren't fucking with this somewhere - ASSERT(_support_windows.back() != None); - XDestroyWindow(_display, _support_windows.back()); - _support_windows.pop_back(); - } -} - - -/* - * Returns an atom from the Xserver, creating it if necessary. - */ -Atom XAtom::getAtom(const char *name) const { - return XInternAtom(_display, name, False); -} - - -/* - * Sets which atoms are supported for NETWM, by Openbox, on the root window. - */ -void XAtom::setSupported(const ScreenInfo *screen) { - // create the netwm support window - Window w = XCreateSimpleWindow(_display, screen->getRootWindow(), - 0, 0, 1, 1, 0, 0, 0); - ASSERT(w != None); - _support_windows.push_back(w); - - // we don't support any yet.. -} - - -/* - * Internal setValue used by all typed setValue functions. - * Sets a window property on a window, optionally appending to the existing - * value. - */ -void XAtom::setValue(Window win, Atom atom, Atom type, unsigned char* data, - int size, int nelements, bool append) const { - ASSERT(win != None); ASSERT(atom != None); ASSERT(type != None); - ASSERT(data != (unsigned char *) 0); - ASSERT(size == 8 || size == 16 || size == 32); - ASSERT(nelements > 0); - XChangeProperty(_display, win, atom, type, size, - (append ? PropModeAppend : PropModeReplace), - data, nelements); -} - - -/* - * Set a 32-bit CARDINAL property value on a window. - */ -void XAtom::setCardValue(Window win, Atom atom, long value) const { - setValue(win, atom, XA_CARDINAL, reinterpret_cast(&value), - 32, 1, false); -} - - -/* - * Set an Atom property value on a window. - */ -void XAtom::setAtomValue(Window win, Atom atom, Atom value) const { - setValue(win, atom, XA_ATOM, reinterpret_cast(&value), - 32, 1, false); -} - - -/* - * Set a Window property value on a window. - */ -void XAtom::setWindowValue(Window win, Atom atom, Window value) const { - setValue(win, atom, XA_WINDOW, reinterpret_cast(&value), - 32, 1, false); -} - - -/* - * Set a Pixmap property value on a window. - */ -void XAtom::setPixmapValue(Window win, Atom atom, Pixmap value) const { - setValue(win, atom, XA_PIXMAP, reinterpret_cast(&value), - 32, 1, false); -} - - -/* - * Set a string property value on a window. - */ -void XAtom::setStringValue(Window win, Atom atom, - const std::string &value) const { - setValue(win, atom, XA_STRING, - const_cast - (reinterpret_cast(value.c_str())), - 8, value.size(), false); -} - - -/* - * Add elements to a 32-bit CARDINAL property value on a window. - */ -void XAtom::addCardValue(Window win, Atom atom, long value) const { - setValue(win, atom, XA_CARDINAL, reinterpret_cast(&value), - 32, 1, true); -} - - -/* - * Add elements to an Atom property value on a window. - */ -void XAtom::addAtomValue(Window win, Atom atom, Atom value) const { - setValue(win, atom, XA_ATOM, reinterpret_cast(&value), - 32, 1, true); -} - - -/* - * Add elements to a Window property value on a window. - */ -void XAtom::addWindowValue(Window win, Atom atom, Window value) const { - setValue(win, atom, XA_WINDOW, reinterpret_cast(&value), - 32, 1, true); -} - - -/* - * Add elements to a Pixmap property value on a window. - */ -void XAtom::addPixmapValue(Window win, Atom atom, Pixmap value) const { - setValue(win, atom, XA_PIXMAP, reinterpret_cast(&value), - 32, 1, true); -} - - -/* - * Add characters to a string property value on a window. - */ -void XAtom::addStringValue(Window win, Atom atom, - const std::string &value) const { - setValue(win, atom, XA_STRING, - const_cast - (reinterpret_cast - (value.c_str())), - 8, value.size(), true); -} - - -/* - * Internal getValue function used by all of the typed getValue functions. - * Gets an property's value from a window. - * Returns true if the property was successfully retrieved; false if the - * property did not exist on the window, or has a different type/size format - * than the user tried to retrieve. - */ -bool XAtom::getValue(Window win, Atom atom, Atom type, unsigned long *nelements, - unsigned char **value, int size) const { - unsigned char *c_val; // value alloc'd with c malloc - Atom ret_type; - int ret_size; - unsigned long ret_bytes; - XGetWindowProperty(_display, win, atom, 0l, 1l, False, AnyPropertyType, - &ret_type, &ret_size, nelements, &ret_bytes, - &c_val); // try get the first element - if (ret_type == None) - // the property does not exist on the window - return false; - if (ret_type != type || ret_size != size) { - // wrong data in property - XFree(c_val); - return false; - } - // the data is correct, now, is there more than 1 element? - if (ret_bytes == 0) { - // we got the whole property's value - *value = new unsigned char[*nelements * size/8 + 1]; - memcpy(*value, c_val, *nelements * size/8 + 1); - XFree(c_val); - return true; - } - // get the entire property since it is larger than one long - free(c_val); - // the number of longs that need to be retreived to get the property's entire - // value. The last + 1 is the first long that we retrieved above. - const int remain = (ret_bytes - 1)/sizeof(long) + 1 + 1; - XGetWindowProperty(_display, win, atom, 0l, remain, False, type, &ret_type, - &ret_size, nelements, &ret_bytes, &c_val); - ASSERT(ret_bytes == 0); - *value = new unsigned char[*nelements * size/8 + 1]; - memcpy(*value, c_val, *nelements * size/8 + 1); - XFree(c_val); - return true; -} - - -/* - * Gets a 32-bit Cardinal property's value from a window. - */ -bool XAtom::getCardValue(Window win, Atom atom, unsigned long *nelements, - long **value) const { - return XAtom::getValue(win, atom, XA_CARDINAL, nelements, - reinterpret_cast(value), 32); -} - - -/* - * Gets an Atom property's value from a window. - */ -bool XAtom::getAtomValue(Window win, Atom atom, unsigned long *nelements, - Atom **value) const { - return XAtom::getValue(win, atom, XA_ATOM, nelements, - reinterpret_cast(value), 32); -} - - -/* - * Gets an Window property's value from a window. - */ -bool XAtom::getWindowValue(Window win, Atom atom, unsigned long *nelements, - Window **value) const { - return XAtom::getValue(win, atom, XA_WINDOW, nelements, - reinterpret_cast(value), 32); -} - - -/* - * Gets an Pixmap property's value from a window. - */ -bool XAtom::getPixmapValue(Window win, Atom atom, unsigned long *nelements, - Pixmap **value) const { - return XAtom::getValue(win, atom, XA_PIXMAP, nelements, - reinterpret_cast(value), 32); -} - - -/* - * Gets an string property's value from a window. - */ -bool XAtom::getStringValue(Window win, Atom atom, std::string &value) const { - unsigned char *data; - unsigned long nelements; - bool ret = XAtom::getValue(win, atom, XA_STRING, &nelements, &data, 8); - if (ret) - value = reinterpret_cast(data); - return ret; -} - - -/* - * Removes a property entirely from a window. - */ -void XAtom::eraseValue(Window win, Atom atom) const { - XDeleteProperty(_display, win, atom); -} diff --git a/src/XAtom.h b/src/XAtom.h deleted file mode 100644 index 03292b5d..00000000 --- a/src/XAtom.h +++ /dev/null @@ -1,238 +0,0 @@ -// XAtom.h for Openbox -// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __XAtom_h -#define __XAtom_h - -#include "../config.h" - -#include -#include -#include -#include - -class Openbox; -class ScreenInfo; - -class XAtom { - typedef std::vector SupportWindows; - - Display *_display; - // windows used to specify support for NETWM - SupportWindows _support_windows; - - Atom -#ifdef HAVE_GETPID - openbox_pid, -#endif // HAVE_GETPID - - // window hints - wm_colormap_windows, - wm_protocols, - wm_state, - wm_delete_window, - wm_take_focus, - wm_change_state, - motif_wm_hints, - openbox_attributes, - openbox_change_attributes, - openbox_hints, - - // blackbox-protocol atoms (wm -> client) - openbox_structure_messages, - openbox_notify_startup, - openbox_notify_window_add, - openbox_notify_window_del, - openbox_notify_window_focus, - openbox_notify_current_workspace, - openbox_notify_workspace_count, - openbox_notify_window_raise, - openbox_notify_window_lower, - // blackbox-protocol atoms (client -> wm) - openbox_change_workspace, - openbox_change_window_focus, - openbox_cycle_window_focus, - - // NETWM atoms - // root window properties - net_supported, - net_client_list, - net_client_list_stacking, - net_number_of_desktops, - net_desktop_geometry, - net_desktop_viewport, - net_current_desktop, - net_desktop_names, - net_active_window, - net_workarea, - net_supporting_wm_check, - net_virtual_roots, - // root window messages - net_close_window, - net_wm_moveresize, - // application window properties - net_properties, - net_wm_name, - net_wm_desktop, - net_wm_window_type, - net_wm_state, - net_wm_strut, - net_wm_icon_geometry, - net_wm_icon, - net_wm_pid, - net_wm_handled_icons, - // application protocols - net_wm_ping; - - Atom getAtom(const char *name) const; - void setSupported(const ScreenInfo *screen); - - void setValue(Window win, Atom atom, Atom type, unsigned char *data, - int size, int nelements, bool append) const; - bool getValue(Window win, Atom atom, Atom type, unsigned long *nelements, - unsigned char **value, int size) const; - - // no copying!! - XAtom(const XAtom &); - XAtom& operator=(const XAtom&); - -public: - XAtom(Openbox &ob); - virtual ~XAtom(); - - void setCardValue(Window win, Atom atom, long value) const; // 32-bit CARDINAL - void setAtomValue(Window win, Atom atom, Atom value) const; - void setWindowValue(Window win, Atom atom, Window value) const; - void setPixmapValue(Window win, Atom atom, Pixmap value) const; - void setStringValue(Window win, Atom atom, const std::string &value) const; - - void addCardValue(Window win, Atom atom, long value) const; // 32-bit CARDINAL - void addAtomValue(Window win, Atom atom, Atom value) const; - void addWindowValue(Window win, Atom atom, Window value) const; - void addPixmapValue(Window win, Atom atom, Pixmap value) const; - void addStringValue(Window win, Atom atom, const std::string &value) const; - - // the 'value' is allocated inside the function and - // delete [] value needs to be called when you are done with it. - // teh 'value' array returned is null terminated, and has 'nelements' - // elements in it plus the null. - bool getCardValue(Window win, Atom atom, unsigned long *nelements, - long **value) const; // 32-bit CARDINAL - bool getAtomValue(Window win, Atom atom, unsigned long *nelements, - Atom **value) const; - bool getWindowValue(Window win, Atom atom, unsigned long *nelements, - Window **value) const; - bool getPixmapValue(Window win, Atom atom, unsigned long *nelements, - Pixmap **value) const; - bool getStringValue(Window win, Atom atom, std::string &value) const; - - void eraseValue(Window win, Atom atom) const; - -#ifdef HAVE_GETPID - inline Atom openboxPid() const { return openbox_pid; } -#endif // HAVE_GETPID - - inline Atom wmChangeState() const { return wm_change_state; } - inline Atom wmState() const { return wm_state; } - inline Atom wmDelete() const { return wm_delete_window; } - inline Atom wmProtocols() const { return wm_protocols; } - inline Atom wmTakeFocus() const { return wm_take_focus; } - inline Atom wmColormap() const { return wm_colormap_windows; } - inline Atom motifWMHints() const { return motif_wm_hints; } - - // this atom is for normal app->WM hints about decorations, stacking, - // starting workspace etc... - inline Atom openboxHints() const { return openbox_hints;} - - // these atoms are for normal app->WM interaction beyond the scope of the - // ICCCM... - inline Atom openboxAttributes() const { return openbox_attributes; } - inline Atom openboxChangeAttributes() const - { return openbox_change_attributes; } - - // these atoms are for window->WM interaction, with more control and - // information on window "structure"... common examples are - // notifying apps when windows are raised/lowered... when the user changes - // workspaces... i.e. "pager talk" - inline Atom openboxStructureMessages() const - { return openbox_structure_messages; } - - inline Atom openboxNotifyStartup() const - { return openbox_notify_startup; } - inline Atom openboxNotifyWindowAdd() const - { return openbox_notify_window_add; } - inline Atom openboxNotifyWindowDel() const - { return openbox_notify_window_del; } - inline Atom openboxNotifyWindowFocus() const - { return openbox_notify_window_focus; } - inline Atom openboxNotifyCurrentWorkspace() const - { return openbox_notify_current_workspace; } - inline Atom openboxNotifyWorkspaceCount() const - { return openbox_notify_workspace_count; } - inline Atom openboxNotifyWindowRaise() const - { return openbox_notify_window_raise; } - inline Atom openboxNotifyWindowLower() const - { return openbox_notify_window_lower; } - - // atoms to change that request changes to the desktop environment during - // runtime... these messages can be sent by any client... as the sending - // client window id is not included in the ClientMessage event... - inline Atom openboxChangeWorkspace() const - { return openbox_change_workspace; } - inline Atom openboxChangeWindowFocus() const - { return openbox_change_window_focus; } - inline Atom openboxCycleWindowFocus() const - { return openbox_cycle_window_focus; } - - // root window properties - inline Atom netClientList() const { return net_client_list; } - inline Atom netClientListStacking() const { return net_client_list_stacking; } - inline Atom netNumberOfDesktops() const { return net_number_of_desktops; } - inline Atom netDesktopGeometry() const { return net_desktop_geometry; } - inline Atom netDesktopViewport() const { return net_desktop_viewport; } - inline Atom netCurrentDesktop() const { return net_current_desktop; } - inline Atom netDesktopNames() const { return net_desktop_names; } - inline Atom netActiveWindow() const { return net_active_window; } - inline Atom netWorkarea() const { return net_workarea; } - inline Atom netSupportingWMCheck() const { return net_supporting_wm_check; } - inline Atom netVirtualRoots() const { return net_virtual_roots; } - - // root window messages - inline Atom netCloseWindow() const { return net_close_window; } - inline Atom netWMMoveResize() const { return net_wm_moveresize; } - - // application window properties - inline Atom netProperties() const { return net_properties; } - inline Atom netWMName() const { return net_wm_name; } - inline Atom netWMDesktop() const { return net_wm_desktop; } - inline Atom netWMWindowType() const { return net_wm_window_type; } - inline Atom netWMState() const { return net_wm_state; } - inline Atom netWMStrut() const { return net_wm_strut; } - inline Atom netWMIconGeometry() const { return net_wm_icon_geometry; } - inline Atom netWMIcon() const { return net_wm_icon; } - inline Atom netWMPid() const { return net_wm_pid; } - inline Atom netWMHandledIcons() const { return net_wm_handled_icons; } - - // application protocols - inline Atom netWMPing() const { return net_wm_ping; } -}; - -#endif // __XAtom_h diff --git a/src/XDisplay.cc b/src/XDisplay.cc deleted file mode 100644 index 1addb2d5..00000000 --- a/src/XDisplay.cc +++ /dev/null @@ -1,260 +0,0 @@ -// XDisplay.cc for Openbox -// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif - -#ifdef HAVE_UNNISTD_H -# include -#endif - -#ifdef HAVE_FCNTL_H -# include -#endif - -#ifdef SHAPE -# include -#endif - -#include "XDisplay.h" -#include "Util.h" -#include -#include - -using std::cerr; -using std::endl; - -std::string XDisplay::_app_name; -Window XDisplay::_last_bad_window = None; - -/* - * X error handler to handle all X errors while the application is - * running. - */ -int XDisplay::errorHandler(Display *d, XErrorEvent *e) { -#ifdef DEBUG - char errtxt[128]; - XGetErrorText(d, e->error_code, errtxt, sizeof(errtxt)/sizeof(char)); - cerr << _app_name.c_str() << ": X error: " << - errtxt << "(" << e->error_code << ") opcodes " << - e->request_code << "/" << e->minor_code << endl; - cerr.flags(std::ios_base::hex); - cerr << " resource 0x" << e->resourceid << endl; - cerr.flags(std::ios_base::dec); -#endif - - if (e->error_code == BadWindow) - _last_bad_window = e->resourceid; - - return False; -} - - -XDisplay::XDisplay(const std::string &application_name, const char *dpyname) { - _app_name = application_name; - _grabs = 0; - _hasshape = false; - - _display = XOpenDisplay(dpyname); - if (_display == NULL) { - cerr << "Could not open display. Connection to X server failed.\n"; - ::exit(2); - } - if (-1 == fcntl(ConnectionNumber(_display), F_SETFD, 1)) { - cerr << "Could not mark display connection as close-on-exec.\n"; - ::exit(2); - } - _name = XDisplayName(dpyname); - - XSetErrorHandler(errorHandler); - -#ifdef SHAPE - int waste; - _hasshape = XShapeQueryExtension(_display, &_shape_event_base, &waste); -#endif // SHAPE - -#ifndef NOCLOBBER - getLockModifiers(); -#endif -} - - -XDisplay::~XDisplay() { - std::for_each(_screens.begin(), _screens.end(), PointerAssassin()); - XCloseDisplay(_display); -} - - -/* - * Grab the X server - */ -void XDisplay::grab() { - if (_grabs++ == 0) - XGrabServer(_display); -} - - -/* - * Release the X server from a grab - */ -void XDisplay::ungrab() { - if (--_grabs == 0) - XUngrabServer(_display); -} - - -/* - * Gets the next event on the queue from the X server. - * - * Returns: true if e contains a new event; false if there is no event to be - * returned. - */ -bool XDisplay::nextEvent(XEvent &e) { - if(!XPending(_display)) - return false; - XNextEvent(_display, &e); - if (_last_bad_window != None) { - if (e.xany.window == _last_bad_window) { - cerr << "XDisplay::nextEvent(): Removing event for bad window from " << - "event queue\n"; - return false; - } else - _last_bad_window = None; - } - return true; -} - - -int XDisplay::connectionNumber() const { - return ConnectionNumber(_display); -} - - -/* - * Creates a font cursor in the X server and returns it. - */ -Cursor createCursor(unsigned int shape) const { - return XCreateFontCursor(_display, shape); -} - - -#ifndef NOCLOBBER -void XDisplay::getLockModifers() { - NumLockMask = ScrollLockMask = 0; - - const XModifierKeymap* const modmap = XGetModifierMapping(display); - if (modmap && modmap->max_keypermod > 0) { - const int mask_table[] = { - ShiftMask, LockMask, ControlMask, Mod1Mask, - Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask - }; - const size_t size = (sizeof(mask_table) / sizeof(mask_table[0])) * - modmap->max_keypermod; - // get the values of the keyboard lock modifiers - // Note: Caps lock is not retrieved the same way as Scroll and Num lock - // since it doesn't need to be. - const KeyCode num_lock_code = XKeysymToKeycode(display, XK_Num_Lock); - const KeyCode scroll_lock_code = XKeysymToKeycode(display, XK_Scroll_Lock); - - for (size_t cnt = 0; cnt < size; ++cnt) { - if (! modmap->modifiermap[cnt]) continue; - - if (num_lock_code == modmap->modifiermap[cnt]) - NumLockMask = mask_table[cnt / modmap->max_keypermod]; - if (scroll_lock_code == modmap->modifiermap[cnt]) - ScrollLockMask = mask_table[cnt / modmap->max_keypermod]; - } - } - - MaskList[0] = 0; - MaskList[1] = LockMask; - MaskList[2] = NumLockMask; - MaskList[3] = ScrollLockMask; - MaskList[4] = LockMask | NumLockMask; - MaskList[5] = NumLockMask | ScrollLockMask; - MaskList[6] = LockMask | ScrollLockMask; - MaskList[7] = LockMask | NumLockMask | ScrollLockMask; - - if (modmap) XFreeModifiermap(const_cast(modmap)); -} -#endif // NOCLOBBER - -unsigned int XDisplay::stripModifiers(const unsigned int state) const { -#ifndef NOCLOBBER - return state &= ~(NumLockMask() | ScrollLockMask | LockMask); -#else - return state &= ~LockMask; -#endif -} - - -/* - * Verifies that a window has not requested to be destroyed/unmapped, so - * if it is a valid window or not. - * Returns: true if the window is valid; false if it is no longer valid. - */ -bool XDisplay::validateWindow(Window window) { - XEvent event; - if (XCheckTypedWindowEvent(_display, window, DestroyNotify, &event)) { - XPutBackEvent(display, &event); - return false; - } - return true; -} - - -/* - * Grabs a button, but also grabs the button in every possible combination with - * the keyboard lock keys, so that they do not cancel out the event. - */ -void BaseDisplay::grabButton(unsigned int button, unsigned int modifiers, - Window grab_window, Bool owner_events, - unsigned int event_mask, int pointer_mode, - int keybaord_mode, Window confine_to, - Cursor cursor) const -{ -#ifndef NOCLOBBER - for (size_t cnt = 0; cnt < 8; ++cnt) - XGrabButton(_display, button, modifiers | MaskList[cnt], grab_window, - owner_events, event_mask, pointer_mode, keybaord_mode, - confine_to, cursor); -#else // NOCLOBBER - XGrabButton(_display, button, modifiers, grab_window, - owner_events, event_mask, pointer_mode, keybaord_mode, - confine_to, cursor); -#endif // NOCLOBBER -} - - -/* - * Releases the grab on a button, and ungrabs all possible combinations of the - * keyboard lock keys. - */ -void BaseDisplay::ungrabButton(unsigned int button, unsigned int modifiers, - Window grab_window) const { -#ifndef NOCLOBBER - for (size_t cnt = 0; cnt < 8; ++cnt) - XUngrabButton(display, button, modifiers | MaskList[cnt], grab_window); -#else // NOCLOBBER - XUngrabButton(display, button, modifiers, grab_window); -#endif // NOCLOBBER -} diff --git a/src/XDisplay.h b/src/XDisplay.h deleted file mode 100644 index 3c4230bd..00000000 --- a/src/XDisplay.h +++ /dev/null @@ -1,97 +0,0 @@ -// XDisplay.h for Openbox -// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __XDisplay_h -#define __XDisplay_h - -#include -#include -#include -#include "XAtom.h" -#include "XScreen.h" - -class XDisplay { - friend XAtom::XAtom(const XDisplay *); - friend XScreen::XScreen(const XDisplay *, const unsigned int); - -private: - Display *_display; - std::string _name; - unsigned int _grabs; - bool _hasshape; - int _shape_event_base; - -#ifndef NOCLOBBER - // the server's values for the lock key modifiers - void getLockModifiers(); - unsigned int MaskList[8]; - // the masks of the modifiers which are ignored in button events. - int NumLockMask, ScrollLockMask; -#endif // NOCLOBBER - - - // X error handling - static int errorHandler(Display *d, XErrorEvent *e); - static std::string _app_name; - static Window _last_bad_window; - - // no copying!! - XDisplay(const XDisplay &); - XDisplay& operator=(const XDisplay&); - -protected: - virtual void process_event(XEvent *) = 0; - -public: - XDisplay(const std::string &application_name, const char *dpyname = 0); - virtual ~XDisplay(); - - inline virtual unsigned int screenCount() const - { return ScreenCount(_display); } - - inline bool hasShape() const { return _hasshape; } - inline int shapeEventBase() const { return _shape_event_base; } - - //inline Display *display() const { return _display; } - - inline std::string applicationName() const { return _app_name; } - inline std::string name() const { return _name; } - - void grab(); - void ungrab(); - - bool nextEvent(XEvent &e); - - int connectionNumber() const; - - Cursor createCursor(unsigned int shape) const; - - unsigned int stripModifiers(const unsigned int state) const; - - // these belong in Xwindow - const bool validateWindow(Window); - void grabButton(unsigned int, unsigned int, Window, Bool, unsigned int, int, - int, Window, Cursor) const; - void ungrabButton(unsigned int button, unsigned int modifiers, - Window grab_window) const; -}; - -#endif // _XDisplay_h diff --git a/src/XScreen.cc b/src/XScreen.cc deleted file mode 100644 index 5ae8becd..00000000 --- a/src/XScreen.cc +++ /dev/null @@ -1,86 +0,0 @@ -// XScreen.cc for Openbox -// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#include -#include "XScreen.h" -#include "XDisplay.h" -#include "Geometry.h" - -XScreen::XScreen(const XDisplay *display, const unsigned int number) { - _display = display->_display; - _number = number; - - _root = RootWindow(_display, _number); - _size = Size(WidthOfScreen(ScreenOfDisplay(_display, _number)), - HeightOfScreen(ScreenOfDisplay(_display, _number))); - setColorData(); -} - - -XScreen::~XScreen() { -} - - -/* - * This sets up the _depth, _visual, and _colormap properties. - */ -void XScreen::setColorData() { - _depth = DefaultDepth(_display, _number); - _visual = (Visual *) 0; - - // search for a TrueColor Visual. If we can't find one, use the default - // visual for the screen - XVisualInfo vinfo_template, *vinfo_return; - int vinfo_nitems; - - vinfo_template.screen = _number; - vinfo_template.c_class = TrueColor; - - vinfo_return = XGetVisualInfo(_display, VisualScreenMask | VisualClassMask, - &vinfo_template, &vinfo_nitems); - if (vinfo_return && vinfo_nitems > 0) { - for (int i = 0; i < vinfo_nitems; i++) - if (_depth < (vinfo_return + i)->depth) { - _depth = (vinfo_return + i)->depth; - _visual = (vinfo_return + i)->visual; - } - XFree(vinfo_return); - } - if (_visual) - _colormap = XCreateColormap(_display, _root, _visual, AllocNone); - else { - _visual = DefaultVisual(_display, _number); - _colormap = DefaultColormap(_display, _number); - } -} - - -/* - * Creates a window on screen. - */ -Window createWindow(Window parent, const Rect &area, int borderw, - unsigned int winclass, unsigned long attrib_mask, - XSetWindowAttributes *attrib) const { - return XCreateWindow(_display, parent, - area.x(), area.y(), area.w(), area.h(), - borderw, depth(), winclass, visual(), - attrib_mask, attrib); -} diff --git a/src/XScreen.h b/src/XScreen.h deleted file mode 100644 index cdfd4257..00000000 --- a/src/XScreen.h +++ /dev/null @@ -1,63 +0,0 @@ -// XScreen.h for Openbox -// Copyright (c) 2002 - 2002 Ben Janens (ben at orodu.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __XScreen_h -#define __XScreen_h - -#include -#include "Geometry.h" - -class XDisplay; - -class XScreen { -private: - Display *_display; - unsigned int _number; - Visual *_visual; - Window _root; - Colormap _colormap; - int _depth; - Size _size; - - void setColorData(); - - // no copying!! - XScreen(const XScreen &); - XScreen& operator=(const XScreen&); - -public: - XScreen(const XDisplay *display, const unsigned int number); - virtual ~XScreen(); - - inline Visual *visual() const { return _visual; } - inline Window rootWindow() const { return _root; } - inline Colormap colormap() const { return _colormap; } - inline unsigned int depth() const { return _depth; } - inline unsigned int number() const { return _number; } - inline const Size &size() const { return _size; } - - Window createWindow(Window parent, const Rect &area, int borderw, - unsigned int winclass, - unsigned long attrib_mask, - XSetWindowAttributes *attrib) const; -}; - -#endif // __XScreen_h diff --git a/src/blackbox.cc b/src/blackbox.cc new file mode 100644 index 00000000..4325933b --- /dev/null +++ b/src/blackbox.cc @@ -0,0 +1,1680 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// blackbox.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif // HAVE_CONFIG_H + +extern "C" { +#include +#include +#include +#include +#include +#include + +#ifdef SHAPE +#include +#endif // SHAPE + +#ifdef HAVE_STDIO_H +# include +#endif // HAVE_STDIO_H + +#ifdef HAVE_STDLIB_H +# include +#endif // HAVE_STDLIB_H + +#ifdef HAVE_STRING_H +# include +#endif // HAVE_STRING_H + +#ifdef HAVE_UNISTD_H +# include +# include +#endif // HAVE_UNISTD_H + +#ifdef HAVE_SYS_PARAM_H +# include +#endif // HAVE_SYS_PARAM_H + +#ifdef HAVE_SYS_SELECT_H +# include +#endif // HAVE_SYS_SELECT_H + +#ifdef HAVE_SIGNAL_H +# include +#endif // HAVE_SIGNAL_H + +#ifdef HAVE_SYS_SIGNAL_H +# include +#endif // HAVE_SYS_SIGNAL_H + +#ifdef HAVE_SYS_STAT_H +# include +# include +#endif // HAVE_SYS_STAT_H + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else // !TIME_WITH_SYS_TIME +# ifdef HAVE_SYS_TIME_H +# include +# else // !HAVE_SYS_TIME_H +# include +# endif // HAVE_SYS_TIME_H +#endif // TIME_WITH_SYS_TIME + +#ifdef HAVE_LIBGEN_H +# include +#endif // HAVE_LIBGEN_H +} + +#include +#include +using std::string; + +#include "i18n.hh" +#include "blackbox.hh" +#include "Basemenu.hh" +#include "Clientmenu.hh" +#include "GCCache.hh" +#include "Image.hh" +#include "Rootmenu.hh" +#include "Screen.hh" +#include "Slit.hh" +#include "Toolbar.hh" +#include "Util.hh" +#include "Window.hh" +#include "Workspace.hh" +#include "Workspacemenu.hh" + + +// X event scanner for enter/leave notifies - adapted from twm +struct scanargs { + Window w; + bool leave, inferior, enter; +}; + +static Bool queueScanner(Display *, XEvent *e, char *args) { + scanargs *scan = (scanargs *) args; + if ((e->type == LeaveNotify) && + (e->xcrossing.window == scan->w) && + (e->xcrossing.mode == NotifyNormal)) { + scan->leave = True; + scan->inferior = (e->xcrossing.detail == NotifyInferior); + } else if ((e->type == EnterNotify) && (e->xcrossing.mode == NotifyUngrab)) { + scan->enter = True; + } + + return False; +} + +Blackbox *blackbox; + + +Blackbox::Blackbox(char **m_argv, char *dpy_name, char *rc) + : BaseDisplay(m_argv[0], dpy_name) { + if (! XSupportsLocale()) + fprintf(stderr, "X server does not support locale\n"); + + if (XSetLocaleModifiers("") == NULL) + fprintf(stderr, "cannot set locale modifiers\n"); + + ::blackbox = this; + argv = m_argv; + if (! rc) rc = "~/.blackboxrc"; + rc_file = expandTilde(rc); + + no_focus = False; + + resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec = 0; + + active_screen = 0; + focused_window = (BlackboxWindow *) 0; + + XrmInitialize(); + load_rc(); + + init_icccm(); + + cursor.session = XCreateFontCursor(getXDisplay(), XC_left_ptr); + cursor.move = XCreateFontCursor(getXDisplay(), XC_fleur); + cursor.ll_angle = XCreateFontCursor(getXDisplay(), XC_ll_angle); + cursor.lr_angle = XCreateFontCursor(getXDisplay(), XC_lr_angle); + + for (unsigned int i = 0; i < getNumberOfScreens(); i++) { + BScreen *screen = new BScreen(this, i); + + if (! screen->isScreenManaged()) { + delete screen; + continue; + } + + screenList.push_back(screen); + } + + if (screenList.empty()) { + fprintf(stderr, + i18n(blackboxSet, blackboxNoManagableScreens, + "Blackbox::Blackbox: no managable screens found, aborting.\n")); + ::exit(3); + } + + // set the screen with mouse to the first managed screen + active_screen = screenList.front(); + setFocusedWindow(0); + + XSynchronize(getXDisplay(), False); + XSync(getXDisplay(), False); + + reconfigure_wait = reread_menu_wait = False; + + timer = new BTimer(this, this); + timer->setTimeout(0l); +} + + +Blackbox::~Blackbox(void) { + std::for_each(screenList.begin(), screenList.end(), PointerAssassin()); + + std::for_each(menuTimestamps.begin(), menuTimestamps.end(), + PointerAssassin()); + + delete timer; +} + + +void Blackbox::process_event(XEvent *e) { + switch (e->type) { + case ButtonPress: { + // strip the lock key modifiers + e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask); + + last_time = e->xbutton.time; + + BlackboxWindow *win = (BlackboxWindow *) 0; + Basemenu *menu = (Basemenu *) 0; + Slit *slit = (Slit *) 0; + Toolbar *tbar = (Toolbar *) 0; + BScreen *scrn = (BScreen *) 0; + + if ((win = searchWindow(e->xbutton.window))) { + win->buttonPressEvent(&e->xbutton); + + /* XXX: is this sane on low colour desktops? */ + if (e->xbutton.button == 1) + win->installColormap(True); + } else if ((menu = searchMenu(e->xbutton.window))) { + menu->buttonPressEvent(&e->xbutton); + } else if ((slit = searchSlit(e->xbutton.window))) { + slit->buttonPressEvent(&e->xbutton); + } else if ((tbar = searchToolbar(e->xbutton.window))) { + tbar->buttonPressEvent(&e->xbutton); + } else if ((scrn = searchScreen(e->xbutton.window))) { + scrn->buttonPressEvent(&e->xbutton); + if (active_screen != scrn) { + active_screen = scrn; + // first, set no focus window on the old screen + setFocusedWindow(0); + // and move focus to this screen + setFocusedWindow(0); + } + } + break; + } + + case ButtonRelease: { + // strip the lock key modifiers + e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask); + + last_time = e->xbutton.time; + + BlackboxWindow *win = (BlackboxWindow *) 0; + Basemenu *menu = (Basemenu *) 0; + Toolbar *tbar = (Toolbar *) 0; + + if ((win = searchWindow(e->xbutton.window))) + win->buttonReleaseEvent(&e->xbutton); + else if ((menu = searchMenu(e->xbutton.window))) + menu->buttonReleaseEvent(&e->xbutton); + else if ((tbar = searchToolbar(e->xbutton.window))) + tbar->buttonReleaseEvent(&e->xbutton); + + break; + } + + case ConfigureRequest: { + // compress configure requests... + XEvent realevent; + unsigned int i = 0; + while(XCheckTypedWindowEvent(getXDisplay(), e->xconfigurerequest.window, + ConfigureRequest, &realevent)) { + i++; + } + if ( i > 0 ) + e = &realevent; + + BlackboxWindow *win = (BlackboxWindow *) 0; + Slit *slit = (Slit *) 0; + + if ((win = searchWindow(e->xconfigurerequest.window))) { + win->configureRequestEvent(&e->xconfigurerequest); + } else if ((slit = searchSlit(e->xconfigurerequest.window))) { + slit->configureRequestEvent(&e->xconfigurerequest); + } else { + if (validateWindow(e->xconfigurerequest.window)) { + XWindowChanges xwc; + + xwc.x = e->xconfigurerequest.x; + xwc.y = e->xconfigurerequest.y; + xwc.width = e->xconfigurerequest.width; + xwc.height = e->xconfigurerequest.height; + xwc.border_width = e->xconfigurerequest.border_width; + xwc.sibling = e->xconfigurerequest.above; + xwc.stack_mode = e->xconfigurerequest.detail; + + XConfigureWindow(getXDisplay(), e->xconfigurerequest.window, + e->xconfigurerequest.value_mask, &xwc); + } + } + + break; + } + + case MapRequest: { +#ifdef DEBUG + fprintf(stderr, "Blackbox::process_event(): MapRequest for 0x%lx\n", + e->xmaprequest.window); +#endif // DEBUG + + BlackboxWindow *win = searchWindow(e->xmaprequest.window); + + if (! win) { + BScreen *screen = searchScreen(e->xmaprequest.parent); + + if (! screen) { + /* + we got a map request for a window who's parent isn't root. this + can happen in only one circumstance: + + a client window unmapped a managed window, and then remapped it + somewhere between unmapping the client window and reparenting it + to root. + + regardless of how it happens, we need to find the screen that + the window is on + */ + XWindowAttributes wattrib; + if (! XGetWindowAttributes(getXDisplay(), e->xmaprequest.window, + &wattrib)) { + // failed to get the window attributes, perhaps the window has + // now been destroyed? + break; + } + + screen = searchScreen(wattrib.root); + assert(screen != 0); // this should never happen + } + + screen->manageWindow(e->xmaprequest.window); + } + + break; + } + + case UnmapNotify: { + BlackboxWindow *win = (BlackboxWindow *) 0; + Slit *slit = (Slit *) 0; + + if ((win = searchWindow(e->xunmap.window))) { + win->unmapNotifyEvent(&e->xunmap); + } else if ((slit = searchSlit(e->xunmap.window))) { + slit->unmapNotifyEvent(&e->xunmap); + } + + break; + } + + case DestroyNotify: { + BlackboxWindow *win = (BlackboxWindow *) 0; + Slit *slit = (Slit *) 0; + BWindowGroup *group = (BWindowGroup *) 0; + + if ((win = searchWindow(e->xdestroywindow.window))) { + win->destroyNotifyEvent(&e->xdestroywindow); + } else if ((slit = searchSlit(e->xdestroywindow.window))) { + slit->removeClient(e->xdestroywindow.window, False); + } else if ((group = searchGroup(e->xdestroywindow.window))) { + delete group; + } + + break; + } + + case ReparentNotify: { + /* + this event is quite rare and is usually handled in unmapNotify + however, if the window is unmapped when the reparent event occurs + the window manager never sees it because an unmap event is not sent + to an already unmapped window. + */ + BlackboxWindow *win = searchWindow(e->xreparent.window); + if (win) { + win->reparentNotifyEvent(&e->xreparent); + } else { + Slit *slit = searchSlit(e->xreparent.window); + if (slit && slit->getWindowID() != e->xreparent.parent) + slit->removeClient(e->xreparent.window, True); + } + break; + } + + case MotionNotify: { + // motion notify compression... + XEvent realevent; + unsigned int i = 0; + while (XCheckTypedWindowEvent(getXDisplay(), e->xmotion.window, + MotionNotify, &realevent)) { + i++; + } + + // if we have compressed some motion events, use the last one + if ( i > 0 ) + e = &realevent; + + // strip the lock key modifiers + e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask); + + last_time = e->xmotion.time; + + BlackboxWindow *win = (BlackboxWindow *) 0; + Basemenu *menu = (Basemenu *) 0; + + if ((win = searchWindow(e->xmotion.window))) + win->motionNotifyEvent(&e->xmotion); + else if ((menu = searchMenu(e->xmotion.window))) + menu->motionNotifyEvent(&e->xmotion); + + break; + } + + case PropertyNotify: { + last_time = e->xproperty.time; + + if (e->xproperty.state != PropertyDelete) { + BlackboxWindow *win = searchWindow(e->xproperty.window); + + if (win) + win->propertyNotifyEvent(e->xproperty.atom); + } + + break; + } + + case EnterNotify: { + last_time = e->xcrossing.time; + + BScreen *screen = (BScreen *) 0; + BlackboxWindow *win = (BlackboxWindow *) 0; + Basemenu *menu = (Basemenu *) 0; + Toolbar *tbar = (Toolbar *) 0; + Slit *slit = (Slit *) 0; + + if (e->xcrossing.mode == NotifyGrab) break; + + XEvent dummy; + scanargs sa; + sa.w = e->xcrossing.window; + sa.enter = sa.leave = False; + XCheckIfEvent(getXDisplay(), &dummy, queueScanner, (char *) &sa); + + if ((e->xcrossing.window == e->xcrossing.root) && + (screen = searchScreen(e->xcrossing.window))) { + screen->getImageControl()->installRootColormap(); + } else if ((win = searchWindow(e->xcrossing.window))) { + if (win->getScreen()->isSloppyFocus() && + (! win->isFocused()) && (! no_focus)) { + if (((! sa.leave) || sa.inferior) && win->isVisible()) { + if (win->setInputFocus()) + win->installColormap(True); // XXX: shouldnt we honour no install? + } + } + } else if ((menu = searchMenu(e->xcrossing.window))) { + menu->enterNotifyEvent(&e->xcrossing); + } else if ((tbar = searchToolbar(e->xcrossing.window))) { + tbar->enterNotifyEvent(&e->xcrossing); + } else if ((slit = searchSlit(e->xcrossing.window))) { + slit->enterNotifyEvent(&e->xcrossing); + } + break; + } + + case LeaveNotify: { + last_time = e->xcrossing.time; + + BlackboxWindow *win = (BlackboxWindow *) 0; + Basemenu *menu = (Basemenu *) 0; + Toolbar *tbar = (Toolbar *) 0; + Slit *slit = (Slit *) 0; + + if ((menu = searchMenu(e->xcrossing.window))) + menu->leaveNotifyEvent(&e->xcrossing); + else if ((win = searchWindow(e->xcrossing.window))) + win->installColormap(False); + else if ((tbar = searchToolbar(e->xcrossing.window))) + tbar->leaveNotifyEvent(&e->xcrossing); + else if ((slit = searchSlit(e->xcrossing.window))) + slit->leaveNotifyEvent(&e->xcrossing); + break; + } + + case Expose: { + // compress expose events + XEvent realevent; + unsigned int i = 0; + int ex1, ey1, ex2, ey2; + ex1 = e->xexpose.x; + ey1 = e->xexpose.y; + ex2 = ex1 + e->xexpose.width - 1; + ey2 = ey1 + e->xexpose.height - 1; + while (XCheckTypedWindowEvent(getXDisplay(), e->xexpose.window, + Expose, &realevent)) { + i++; + + // merge expose area + ex1 = std::min(realevent.xexpose.x, ex1); + ey1 = std::min(realevent.xexpose.y, ey1); + ex2 = std::max(realevent.xexpose.x + realevent.xexpose.width - 1, ex2); + ey2 = std::max(realevent.xexpose.y + realevent.xexpose.height - 1, ey2); + } + if ( i > 0 ) + e = &realevent; + + // use the merged area + e->xexpose.x = ex1; + e->xexpose.y = ey1; + e->xexpose.width = ex2 - ex1 + 1; + e->xexpose.height = ey2 - ey1 + 1; + + BlackboxWindow *win = (BlackboxWindow *) 0; + Basemenu *menu = (Basemenu *) 0; + Toolbar *tbar = (Toolbar *) 0; + + if ((win = searchWindow(e->xexpose.window))) + win->exposeEvent(&e->xexpose); + else if ((menu = searchMenu(e->xexpose.window))) + menu->exposeEvent(&e->xexpose); + else if ((tbar = searchToolbar(e->xexpose.window))) + tbar->exposeEvent(&e->xexpose); + + break; + } + + case KeyPress: { + Toolbar *tbar = searchToolbar(e->xkey.window); + + if (tbar && tbar->isEditing()) + tbar->keyPressEvent(&e->xkey); + + break; + } + + case ColormapNotify: { + BScreen *screen = searchScreen(e->xcolormap.window); + + if (screen) + screen->setRootColormapInstalled((e->xcolormap.state == + ColormapInstalled) ? True : False); + + break; + } + + case FocusIn: { + if (e->xfocus.detail != NotifyNonlinear) { + /* + don't process FocusIns when: + 1. the new focus window isn't an ancestor or inferior of the old + focus window (NotifyNonlinear) + */ + break; + } + + BlackboxWindow *win = searchWindow(e->xfocus.window); + if (win) { + if (! win->isFocused()) + win->setFocusFlag(True); + + /* + set the event window to None. when the FocusOut event handler calls + this function recursively, it uses this as an indication that focus + has moved to a known window. + */ + e->xfocus.window = None; + } + + break; + } + + case FocusOut: { + if (e->xfocus.detail != NotifyNonlinear) { + /* + don't process FocusOuts when: + 2. the new focus window isn't an ancestor or inferior of the old + focus window (NotifyNonlinear) + */ + break; + } + + BlackboxWindow *win = searchWindow(e->xfocus.window); + if (win && win->isFocused()) { + /* + before we mark "win" as unfocused, we need to verify that focus is + going to a known location, is in a known location, or set focus + to a known location. + */ + + XEvent event; + // don't check the current focus if FocusOut was generated during a grab + bool check_focus = (e->xfocus.mode == NotifyNormal); + + /* + First, check if there is a pending FocusIn event waiting. if there + is, process it and determine if focus has moved to another window + (the FocusIn event handler sets the window in the event + structure to None to indicate this). + */ + if (XCheckTypedEvent(getXDisplay(), FocusIn, &event)) { + + process_event(&event); + if (event.xfocus.window == None) { + // focus has moved + check_focus = False; + } + } + + if (check_focus) { + /* + Second, we query the X server for the current input focus. + to make sure that we keep a consistent state. + */ + BlackboxWindow *focus; + Window w; + int revert; + XGetInputFocus(getXDisplay(), &w, &revert); + focus = searchWindow(w); + if (focus) { + /* + focus got from "win" to "focus" under some very strange + circumstances, and we need to make sure that the focus indication + is correct. + */ + setFocusedWindow(focus); + } else { + // we have no idea where focus went... so we set it to somewhere + setFocusedWindow(0); + } + } + } + + break; + } + + case ClientMessage: { + if (e->xclient.format == 32) { + if (e->xclient.message_type == getWMChangeStateAtom()) { + BlackboxWindow *win = searchWindow(e->xclient.window); + if (! win || ! win->validateClient()) return; + + if (e->xclient.data.l[0] == IconicState) + win->iconify(); + if (e->xclient.data.l[0] == NormalState) + win->deiconify(); + } else if(e->xclient.message_type == getBlackboxChangeWorkspaceAtom()) { + BScreen *screen = searchScreen(e->xclient.window); + + if (screen && e->xclient.data.l[0] >= 0 && + e->xclient.data.l[0] < + static_cast(screen->getWorkspaceCount())) + screen->changeWorkspaceID(e->xclient.data.l[0]); + } else if (e->xclient.message_type == getBlackboxChangeWindowFocusAtom()) { + BlackboxWindow *win = searchWindow(e->xclient.window); + + if (win && win->isVisible() && win->setInputFocus()) + win->installColormap(True); + } else if (e->xclient.message_type == getBlackboxCycleWindowFocusAtom()) { + BScreen *screen = searchScreen(e->xclient.window); + + if (screen) { + if (! e->xclient.data.l[0]) + screen->prevFocus(); + else + screen->nextFocus(); + } + } else if (e->xclient.message_type == getBlackboxChangeAttributesAtom()) { + BlackboxWindow *win = searchWindow(e->xclient.window); + + if (win && win->validateClient()) { + BlackboxHints net; + net.flags = e->xclient.data.l[0]; + net.attrib = e->xclient.data.l[1]; + net.workspace = e->xclient.data.l[2]; + net.stack = e->xclient.data.l[3]; + net.decoration = e->xclient.data.l[4]; + + win->changeBlackboxHints(&net); + } + } + } + + break; + } + + case NoExpose: + case ConfigureNotify: + case MapNotify: + break; // not handled, just ignore + + default: { +#ifdef SHAPE + if (e->type == getShapeEventBase()) { + XShapeEvent *shape_event = (XShapeEvent *) e; + BlackboxWindow *win = searchWindow(e->xany.window); + + if (win) + win->shapeEvent(shape_event); + } +#endif // SHAPE + } + } // switch +} + + +bool Blackbox::handleSignal(int sig) { + switch (sig) { + case SIGHUP: + reconfigure(); + break; + + case SIGUSR1: + reload_rc(); + break; + + case SIGUSR2: + rereadMenu(); + break; + + case SIGPIPE: + case SIGSEGV: + case SIGFPE: + case SIGINT: + case SIGTERM: + shutdown(); + + default: + return False; + } + + return True; +} + + +void Blackbox::init_icccm(void) { + xa_wm_colormap_windows = + XInternAtom(getXDisplay(), "WM_COLORMAP_WINDOWS", False); + xa_wm_protocols = XInternAtom(getXDisplay(), "WM_PROTOCOLS", False); + xa_wm_state = XInternAtom(getXDisplay(), "WM_STATE", False); + xa_wm_change_state = XInternAtom(getXDisplay(), "WM_CHANGE_STATE", False); + xa_wm_delete_window = XInternAtom(getXDisplay(), "WM_DELETE_WINDOW", False); + xa_wm_take_focus = XInternAtom(getXDisplay(), "WM_TAKE_FOCUS", False); + motif_wm_hints = XInternAtom(getXDisplay(), "_MOTIF_WM_HINTS", False); + + blackbox_hints = XInternAtom(getXDisplay(), "_BLACKBOX_HINTS", False); + blackbox_attributes = + XInternAtom(getXDisplay(), "_BLACKBOX_ATTRIBUTES", False); + blackbox_change_attributes = + XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_ATTRIBUTES", False); + blackbox_structure_messages = + XInternAtom(getXDisplay(), "_BLACKBOX_STRUCTURE_MESSAGES", False); + blackbox_notify_startup = + XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_STARTUP", False); + blackbox_notify_window_add = + XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_ADD", False); + blackbox_notify_window_del = + XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_DEL", False); + blackbox_notify_current_workspace = + XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_CURRENT_WORKSPACE", False); + blackbox_notify_workspace_count = + XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WORKSPACE_COUNT", False); + blackbox_notify_window_focus = + XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_FOCUS", False); + blackbox_notify_window_raise = + XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_RAISE", False); + blackbox_notify_window_lower = + XInternAtom(getXDisplay(), "_BLACKBOX_NOTIFY_WINDOW_LOWER", False); + blackbox_change_workspace = + XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_WORKSPACE", False); + blackbox_change_window_focus = + XInternAtom(getXDisplay(), "_BLACKBOX_CHANGE_WINDOW_FOCUS", False); + blackbox_cycle_window_focus = + XInternAtom(getXDisplay(), "_BLACKBOX_CYCLE_WINDOW_FOCUS", False); + +#ifdef NEWWMSPEC + net_supported = XInternAtom(getXDisplay(), "_NET_SUPPORTED", False); + net_client_list = XInternAtom(getXDisplay(), "_NET_CLIENT_LIST", False); + net_client_list_stacking = + XInternAtom(getXDisplay(), "_NET_CLIENT_LIST_STACKING", False); + net_number_of_desktops = + XInternAtom(getXDisplay(), "_NET_NUMBER_OF_DESKTOPS", False); + net_desktop_geometry = + XInternAtom(getXDisplay(), "_NET_DESKTOP_GEOMETRY", False); + net_desktop_viewport = + XInternAtom(getXDisplay(), "_NET_DESKTOP_VIEWPORT", False); + net_current_desktop = + XInternAtom(getXDisplay(), "_NET_CURRENT_DESKTOP", False); + net_desktop_names = XInternAtom(getXDisplay(), "_NET_DESKTOP_NAMES", False); + net_active_window = XInternAtom(getXDisplay(), "_NET_ACTIVE_WINDOW", False); + net_workarea = XInternAtom(getXDisplay(), "_NET_WORKAREA", False); + net_supporting_wm_check = + XInternAtom(getXDisplay(), "_NET_SUPPORTING_WM_CHECK", False); + net_virtual_roots = XInternAtom(getXDisplay(), "_NET_VIRTUAL_ROOTS", False); + net_close_window = XInternAtom(getXDisplay(), "_NET_CLOSE_WINDOW", False); + net_wm_moveresize = XInternAtom(getXDisplay(), "_NET_WM_MOVERESIZE", False); + net_properties = XInternAtom(getXDisplay(), "_NET_PROPERTIES", False); + net_wm_name = XInternAtom(getXDisplay(), "_NET_WM_NAME", False); + net_wm_desktop = XInternAtom(getXDisplay(), "_NET_WM_DESKTOP", False); + net_wm_window_type = + XInternAtom(getXDisplay(), "_NET_WM_WINDOW_TYPE", False); + net_wm_state = XInternAtom(getXDisplay(), "_NET_WM_STATE", False); + net_wm_strut = XInternAtom(getXDisplay(), "_NET_WM_STRUT", False); + net_wm_icon_geometry = + XInternAtom(getXDisplay(), "_NET_WM_ICON_GEOMETRY", False); + net_wm_icon = XInternAtom(getXDisplay(), "_NET_WM_ICON", False); + net_wm_pid = XInternAtom(getXDisplay(), "_NET_WM_PID", False); + net_wm_handled_icons = + XInternAtom(getXDisplay(), "_NET_WM_HANDLED_ICONS", False); + net_wm_ping = XInternAtom(getXDisplay(), "_NET_WM_PING", False); +#endif // NEWWMSPEC + +#ifdef HAVE_GETPID + blackbox_pid = XInternAtom(getXDisplay(), "_BLACKBOX_PID", False); +#endif // HAVE_GETPID +} + + +bool Blackbox::validateWindow(Window window) { + XEvent event; + if (XCheckTypedWindowEvent(getXDisplay(), window, DestroyNotify, &event)) { + XPutBackEvent(getXDisplay(), &event); + + return False; + } + + return True; +} + + +BScreen *Blackbox::searchScreen(Window window) { + ScreenList::iterator it = screenList.begin(); + + for (; it != screenList.end(); ++it) { + BScreen *s = *it; + if (s->getRootWindow() == window) + return s; + } + + return (BScreen *) 0; +} + + +BlackboxWindow *Blackbox::searchWindow(Window window) { + WindowLookup::iterator it = windowSearchList.find(window); + if (it != windowSearchList.end()) + return it->second; + + return (BlackboxWindow*) 0; +} + + +BWindowGroup *Blackbox::searchGroup(Window window) { + GroupLookup::iterator it = groupSearchList.find(window); + if (it != groupSearchList.end()) + return it->second; + + return (BWindowGroup *) 0; +} + + +Basemenu *Blackbox::searchMenu(Window window) { + MenuLookup::iterator it = menuSearchList.find(window); + if (it != menuSearchList.end()) + return it->second; + + return (Basemenu*) 0; +} + + +Toolbar *Blackbox::searchToolbar(Window window) { + ToolbarLookup::iterator it = toolbarSearchList.find(window); + if (it != toolbarSearchList.end()) + return it->second; + + return (Toolbar*) 0; +} + + +Slit *Blackbox::searchSlit(Window window) { + SlitLookup::iterator it = slitSearchList.find(window); + if (it != slitSearchList.end()) + return it->second; + + return (Slit*) 0; +} + + +void Blackbox::saveWindowSearch(Window window, BlackboxWindow *data) { + windowSearchList.insert(WindowLookupPair(window, data)); +} + + +void Blackbox::saveGroupSearch(Window window, BWindowGroup *data) { + groupSearchList.insert(GroupLookupPair(window, data)); +} + + +void Blackbox::saveMenuSearch(Window window, Basemenu *data) { + menuSearchList.insert(MenuLookupPair(window, data)); +} + + +void Blackbox::saveToolbarSearch(Window window, Toolbar *data) { + toolbarSearchList.insert(ToolbarLookupPair(window, data)); +} + + +void Blackbox::saveSlitSearch(Window window, Slit *data) { + slitSearchList.insert(SlitLookupPair(window, data)); +} + + +void Blackbox::removeWindowSearch(Window window) { + windowSearchList.erase(window); +} + + +void Blackbox::removeGroupSearch(Window window) { + groupSearchList.erase(window); +} + + +void Blackbox::removeMenuSearch(Window window) { + menuSearchList.erase(window); +} + + +void Blackbox::removeToolbarSearch(Window window) { + toolbarSearchList.erase(window); +} + + +void Blackbox::removeSlitSearch(Window window) { + slitSearchList.erase(window); +} + + +void Blackbox::restart(const char *prog) { + shutdown(); + + if (prog) { + execlp(prog, prog, NULL); + perror(prog); + } + + // fall back in case the above execlp doesn't work + execvp(argv[0], argv); + string name = basename(argv[0]); + execvp(name.c_str(), argv); +} + + +void Blackbox::shutdown(void) { + BaseDisplay::shutdown(); + + XSetInputFocus(getXDisplay(), PointerRoot, None, CurrentTime); + + std::for_each(screenList.begin(), screenList.end(), + std::mem_fun(&BScreen::shutdown)); + + XSync(getXDisplay(), False); + + save_rc(); +} + + +void Blackbox::save_rc(void) { + XrmDatabase new_blackboxrc = (XrmDatabase) 0; + char rc_string[1024]; + + load_rc(); + + sprintf(rc_string, "session.menuFile: %s", getMenuFilename()); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.colorsPerChannel: %d", + resource.colors_per_channel); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.doubleClickInterval: %lu", + resource.double_click_interval); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.autoRaiseDelay: %lu", + ((resource.auto_raise_delay.tv_sec * 1000) + + (resource.auto_raise_delay.tv_usec / 1000))); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.cacheLife: %lu", resource.cache_life / 60000); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.cacheMax: %lu", resource.cache_max); + XrmPutLineResource(&new_blackboxrc, rc_string); + + ScreenList::iterator it = screenList.begin(); + for (; it != screenList.end(); ++it) { + BScreen *screen = *it; + int screen_number = screen->getScreenNumber(); + + char *placement = (char *) 0; + + switch (screen->getSlitPlacement()) { + case Slit::TopLeft: placement = "TopLeft"; break; + case Slit::CenterLeft: placement = "CenterLeft"; break; + case Slit::BottomLeft: placement = "BottomLeft"; break; + case Slit::TopCenter: placement = "TopCenter"; break; + case Slit::BottomCenter: placement = "BottomCenter"; break; + case Slit::TopRight: placement = "TopRight"; break; + case Slit::BottomRight: placement = "BottomRight"; break; + case Slit::CenterRight: default: placement = "CenterRight"; break; + } + + sprintf(rc_string, "session.screen%d.slit.placement: %s", screen_number, + placement); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.slit.direction: %s", screen_number, + ((screen->getSlitDirection() == Slit::Horizontal) ? "Horizontal" : + "Vertical")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.slit.onTop: %s", screen_number, + ((screen->getSlit()->isOnTop()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.slit.autoHide: %s", screen_number, + ((screen->getSlit()->doAutoHide()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.opaqueMove: %s", + ((screen->doOpaqueMove()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.imageDither: %s", + ((screen->getImageControl()->doDither()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.fullMaximization: %s", screen_number, + ((screen->doFullMax()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.focusNewWindows: %s", screen_number, + ((screen->doFocusNew()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.focusLastWindow: %s", screen_number, + ((screen->doFocusLast()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.rowPlacementDirection: %s", + screen_number, + ((screen->getRowPlacementDirection() == BScreen::LeftRight) ? + "LeftToRight" : "RightToLeft")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.colPlacementDirection: %s", + screen_number, + ((screen->getColPlacementDirection() == BScreen::TopBottom) ? + "TopToBottom" : "BottomToTop")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + switch (screen->getPlacementPolicy()) { + case BScreen::CascadePlacement: + placement = "CascadePlacement"; + break; + case BScreen::ColSmartPlacement: + placement = "ColSmartPlacement"; + break; + + case BScreen::RowSmartPlacement: + default: + placement = "RowSmartPlacement"; + break; + } + sprintf(rc_string, "session.screen%d.windowPlacement: %s", screen_number, + placement); + XrmPutLineResource(&new_blackboxrc, rc_string); + + string fmodel; + if (screen->isSloppyFocus()) { + fmodel = "SloppyFocus"; + if (screen->doAutoRaise()) fmodel += " AutoRaise"; + if (screen->doClickRaise()) fmodel += " ClickRaise"; + } else { + fmodel = "ClickToFocus"; + } + sprintf(rc_string, "session.screen%d.focusModel: %s", screen_number, + fmodel.c_str()); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.workspaces: %d", screen_number, + screen->getWorkspaceCount()); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.toolbar.onTop: %s", screen_number, + ((screen->getToolbar()->isOnTop()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.toolbar.autoHide: %s", + screen_number, + ((screen->getToolbar()->doAutoHide()) ? "True" : "False")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + switch (screen->getToolbarPlacement()) { + case Toolbar::TopLeft: placement = "TopLeft"; break; + case Toolbar::BottomLeft: placement = "BottomLeft"; break; + case Toolbar::TopCenter: placement = "TopCenter"; break; + case Toolbar::TopRight: placement = "TopRight"; break; + case Toolbar::BottomRight: placement = "BottomRight"; break; + case Toolbar::BottomCenter: default: placement = "BottomCenter"; break; + } + + sprintf(rc_string, "session.screen%d.toolbar.placement: %s", + screen_number, placement); + XrmPutLineResource(&new_blackboxrc, rc_string); + + load_rc(screen); + + // these are static, but may not be saved in the users .blackboxrc, + // writing these resources will allow the user to edit them at a later + // time... but loading the defaults before saving allows us to rewrite the + // users changes... + +#ifdef HAVE_STRFTIME + sprintf(rc_string, "session.screen%d.strftimeFormat: %s", screen_number, + screen->getStrftimeFormat()); + XrmPutLineResource(&new_blackboxrc, rc_string); +#else // !HAVE_STRFTIME + sprintf(rc_string, "session.screen%d.dateFormat: %s", screen_number, + ((screen->getDateFormat() == B_EuropeanDate) ? + "European" : "American")); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.clockFormat: %d", screen_number, + ((screen->isClock24Hour()) ? 24 : 12)); + XrmPutLineResource(&new_blackboxrc, rc_string); +#endif // HAVE_STRFTIME + + sprintf(rc_string, "session.screen%d.edgeSnapThreshold: %d", + screen_number, screen->getEdgeSnapThreshold()); + XrmPutLineResource(&new_blackboxrc, rc_string); + + sprintf(rc_string, "session.screen%d.toolbar.widthPercent: %d", + screen_number, screen->getToolbarWidthPercent()); + XrmPutLineResource(&new_blackboxrc, rc_string); + + // write out the user's workspace names + + string save_string = screen->getWorkspace(0)->getName(); + for (unsigned int i = 1; i < screen->getWorkspaceCount(); ++i) { + save_string += ','; + save_string += screen->getWorkspace(i)->getName(); + } + + char *resource_string = new char[save_string.length() + 48]; + sprintf(resource_string, "session.screen%d.workspaceNames: %s", + screen_number, save_string.c_str()); + XrmPutLineResource(&new_blackboxrc, resource_string); + + delete [] resource_string; + } + + XrmDatabase old_blackboxrc = XrmGetFileDatabase(rc_file.c_str()); + + XrmMergeDatabases(new_blackboxrc, &old_blackboxrc); + XrmPutFileDatabase(old_blackboxrc, rc_file.c_str()); + XrmDestroyDatabase(old_blackboxrc); +} + + +void Blackbox::load_rc(void) { + XrmDatabase database = (XrmDatabase) 0; + + database = XrmGetFileDatabase(rc_file.c_str()); + + XrmValue value; + char *value_type; + int int_value; + unsigned long long_value; + + if (XrmGetResource(database, "session.menuFile", "Session.MenuFile", + &value_type, &value)) { + resource.menu_file = expandTilde(value.addr); + } else { + resource.menu_file = DEFAULTMENU; + } + + resource.colors_per_channel = 4; + if (XrmGetResource(database, "session.colorsPerChannel", + "Session.ColorsPerChannel", &value_type, &value) && + sscanf(value.addr, "%d", &int_value) == 1) { + resource.colors_per_channel = int_value; + if (resource.colors_per_channel < 2) resource.colors_per_channel = 2; + if (resource.colors_per_channel > 6) resource.colors_per_channel = 6; + } + + if (XrmGetResource(database, "session.styleFile", "Session.StyleFile", + &value_type, &value)) + resource.style_file = expandTilde(value.addr); + else + resource.style_file = DEFAULTSTYLE; + + resource.double_click_interval = 250; + if (XrmGetResource(database, "session.doubleClickInterval", + "Session.DoubleClickInterval", &value_type, &value) && + sscanf(value.addr, "%lu", &long_value) == 1) { + resource.double_click_interval = long_value; + } + + resource.auto_raise_delay.tv_usec = 400; + if (XrmGetResource(database, "session.autoRaiseDelay", + "Session.AutoRaiseDelay", &value_type, &value) && + sscanf(value.addr, "%lu", &long_value) == 1) { + resource.auto_raise_delay.tv_usec = long_value; + } + + resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec / 1000; + resource.auto_raise_delay.tv_usec -= + (resource.auto_raise_delay.tv_sec * 1000); + resource.auto_raise_delay.tv_usec *= 1000; + + resource.cache_life = 5l; + if (XrmGetResource(database, "session.cacheLife", "Session.CacheLife", + &value_type, &value) && + sscanf(value.addr, "%lu", &long_value) == 1) { + resource.cache_life = long_value; + } + resource.cache_life *= 60000; + + resource.cache_max = 200; + if (XrmGetResource(database, "session.cacheMax", "Session.CacheMax", + &value_type, &value) && + sscanf(value.addr, "%lu", &long_value) == 1) { + resource.cache_max = long_value; + } +} + + +void Blackbox::load_rc(BScreen *screen) { + XrmDatabase database = (XrmDatabase) 0; + + database = XrmGetFileDatabase(rc_file.c_str()); + + XrmValue value; + char *value_type, name_lookup[1024], class_lookup[1024]; + int screen_number = screen->getScreenNumber(); + int int_value; + + sprintf(name_lookup, "session.screen%d.fullMaximization", screen_number); + sprintf(class_lookup, "Session.Screen%d.FullMaximization", screen_number); + screen->saveFullMax(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "true", value.size)) { + screen->saveFullMax(True); + } + + sprintf(name_lookup, "session.screen%d.focusNewWindows", screen_number); + sprintf(class_lookup, "Session.Screen%d.FocusNewWindows", screen_number); + screen->saveFocusNew(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "true", value.size)) { + screen->saveFocusNew(True); + } + + sprintf(name_lookup, "session.screen%d.focusLastWindow", screen_number); + sprintf(class_lookup, "Session.Screen%d.focusLastWindow", screen_number); + screen->saveFocusLast(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "true", value.size)) { + screen->saveFocusLast(True); + } + + sprintf(name_lookup, "session.screen%d.rowPlacementDirection", + screen_number); + sprintf(class_lookup, "Session.Screen%d.RowPlacementDirection", + screen_number); + screen->saveRowPlacementDirection(BScreen::LeftRight); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "righttoleft", value.size)) { + screen->saveRowPlacementDirection(BScreen::RightLeft); + } + + sprintf(name_lookup, "session.screen%d.colPlacementDirection", + screen_number); + sprintf(class_lookup, "Session.Screen%d.ColPlacementDirection", + screen_number); + screen->saveColPlacementDirection(BScreen::TopBottom); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "bottomtotop", value.size)) { + screen->saveColPlacementDirection(BScreen::BottomTop); + } + + sprintf(name_lookup, "session.screen%d.workspaces", screen_number); + sprintf(class_lookup, "Session.Screen%d.Workspaces", screen_number); + screen->saveWorkspaces(1); + if (XrmGetResource(database, name_lookup, class_lookup, + &value_type, &value) && + sscanf(value.addr, "%d", &int_value) == 1 && + int_value > 0 && int_value < 128) { + screen->saveWorkspaces(int_value); + } + + sprintf(name_lookup, "session.screen%d.toolbar.widthPercent", + screen_number); + sprintf(class_lookup, "Session.Screen%d.Toolbar.WidthPercent", + screen_number); + screen->saveToolbarWidthPercent(66); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + sscanf(value.addr, "%d", &int_value) == 1 && + int_value > 0 && int_value <= 100) { + screen->saveToolbarWidthPercent(int_value); + } + + sprintf(name_lookup, "session.screen%d.toolbar.placement", screen_number); + sprintf(class_lookup, "Session.Screen%d.Toolbar.Placement", screen_number); + screen->saveToolbarPlacement(Toolbar::BottomCenter); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value)) { + if (! strncasecmp(value.addr, "TopLeft", value.size)) + screen->saveToolbarPlacement(Toolbar::TopLeft); + else if (! strncasecmp(value.addr, "BottomLeft", value.size)) + screen->saveToolbarPlacement(Toolbar::BottomLeft); + else if (! strncasecmp(value.addr, "TopCenter", value.size)) + screen->saveToolbarPlacement(Toolbar::TopCenter); + else if (! strncasecmp(value.addr, "TopRight", value.size)) + screen->saveToolbarPlacement(Toolbar::TopRight); + else if (! strncasecmp(value.addr, "BottomRight", value.size)) + screen->saveToolbarPlacement(Toolbar::BottomRight); + } + screen->removeWorkspaceNames(); + + sprintf(name_lookup, "session.screen%d.workspaceNames", screen_number); + sprintf(class_lookup, "Session.Screen%d.WorkspaceNames", screen_number); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value)) { + string search = value.addr; + string::const_iterator it = search.begin(), + end = search.end(); + while (1) { + string::const_iterator tmp = it; // current string.begin() + it = std::find(tmp, end, ','); // look for comma between tmp and end + screen->addWorkspaceName(string(tmp, it)); // string = search[tmp:it] + if (it == end) break; + ++it; + } + } + + sprintf(name_lookup, "session.screen%d.toolbar.onTop", screen_number); + sprintf(class_lookup, "Session.Screen%d.Toolbar.OnTop", screen_number); + screen->saveToolbarOnTop(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "true", value.size)) { + screen->saveToolbarOnTop(True); + } + + sprintf(name_lookup, "session.screen%d.toolbar.autoHide", screen_number); + sprintf(class_lookup, "Session.Screen%d.Toolbar.autoHide", screen_number); + screen->saveToolbarAutoHide(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "true", value.size)) { + screen->saveToolbarAutoHide(True); + } + + sprintf(name_lookup, "session.screen%d.focusModel", screen_number); + sprintf(class_lookup, "Session.Screen%d.FocusModel", screen_number); + screen->saveSloppyFocus(True); + screen->saveAutoRaise(False); + screen->saveClickRaise(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value)) { + string fmodel = value.addr; + + if (fmodel.find("ClickToFocus") != string::npos) { + screen->saveSloppyFocus(False); + } else { + // must be sloppy + + if (fmodel.find("AutoRaise") != string::npos) + screen->saveAutoRaise(True); + if (fmodel.find("ClickRaise") != string::npos) + screen->saveClickRaise(True); + } + } + + sprintf(name_lookup, "session.screen%d.windowPlacement", screen_number); + sprintf(class_lookup, "Session.Screen%d.WindowPlacement", screen_number); + screen->savePlacementPolicy(BScreen::RowSmartPlacement); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value)) { + if (! strncasecmp(value.addr, "RowSmartPlacement", value.size)) + /* pass */; + else if (! strncasecmp(value.addr, "ColSmartPlacement", value.size)) + screen->savePlacementPolicy(BScreen::ColSmartPlacement); + else if (! strncasecmp(value.addr, "CascadePlacement", value.size)) + screen->savePlacementPolicy(BScreen::CascadePlacement); + } + + sprintf(name_lookup, "session.screen%d.slit.placement", screen_number); + sprintf(class_lookup, "Session.Screen%d.Slit.Placement", screen_number); + screen->saveSlitPlacement(Slit::CenterRight); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value)) { + if (! strncasecmp(value.addr, "TopLeft", value.size)) + screen->saveSlitPlacement(Slit::TopLeft); + else if (! strncasecmp(value.addr, "CenterLeft", value.size)) + screen->saveSlitPlacement(Slit::CenterLeft); + else if (! strncasecmp(value.addr, "BottomLeft", value.size)) + screen->saveSlitPlacement(Slit::BottomLeft); + else if (! strncasecmp(value.addr, "TopCenter", value.size)) + screen->saveSlitPlacement(Slit::TopCenter); + else if (! strncasecmp(value.addr, "BottomCenter", value.size)) + screen->saveSlitPlacement(Slit::BottomCenter); + else if (! strncasecmp(value.addr, "TopRight", value.size)) + screen->saveSlitPlacement(Slit::TopRight); + else if (! strncasecmp(value.addr, "BottomRight", value.size)) + screen->saveSlitPlacement(Slit::BottomRight); + } + + sprintf(name_lookup, "session.screen%d.slit.direction", screen_number); + sprintf(class_lookup, "Session.Screen%d.Slit.Direction", screen_number); + screen->saveSlitDirection(Slit::Vertical); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "Horizontal", value.size)) { + screen->saveSlitDirection(Slit::Horizontal); + } + + sprintf(name_lookup, "session.screen%d.slit.onTop", screen_number); + sprintf(class_lookup, "Session.Screen%d.Slit.OnTop", screen_number); + screen->saveSlitOnTop(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "True", value.size)) { + screen->saveSlitOnTop(True); + } + + sprintf(name_lookup, "session.screen%d.slit.autoHide", screen_number); + sprintf(class_lookup, "Session.Screen%d.Slit.AutoHide", screen_number); + screen->saveSlitAutoHide(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + ! strncasecmp(value.addr, "true", value.size)) { + screen->saveSlitAutoHide(True); + } + +#ifdef HAVE_STRFTIME + sprintf(name_lookup, "session.screen%d.strftimeFormat", screen_number); + sprintf(class_lookup, "Session.Screen%d.StrftimeFormat", screen_number); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value)) { + screen->saveStrftimeFormat(value.addr); + } else { + screen->saveStrftimeFormat("%I:%M %p"); + } +#else // HAVE_STRFTIME + sprintf(name_lookup, "session.screen%d.dateFormat", screen_number); + sprintf(class_lookup, "Session.Screen%d.DateFormat", screen_number); + screen->saveDateFormat(B_AmericanDate); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value)) { + if (! strncasecmp(value.addr, "european", value.size)) + screen->saveDateFormat(B_EuropeanDate); + } + + sprintf(name_lookup, "session.screen%d.clockFormat", screen_number); + sprintf(class_lookup, "Session.Screen%d.ClockFormat", screen_number); + screen->saveClock24Hour(False); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + sscanf(value.addr, "%d", &int_value) == 1 && int_value == 24) { + screen->saveClock24Hour(True); + } +#endif // HAVE_STRFTIME + + sprintf(name_lookup, "session.screen%d.edgeSnapThreshold", screen_number); + sprintf(class_lookup, "Session.Screen%d.EdgeSnapThreshold", screen_number); + if (XrmGetResource(database, name_lookup, class_lookup, &value_type, + &value) && + sscanf(value.addr, "%d", &int_value) == 1) { + screen->saveEdgeSnapThreshold(int_value); + } + + screen->saveImageDither(True); + if (XrmGetResource(database, "session.imageDither", "Session.ImageDither", + &value_type, &value) && + ! strncasecmp("false", value.addr, value.size)) { + screen->saveImageDither(False); + } + + screen->saveOpaqueMove(False); + if (XrmGetResource(database, "session.opaqueMove", "Session.OpaqueMove", + &value_type, &value) && + ! strncasecmp("true", value.addr, value.size)) { + screen->saveOpaqueMove(True); + } + + XrmDestroyDatabase(database); +} + + +void Blackbox::reload_rc(void) { + load_rc(); + reconfigure(); +} + + +void Blackbox::reconfigure(void) { + reconfigure_wait = True; + + if (! timer->isTiming()) timer->start(); +} + + +void Blackbox::real_reconfigure(void) { + XrmDatabase new_blackboxrc = (XrmDatabase) 0; + char *style = new char[resource.style_file.length() + 20]; + + sprintf(style, "session.styleFile: %s", getStyleFilename()); + XrmPutLineResource(&new_blackboxrc, style); + + delete [] style; + + XrmDatabase old_blackboxrc = XrmGetFileDatabase(rc_file.c_str()); + + XrmMergeDatabases(new_blackboxrc, &old_blackboxrc); + XrmPutFileDatabase(old_blackboxrc, rc_file.c_str()); + if (old_blackboxrc) XrmDestroyDatabase(old_blackboxrc); + + std::for_each(menuTimestamps.begin(), menuTimestamps.end(), + PointerAssassin()); + menuTimestamps.clear(); + + gcCache()->purge(); + + std::for_each(screenList.begin(), screenList.end(), + std::mem_fun(&BScreen::reconfigure)); +} + + +void Blackbox::checkMenu(void) { + bool reread = False; + MenuTimestampList::iterator it = menuTimestamps.begin(); + for(; it != menuTimestamps.end(); ++it) { + MenuTimestamp *tmp = *it; + struct stat buf; + + if (! stat(tmp->filename.c_str(), &buf)) { + if (tmp->timestamp != buf.st_ctime) + reread = True; + } else { + reread = True; + } + } + + if (reread) rereadMenu(); +} + + +void Blackbox::rereadMenu(void) { + reread_menu_wait = True; + + if (! timer->isTiming()) timer->start(); +} + + +void Blackbox::real_rereadMenu(void) { + std::for_each(menuTimestamps.begin(), menuTimestamps.end(), + PointerAssassin()); + menuTimestamps.clear(); + + std::for_each(screenList.begin(), screenList.end(), + std::mem_fun(&BScreen::rereadMenu)); +} + + +void Blackbox::saveStyleFilename(const string& filename) { + assert(! filename.empty()); + resource.style_file = filename; +} + + +void Blackbox::saveMenuFilename(const string& filename) { + assert(! filename.empty()); + bool found = False; + + MenuTimestampList::iterator it = menuTimestamps.begin(); + for (; it != menuTimestamps.end() && !found; ++it) { + if ((*it)->filename == filename) found = True; + } + if (! found) { + struct stat buf; + + if (! stat(filename.c_str(), &buf)) { + MenuTimestamp *ts = new MenuTimestamp; + + ts->filename = filename; + ts->timestamp = buf.st_ctime; + + menuTimestamps.push_back(ts); + } + } +} + + +void Blackbox::timeout(void) { + if (reconfigure_wait) + real_reconfigure(); + + if (reread_menu_wait) + real_rereadMenu(); + + reconfigure_wait = reread_menu_wait = False; +} + + +void Blackbox::setFocusedWindow(BlackboxWindow *win) { + if (focused_window && focused_window == win) // nothing to do + return; + + BScreen *old_screen = 0; + + if (focused_window) { + focused_window->setFocusFlag(False); + old_screen = focused_window->getScreen(); + } + + if (win && ! win->isIconic()) { + // the active screen is the one with the last focused window... + // this will keep focus on this screen no matter where the mouse goes, + // so multihead keybindings will continue to work on that screen until the + // user focuses a window on a different screen. + active_screen = win->getScreen(); + focused_window = win; + } else { + focused_window = 0; + if (! old_screen) { + if (active_screen) { + // set input focus to the toolbar of the screen with mouse + XSetInputFocus(getXDisplay(), + active_screen->getToolbar()->getWindowID(), + RevertToPointerRoot, CurrentTime); + } else { + // set input focus to the toolbar of the first managed screen + XSetInputFocus(getXDisplay(), + screenList.front()->getToolbar()->getWindowID(), + RevertToPointerRoot, CurrentTime); + } + } else { + // set input focus to the toolbar of the last screen + XSetInputFocus(getXDisplay(), old_screen->getToolbar()->getWindowID(), + RevertToPointerRoot, CurrentTime); + } + } + + if (active_screen && active_screen->isScreenManaged()) { + active_screen->getToolbar()->redrawWindowLabel(True); + active_screen->updateNetizenWindowFocus(); + } + + if (old_screen && old_screen != active_screen) { + old_screen->getToolbar()->redrawWindowLabel(True); + old_screen->updateNetizenWindowFocus(); + } +} diff --git a/src/blackbox.hh b/src/blackbox.hh new file mode 100644 index 00000000..b494039c --- /dev/null +++ b/src/blackbox.hh @@ -0,0 +1,410 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// blackbox.hh for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry +// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef __blackbox_hh +#define __blackbox_hh + +extern "C" { +#include +#include + +#ifdef HAVE_STDIO_H +# include +#endif // HAVE_STDIO_H + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else // !TIME_WITH_SYS_TIME +# ifdef HAVE_SYS_TIME_H +# include +# else // !HAVE_SYS_TIME_H +# include +# endif // HAVE_SYS_TIME_H +#endif // TIME_WITH_SYS_TIME +} + +#include +#include +#include + +#include "i18n.hh" +#include "BaseDisplay.hh" +#include "Timer.hh" + +#define AttribShaded (1l << 0) +#define AttribMaxHoriz (1l << 1) +#define AttribMaxVert (1l << 2) +#define AttribOmnipresent (1l << 3) +#define AttribWorkspace (1l << 4) +#define AttribStack (1l << 5) +#define AttribDecoration (1l << 6) + +#define StackTop (0) +#define StackNormal (1) +#define StackBottom (2) + +#define DecorNone (0) +#define DecorNormal (1) +#define DecorTiny (2) +#define DecorTool (3) + +struct BlackboxHints { + unsigned long flags, attrib, workspace, stack, decoration; +}; + +struct BlackboxAttributes { + unsigned long flags, attrib, workspace, stack, decoration; + int premax_x, premax_y; + unsigned int premax_w, premax_h; +}; + +#define PropBlackboxHintsElements (5) +#define PropBlackboxAttributesElements (9) + + +//forward declaration +class BScreen; +class Blackbox; +class BlackboxWindow; +class BWindowGroup; +class Basemenu; +class Toolbar; +class Slit; + +extern I18n i18n; + +class Blackbox : public BaseDisplay, public TimeoutHandler { +private: + struct BCursor { + Cursor session, move, ll_angle, lr_angle; + }; + BCursor cursor; + + struct MenuTimestamp { + std::string filename; + time_t timestamp; + }; + + struct BResource { + Time double_click_interval; + + std::string menu_file, style_file; + int colors_per_channel; + timeval auto_raise_delay; + unsigned long cache_life, cache_max; + } resource; + + typedef std::map WindowLookup; + typedef WindowLookup::value_type WindowLookupPair; + WindowLookup windowSearchList; + + typedef std::map GroupLookup; + typedef GroupLookup::value_type GroupLookupPair; + GroupLookup groupSearchList; + + typedef std::map MenuLookup; + typedef MenuLookup::value_type MenuLookupPair; + MenuLookup menuSearchList; + + typedef std::map ToolbarLookup; + typedef ToolbarLookup::value_type ToolbarLookupPair; + ToolbarLookup toolbarSearchList; + + typedef std::map SlitLookup; + typedef SlitLookup::value_type SlitLookupPair; + SlitLookup slitSearchList; + + typedef std::list MenuTimestampList; + MenuTimestampList menuTimestamps; + + typedef std::list ScreenList; + ScreenList screenList; + + BScreen *active_screen; + BlackboxWindow *focused_window; + BTimer *timer; + + bool no_focus, reconfigure_wait, reread_menu_wait; + Time last_time; + char **argv; + std::string rc_file; + + Atom xa_wm_colormap_windows, xa_wm_protocols, xa_wm_state, + xa_wm_delete_window, xa_wm_take_focus, xa_wm_change_state, + motif_wm_hints; + + // NETAttributes + Atom blackbox_attributes, blackbox_change_attributes, blackbox_hints; +#ifdef HAVE_GETPID + Atom blackbox_pid; +#endif // HAVE_GETPID + + // NETStructureMessages + Atom blackbox_structure_messages, blackbox_notify_startup, + blackbox_notify_window_add, blackbox_notify_window_del, + blackbox_notify_window_focus, blackbox_notify_current_workspace, + blackbox_notify_workspace_count, blackbox_notify_window_raise, + blackbox_notify_window_lower; + + // message_types for client -> wm messages + Atom blackbox_change_workspace, blackbox_change_window_focus, + blackbox_cycle_window_focus; + +#ifdef NEWWMSPEC + // root window properties + Atom net_supported, net_client_list, net_client_list_stacking, + net_number_of_desktops, net_desktop_geometry, net_desktop_viewport, + net_current_desktop, net_desktop_names, net_active_window, net_workarea, + net_supporting_wm_check, net_virtual_roots; + + // root window messages + Atom net_close_window, net_wm_moveresize; + + // application window properties + Atom net_properties, net_wm_name, net_wm_desktop, net_wm_window_type, + net_wm_state, net_wm_strut, net_wm_icon_geometry, net_wm_icon, net_wm_pid, + net_wm_handled_icons; + + // application protocols + Atom net_wm_ping; +#endif // NEWWMSPEC + + Blackbox(const Blackbox&); + Blackbox& operator=(const Blackbox&); + + void load_rc(void); + void save_rc(void); + void reload_rc(void); + void real_rereadMenu(void); + void real_reconfigure(void); + + void init_icccm(void); + + virtual void process_event(XEvent *); + + +public: + Blackbox(char **m_argv, char *dpy_name = 0, char *rc = 0); + virtual ~Blackbox(void); + + Basemenu *searchMenu(Window window); + BWindowGroup *searchGroup(Window window); + BlackboxWindow *searchWindow(Window window); + BScreen *searchScreen(Window window); + Toolbar *searchToolbar(Window); + Slit *searchSlit(Window); + + void saveMenuSearch(Window window, Basemenu *data); + void saveWindowSearch(Window window, BlackboxWindow *data); + void saveGroupSearch(Window window, BWindowGroup *data); + void saveToolbarSearch(Window window, Toolbar *data); + void saveSlitSearch(Window window, Slit *data); + void removeMenuSearch(Window window); + void removeWindowSearch(Window window); + void removeGroupSearch(Window window); + void removeToolbarSearch(Window window); + void removeSlitSearch(Window window); + + inline BlackboxWindow *getFocusedWindow(void) { return focused_window; } + + inline const Time &getDoubleClickInterval(void) const + { return resource.double_click_interval; } + inline const Time &getLastTime(void) const { return last_time; } + + inline const char *getStyleFilename(void) const + { return resource.style_file.c_str(); } + inline const char *getMenuFilename(void) const + { return resource.menu_file.c_str(); } + + inline int getColorsPerChannel(void) const + { return resource.colors_per_channel; } + + inline const timeval &getAutoRaiseDelay(void) const + { return resource.auto_raise_delay; } + + inline unsigned long getCacheLife(void) const + { return resource.cache_life; } + inline unsigned long getCacheMax(void) const + { return resource.cache_max; } + + inline void setNoFocus(bool f) { no_focus = f; } + + inline Cursor getSessionCursor(void) const + { return cursor.session; } + inline Cursor getMoveCursor(void) const + { return cursor.move; } + inline Cursor getLowerLeftAngleCursor(void) const + { return cursor.ll_angle; } + inline Cursor getLowerRightAngleCursor(void) const + { return cursor.lr_angle; } + + void setFocusedWindow(BlackboxWindow *w); + void shutdown(void); + void load_rc(BScreen *screen); + void saveStyleFilename(const std::string& filename); + void saveMenuFilename(const std::string& filename); + void restart(const char *prog = 0); + void reconfigure(void); + void rereadMenu(void); + void checkMenu(void); + + bool validateWindow(Window window); + + virtual bool handleSignal(int sig); + + virtual void timeout(void); + +#ifndef HAVE_STRFTIME + enum { B_AmericanDate = 1, B_EuropeanDate }; +#endif // HAVE_STRFTIME + +#ifdef HAVE_GETPID + inline Atom getBlackboxPidAtom(void) const { return blackbox_pid; } +#endif // HAVE_GETPID + + inline Atom getWMChangeStateAtom(void) const + { return xa_wm_change_state; } + inline Atom getWMStateAtom(void) const + { return xa_wm_state; } + inline Atom getWMDeleteAtom(void) const + { return xa_wm_delete_window; } + inline Atom getWMProtocolsAtom(void) const + { return xa_wm_protocols; } + inline Atom getWMTakeFocusAtom(void) const + { return xa_wm_take_focus; } + inline Atom getWMColormapAtom(void) const + { return xa_wm_colormap_windows; } + inline Atom getMotifWMHintsAtom(void) const + { return motif_wm_hints; } + + // this atom is for normal app->WM hints about decorations, stacking, + // starting workspace etc... + inline Atom getBlackboxHintsAtom(void) const + { return blackbox_hints;} + + // these atoms are for normal app->WM interaction beyond the scope of the + // ICCCM... + inline Atom getBlackboxAttributesAtom(void) const + { return blackbox_attributes; } + inline Atom getBlackboxChangeAttributesAtom(void) const + { return blackbox_change_attributes; } + + // these atoms are for window->WM interaction, with more control and + // information on window "structure"... common examples are + // notifying apps when windows are raised/lowered... when the user changes + // workspaces... i.e. "pager talk" + inline Atom getBlackboxStructureMessagesAtom(void) const + { return blackbox_structure_messages; } + + // *Notify* portions of the NETStructureMessages protocol + inline Atom getBlackboxNotifyStartupAtom(void) const + { return blackbox_notify_startup; } + inline Atom getBlackboxNotifyWindowAddAtom(void) const + { return blackbox_notify_window_add; } + inline Atom getBlackboxNotifyWindowDelAtom(void) const + { return blackbox_notify_window_del; } + inline Atom getBlackboxNotifyWindowFocusAtom(void) const + { return blackbox_notify_window_focus; } + inline Atom getBlackboxNotifyCurrentWorkspaceAtom(void) const + { return blackbox_notify_current_workspace; } + inline Atom getBlackboxNotifyWorkspaceCountAtom(void) const + { return blackbox_notify_workspace_count; } + inline Atom getBlackboxNotifyWindowRaiseAtom(void) const + { return blackbox_notify_window_raise; } + inline Atom getBlackboxNotifyWindowLowerAtom(void) const + { return blackbox_notify_window_lower; } + + // atoms to change that request changes to the desktop environment during + // runtime... these messages can be sent by any client... as the sending + // client window id is not included in the ClientMessage event... + inline Atom getBlackboxChangeWorkspaceAtom(void) const + { return blackbox_change_workspace; } + inline Atom getBlackboxChangeWindowFocusAtom(void) const + { return blackbox_change_window_focus; } + inline Atom getBlackboxCycleWindowFocusAtom(void) const + { return blackbox_cycle_window_focus; } + +#ifdef NEWWMSPEC + // root window properties + inline Atom getNETSupportedAtom(void) const + { return net_supported; } + inline Atom getNETClientListAtom(void) const + { return net_client_list; } + inline Atom getNETClientListStackingAtom(void) const + { return net_client_list_stacking; } + inline Atom getNETNumberOfDesktopsAtom(void) const + { return net_number_of_desktops; } + inline Atom getNETDesktopGeometryAtom(void) const + { return net_desktop_geometry; } + inline Atom getNETDesktopViewportAtom(void) const + { return net_desktop_viewport; } + inline Atom getNETCurrentDesktopAtom(void) const + { return net_current_desktop; } + inline Atom getNETDesktopNamesAtom(void) const + { return net_desktop_names; } + inline Atom getNETActiveWindowAtom(void) const + { return net_active_window; } + inline Atom getNETWorkareaAtom(void) const + { return net_workarea; } + inline Atom getNETSupportingWMCheckAtom(void) const + { return net_supporting_wm_check; } + inline Atom getNETVirtualRootsAtom(void) const + { return net_virtual_roots; } + + // root window messages + inline Atom getNETCloseWindowAtom(void) const + { return net_close_window; } + inline Atom getNETWMMoveResizeAtom(void) const + { return net_wm_moveresize; } + + // application window properties + inline Atom getNETPropertiesAtom(void) const + { return net_properties; } + inline Atom getNETWMNameAtom(void) const + { return net_wm_name; } + inline Atom getNETWMDesktopAtom(void) const + { return net_wm_desktop; } + inline Atom getNETWMWindowTypeAtom(void) const + { return net_wm_window_type; } + inline Atom getNETWMStateAtom(void) const + { return net_wm_state; } + inline Atom getNETWMStrutAtom(void) const + { return net_wm_strut; } + inline Atom getNETWMIconGeometryAtom(void) const + { return net_wm_icon_geometry; } + inline Atom getNETWMIconAtom(void) const + { return net_wm_icon; } + inline Atom getNETWMPidAtom(void) const + { return net_wm_pid; } + inline Atom getNETWMHandledIconsAtom(void) const + { return net_wm_handled_icons; } + + // application protocols + inline Atom getNETWMPingAtom(void) const + { return net_wm_ping; } +#endif // NEWWMSPEC +}; + + +#endif // __blackbox_hh diff --git a/src/bsd-snprintf.c b/src/bsd-snprintf.c deleted file mode 100644 index 4716ee29..00000000 --- a/src/bsd-snprintf.c +++ /dev/null @@ -1,788 +0,0 @@ -/************************************************************** - * Original: - * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 - * A bombproof version of doprnt (dopr) included. - * Sigh. This sort of thing is always nasty do deal with. Note that - * the version here does not include floating point... - * - * snprintf() is used instead of sprintf() as it does limit checks - * for string length. This covers a nasty loophole. - * - * The other functions are there to prevent NULL pointers from - * causing nast effects. - * - * More Recently: - * Brandon Long 9/15/96 for mutt 0.43 - * This was ugly. It is still ugly. I opted out of floating point - * numbers, but the formatter understands just about everything - * from the normal C string format, at least as far as I can tell from - * the Solaris 2.5 printf(3S) man page. - * - * Brandon Long 10/22/97 for mutt 0.87.1 - * Ok, added some minimal floating point support, which means this - * probably requires libm on most operating systems. Don't yet - * support the exponent (e,E) and sigfig (g,G). Also, fmtint() - * was pretty badly broken, it just wasn't being exercised in ways - * which showed it, so that's been fixed. Also, formated the code - * to mutt conventions, and removed dead code left over from the - * original. Also, there is now a builtin-test, just compile with: - * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm - * and run snprintf for results. - * - * Thomas Roessler 01/27/98 for mutt 0.89i - * The PGP code was using unsigned hexadecimal formats. - * Unfortunately, unsigned formats simply didn't work. - * - * Michael Elkins 03/05/98 for mutt 0.90.8 - * The original code assumed that both snprintf() and vsnprintf() were - * missing. Some systems only have snprintf() but not vsnprintf(), so - * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. - * - **************************************************************/ - -#include "config.h" - -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) - -#include -# include -#include - -/* Define this as a fall through, HAVE_STDARG_H is probably already set */ - -#define HAVE_VARARGS_H - -/* varargs declarations: */ - -#if defined(HAVE_STDARG_H) -# include -# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ -# define VA_LOCAL_DECL va_list ap -# define VA_START(f) va_start(ap, f) -# define VA_SHIFT(v,t) ; /* no-op for ANSI */ -# define VA_END va_end(ap) -#else -# if defined(HAVE_VARARGS_H) -# include -# undef HAVE_STDARGS -# define VA_LOCAL_DECL va_list ap -# define VA_START(f) va_start(ap) /* f is ignored! */ -# define VA_SHIFT(v,t) v = va_arg(ap,t) -# define VA_END va_end(ap) -# else -/*XX ** NO VARARGS ** XX*/ -# endif -#endif - -/*int snprintf (char *str, size_t count, const char *fmt, ...);*/ -/*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/ - -static void dopr (char *buffer, size_t maxlen, const char *format, - va_list args); -static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max); -static void fmtint (char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags); -static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, - long double fvalue, int min, int max, int flags); -static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); - -/* - * dopr(): poor man's version of doprintf - */ - -/* format read states */ -#define DP_S_DEFAULT 0 -#define DP_S_FLAGS 1 -#define DP_S_MIN 2 -#define DP_S_DOT 3 -#define DP_S_MAX 4 -#define DP_S_MOD 5 -#define DP_S_CONV 6 -#define DP_S_DONE 7 - -/* format flags - Bits */ -#define DP_F_MINUS (1 << 0) -#define DP_F_PLUS (1 << 1) -#define DP_F_SPACE (1 << 2) -#define DP_F_NUM (1 << 3) -#define DP_F_ZERO (1 << 4) -#define DP_F_UP (1 << 5) -#define DP_F_UNSIGNED (1 << 6) - -/* Conversion Flags */ -#define DP_C_SHORT 1 -#define DP_C_LONG 2 -#define DP_C_LDOUBLE 3 - -#define char_to_int(p) (p - '0') -#define MAX(p,q) ((p >= q) ? p : q) - -static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) -{ - char ch; - long value; - long double fvalue; - char *strvalue; - int min; - int max; - int state; - int flags; - int cflags; - size_t currlen; - - state = DP_S_DEFAULT; - currlen = flags = cflags = min = 0; - max = -1; - ch = *format++; - - while (state != DP_S_DONE) - { - if ((ch == '\0') || (currlen >= maxlen)) - state = DP_S_DONE; - - switch(state) - { - case DP_S_DEFAULT: - if (ch == '%') - state = DP_S_FLAGS; - else - dopr_outch (buffer, &currlen, maxlen, ch); - ch = *format++; - break; - case DP_S_FLAGS: - switch (ch) - { - case '-': - flags |= DP_F_MINUS; - ch = *format++; - break; - case '+': - flags |= DP_F_PLUS; - ch = *format++; - break; - case ' ': - flags |= DP_F_SPACE; - ch = *format++; - break; - case '#': - flags |= DP_F_NUM; - ch = *format++; - break; - case '0': - flags |= DP_F_ZERO; - ch = *format++; - break; - default: - state = DP_S_MIN; - break; - } - break; - case DP_S_MIN: - if (isdigit((unsigned char)ch)) - { - min = 10*min + char_to_int (ch); - ch = *format++; - } - else if (ch == '*') - { - min = va_arg (args, int); - ch = *format++; - state = DP_S_DOT; - } - else - state = DP_S_DOT; - break; - case DP_S_DOT: - if (ch == '.') - { - state = DP_S_MAX; - ch = *format++; - } - else - state = DP_S_MOD; - break; - case DP_S_MAX: - if (isdigit((unsigned char)ch)) - { - if (max < 0) - max = 0; - max = 10*max + char_to_int (ch); - ch = *format++; - } - else if (ch == '*') - { - max = va_arg (args, int); - ch = *format++; - state = DP_S_MOD; - } - else - state = DP_S_MOD; - break; - case DP_S_MOD: - /* Currently, we don't support Long Long, bummer */ - switch (ch) - { - case 'h': - cflags = DP_C_SHORT; - ch = *format++; - break; - case 'l': - cflags = DP_C_LONG; - ch = *format++; - break; - case 'L': - cflags = DP_C_LDOUBLE; - ch = *format++; - break; - default: - break; - } - state = DP_S_CONV; - break; - case DP_S_CONV: - switch (ch) - { - case 'd': - case 'i': - if (cflags == DP_C_SHORT) - value = va_arg (args, short int); - else if (cflags == DP_C_LONG) - value = va_arg (args, long int); - else - value = va_arg (args, int); - fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; - case 'o': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned short int); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else - value = va_arg (args, unsigned int); - fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); - break; - case 'u': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned short int); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else - value = va_arg (args, unsigned int); - fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; - case 'X': - flags |= DP_F_UP; - case 'x': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned short int); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else - value = va_arg (args, unsigned int); - fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); - break; - case 'f': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, long double); - else - fvalue = va_arg (args, double); - /* um, floating point? */ - fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); - break; - case 'E': - flags |= DP_F_UP; - case 'e': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, long double); - else - fvalue = va_arg (args, double); - break; - case 'G': - flags |= DP_F_UP; - case 'g': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, long double); - else - fvalue = va_arg (args, double); - break; - case 'c': - dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); - break; - case 's': - strvalue = va_arg (args, char *); - if (max < 0) - max = maxlen; /* ie, no max */ - fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); - break; - case 'p': - strvalue = va_arg (args, void *); - fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); - break; - case 'n': - if (cflags == DP_C_SHORT) - { - short int *num; - num = va_arg (args, short int *); - *num = currlen; - } - else if (cflags == DP_C_LONG) - { - long int *num; - num = va_arg (args, long int *); - *num = currlen; - } - else - { - int *num; - num = va_arg (args, int *); - *num = currlen; - } - break; - case '%': - dopr_outch (buffer, &currlen, maxlen, ch); - break; - case 'w': - /* not supported yet, treat as next char */ - ch = *format++; - break; - default: - /* Unknown, skip */ - break; - } - ch = *format++; - state = DP_S_DEFAULT; - flags = cflags = min = 0; - max = -1; - break; - case DP_S_DONE: - break; - default: - /* hmm? */ - break; /* some picky compilers need this */ - } - } - if (currlen < maxlen - 1) - buffer[currlen] = '\0'; - else - buffer[maxlen - 1] = '\0'; -} - -static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max) -{ - int padlen, strln; /* amount to pad */ - int cnt = 0; - - if (value == 0) - { - value = ""; - } - - for (strln = 0; value[strln]; ++strln); /* strlen */ - padlen = min - strln; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justify */ - - while ((padlen > 0) && (cnt < max)) - { - dopr_outch (buffer, currlen, maxlen, ' '); - --padlen; - ++cnt; - } - while (*value && (cnt < max)) - { - dopr_outch (buffer, currlen, maxlen, *value++); - ++cnt; - } - while ((padlen < 0) && (cnt < max)) - { - dopr_outch (buffer, currlen, maxlen, ' '); - ++padlen; - ++cnt; - } -} - -/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ - -static void fmtint (char *buffer, size_t *currlen, size_t maxlen, - long value, int base, int min, int max, int flags) -{ - int signvalue = 0; - unsigned long uvalue; - char convert[20]; - int place = 0; - int spadlen = 0; /* amount to space pad */ - int zpadlen = 0; /* amount to zero pad */ - int caps = 0; - - if (max < 0) - max = 0; - - uvalue = value; - - if(!(flags & DP_F_UNSIGNED)) - { - if( value < 0 ) { - signvalue = '-'; - uvalue = -value; - } - else - if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; - else - if (flags & DP_F_SPACE) - signvalue = ' '; - } - - if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ - - do { - convert[place++] = - (caps? "0123456789ABCDEF":"0123456789abcdef") - [uvalue % (unsigned)base ]; - uvalue = (uvalue / (unsigned)base ); - } while(uvalue && (place < 20)); - if (place == 20) place--; - convert[place] = 0; - - zpadlen = max - place; - spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); - if (zpadlen < 0) zpadlen = 0; - if (spadlen < 0) spadlen = 0; - if (flags & DP_F_ZERO) - { - zpadlen = MAX(zpadlen, spadlen); - spadlen = 0; - } - if (flags & DP_F_MINUS) - spadlen = -spadlen; /* Left Justifty */ - -#ifdef DEBUG_SNPRINTF - dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", - zpadlen, spadlen, min, max, place)); -#endif - - /* Spaces */ - while (spadlen > 0) - { - dopr_outch (buffer, currlen, maxlen, ' '); - --spadlen; - } - - /* Sign */ - if (signvalue) - dopr_outch (buffer, currlen, maxlen, signvalue); - - /* Zeros */ - if (zpadlen > 0) - { - while (zpadlen > 0) - { - dopr_outch (buffer, currlen, maxlen, '0'); - --zpadlen; - } - } - - /* Digits */ - while (place > 0) - dopr_outch (buffer, currlen, maxlen, convert[--place]); - - /* Left Justified spaces */ - while (spadlen < 0) { - dopr_outch (buffer, currlen, maxlen, ' '); - ++spadlen; - } -} - -static long double abs_val (long double value) -{ - long double result = value; - - if (value < 0) - result = -value; - - return result; -} - -static long double pow10 (int exp) -{ - long double result = 1; - - while (exp) - { - result *= 10; - exp--; - } - - return result; -} - -static long round (long double value) -{ - long intpart; - - intpart = value; - value = value - intpart; - if (value >= 0.5) - intpart++; - - return intpart; -} - -static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, - long double fvalue, int min, int max, int flags) -{ - int signvalue = 0; - long double ufvalue; - char iconvert[20]; - char fconvert[20]; - int iplace = 0; - int fplace = 0; - int padlen = 0; /* amount to pad */ - int zpadlen = 0; - int caps = 0; - long intpart; - long fracpart; - - /* - * AIX manpage says the default is 0, but Solaris says the default - * is 6, and sprintf on AIX defaults to 6 - */ - if (max < 0) - max = 6; - - ufvalue = abs_val (fvalue); - - if (fvalue < 0) - signvalue = '-'; - else - if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; - else - if (flags & DP_F_SPACE) - signvalue = ' '; - -#if 0 - if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ -#endif - - intpart = ufvalue; - - /* - * Sorry, we only support 9 digits past the decimal because of our - * conversion method - */ - if (max > 9) - max = 9; - - /* We "cheat" by converting the fractional part to integer by - * multiplying by a factor of 10 - */ - fracpart = round ((pow10 (max)) * (ufvalue - intpart)); - - if (fracpart >= pow10 (max)) - { - intpart++; - fracpart -= pow10 (max); - } - -#ifdef DEBUG_SNPRINTF - dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); -#endif - - /* Convert integer part */ - do { - iconvert[iplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; - intpart = (intpart / 10); - } while(intpart && (iplace < 20)); - if (iplace == 20) iplace--; - iconvert[iplace] = 0; - - /* Convert fractional part */ - do { - fconvert[fplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; - fracpart = (fracpart / 10); - } while(fracpart && (fplace < 20)); - if (fplace == 20) fplace--; - fconvert[fplace] = 0; - - /* -1 for decimal point, another -1 if we are printing a sign */ - padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); - zpadlen = max - fplace; - if (zpadlen < 0) - zpadlen = 0; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; /* Left Justifty */ - - if ((flags & DP_F_ZERO) && (padlen > 0)) - { - if (signvalue) - { - dopr_outch (buffer, currlen, maxlen, signvalue); - --padlen; - signvalue = 0; - } - while (padlen > 0) - { - dopr_outch (buffer, currlen, maxlen, '0'); - --padlen; - } - } - while (padlen > 0) - { - dopr_outch (buffer, currlen, maxlen, ' '); - --padlen; - } - if (signvalue) - dopr_outch (buffer, currlen, maxlen, signvalue); - - while (iplace > 0) - dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); - - /* - * Decimal point. This should probably use locale to find the correct - * char to print out. - */ - dopr_outch (buffer, currlen, maxlen, '.'); - - while (fplace > 0) - dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); - - while (zpadlen > 0) - { - dopr_outch (buffer, currlen, maxlen, '0'); - --zpadlen; - } - - while (padlen < 0) - { - dopr_outch (buffer, currlen, maxlen, ' '); - ++padlen; - } -} - -static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) -{ - if (*currlen < maxlen) - buffer[(*currlen)++] = c; -} -#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ - -#ifndef HAVE_VSNPRINTF -int vsnprintf (char *str, size_t count, const char *fmt, va_list args) -{ - str[0] = 0; - dopr(str, count, fmt, args); - return(strlen(str)); -} -#endif /* !HAVE_VSNPRINTF */ - -#ifndef HAVE_SNPRINTF -/* VARARGS3 */ -#ifdef HAVE_STDARGS -int snprintf (char *str,size_t count,const char *fmt,...) -#else -int snprintf (va_alist) va_dcl -#endif -{ -#ifndef HAVE_STDARGS - char *str; - size_t count; - char *fmt; -#endif - VA_LOCAL_DECL; - - VA_START (fmt); - VA_SHIFT (str, char *); - VA_SHIFT (count, size_t ); - VA_SHIFT (fmt, char *); - (void) vsnprintf(str, count, fmt, ap); - VA_END; - return(strlen(str)); -} - -#ifdef TEST_SNPRINTF -#ifndef LONG_STRING -#define LONG_STRING 1024 -#endif -int main (void) -{ - char buf1[LONG_STRING]; - char buf2[LONG_STRING]; - char *fp_fmt[] = { - "%-1.5f", - "%1.5f", - "%123.9f", - "%10.5f", - "% 10.5f", - "%+22.9f", - "%+4.9f", - "%01.3f", - "%4f", - "%3.1f", - "%3.2f", - NULL - }; - double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, - 0.9996, 1.996, 4.136, 0}; - char *int_fmt[] = { - "%-1.5d", - "%1.5d", - "%123.9d", - "%5.5d", - "%10.5d", - "% 10.5d", - "%+22.33d", - "%01.3d", - "%4d", - NULL - }; - long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; - int x, y; - int fail = 0; - int num = 0; - - printf ("Testing snprintf format codes against system sprintf...\n"); - - for (x = 0; fp_fmt[x] != NULL ; x++) - for (y = 0; fp_nums[y] != 0 ; y++) - { - snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); - sprintf (buf2, fp_fmt[x], fp_nums[y]); - if (strcmp (buf1, buf2)) - { - printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", - fp_fmt[x], buf1, buf2); - fail++; - } - num++; - } - - for (x = 0; int_fmt[x] != NULL ; x++) - for (y = 0; int_nums[y] != 0 ; y++) - { - snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); - sprintf (buf2, int_fmt[x], int_nums[y]); - if (strcmp (buf1, buf2)) - { - printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", - int_fmt[x], buf1, buf2); - fail++; - } - num++; - } - printf ("%d tests failed out of %d.\n", fail, num); -} -#endif /* SNPRINTF_TEST */ - -#endif /* !HAVE_SNPRINTF */ diff --git a/src/bsd-snprintf.h b/src/bsd-snprintf.h deleted file mode 100644 index ed7a21c9..00000000 --- a/src/bsd-snprintf.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _BSD_SNPRINTF_H -#define _BSD_SNPRINTF_H - -#include "config.h" - -#include /* For size_t */ - -#ifndef HAVE_SNPRINTF -int snprintf(char *str, size_t count, const char *fmt, ...); -#endif /* !HAVE_SNPRINTF */ - -#ifndef HAVE_VSNPRINTF -int vsnprintf(char *str, size_t count, const char *fmt, va_list args); -#endif /* !HAVE_SNPRINTF */ - - -#endif /* _BSD_SNPRINTF_H */ diff --git a/src/i18n.cc b/src/i18n.cc index 718ee4e7..0eb0a911 100644 --- a/src/i18n.cc +++ b/src/i18n.cc @@ -1,5 +1,5 @@ // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -// i18n.cc for Openbox +// i18n.cc for Blackbox - an X11 Window manager // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // @@ -46,11 +46,17 @@ extern "C" { } #include +using std::string; -#include "i18n.h" +#include "i18n.hh" -I18n::I18n(const char *catalog) { - mb = false; + +// the rest of bb source uses True and False from X, so we continue that +#define True true +#define False false + +I18n::I18n(void) { + mb = False; #ifdef HAVE_SETLOCALE locale = setlocale(LC_ALL, ""); if (! locale) { @@ -61,7 +67,7 @@ I18n::I18n(const char *catalog) { } else { // MB_CUR_MAX returns the size of a char in the current locale if (MB_CUR_MAX > 1) - mb = true; + mb = True; // truncate any encoding off the end of the locale char *l = strchr(locale, '@'); if (l) *l = '\0'; @@ -73,12 +79,10 @@ I18n::I18n(const char *catalog) { catalog_fd = (nl_catd) -1; #endif #endif // HAVE_SETLOCALE - if (catalog) - openCatalog(catalog); } -I18n::~I18n() { +I18n::~I18n(void) { #if defined(NLS) && defined(HAVE_CATCLOSE) if (catalog_fd != (nl_catd) -1) catclose(catalog_fd); @@ -86,9 +90,9 @@ I18n::~I18n() { } -#if defined(NLS) && defined(HAVE_CATOPEN) void I18n::openCatalog(const char *catalog) { - std::string catalog_filename = LOCALEPATH; +#if defined(NLS) && defined(HAVE_CATOPEN) + string catalog_filename = LOCALEPATH; catalog_filename += '/'; catalog_filename += locale; catalog_filename += '/'; @@ -102,21 +106,14 @@ void I18n::openCatalog(const char *catalog) { if (catalog_fd == (nl_catd) -1) fprintf(stderr, "failed to open catalog, using default messages\n"); -} -#else -void I18n::openCatalog(const char *) { -} #endif // HAVE_CATOPEN +} -#if defined(NLS) && defined(HAVE_CATGETS) const char* I18n::operator()(int set, int msg, const char *msgString) const { +#if defined(NLS) && defined(HAVE_CATGETS) if (catalog_fd != (nl_catd) -1) return catgets(catalog_fd, set, msg, msgString); else +#endif return msgString; } -#else -const char* I18n::operator()(int, int, const char *msgString) const { - return msgString; -} -#endif diff --git a/src/i18n.h b/src/i18n.hh similarity index 92% rename from src/i18n.h rename to src/i18n.hh index d8d29a4a..b86d9d80 100644 --- a/src/i18n.h +++ b/src/i18n.hh @@ -1,5 +1,5 @@ // -*- mode: C++; indent-tabs-mode: nil; -*- -// i18n.hh for Openbox +// i18n.hh for Blackbox - an X11 Window manager // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // @@ -27,7 +27,7 @@ // always include this just for the #defines // this keeps the calls to i18n->getMessage clean, otherwise we have to // add ifdefs to every call to getMessage -#include "../nls/openbox-nls.h" +#include "../nls/blackbox-nls.hh" extern "C" { #ifdef HAVE_LOCALE_H @@ -49,8 +49,8 @@ private: #endif public: - I18n(const char *catalog = 0); - ~I18n(); + I18n(void); + ~I18n(void); inline bool multibyte(void) const { return mb; } @@ -58,6 +58,6 @@ public: void openCatalog(const char *catalog); }; -extern I18n i18n; // located in main.cc +extern I18n i18n; #endif // __i18n_h diff --git a/src/main.cc b/src/main.cc index 5cf68b42..a0edb83f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,5 +1,6 @@ -// main.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry +// -*- mode: C++; indent-tabs-mode: nil; -*- +// main.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) // // Permission is hereby granted, free of charge, to any person obtaining a @@ -20,27 +21,22 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - #include "../version.h" #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H +extern "C" { #ifdef HAVE_STDIO_H # include #endif // HAVE_STDIO_H -#ifdef HAVE_STDLIB_H +#ifdef HAVE_STDLIB_H # include #endif // HAVE_STDLIB_H -#ifdef HAVE_STRING_H +#ifdef HAVE_STRING_H # include #endif // HAVE_STRING_H @@ -51,83 +47,62 @@ #ifdef HAVE_SYS_PARAM_H # include #endif // HAVE_SYS_PARAM_H +} -#ifndef MAXPATHLEN -#define MAXPATHLEN 255 -#endif // MAXPATHLEN +#include +using std::string; -#include "openbox.h" -#include "i18n.h" +#include "i18n.hh" +#include "blackbox.hh" -I18n i18n("openbox.cat"); + +I18n i18n; // initialized in main static void showHelp(int exitval) { // print program usage and command line options printf(i18n(mainSet, mainUsage, - "Openbox %s : (c) 2002 - 2002 Ben Jansens\n" - "\t\t\t 2001 - 2002 Sean 'Shaleh' Perry\n\n" - "\t\t\t 1997 - 2000 Brad Hughes\n\n" + "Blackbox %s : (c) 2001 - 2002 Sean 'Shaleh' Perry\n" + "\t\t\t 1997 - 2000, 2002 Brad Hughes\n\n" " -display \t\tuse display connection.\n" " -rc \t\t\tuse alternate resource file.\n" - " -menu \t\t\tuse alternate menu file.\n" " -version\t\t\tdisplay version and exit.\n" " -help\t\t\t\tdisplay this help text and exit.\n\n"), - __openbox_version); + __blackbox_version); // some people have requested that we print out compile options // as well - fprintf(stdout,i18n(mainSet, mainCompileOptions, - "Compile time options:\n" - " Debugging:\t\t\t%s\n" - " Interlacing:\t\t\t%s\n" - " Shape:\t\t\t%s\n" - " Slit:\t\t\t\t%s\n" - " 8bpp Ordered Dithering:\t%s\n" - " Event Clobbering:\t\t%s\n\n"), + printf(i18n(mainSet, mainCompileOptions, + "Compile time options:\n" + " Debugging:\t\t\t%s\n" + " Shape:\t\t\t%s\n" + " 8bpp Ordered Dithering:\t%s\n\n"), #ifdef DEBUG - i18n(CommonSet, CommonYes, "yes"), + i18n(CommonSet, CommonYes, "yes"), #else // !DEBUG - i18n(CommonSet, CommonNo, "no"), + i18n(CommonSet, CommonNo, "no"), #endif // DEBUG -#ifdef INTERLACE - i18n(CommonSet, CommonYes, "yes"), -#else // !INTERLACE - i18n(CommonSet, CommonNo, "no"), -#endif // INTERLACE - #ifdef SHAPE - i18n(CommonSet, CommonYes, "yes"), + i18n(CommonSet, CommonYes, "yes"), #else // !SHAPE - i18n(CommonSet, CommonNo, "no"), + i18n(CommonSet, CommonNo, "no"), #endif // SHAPE -#ifdef SLIT - i18n(CommonSet, CommonYes, "yes"), -#else // !SLIT - i18n(CommonSet, CommonNo, "no"), -#endif // SLIT - #ifdef ORDEREDPSEUDO - i18n(CommonSet, CommonYes, "yes"), + i18n(CommonSet, CommonYes, "yes") #else // !ORDEREDPSEUDO - i18n(CommonSet, CommonNo, "no"), + i18n(CommonSet, CommonNo, "no") #endif // ORDEREDPSEUDO + ); -#ifndef NOCLOBBER - i18n(CommonSet, CommonYes, "yes") -#else // !NOCLOBBER - i18n(CommonSet, CommonNo, "no") -#endif // NOCLOBBER - ); - - ::exit(exitval); + ::exit(exitval); } int main(int argc, char **argv) { char *session_display = (char *) 0; char *rc_file = (char *) 0; - char *menu_file = (char *) 0; + + i18n.openCatalog("blackbox.cat"); for (int i = 1; i < argc; ++i) { if (! strcmp(argv[i], "-rc")) { @@ -136,24 +111,12 @@ int main(int argc, char **argv) { if ((++i) >= argc) { fprintf(stderr, i18n(mainSet, mainRCRequiresArg, - "error: '-rc' requires and argument\n")); + "error: '-rc' requires and argument\n")); ::exit(1); } rc_file = argv[i]; - } else if (! strcmp(argv[i], "-menu")) { - // look for alternative menu file to use - - if ((++i) >= argc) { - fprintf(stderr, - i18n(mainSet, mainMENURequiresArg, - "error: '-menu' requires and argument\n")); - - ::exit(1); - } - - menu_file = argv[i]; } else if (! strcmp(argv[i], "-display")) { // check for -display option... to run on a display other than the one // set by the environment variable DISPLAY @@ -161,27 +124,25 @@ int main(int argc, char **argv) { if ((++i) >= argc) { fprintf(stderr, i18n(mainSet, mainDISPLAYRequiresArg, - "error: '-display' requires an argument\n")); + "error: '-display' requires an argument\n")); ::exit(1); } session_display = argv[i]; - char dtmp[MAXPATHLEN]; - sprintf(dtmp, "DISPLAY=%s", session_display); + string dtmp = "DISPLAY="; + dtmp += session_display; - if (putenv(dtmp)) { - fprintf(stderr, - i18n(mainSet, mainWarnDisplaySet, - "warning: couldn't set environment variable 'DISPLAY'\n")); + if (putenv(const_cast(dtmp.c_str()))) { + fprintf(stderr, i18n(mainSet, mainWarnDisplaySet, + "warning: couldn't set environment variable 'DISPLAY'\n")); perror("putenv()"); } } else if (! strcmp(argv[i], "-version")) { // print current version string - printf("Openbox %s : (c) 2002 - 2002 Ben Jansens\n" - "\t\t 2001 - 2002 Sean 'Shaleh' Perry\n" - "\t\t 1997 - 2000 Brad Hughes\n", - __openbox_version); + printf("Blackbox %s : (c) 2001 - 2002 Sean 'Shaleh' Perry\n", + "\t\t\t 1997 - 2000 Brad Hughes\n" + __blackbox_version); ::exit(0); } else if (! strcmp(argv[i], "-help")) { @@ -195,8 +156,8 @@ int main(int argc, char **argv) { _chdir2(getenv("X11ROOT")); #endif // __EMX__ - Openbox openbox(argc, argv, session_display, rc_file, menu_file); - openbox.eventLoop(); + Blackbox blackbox(argv, session_display, rc_file); + blackbox.eventLoop(); return(0); } diff --git a/src/openbox.cc b/src/openbox.cc deleted file mode 100644 index 6df793a2..00000000 --- a/src/openbox.cc +++ /dev/null @@ -1,1109 +0,0 @@ -// openbox.cc for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -// stupid macros needed to access some functions in version 2 of the GNU C -// library -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif // _GNU_SOURCE - -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif // HAVE_CONFIG_H - -#include -#include -#include -#include -#include - -#ifdef SHAPE -#include -#endif // SHAPE - -#include "i18n.h" -#include "openbox.h" -#include "Basemenu.h" -#include "Clientmenu.h" -#include "Rootmenu.h" -#include "Screen.h" - -#ifdef SLIT -#include "Slit.h" -#endif // SLIT - -#include "Toolbar.h" -#include "Window.h" -#include "Workspace.h" -#include "Workspacemenu.h" -#include "Util.h" - -#include -#include - -#ifdef HAVE_STDIO_H -# include -#endif // HAVE_STDIO_H - -#ifdef HAVE_STDLIB_H -# include -#endif // HAVE_STDLIB_H - -#ifdef HAVE_STRING_H -# include -#endif // HAVE_STRING_H - -#ifdef HAVE_UNISTD_H -# include -# include -#endif // HAVE_UNISTD_H - -#ifdef HAVE_SYS_PARAM_H -# include -#endif // HAVE_SYS_PARAM_H - -#ifndef MAXPATHLEN -#define MAXPATHLEN 255 -#endif // MAXPATHLEN - -#ifdef HAVE_SYS_SELECT_H -# include -#endif // HAVE_SYS_SELECT_H - -#ifdef HAVE_SIGNAL_H -# include -#endif // HAVE_SIGNAL_H - -#ifdef HAVE_SYS_SIGNAL_H -# include -#endif // HAVE_SYS_SIGNAL_H - -#ifdef HAVE_SYS_STAT_H -# include -# include -#endif // HAVE_SYS_STAT_H - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else // !TIME_WITH_SYS_TIME -# ifdef HAVE_SYS_TIME_H -# include -# else // !HAVE_SYS_TIME_H -# include -# endif // HAVE_SYS_TIME_H -#endif // TIME_WITH_SYS_TIME - -#ifdef HAVE_LIBGEN_H -# include -#endif // HAVE_LIBGEN_H - -#ifndef HAVE_BASENAME -static inline char *basename (char *s) { - char *save = s; - - while (*s) if (*s++ == '/') save = s; - - return save; -} -#endif // HAVE_BASENAME - - -// X event scanner for enter/leave notifies - adapted from twm -typedef struct scanargs { - Window w; - Bool leave, inferior, enter; -} scanargs; - -static Bool queueScanner(Display *, XEvent *e, char *args) { - if ((e->type == LeaveNotify) && - (e->xcrossing.window == ((scanargs *) args)->w) && - (e->xcrossing.mode == NotifyNormal)) { - ((scanargs *) args)->leave = True; - ((scanargs *) args)->inferior = (e->xcrossing.detail == NotifyInferior); - } else if ((e->type == EnterNotify) && - (e->xcrossing.mode == NotifyUngrab)) { - ((scanargs *) args)->enter = True; - } - - return False; -} - -Openbox *openbox; - - -Openbox::Openbox(int m_argc, char **m_argv, char *dpy_name, char *rc, - char *menu) : BaseDisplay(m_argv[0], dpy_name) { - grab(); - - if (! XSupportsLocale()) - fprintf(stderr, "X server does not support locale\n"); - - if (XSetLocaleModifiers("") == NULL) - fprintf(stderr, "cannot set locale modifiers\n"); - - ::openbox = this; - argc = m_argc; - argv = m_argv; - if (rc == NULL || menu == NULL) { - char *homedir = getenv("HOME"); - char *configdir = new char[strlen(homedir) + strlen("/.openbox") + 1]; - sprintf(configdir, "%s/.openbox", homedir); - // try to make sure the ~/.openbox directory exists - mkdir(configdir, S_IREAD | S_IWRITE | S_IEXEC | - S_IRGRP | S_IWGRP | S_IXGRP | - S_IROTH | S_IWOTH | S_IXOTH); - - - if (rc == NULL) { - rc_file = new char[strlen(configdir) + strlen("/rc") + 1]; - sprintf(rc_file, "%s/rc", configdir); - } else - rc_file = bstrdup(rc); - - if (menu == NULL) { - menu_file = new char[strlen(configdir) + strlen("/menu") + 1]; - sprintf(menu_file, "%s/menu", configdir); - } else - menu_file = bstrdup(menu); - - delete [] configdir; - } - config.setFile(rc_file); - - no_focus = False; - - resource.style_file = NULL; - resource.titlebar_layout = NULL; - resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec = 0; - - current_screen = (BScreen *) 0; - masked_window = (OpenboxWindow *) 0; - masked = None; - - load(); - -#ifdef HAVE_GETPID - openbox_pid = XInternAtom(getXDisplay(), "_BLACKBOX_PID", False); -#endif // HAVE_GETPID - - for (unsigned int s = 0; s < numberOfScreens(); s++) { - BScreen *screen = new BScreen(*this, s, config); - - if (! screen->isScreenManaged()) { - delete screen; - continue; - } - - screenList.push_back(screen); - } - - if (screenList.empty()) { - fprintf(stderr, - i18n(openboxSet, openboxNoManagableScreens, - "Openbox::Openbox: no managable screens found, aborting.\n")); - ::exit(3); - } - current_screen = screenList[0]; - - // save current settings and default values - save(); - - XSynchronize(getXDisplay(), False); - XSync(getXDisplay(), False); - - reconfigure_wait = reread_menu_wait = False; - - timer = new BTimer(*this, *this); - timer->setTimeout(0); - timer->fireOnce(True); - - ungrab(); - - focusWindow(0); - } - - -Openbox::~Openbox() { - for_each(screenList.begin(), screenList.end(), - PointerAssassin()); - - for_each(menuTimestamps.begin(), menuTimestamps.end(), - PointerAssassin()); - - if (resource.style_file) - delete [] resource.style_file; - - if (resource.titlebar_layout) - delete [] resource.titlebar_layout; - - delete timer; - - delete [] rc_file; - delete [] menu_file; -} - - -void Openbox::process_event(XEvent *e) { - if ((masked == e->xany.window && masked_window) && - (e->type == MotionNotify)) { - last_time = e->xmotion.time; - masked_window->motionNotifyEvent(&e->xmotion); - return; - } - - switch (e->type) { - case ButtonPress: { - // strip the lock key modifiers - e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask); - - last_time = e->xbutton.time; - - OpenboxWindow *win = (OpenboxWindow *) 0; - Basemenu *menu = (Basemenu *) 0; - -#ifdef SLIT - Slit *slit = (Slit *) 0; -#endif // SLIT - - Toolbar *tbar = (Toolbar *) 0; - - if ((win = searchWindow(e->xbutton.window))) { - win->buttonPressEvent(&e->xbutton); - - if (e->xbutton.button == 1) - win->installColormap(True); - } else if ((menu = searchMenu(e->xbutton.window))) { - menu->buttonPressEvent(&e->xbutton); - -#ifdef SLIT - } else if ((slit = searchSlit(e->xbutton.window))) { - slit->buttonPressEvent(&e->xbutton); -#endif // SLIT - - } else if ((tbar = searchToolbar(e->xbutton.window))) { - tbar->buttonPressEvent(&e->xbutton); - } else { - ScreenList::iterator it; - for (it = screenList.begin(); it != screenList.end(); ++it) { - BScreen *screen = *it; - if (e->xbutton.window == screen->getRootWindow()) { - if (e->xbutton.button == 1) { - if (! screen->isRootColormapInstalled()) - screen->getImageControl()->installRootColormap(); - - if (screen->getWorkspacemenu()->isVisible()) - screen->getWorkspacemenu()->hide(); - - if (screen->getRootmenu()->isVisible()) - screen->getRootmenu()->hide(); - } else if (e->xbutton.button == 2) { - int mx = e->xbutton.x_root - - (screen->getWorkspacemenu()->getWidth() / 2); - int my = e->xbutton.y_root - - (screen->getWorkspacemenu()->getTitleHeight() / 2); - - if (mx < 0) mx = 0; - if (my < 0) my = 0; - - if (mx + screen->getWorkspacemenu()->getWidth() > - screen->size().w()) - mx = screen->size().w() - - screen->getWorkspacemenu()->getWidth() - - screen->getBorderWidth(); - - if (my + screen->getWorkspacemenu()->getHeight() > - screen->size().h()) - my = screen->size().h() - - screen->getWorkspacemenu()->getHeight() - - screen->getBorderWidth(); - - screen->getWorkspacemenu()->move(mx, my); - - if (! screen->getWorkspacemenu()->isVisible()) { - screen->getWorkspacemenu()->removeParent(); - screen->getWorkspacemenu()->show(); - } - } else if (e->xbutton.button == 3) { - int mx = e->xbutton.x_root - - (screen->getRootmenu()->getWidth() / 2); - int my = e->xbutton.y_root - - (screen->getRootmenu()->getTitleHeight() / 2); - - if (mx < 0) mx = 0; - if (my < 0) my = 0; - - if (mx + screen->getRootmenu()->getWidth() > screen->size().w()) - mx = screen->size().w() - - screen->getRootmenu()->getWidth() - - screen->getBorderWidth(); - - if (my + screen->getRootmenu()->getHeight() > screen->size().h()) - my = screen->size().h() - - screen->getRootmenu()->getHeight() - - screen->getBorderWidth(); - - screen->getRootmenu()->move(mx, my); - - if (! screen->getRootmenu()->isVisible()) { - checkMenu(); - screen->getRootmenu()->show(); - } - } else if (e->xbutton.button == 4) { - if ((screen->getCurrentWorkspaceID() + 1) > - screen->getWorkspaceCount() - 1) - screen->changeWorkspaceID(0); - else - screen->changeWorkspaceID(screen->getCurrentWorkspaceID() + 1); - } else if (e->xbutton.button == 5) { - if ((screen->getCurrentWorkspaceID() - 1) < 0) - screen->changeWorkspaceID(screen->getWorkspaceCount() - 1); - else - screen->changeWorkspaceID(screen->getCurrentWorkspaceID() - 1); - } - } - } - } - - break; - } - - case ButtonRelease: { - // strip the lock key modifiers - e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask); - - last_time = e->xbutton.time; - - OpenboxWindow *win = (OpenboxWindow *) 0; - Basemenu *menu = (Basemenu *) 0; - Toolbar *tbar = (Toolbar *) 0; - - if ((win = searchWindow(e->xbutton.window))) - win->buttonReleaseEvent(&e->xbutton); - else if ((menu = searchMenu(e->xbutton.window))) - menu->buttonReleaseEvent(&e->xbutton); - else if ((tbar = searchToolbar(e->xbutton.window))) - tbar->buttonReleaseEvent(&e->xbutton); - - break; - } - - case ConfigureRequest: { - OpenboxWindow *win = (OpenboxWindow *) 0; - -#ifdef SLIT - Slit *slit = (Slit *) 0; -#endif // SLIT - - if ((win = searchWindow(e->xconfigurerequest.window))) { - win->configureRequestEvent(&e->xconfigurerequest); - -#ifdef SLIT - } else if ((slit = searchSlit(e->xconfigurerequest.window))) { - slit->configureRequestEvent(&e->xconfigurerequest); -#endif // SLIT - - } else { - grab(); - - if (validateWindow(e->xconfigurerequest.window)) { - XWindowChanges xwc; - - xwc.x = e->xconfigurerequest.x; - xwc.y = e->xconfigurerequest.y; - xwc.width = e->xconfigurerequest.width; - xwc.height = e->xconfigurerequest.height; - xwc.border_width = e->xconfigurerequest.border_width; - xwc.sibling = e->xconfigurerequest.above; - xwc.stack_mode = e->xconfigurerequest.detail; - - XConfigureWindow(getXDisplay(), e->xconfigurerequest.window, - e->xconfigurerequest.value_mask, &xwc); - } - - ungrab(); - } - - break; - } - - case MapRequest: { -#ifdef DEBUG - fprintf(stderr, - i18n(openboxSet, openboxMapRequest, - "Openbox::process_event(): MapRequest for 0x%lx\n"), - e->xmaprequest.window); -#endif // DEBUG - - OpenboxWindow *win = searchWindow(e->xmaprequest.window); - - if (! win) - win = new OpenboxWindow(*this, e->xmaprequest.window); - - if ((win = searchWindow(e->xmaprequest.window))) - win->mapRequestEvent(&e->xmaprequest); - - break; - } - - case MapNotify: { - OpenboxWindow *win = searchWindow(e->xmap.window); - - if (win) - win->mapNotifyEvent(&e->xmap); - - break; - } - - case UnmapNotify: { - OpenboxWindow *win = (OpenboxWindow *) 0; - -#ifdef SLIT - Slit *slit = (Slit *) 0; -#endif // SLIT - - if ((win = searchWindow(e->xunmap.window))) { - win->unmapNotifyEvent(&e->xunmap); -#ifdef SLIT - } else if ((slit = searchSlit(e->xunmap.window))) { - slit->removeClient(e->xunmap.window); -#endif // SLIT - - } - - break; - } - - case DestroyNotify: { - OpenboxWindow *win = (OpenboxWindow *) 0; - -#ifdef SLIT - Slit *slit = (Slit *) 0; -#endif // SLIT - - if ((win = searchWindow(e->xdestroywindow.window))) { - win->destroyNotifyEvent(&e->xdestroywindow); -#ifdef SLIT - } else if ((slit = searchSlit(e->xdestroywindow.window))) { - slit->removeClient(e->xdestroywindow.window, False); -#endif // SLIT - } - - break; - } - - case MotionNotify: { - // strip the lock key modifiers - e->xbutton.state &= ~(NumLockMask | ScrollLockMask | LockMask); - - last_time = e->xmotion.time; - - OpenboxWindow *win = (OpenboxWindow *) 0; - Basemenu *menu = (Basemenu *) 0; - - if ((win = searchWindow(e->xmotion.window))) - win->motionNotifyEvent(&e->xmotion); - else if ((menu = searchMenu(e->xmotion.window))) - menu->motionNotifyEvent(&e->xmotion); - - break; - } - - case PropertyNotify: { - last_time = e->xproperty.time; - - if (e->xproperty.state != PropertyDelete) { - OpenboxWindow *win = searchWindow(e->xproperty.window); - - if (win) - win->propertyNotifyEvent(e->xproperty.atom); - } - - break; - } - - case EnterNotify: { - last_time = e->xcrossing.time; - - BScreen *screen = (BScreen *) 0; - OpenboxWindow *win = (OpenboxWindow *) 0; - Basemenu *menu = (Basemenu *) 0; - Toolbar *tbar = (Toolbar *) 0; - -#ifdef SLIT - Slit *slit = (Slit *) 0; -#endif // SLIT - - if (e->xcrossing.mode == NotifyGrab) break; - - XEvent dummy; - scanargs sa; - sa.w = e->xcrossing.window; - sa.enter = sa.leave = False; - XCheckIfEvent(getXDisplay(), &dummy, queueScanner, (char *) &sa); - - if ((e->xcrossing.window == e->xcrossing.root) && - (screen = searchScreen(e->xcrossing.window))) { - screen->getImageControl()->installRootColormap(); - } else if ((win = searchWindow(e->xcrossing.window))) { - if (win->getScreen()->sloppyFocus() && - (! win->isFocused()) && (! no_focus)) { - grab(); - - if (((! sa.leave) || sa.inferior) && win->isVisible() && - win->setInputFocus()) - win->installColormap(True); - - ungrab(); - } - } else if ((menu = searchMenu(e->xcrossing.window))) { - menu->enterNotifyEvent(&e->xcrossing); - } else if ((tbar = searchToolbar(e->xcrossing.window))) { - tbar->enterNotifyEvent(&e->xcrossing); -#ifdef SLIT - } else if ((slit = searchSlit(e->xcrossing.window))) { - slit->enterNotifyEvent(&e->xcrossing); -#endif // SLIT - } - break; - } - - case LeaveNotify: { - last_time = e->xcrossing.time; - - OpenboxWindow *win = (OpenboxWindow *) 0; - Basemenu *menu = (Basemenu *) 0; - Toolbar *tbar = (Toolbar *) 0; - -#ifdef SLIT - Slit *slit = (Slit *) 0; -#endif // SLIT - - if ((menu = searchMenu(e->xcrossing.window))) - menu->leaveNotifyEvent(&e->xcrossing); - else if ((win = searchWindow(e->xcrossing.window))) - win->installColormap(False); - else if ((tbar = searchToolbar(e->xcrossing.window))) - tbar->leaveNotifyEvent(&e->xcrossing); -#ifdef SLIT - else if ((slit = searchSlit(e->xcrossing.window))) - slit->leaveNotifyEvent(&e->xcrossing); -#endif // SLIT - - break; - } - - case Expose: { - OpenboxWindow *win = (OpenboxWindow *) 0; - Basemenu *menu = (Basemenu *) 0; - Toolbar *tbar = (Toolbar *) 0; - - if ((win = searchWindow(e->xexpose.window))) - win->exposeEvent(&e->xexpose); - else if ((menu = searchMenu(e->xexpose.window))) - menu->exposeEvent(&e->xexpose); - else if ((tbar = searchToolbar(e->xexpose.window))) - tbar->exposeEvent(&e->xexpose); - - break; - } - - case KeyPress: { - Toolbar *tbar = searchToolbar(e->xkey.window); - - if (tbar && tbar->isEditing()) - tbar->keyPressEvent(&e->xkey); - - break; - } - - case ColormapNotify: { - BScreen *screen = searchScreen(e->xcolormap.window); - - if (screen) - screen->setRootColormapInstalled((e->xcolormap.state == - ColormapInstalled) ? True : False); - - break; - } - - case FocusIn: { - if (e->xfocus.mode == NotifyUngrab || e->xfocus.detail == NotifyPointer) - break; - - OpenboxWindow *win = searchWindow(e->xfocus.window); - if (win && !win->isFocused()) - focusWindow(win); - - break; - } - - case FocusOut: - break; - - case ClientMessage: { - if (e->xclient.format == 32) { - if (e->xclient.message_type == getWMChangeStateAtom()) { - OpenboxWindow *win = searchWindow(e->xclient.window); - if (! win || ! win->validateClient()) return; - - if (e->xclient.data.l[0] == IconicState) - win->iconify(); - if (e->xclient.data.l[0] == NormalState) - win->deiconify(); - } else if (e->xclient.message_type == getOpenboxChangeWorkspaceAtom()) { - BScreen *screen = searchScreen(e->xclient.window); - - if (screen && e->xclient.data.l[0] >= 0 && - e->xclient.data.l[0] < screen->getWorkspaceCount()) - screen->changeWorkspaceID(e->xclient.data.l[0]); - } else if (e->xclient.message_type == getOpenboxChangeWindowFocusAtom()) { - OpenboxWindow *win = searchWindow(e->xclient.window); - - if (win && win->isVisible() && win->setInputFocus()) - win->installColormap(True); - } else if (e->xclient.message_type == getOpenboxCycleWindowFocusAtom()) { - BScreen *screen = searchScreen(e->xclient.window); - - if (screen) { - if (! e->xclient.data.l[0]) - screen->prevFocus(); - else - screen->nextFocus(); - } - } else if (e->xclient.message_type == getOpenboxChangeAttributesAtom()) { - OpenboxWindow *win = searchWindow(e->xclient.window); - - if (win && win->validateClient()) { - OpenboxHints net; - net.flags = e->xclient.data.l[0]; - net.attrib = e->xclient.data.l[1]; - net.workspace = e->xclient.data.l[2]; - net.stack = e->xclient.data.l[3]; - net.decoration = e->xclient.data.l[4]; - - win->changeOpenboxHints(&net); - } - } - } - - break; - } - - - default: { -#ifdef SHAPE - if (e->type == getShapeEventBase()) { - XShapeEvent *shape_event = (XShapeEvent *) e; - OpenboxWindow *win = (OpenboxWindow *) 0; - - if ((win = searchWindow(e->xany.window)) || - (shape_event->kind != ShapeBounding)) - win->shapeEvent(shape_event); - } -#endif // SHAPE - - } - } // switch -} - - -Bool Openbox::handleSignal(int sig) { - switch (sig) { - case SIGHUP: - case SIGUSR1: - reconfigure(); - break; - - case SIGUSR2: - rereadMenu(); - break; - - case SIGPIPE: - case SIGSEGV: - case SIGFPE: - case SIGINT: - case SIGTERM: - shutdown(); - - default: - return False; - } - - return True; -} - - -BScreen *Openbox::searchScreen(Window window) { - ScreenList::iterator it; - for (it = screenList.begin(); it != screenList.end(); ++it) - if ((*it)->getRootWindow() == window) - return *it; - return (BScreen *) 0; -} - - -OpenboxWindow *Openbox::searchWindow(Window window) { - WindowLookup::iterator it = windowSearchList.find(window); - if (it == windowSearchList.end()) - return (OpenboxWindow *) 0; - return it->second; -} - - -OpenboxWindow *Openbox::searchGroup(Window window, OpenboxWindow *win) { - WindowLookup::iterator it = groupSearchList.find(window); - if (it != groupSearchList.end()) - if (it->second->getClientWindow() != win->getClientWindow()) - return win; - return (OpenboxWindow *) 0; -} - - -Basemenu *Openbox::searchMenu(Window window) { - MenuLookup::iterator it = menuSearchList.find(window); - if (it == menuSearchList.end()) - return (Basemenu *) 0; - return it->second; -} - - -Toolbar *Openbox::searchToolbar(Window window) { - ToolbarLookup::iterator it = toolbarSearchList.find(window); - if (it == toolbarSearchList.end()) - return (Toolbar *) 0; - return it->second; -} - - -#ifdef SLIT -Slit *Openbox::searchSlit(Window window) { - SlitLookup::iterator it = slitSearchList.find(window); - if (it == slitSearchList.end()) - return (Slit *) 0; - return it->second; -} -#endif // SLIT - - -void Openbox::saveWindowSearch(Window window, OpenboxWindow *data) { - windowSearchList.insert(WindowLookupPair(window, data)); -} - - -void Openbox::saveGroupSearch(Window window, OpenboxWindow *data) { - groupSearchList.insert(WindowLookupPair(window, data)); -} - - -void Openbox::saveMenuSearch(Window window, Basemenu *data) { - menuSearchList.insert(MenuLookupPair(window, data)); -} - - -void Openbox::saveToolbarSearch(Window window, Toolbar *data) { - toolbarSearchList.insert(ToolbarLookupPair(window, data)); -} - - -#ifdef SLIT -void Openbox::saveSlitSearch(Window window, Slit *data) { - slitSearchList.insert(SlitLookupPair(window, data)); -} -#endif // SLIT - - -void Openbox::removeWindowSearch(Window window) { - windowSearchList.erase(window); -} - - -void Openbox::removeGroupSearch(Window window) { - groupSearchList.erase(window); -} - - -void Openbox::removeMenuSearch(Window window) { - menuSearchList.erase(window); -} - - -void Openbox::removeToolbarSearch(Window window) { - toolbarSearchList.erase(window); -} - - -#ifdef SLIT -void Openbox::removeSlitSearch(Window window) { - slitSearchList.erase(window); -} -#endif // SLIT - - -void Openbox::restart(const char *prog) { - shutdown(); - - if (prog) { - execlp(prog, prog, NULL); - perror(prog); - } - - // fall back in case the above execlp doesn't work - execvp(argv[0], argv); - execvp(basename(argv[0]), argv); -} - - -void Openbox::shutdown() { - BaseDisplay::shutdown(); - - std::for_each(screenList.begin(), screenList.end(), - std::mem_fun(&BScreen::shutdown)); - - focusWindow(0); - - XSync(getXDisplay(), False); -} - - -void Openbox::save() { - config.setAutoSave(false); - - // save all values as they are so that the defaults will be written to the rc - // file - - config.setValue("session.colorsPerChannel", - resource.colors_per_channel); - config.setValue("session.styleFile", resource.style_file); - config.setValue("session.titlebarLayout", resource.titlebar_layout); - config.setValue("session.doubleClickInterval", - (long)resource.double_click_interval); - config.setValue("session.autoRaiseDelay", - ((resource.auto_raise_delay.tv_sec * 1000) + - (resource.auto_raise_delay.tv_usec / 1000))); - config.setValue("session.cacheLife", (long)resource.cache_life / 60000); - config.setValue("session.cacheMax", (long)resource.cache_max); - - std::for_each(screenList.begin(), screenList.end(), - std::mem_fun(&BScreen::save)); - - config.setAutoSave(true); - config.save(); -} - -void Openbox::load() { - if (!config.load()) - config.create(); - - std::string s; - long l; - - if (config.getValue("session.colorsPerChannel", "Session.ColorsPerChannel", - l)) - resource.colors_per_channel = (l < 2 ? 2 : (l > 6 ? 6 : l)); // >= 2, <= 6 - else - resource.colors_per_channel = 4; - - if (resource.style_file) - delete [] resource.style_file; - if (config.getValue("session.styleFile", "Session.StyleFile", s)) - resource.style_file = bstrdup(s.c_str()); - else - resource.style_file = bstrdup(DEFAULTSTYLE); - - if (resource.titlebar_layout) - delete [] resource.titlebar_layout; - if (config.getValue("session.titlebarLayout", "Session.TitlebarLayout", s)) - resource.titlebar_layout = bstrdup(s.c_str()); - else - resource.titlebar_layout = bstrdup("ILMC"); - - if (config.getValue("session.doubleClickInterval", - "Session.DoubleClickInterval", l)) - resource.double_click_interval = l; - else - resource.double_click_interval = 250; - - if (config.getValue("session.autoRaiseDelay", "Session.AutoRaiseDelay", l)) - resource.auto_raise_delay.tv_usec = l; - else - resource.auto_raise_delay.tv_usec = 400; - resource.auto_raise_delay.tv_sec = resource.auto_raise_delay.tv_usec / 1000; - resource.auto_raise_delay.tv_usec -= - (resource.auto_raise_delay.tv_sec * 1000); - resource.auto_raise_delay.tv_usec *= 1000; - - if (config.getValue("session.cacheLife", "Session.CacheLife", l)) - resource.cache_life = l; - else - resource.cache_life = 51; - resource.cache_life *= 60000; - - if (config.getValue("session.cacheMax", "Session.CacheMax", l)) - resource.cache_max = l; - else - resource.cache_max = 200; -} - - -void Openbox::reconfigure() { - reconfigure_wait = True; - - if (! timer->isTiming()) timer->start(); -} - - -void Openbox::real_reconfigure() { - grab(); - - load(); - - for_each(menuTimestamps.begin(), menuTimestamps.end(), - PointerAssassin()); - menuTimestamps.clear(); - - std::for_each(screenList.begin(), screenList.end(), - std::mem_fun(&BScreen::reconfigure)); - - ungrab(); -} - - -void Openbox::checkMenu() { - MenuTimestampList::iterator it; - for (it = menuTimestamps.begin(); it != menuTimestamps.end(); ++it) { - struct stat buf; - - if (stat((*it)->filename, &buf) || (*it)->timestamp != buf.st_ctime) { - rereadMenu(); - return; - } - } -} - - -void Openbox::addMenuTimestamp(const char *filename) { - bool found = false; - - MenuTimestampList::iterator it; - for (it = menuTimestamps.begin(); it != menuTimestamps.end(); ++it) - if (! strcmp((*it)->filename, filename)) { - found = true; - break; - } - if (!found) { - struct stat buf; - - if (! stat(filename, &buf)) { - MenuTimestamp *ts = new MenuTimestamp; - - ts->filename = bstrdup(filename); - ts->timestamp = buf.st_ctime; - - menuTimestamps.push_back(ts); - } - } -} - -void Openbox::rereadMenu() { - reread_menu_wait = True; - - if (! timer->isTiming()) timer->start(); -} - - -void Openbox::real_rereadMenu() { - std::for_each(menuTimestamps.begin(), menuTimestamps.end(), - PointerAssassin()); - menuTimestamps.clear(); - - std::for_each(screenList.begin(), screenList.end(), - std::mem_fun(&BScreen::rereadMenu)); -} - - -void Openbox::setStyleFilename(const char *filename) { - if (resource.style_file) - delete [] resource.style_file; - - resource.style_file = bstrdup(filename); - config.setValue("session.styleFile", resource.style_file); -} - - -void Openbox::timeout() { - if (reconfigure_wait) - real_reconfigure(); - - if (reread_menu_wait) - real_rereadMenu(); - - reconfigure_wait = reread_menu_wait = False; -} - - -OpenboxWindow *Openbox::focusedWindow() { - Workspace *w; - if (current_screen) - if ((w = current_screen->getCurrentWorkspace())) - return w->focusedWindow(); - return (OpenboxWindow *) 0; -} - - -void Openbox::focusWindow(OpenboxWindow *win) { - BScreen *old_screen = (BScreen *) 0; - Toolbar *old_tbar = (Toolbar *) 0, *tbar = (Toolbar *) 0; - Workspace *old_wkspc = (Workspace *) 0, *wkspc = (Workspace *) 0; - - OpenboxWindow *old_win = focusedWindow(); - if (old_win != (OpenboxWindow *) 0) { - old_screen = old_win->getScreen(); - old_wkspc = old_screen->getWorkspace(old_win->getWorkspaceNumber()); - old_tbar = old_screen->getToolbar(); - - old_win->setFocusFlag(false); - old_wkspc->focusWindow((OpenboxWindow *) 0); - } - - if (win && !win->isIconic()) { - current_screen = win->getScreen(); - tbar = current_screen->getToolbar(); - if (win->isStuck()) - wkspc = current_screen->getCurrentWorkspace(); - else - wkspc = current_screen->getWorkspace(win->getWorkspaceNumber()); - win->setFocusFlag(true); - wkspc->focusWindow(win); - - if (tbar) - tbar->redrawWindowLabel(true); - current_screen->updateNetizenWindowFocus(); - } else { - XSetInputFocus(getXDisplay(), PointerRoot, None, CurrentTime); - } - - if (old_tbar && old_tbar != tbar) - old_tbar->redrawWindowLabel(true); - if (old_screen && old_screen != current_screen) - old_screen->updateNetizenWindowFocus(); -} diff --git a/src/openbox.h b/src/openbox.h deleted file mode 100644 index 009b57fc..00000000 --- a/src/openbox.h +++ /dev/null @@ -1,239 +0,0 @@ -// openbox.h for Openbox -// Copyright (c) 2001 Sean 'Shaleh' Perry -// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef __openbox_hh -#define __openbox_hh - -#include -#include - -#ifdef HAVE_STDIO_H -# include -#endif // HAVE_STDIO_H - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else // !TIME_WITH_SYS_TIME -# ifdef HAVE_SYS_TIME_H -# include -# else // !HAVE_SYS_TIME_H -# include -# endif // HAVE_SYS_TIME_H -#endif // TIME_WITH_SYS_TIME - -#include "Resource.h" -#include "BaseDisplay.h" -#include "Timer.h" - -#include -#include -#include - -//forward declaration -class BScreen; -class Openbox; -class BImageControl; -class OpenboxWindow; -class Basemenu; -class Toolbar; -#ifdef SLIT -class Slit; -#endif // SLIT - -template -class DataSearch { -private: - Window window; - Z *data; - -public: - DataSearch(Window w, Z *d): window(w), data(d) {} - - inline const Window &getWindow() const { return window; } - inline Z *getData() { return data; } -}; - - -class Openbox : public BaseDisplay, public TimeoutHandler { -private: - typedef struct MenuTimestamp { - virtual ~MenuTimestamp() { - if (filename != (char *) 0) - delete [] filename; - } - char *filename; - time_t timestamp; - } MenuTimestamp; - - struct resource { - Time double_click_interval; - - char *style_file; - char *titlebar_layout; - int colors_per_channel; - timeval auto_raise_delay; - unsigned long cache_life, cache_max; - } resource; - - typedef std::map WindowLookup; - typedef WindowLookup::value_type WindowLookupPair; - WindowLookup windowSearchList, groupSearchList; - - typedef std::map MenuLookup; - typedef MenuLookup::value_type MenuLookupPair; - MenuLookup menuSearchList; - - typedef std::map ToolbarLookup; - typedef ToolbarLookup::value_type ToolbarLookupPair; - ToolbarLookup toolbarSearchList; - -#ifdef SLIT - typedef std::map SlitLookup; - typedef SlitLookup::value_type SlitLookupPair; - SlitLookup slitSearchList; -#endif // SLIT - - typedef std::list MenuTimestampList; - MenuTimestampList menuTimestamps; - - typedef std::vector ScreenList; - ScreenList screenList; - - BScreen *current_screen; - OpenboxWindow *masked_window; - BTimer *timer; - -#ifdef HAVE_GETPID - Atom openbox_pid; -#endif // HAVE_GETPID - - Bool no_focus, reconfigure_wait, reread_menu_wait; - Time last_time; - Window masked; - char *menu_file, *rc_file, **argv; - int argc; - Resource config; - - -protected: - void load(); - void save(); - void real_rereadMenu(); - void real_reconfigure(); - - virtual void process_event(XEvent *); - - -public: - Openbox(int, char **, char * = 0, char * = 0, char * = 0); - virtual ~Openbox(); - -#ifdef HAVE_GETPID - inline const Atom &getOpenboxPidAtom() const { return openbox_pid; } -#endif // HAVE_GETPID - - Basemenu *searchMenu(Window); - - OpenboxWindow *searchGroup(Window, OpenboxWindow *); - OpenboxWindow *searchWindow(Window); - OpenboxWindow *focusedWindow(); - void focusWindow(OpenboxWindow *w); - - inline BScreen *getScreen(unsigned int s) { - ASSERT(s < screenList.size()); - return screenList[s]; - } - BScreen *searchScreen(Window); - inline unsigned int managedScreenCount() const { - return screenList.size(); - } - - inline Resource &getConfig() { - return config; - } - inline const Time &getDoubleClickInterval() const - { return resource.double_click_interval; } - inline const Time &getLastTime() const { return last_time; } - - Toolbar *searchToolbar(Window); - - inline const char *getStyleFilename() const - { return resource.style_file; } - inline const char *getMenuFilename() const - { return menu_file; } - void addMenuTimestamp(const char *filename); - - inline const int &getColorsPerChannel() const - { return resource.colors_per_channel; } - - inline const timeval &getAutoRaiseDelay() const - { return resource.auto_raise_delay; } - - inline const char *getTitleBarLayout() const - { return resource.titlebar_layout; } - - inline const unsigned long &getCacheLife() const - { return resource.cache_life; } - inline const unsigned long &getCacheMax() const - { return resource.cache_max; } - - inline OpenboxWindow *getMaskedWindow() const - { return masked_window; } - inline void maskWindowEvents(Window w, OpenboxWindow *bw) - { masked = w; masked_window = bw; } - inline void setNoFocus(Bool f) { no_focus = f; } - - void shutdown(); - void setStyleFilename(const char *); - void saveMenuSearch(Window, Basemenu *); - void saveWindowSearch(Window, OpenboxWindow *); - void saveToolbarSearch(Window, Toolbar *); - void saveGroupSearch(Window, OpenboxWindow *); - void removeMenuSearch(Window); - void removeWindowSearch(Window); - void removeToolbarSearch(Window); - void removeGroupSearch(Window); - void restart(const char * = 0); - void reconfigure(); - void rereadMenu(); - void checkMenu(); - - virtual Bool handleSignal(int); - - virtual void timeout(); - -#ifdef SLIT - Slit *searchSlit(Window); - - void saveSlitSearch(Window, Slit *); - void removeSlitSearch(Window); -#endif // SLIT - -#ifndef HAVE_STRFTIME - - enum { B_AmericanDate = 1, B_EuropeanDate }; -#endif // HAVE_STRFTIME -}; - - -#endif // __openbox_hh -- 2.45.2