all repos — openbox @ a52a6d96d701c993896f276e4198003317632aaf

openbox fork - make it a bit more like ryudo

rm the old code including the .pys and the c++ shit
Dana Jansens danakj@orodu.net
commit

a52a6d96d701c993896f276e4198003317632aaf

parent

a36c7543d4eedaa9e10bfd9f4d9b81279b1bb7e6

99 files changed, 0 insertions(+), 17617 deletions(-)

jump to
D otk/.cvsignore

@@ -1,45 +0,0 @@

-Makefile -Makefile.in -.deps -otk_test -otk_wrap.cc -.libs -application.lo -appwidget.lo -button.lo -color.lo -configuration.lo -display.lo -eventdispatcher.lo -eventhandler.lo -focuslabel.lo -focuswidget.lo -font.lo -gccache.lo -image.lo -imagecontrol.lo -label.lo -libotk.la -otk_wrap.lo -property.lo -rect.lo -screeninfo.lo -style.lo -texture.lo -timer.lo -timerqueuemanager.lo -truerendercontrol.lo -pseudorendercontrol.lo -util.lo -widget.lo -ustring.lo -surface.lo -rendertexture.lo -rendertest -renderstyle.lo -messagedialog.lo -rendercontrol.lo -rendercolor.lo -otk.py -otk.pc -otk.lo
D otk/Makefile.am

@@ -1,51 +0,0 @@

-buttonsdir = $(pkgdatadir)/buttons -includeotkdir = $(includedir)/otk -pkgconfigdir = $(libdir)/pkgconfig - -CPPFLAGS=$(XFT_CFLAGS) @CPPFLAGS@ -DBUTTONSDIR=\"$(buttonsdir)\" - -lib_LTLIBRARIES=libotk.la - -libotk_la_SOURCES=rendercontrol.cc truerendercontrol.cc surface.cc util.cc \ - renderstyle.cc rendercolor.cc pseudorendercontrol.cc \ - display.cc font.cc property.cc timer.cc \ - eventdispatcher.cc eventhandler.cc ustring.cc \ - widget.cc application.cc label.cc appwidget.cc button.cc \ - otk.cc messagedialog.cc - -#focuswidget.cc focuslabel.cc - -includeotk_HEADERS=application.hh appwidget.hh assassin.hh button.hh \ - display.hh eventdispatcher.hh eventhandler.hh font.hh \ - label.hh otk.hh point.hh property.hh pseudorendercontrol.hh\ - rect.hh rendercolor.hh rendercontrol.hh renderstyle.hh \ - rendertexture.hh size.hh strut.hh surface.hh \ - timer.hh truerendercontrol.hh ustring.hh util.hh widget.hh \ - messagedialog.hh ../config.h - -EXTRA_DIST = otk.pc.in - -DISTCLEANFILES = otk.pc -MAINTAINERCLEANFILES= Makefile.in - -pkgconfig_DATA = otk.pc - -otk.pc: otk.pc.in - @regex_cmd@ -e "s,\@prefix\@,$(prefix)," \ - -e "s,\@version\@,$(VERSION)," \ - @srcdir@/$^ > $@ - -distclean-local: - $(RM) *\~ *.orig *.rej .\#* - -uninstall-am: - -rmdir -p $(includeotkdir) - -rmdir -p $(pkgconfigdir) - -otk_test: libotk.la otk_test.cc - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DHAVE_CONFIG_H -I. -I. -I.. -I../src $(XFT_CFLAGS) -Wall -W -pedantic -DNDEBUG -g -O2 -o otk_test otk_test.cc $(XFT_LIBS) -L. -lotk @LIBS@ - -rendertest: libotk.la rendertest.cc - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DHAVE_CONFIG_H -I. -I. -I.. -I../src $(XFT_CFLAGS) -Wall -W -pedantic -DNDEBUG -g -O2 -o $@ rendertest.cc $(XFT_LIBS) -L. -lotk @LIBS@ - -# local dependencies
D otk/TODO

@@ -1,38 +0,0 @@

-* Implement borders and border overlapping in widget - the widget has a outer geometry(that of the border) and a inner one - (the current geometry) - if the overlap flag is true, the inner widgets' borders are overlapped - as much as possible while the widgets are still entirely visible. - -* make OtkButton do pixmaps - -* OtkMenu - this can wait, probably - -* OtkWidget - see about focus() - focus() on widgets means 'highlight', not take Focus. solve this mess - -* OtkTextWidget - widget that holds text that can be justified and whatnot - the button should prolly be modified to subclass this - -* OtkApplication - do all derty work init display/screen/style/image control etc - event loop - do docking - close app, clean up crap - watch for style properties on the root window, update crap - on the fly. - -* widget factory for openbox - singleton that fetches widgets to openbox so that openbox - doesn't need to do useless work in creating/initializing/etc - -* cleanup image code - less deps on screen and display - what's this thing about 8bpp being busticatered - -* cleanups - name classes OtkBummy instead of OB... or B... - make Style hold pointers to colors and textures
D otk/application.cc

@@ -1,65 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "application.hh" -#include "eventhandler.hh" -#include "timer.hh" -#include "property.hh" -#include "rendercolor.hh" -#include "renderstyle.hh" -#include "display.hh" - -#include <cstdlib> -#include <iostream> - -namespace otk { - -extern void initialize(); -extern void destroy(); - -Application::Application(int argc, char **argv) - : EventDispatcher(), - _dockable(false), - _appwidget_count(0) -{ - (void)argc; - (void)argv; - - otk::initialize(); - - _screen = DefaultScreen(**display); - - loadStyle(); -} - -Application::~Application() -{ - otk::destroy(); -} - -void Application::loadStyle(void) -{ - // XXX: find the style name as a property - std::string style = "/usr/local/share/openbox/styles/artwiz"; - //_style->load(style); - otk::RenderStyle::setStyle(_screen, style); -} - -void Application::run(void) -{ - if (_appwidget_count <= 0) { - std::cerr << "ERROR: No main widgets exist. You must create and show() " << - "an AppWidget for the Application before calling " << - "Application::run().\n"; - ::exit(1); - } - - while (_appwidget_count > 0) { - dispatchEvents(); - if (_appwidget_count > 0) - Timer::dispatchTimers(); // fire pending events - } -} - -}
D otk/application.hh

@@ -1,39 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __application_hh -#define __application_hh - -#include "eventdispatcher.hh" - -namespace otk { - -class AppWidget; - -class Application : public EventDispatcher { - -public: - - Application(int argc, char **argv); - virtual ~Application(); - - inline int screen() const { return _screen; } - - virtual void run(void); - // more bummy cool functionality - - void setDockable(bool dockable) { _dockable = dockable; } - inline bool isDockable(void) const { return _dockable; } - -private: - void loadStyle(void); - - int _screen; - bool _dockable; - - int _appwidget_count; - - friend class AppWidget; -}; - -} - -#endif
D otk/appwidget.cc

@@ -1,56 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "appwidget.hh" -#include "application.hh" -#include "property.hh" -#include "renderstyle.hh" -#include "display.hh" - -extern "C" { -#include <X11/Xlib.h> -} - -namespace otk { - -AppWidget::AppWidget(Application *app, Direction direction, int bevel) - : Widget(app->screen(), app, direction, bevel), - _application(app) -{ - assert(app); - - // set WM Protocols on the window - Atom protocols[2]; - protocols[0] = Property::atoms.wm_protocols; - protocols[1] = Property::atoms.wm_delete_window; - XSetWMProtocols(**display, window(), protocols, 2); -} - -AppWidget::~AppWidget() -{ -} - -void AppWidget::show() -{ - if (!visible()) - _application->_appwidget_count++; - Widget::show(true); -} - -void AppWidget::hide() -{ - if (visible()) - _application->_appwidget_count--; - Widget::hide(); -} - -void AppWidget::clientMessageHandler(const XClientMessageEvent &e) -{ - EventHandler::clientMessageHandler(e); - if (e.message_type == Property::atoms.wm_protocols && - static_cast<Atom>(e.data.l[0]) == Property::atoms.wm_delete_window) - hide(); -} - -}
D otk/appwidget.hh

@@ -1,29 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __appwidget_hh -#define __appwidget_hh - -#include "widget.hh" - -namespace otk { - -class Application; - -class AppWidget : public Widget { - -public: - AppWidget(Application *app, Direction direction = Horizontal, int bevel = 0); - virtual ~AppWidget(); - - virtual void show(); - virtual void hide(); - - virtual void clientMessageHandler(const XClientMessageEvent &e); - -private: - - Application *_application; -}; - -} - -#endif // __appwidget_hh
D otk/assassin.hh

@@ -1,16 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __assassin_hh -#define __assassin_hh - -namespace otk { - -struct PointerAssassin { - template<typename T> - inline void operator()(const T ptr) const { - delete ptr; - } -}; - -} - -#endif // __assassin_hh
D otk/button.cc

@@ -1,77 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "button.hh" - -namespace otk { - -Button::Button(Widget *parent) - : Label(parent), - _pressed(false) -{ - setHorizontalJustify(RenderStyle::CenterJustify); - setVerticalJustify(RenderStyle::CenterJustify); - styleChanged(*RenderStyle::style(screen())); -} - -Button::~Button() -{ -} - -void Button::press(unsigned int mouse_button) -{ - if (_pressed) return; - - _pressed = true; - _mouse_button = mouse_button; - - styleChanged(*RenderStyle::style(screen())); - refresh(); -} - -void Button::release(unsigned int mouse_button) -{ - if (!_pressed || _mouse_button != mouse_button) return; // wrong button - - _pressed = false; - - styleChanged(*RenderStyle::style(screen())); - refresh(); -} - -void Button::buttonPressHandler(const XButtonEvent &e) -{ - Widget::buttonPressHandler(e); - press(e.button); -} - -void Button::buttonReleaseHandler(const XButtonEvent &e) -{ - Widget::buttonReleaseHandler(e); - bool p = _pressed; - release(e.button); - if (p && !_pressed && e.x > 0 && e.y > 0 && - e.x < area().width() && e.y < area().height()) - clickHandler(_mouse_button); -} - -void Button::styleChanged(const RenderStyle &style) -{ - if (isHighlighted()) { - if (_pressed) - _texture = style.buttonPressFocusBackground(); - else - _texture = style.buttonUnpressFocusBackground(); - _forecolor = style.buttonFocusColor(); - } else { - if (_pressed) - _texture = style.buttonPressUnfocusBackground(); - else - _texture = style.buttonUnpressUnfocusBackground(); - _forecolor = style.buttonUnfocusColor(); - } - refresh(); -} - -}
D otk/button.hh

@@ -1,34 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __button_hh -#define __button_hh - -#include "label.hh" - -namespace otk { - -class Button : public Label { - -public: - Button(Widget *parent); - virtual ~Button(); - - virtual inline bool isPressed() const { return _pressed; } - - virtual void press(unsigned int mouse_button); - virtual void release(unsigned int mouse_button); - - virtual void buttonPressHandler(const XButtonEvent &e); - virtual void buttonReleaseHandler(const XButtonEvent &e); - - virtual void clickHandler(unsigned int button) {(void)button;} - - virtual void styleChanged(const RenderStyle &style); - -private: - bool _pressed; - unsigned int _mouse_button; -}; - -} - -#endif
D otk/display.cc

@@ -1,306 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "display.hh" -#include "util.hh" - -extern "C" { -#include <X11/keysym.h> - -#ifdef XKB -#include <X11/XKBlib.h> -#endif // XKB - -#ifdef SHAPE -#include <X11/extensions/shape.h> -#endif // SHAPE - -#ifdef XINERAMA -#include <X11/extensions/Xinerama.h> -#endif // XINERAMA - -#ifdef HAVE_SIGNAL_H -# include <signal.h> -#endif // HAVE_SIGNAL_H - -#ifdef HAVE_FCNTL_H -# include <fcntl.h> -#endif // HAVE_FCNTL_H - -#ifdef HAVE_UNISTD_H -# include <sys/types.h> -# include <unistd.h> -#endif // HAVE_UNISTD_H - -#include "../src/gettext.h" -#define _(str) gettext(str) -} - -#include <cstdio> - -namespace otk { - - -Display *display = (Display*) 0; - -static int xerrorHandler(::Display *d, XErrorEvent *e) -{ - if (!display->ignoreErrors()) { -#ifdef DEBUG - char errtxt[128]; - - //if (e->error_code != BadWindow) - { - XGetErrorText(d, e->error_code, errtxt, 127); - printf("X Error: %s\n", errtxt); - if (e->error_code != BadWindow) - abort(); - } -#else - (void)d; - (void)e; -#endif - } - return false; -} - - -Display::Display(::Display *d) - : _display(d), - _xkb(false), - _xkb_event_basep(0), - _shape(false), - _shape_event_basep(0), - _xinerama(false), - _xinerama_event_basep(0), - _mask_list(), - _num_lock_mask(0), - _scroll_lock_mask(0), - _grab_count(0) -{ - int junk; - (void)junk; - - assert(_display); - - display = this; - - if (fcntl(ConnectionNumber(_display), F_SETFD, 1) == -1) { - printf(_("Couldn't mark display connection as close-on-exec.\n\n")); - ::exit(1); - } - if (!XSupportsLocale()) - printf(_("X server does not support locale.\n")); - if (!XSetLocaleModifiers("")) - printf(_("Cannot set locale modifiers for the X server.\n")); - - // set our error handler for X errors - XSetErrorHandler(xerrorHandler); - - // set the DISPLAY environment variable for any lauched children, to the - // display we're using, so they open in the right place. - putenv(std::string("DISPLAY=") + DisplayString(_display)); - - // find the availability of X extensions we like to use -#ifdef XKB - _xkb = XkbQueryExtension(_display, &junk, &_xkb_event_basep, &junk, NULL, - NULL); -#endif - -#ifdef SHAPE - _shape = XShapeQueryExtension(_display, &_shape_event_basep, &junk); -#endif - -#ifdef XINERAMA - _xinerama = XineramaQueryExtension(_display, &_xinerama_event_basep, &junk); -#endif // XINERAMA - - // get lock masks that are defined by the display (not constant) - _modmap = XGetModifierMapping(_display); - assert(_modmap); - 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 = 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 == _modmap->modifiermap[cnt]) - _num_lock_mask = mask_table[cnt / _modmap->max_keypermod]; - if (scroll_lock == _modmap->modifiermap[cnt]) - _scroll_lock_mask = mask_table[cnt / _modmap->max_keypermod]; - } - } - - _mask_list[0] = 0; - _mask_list[1] = LockMask; - _mask_list[2] = _num_lock_mask; - _mask_list[3] = LockMask | _num_lock_mask; - _mask_list[4] = _scroll_lock_mask; - _mask_list[5] = _scroll_lock_mask | LockMask; - _mask_list[6] = _scroll_lock_mask | _num_lock_mask; - _mask_list[7] = _scroll_lock_mask | LockMask | _num_lock_mask; - - /* - If the default depth is at least 8 we will use that, - otherwise we try to find the largest TrueColor visual. - Preference is given to 24 bit over larger depths if 24 bit is an option. - */ - - int screen = DefaultScreen(_display); - _depth = DefaultDepth(_display, screen); - _visual = DefaultVisual(_display, screen); - _colormap = DefaultColormap(_display, screen); - - if (_depth < 8) { - // search for a TrueColor Visual... if we can't find one... - // we will use the default visual for the screen - XVisualInfo vinfo_template, *vinfo_return; - int vinfo_nitems; - int best = -1; - - vinfo_template.screen = screen; - vinfo_template.c_class = TrueColor; - - vinfo_return = XGetVisualInfo(_display, - VisualScreenMask | VisualClassMask, - &vinfo_template, &vinfo_nitems); - if (vinfo_return) { - int max_depth = 1; - for (int i = 0; i < vinfo_nitems; ++i) { - if (vinfo_return[i].depth > max_depth) { - if (max_depth == 24 && vinfo_return[i].depth > 24) - break; // prefer 24 bit over 32 - max_depth = vinfo_return[i].depth; - best = i; - } - } - if (max_depth < _depth) best = -1; - } - - if (best != -1) { - _depth = vinfo_return[best].depth; - _visual = vinfo_return[best].visual; - _colormap = XCreateColormap(_display, RootWindow(_display, screen), - _visual, AllocNone); - } - - XFree(vinfo_return); - } -} - - -Display::~Display() -{ - while (_grab_count > 0) - ungrab(); - - XFreeModifiermap(_modmap); - - XCloseDisplay(_display); -} - - -void Display::setIgnoreErrors(bool t) -{ - // sync up so that anything already sent is/isn't ignored! - XSync(_display, false); - _ignore_errors = t; -} - -void Display::grab() -{ - if (_grab_count == 0) { - XGrabServer(_display); - XSync(_display, false); // make sure it kicks in - } - _grab_count++; -} - - -void Display::ungrab() -{ - if (_grab_count == 0) return; - _grab_count--; - if (_grab_count == 0) { - XUngrabServer(_display); - XFlush(_display); // ungrab as soon as possible - } -} - - - - - - - -/* - * 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. - - * if allow_scroll_lock is true then only the top half of the lock mask - * table is used and scroll lock is ignored. This value defaults to false. - */ -void Display::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, bool allow_scroll_lock) const -{ - unsigned int length = (allow_scroll_lock) ? 8 / 2: - 8; - for (size_t cnt = 0; cnt < length; ++cnt) - XGrabButton(_display, button, modifiers | _mask_list[cnt], - grab_window, owner_events, event_mask, pointer_mode, - keyboard_mode, confine_to, cursor); -} - - -/* - * Releases the grab on a button, and ungrabs all possible combinations of the - * keyboard lock keys. - */ -void Display::ungrabButton(unsigned int button, unsigned int modifiers, - Window grab_window) const -{ - for (size_t cnt = 0; cnt < 8; ++cnt) - XUngrabButton(_display, button, modifiers | _mask_list[cnt], - grab_window); -} - -void Display::grabKey(unsigned int keycode, unsigned int modifiers, - Window grab_window, bool owner_events, - int pointer_mode, int keyboard_mode, - bool allow_scroll_lock) const -{ - unsigned int length = (allow_scroll_lock) ? 8 / 2: - 8; - for (size_t cnt = 0; cnt < length; ++cnt) - XGrabKey(_display, keycode, modifiers | _mask_list[cnt], - grab_window, owner_events, pointer_mode, keyboard_mode); -} - -void Display::ungrabKey(unsigned int keycode, unsigned int modifiers, - Window grab_window) const -{ - for (size_t cnt = 0; cnt < 8; ++cnt) - XUngrabKey(_display, keycode, modifiers | _mask_list[cnt], - grab_window); -} - -void Display::ungrabAllKeys(Window grab_window) const -{ - XUngrabKey(_display, AnyKey, AnyModifier, grab_window); -} - -}
D otk/display.hh

@@ -1,126 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __display_hh -#define __display_hh - -extern "C" { -#include <X11/Xlib.h> -} - -namespace otk { - -class RenderControl; - -class Display; - -//! The display instance for the library -extern Display *display; - -//! Manages a single X11 display. -class Display -{ -private: - //! The X display - ::Display *_display; - - //! Does the display have the XKB extension? - bool _xkb; - //! Base for events for the XKB extension - int _xkb_event_basep; - - //! Does the display have the Shape extension? - bool _shape; - //! Base for events for the Shape extension - int _shape_event_basep; - - //! Does the display have the Xinerama extension? - bool _xinerama; - //! Base for events for the Xinerama extension - int _xinerama_event_basep; - - //! A list of all possible combinations of keyboard lock masks - unsigned int _mask_list[8]; - - //! The value of the mask for the NumLock modifier - unsigned int _num_lock_mask; - - //! The value of the mask for the ScrollLock modifier - unsigned int _scroll_lock_mask; - - //! The key codes for the modifier keys - XModifierKeymap *_modmap; - - //! The number of requested grabs on the display - int _grab_count; - - //! When true, X errors will be ignored. Use with care. - bool _ignore_errors; - - //! The optimal visual for the display - Visual *_visual; - - //! Our colormap built for the optimal visual - Colormap _colormap; - - //! The depth of our optimal visual - int _depth; - -public: - //! Wraps an open Display connection - /*! - @param d An open Display connection. - */ - Display(::Display *d); - //! Destroys the class, closes the X display - ~Display(); - - //! Returns if the display has the xkb extension available - inline bool xkb() const { return _xkb; } - //! Returns the xkb extension's event base - inline int xkbEventBase() const { return _xkb_event_basep; } - - //! Returns if the display has the shape extension available - inline bool shape() const { return _shape; } - //! Returns the shape extension's event base - inline int shapeEventBase() const { return _shape_event_basep; } - //! Returns if the display has the xinerama extension available - inline bool xinerama() const { return _xinerama; } - - inline unsigned int numLockMask() const { return _num_lock_mask; } - inline unsigned int scrollLockMask() const { return _scroll_lock_mask; } - const XModifierKeymap *modifierMap() const { return _modmap; } - - inline ::Display* operator*() const { return _display; } - - //! When true, X errors will be ignored. - inline bool ignoreErrors() const { return _ignore_errors; } - //! Set whether X errors should be ignored. Use with care. - void setIgnoreErrors(bool t); - - //! Grabs the display - void grab(); - - //! Ungrabs the display - void ungrab(); - - - - /* TEMPORARY */ - 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, - bool allow_scroll_lock) const; - void ungrabButton(unsigned int button, unsigned int modifiers, - Window grab_window) const; - void grabKey(unsigned int keycode, unsigned int modifiers, - Window grab_window, bool owner_events, - int pointer_mode, int keyboard_mode, - bool allow_scroll_lock) const; - void ungrabKey(unsigned int keycode, unsigned int modifiers, - Window grab_window) const; - void ungrabAllKeys(Window grab_window) const; -}; - -} - -#endif // __display_hh
D otk/eventdispatcher.cc

@@ -1,217 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "eventdispatcher.hh" -#include "display.hh" - -#include <cstdio> -#include <iostream> - -namespace otk { - -EventDispatcher::EventDispatcher() - : _fallback(0), _master(0) -{ -} - -EventDispatcher::~EventDispatcher() -{ -} - -void EventDispatcher::clearAllHandlers(void) -{ - _map.clear(); -} - -void EventDispatcher::registerHandler(Window id, EventHandler *handler) -{ - _map.insert(std::pair<Window, EventHandler*>(id, handler)); -} - -void EventDispatcher::clearHandler(Window id) -{ - _map.erase(id); -} - -void EventDispatcher::dispatchEvents(bool remote) -{ - XEvent e; - - while (true) { - /* - There are slightly different event retrieval semantics here for local (or - high bandwidth) versus remote (or low bandwidth) connections to the - display/Xserver. - */ - if (remote) { - if (!XPending(**display)) - return; - } else { - /* - This XSync allows for far more compression of events, which makes - things like Motion events perform far far better. Since it also means - network traffic for every event instead of every X events (where X is - the number retrieved at a time), it probably should not be used for - setups where Openbox is running on a remote/low bandwidth - display/Xserver. - */ - XSync(**display, false); - if (!XEventsQueued(**display, QueuedAlready)) - return; - } - XNextEvent(**display, &e); - -#if 0//defined(DEBUG) - printf("Event %d window %lx\n", e.type, e.xany.window); -#endif - - if (e.type == FocusIn || e.type == FocusOut) { - // focus events are a beast all their own.. yuk, hate, etc. - dispatchFocus(e); - } else { - Window win; - - // pick a window - switch (e.type) { - case UnmapNotify: - win = e.xunmap.window; - break; - case DestroyNotify: - win = e.xdestroywindow.window; - break; - case ConfigureRequest: - win = e.xconfigurerequest.window; - break; - default: - win = e.xany.window; - } - - // grab the lasttime and hack up the modifiers - switch (e.type) { - case ButtonPress: - case ButtonRelease: - _lasttime = e.xbutton.time; - e.xbutton.state &= ~(LockMask | display->numLockMask() | - display->scrollLockMask()); - break; - case KeyPress: - e.xkey.state &= ~(LockMask | display->numLockMask() | - display->scrollLockMask()); - break; - case MotionNotify: - _lasttime = e.xmotion.time; - e.xmotion.state &= ~(LockMask | display->numLockMask() | - display->scrollLockMask()); - break; - case PropertyNotify: - _lasttime = e.xproperty.time; - break; - case EnterNotify: - case LeaveNotify: - _lasttime = e.xcrossing.time; - if (e.xcrossing.mode != NotifyNormal) - continue; // skip me! - break; - } - - dispatch(win, e); - } - } -} - -void EventDispatcher::dispatchFocus(const XEvent &e) -{ -// printf("focus %s detail %d -> 0x%lx\n", -// (e.xfocus.type == FocusIn ? "IN" : "OUT"), -// e.xfocus.detail, e.xfocus.window); - // ignore focus changes from grabs - if (e.xfocus.mode == NotifyGrab) //|| e.xfocus.mode == NotifyUngrab || - // From Metacity, from WindowMaker, ignore all funky pointer root events - // its commented out cuz I don't think we need this at all. If problems - // arise we can look into it - //e.xfocus.detail > NotifyNonlinearVirtual) - return; - - if (e.type == FocusIn) { - //printf("Got FocusIn!\n"); - - // send a FocusIn to whatever was just focused - dispatch(e.xfocus.window, e); - //printf("Sent FocusIn 0x%lx\n", e.xfocus.window); - - } else if (e.type == FocusOut) { - //printf("Got FocusOut!\n"); - - // FocusOut events just make us look for FocusIn events. They are ignored - // otherwise. - XEvent fi; - if (XCheckTypedEvent(**display, FocusIn, &fi)) { - //printf("Found FocusIn\n"); - dispatchFocus(fi); - // dont unfocus the window we just focused! - if (fi.xfocus.window == e.xfocus.window) - return; - } - - dispatch(e.xfocus.window, e); - //printf("Sent FocusOut 0x%lx\n", e.xfocus.window); - } -} - -void EventDispatcher::dispatch(Window win, const XEvent &e) -{ - EventHandler *handler = 0; - EventMap::iterator it; - - // master gets everything first - if (_master) - _master->handle(e); - - // find handler for the chosen window - it = _map.find(win); - - if (it != _map.end()) { - // if we found a handler - handler = it->second; - } else if (e.type == ConfigureRequest) { - // unhandled configure requests must be used to configure the window - // directly - 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; - -#ifdef DEBUG - printf("Proxying configure event for 0x%lx\n", e.xconfigurerequest.window); -#endif - - // we are not to be held responsible if someone sends us an invalid - // request! - display->setIgnoreErrors(true); - XConfigureWindow(**display, e.xconfigurerequest.window, - e.xconfigurerequest.value_mask, &xwc); - display->setIgnoreErrors(false); - } else { - // grab a falback if it exists - handler = _fallback; - } - - if (handler) - handler->handle(e); -} - -EventHandler *EventDispatcher::findHandler(Window win) -{ - EventMap::iterator it = _map.find(win); - if (it != _map.end()) - return it->second; - return 0; -} - -}
D otk/eventdispatcher.hh

@@ -1,62 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __eventdispatcher -#define __eventdispatcher - -#include "eventhandler.hh" -#include <map> -#include <utility> - -namespace otk { - -typedef std::map<unsigned int, EventHandler *> EventMap; - -class EventDispatcher { -public: - - EventDispatcher(); - virtual ~EventDispatcher(); - - virtual void clearAllHandlers(void); - virtual void registerHandler(Window id, EventHandler *handler); - virtual void clearHandler(Window id); - //! Dispatch events from the X server to the appropriate EventHandlers - /*! - @param remote Is the Xserver on a remote (low bandwidth) connection or on a - local (high bandwidth) connection. This allows you to specify - 'false' in which case slightly different semantics are used - for event retrieval.<br> - The default is 'true' since this should generally be used, - only the Openbox window manager should need to specify - 'false' here. - */ - virtual void dispatchEvents(bool remote = true); - - inline void setFallbackHandler(EventHandler *fallback) - { _fallback = fallback; } - EventHandler *getFallbackHandler(void) const { return _fallback; } - - //! Sets an event handler that gets all events for all handlers after - //! any specific handlers have received them - inline void setMasterHandler(EventHandler *master) - { _master = master; } - EventHandler *getMasterHandler(void) const { return _master; } - - EventHandler *findHandler(Window win); - - inline Time lastTime() const { return _lasttime; } - -private: - EventMap _map; - EventHandler *_fallback; - EventHandler *_master; - - //! The time at which the last XEvent with a time was received - Time _lasttime; - - void dispatch(Window win, const XEvent &e); - void dispatchFocus(const XEvent &e); -}; - -} - -#endif
D otk/eventhandler.cc

@@ -1,106 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "display.hh" -#include "eventhandler.hh" - -namespace otk { - -EventHandler::EventHandler() -{ -} - - -EventHandler::~EventHandler() -{ -} - - -void EventHandler::handle(const XEvent &e) -{ - switch(e.type){ - case KeyPress: - return keyPressHandler(e.xkey); - case KeyRelease: - return keyReleaseHandler(e.xkey); - case ButtonPress: - return buttonPressHandler(e.xbutton); - case ButtonRelease: - return buttonReleaseHandler(e.xbutton); - case MotionNotify: - return motionHandler(e.xmotion); - case EnterNotify: - return enterHandler(e.xcrossing); - case LeaveNotify: - return leaveHandler(e.xcrossing); - case FocusIn: - return focusHandler(e.xfocus); - case FocusOut: - return unfocusHandler(e.xfocus); - case Expose: - return exposeHandler(e.xexpose); - case GraphicsExpose: - return graphicsExposeHandler(e.xgraphicsexpose); - case NoExpose: - return noExposeEventHandler(e.xnoexpose); - case CirculateRequest: - return circulateRequestHandler(e.xcirculaterequest); - case ConfigureRequest: - return configureRequestHandler(e.xconfigurerequest); - case MapRequest: - return mapRequestHandler(e.xmaprequest); - case ResizeRequest: - return resizeRequestHandler(e.xresizerequest); - case CirculateNotify: - return circulateHandler(e.xcirculate); - case ConfigureNotify: - return configureHandler(e.xconfigure); - case CreateNotify: - return createHandler(e.xcreatewindow); - case DestroyNotify: - return destroyHandler(e.xdestroywindow); - case GravityNotify: - return gravityHandler(e.xgravity); - case MapNotify: - return mapHandler(e.xmap); - case MappingNotify: - return mappingHandler(e.xmapping); - case ReparentNotify: - return reparentHandler(e.xreparent); - case UnmapNotify: - return unmapHandler(e.xunmap); - case VisibilityNotify: - return visibilityHandler(e.xvisibility); - case ColormapNotify: - return colorMapHandler(e.xcolormap); - case ClientMessage: - return clientMessageHandler(e.xclient); - case PropertyNotify: - return propertyHandler(e.xproperty); - case SelectionClear: - return selectionClearHandler(e.xselectionclear); - case SelectionNotify: - return selectionHandler(e.xselection); - case SelectionRequest: - return selectionRequestHandler(e.xselectionrequest); - default: -#ifdef SHAPE - if (e.type == display->shapeEventBase()) - return shapeHandler((*(XShapeEvent*)&e)); -#endif // SHAPE -#ifdef XKB - if (e.type == display->xkbEventBase()) - return xkbHandler((*(XkbEvent*)&e)); -#endif // XKB - ; - } -} - - -void EventHandler::clientMessageHandler(const XClientMessageEvent &) -{ - -} - -}
D otk/eventhandler.hh

@@ -1,152 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __eventhandler__hh -#define __eventhandler__hh - -extern "C" { -#include <X11/Xlib.h> - -#ifdef SHAPE -#include <X11/extensions/shape.h> -#endif // SHAPE - -#ifdef XKB -#include <X11/XKBlib.h> -#endif // XKB - -} - -namespace otk { - -class EventHandler { -public: - //! Dispatches events to one of the other handlers based on their type. - virtual void handle(const XEvent &e); - - //! Called whenever any key is pressed. - virtual void keyPressHandler(const XKeyEvent &) {} - - //! Called whenever any key is released. - virtual void keyReleaseHandler(const XKeyEvent &) {} - - //! Called whenever a button of the pointer is pressed. - virtual void buttonPressHandler(const XButtonEvent &) {} - - //! Called whenever a button of the pointer is released. - virtual void buttonReleaseHandler(const XButtonEvent &) {} - - //! Called whenever the pointer moved - virtual void motionHandler(const XMotionEvent &) {} - - //! Called whenever the pointer enters a window. - virtual void enterHandler(const XCrossingEvent &) {} - - //! Called whenever the pointer leaves a window. - virtual void leaveHandler(const XCrossingEvent &) {} - - //! Called when a window gains focus. - virtual void focusHandler(const XFocusChangeEvent &) {} - - //! Called when a window looses focus. - virtual void unfocusHandler(const XFocusChangeEvent &) {} - - //! Called when a window becomes visible to the user. - virtual void exposeHandler(const XExposeEvent &) {} - - //! Called to handle GraphicsExpose events. - virtual void graphicsExposeHandler(const XGraphicsExposeEvent &) {} - - //! Called to handle NoExpose events. - virtual void noExposeEventHandler(const XNoExposeEvent &) {} - - //! Called when the window requests a change in its z-order. - virtual void circulateRequestHandler(const XCirculateRequestEvent &) - {} - - //! Called when a different client initiates a configure window request. - virtual void configureRequestHandler(const XConfigureRequestEvent &) - {} - - //! Called when a different client tries to map a window. - virtual void mapRequestHandler(const XMapRequestEvent &) {} - - //! Called when another client attemps to change the size of a window. - virtual void resizeRequestHandler(const XResizeRequestEvent &) {} - - //! Called when the z-order of the window has changed. - virtual void circulateHandler(const XCirculateEvent &) {} - - //! Called when the window as been reconfigured. - virtual void configureHandler(const XConfigureEvent &) {} - - //! Called when a window is created. - virtual void createHandler(const XCreateWindowEvent &) {} - - //! Called when a window is destroyed. - virtual void destroyHandler(const XDestroyWindowEvent &) {} - - //! Called when a window is moved because of a change in the size of its - //! parent. - virtual void gravityHandler(const XGravityEvent &) {} - - //! Called when a window is mapped. - virtual void mapHandler(const XMapEvent &) {} - - //! Called when the server generats a MappingNotify event - virtual void mappingHandler(const XMappingEvent &) {} - - //! Called when a window is reparented - virtual void reparentHandler(const XReparentEvent &) {} - - //! Called when a window is unmapped - virtual void unmapHandler(const XUnmapEvent &) {} - - //! Called when a the visibilty of a window changes - virtual void visibilityHandler(const XVisibilityEvent &) {} - - //! Called when the colormap changes, or is installed or unistalled - virtual void colorMapHandler(const XColormapEvent &) {} - - //! Called when a property of a window changes - virtual void propertyHandler(const XPropertyEvent &) {} - - //! Called when the client loses ownership of a selection - virtual void selectionClearHandler(const XSelectionClearEvent &) {} - - //! Called when a ConvertSelection protocol request is sent - virtual void selectionHandler(const XSelectionEvent &) {} - - //! Called when a SelectionEvent occurs - virtual void selectionRequestHandler(const XSelectionRequestEvent &) {} - - //! Called when a client calls XSendEvent - /*! - Some types of client messages are filtered out and sent to more specific - event handler functions. - */ - virtual void clientMessageHandler(const XClientMessageEvent &); - -#if defined(SHAPE) || defined(DOXYGEN_IGNORE) - //! Called when a shape extension event fires - virtual void shapeHandler(const XShapeEvent &) {} -#endif // SHAPE - -#if defined(XKB) || defined(DOXYGEN_IGNORE) - //! Called when an xkb extension event fires - virtual void xkbHandler(const XkbEvent &) {} -#endif // XKB - - virtual ~EventHandler(); - -protected: - /*! Constructor for the EventHandler class. - This is protected so that EventHandlers can't be instantiated on their - own. - */ - EventHandler(); - -private: -}; - -} - -#endif
D otk/font.cc

@@ -1,102 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "font.hh" -#include "surface.hh" -#include "util.hh" -#include "display.hh" -#include "screeninfo.hh" - -extern "C" { -#include "../src/gettext.h" -#define _(str) gettext(str) -} - -#include <cstdio> -#include <cstdlib> -#include <iostream> -#include <algorithm> - -namespace otk { - -bool Font::_xft_init = false; - -Font::Font(int screen_num, const std::string &fontstring, - bool shadow, unsigned char offset, unsigned char tint) - : _screen_num(screen_num), - _fontstring(fontstring), - _shadow(shadow), - _offset(offset), - _tint(tint), - _xftfont(0) -{ - assert(screen_num >= 0); - assert(tint <= CHAR_MAX); - - if (!_xft_init) { - if (!XftInit(0)) { - printf(_("Couldn't initialize Xft.\n\n")); - ::exit(3); - } -#ifdef DEBUG - int version = XftGetVersion(); - printf("Using Xft %d.%d.%d (Built against %d.%d.%d).\n", - version / 10000 % 100, version / 100 % 100, version % 100, - XFT_MAJOR, XFT_MINOR, XFT_REVISION); -#endif - _xft_init = true; - } - - if ((_xftfont = XftFontOpenName(**display, _screen_num, - _fontstring.c_str()))) - return; - - printf(_("Unable to load font: %s\n"), _fontstring.c_str()); - printf(_("Trying fallback font: %s\n"), "fixed"); - - if ((_xftfont = XftFontOpenName(**display, _screen_num, - "fixed"))) - return; - - printf(_("Unable to load font: %s\n"), "fixed"); - printf(_("Aborting!.\n")); - - ::exit(3); // can't continue without a font -} - - -Font::~Font(void) -{ - if (_xftfont) - XftFontClose(**display, _xftfont); -} - - -int Font::measureString(const ustring &string) const -{ - XGlyphInfo info; - - if (string.utf8()) - XftTextExtentsUtf8(**display, _xftfont, - (FcChar8*)string.c_str(), string.bytes(), &info); - else - XftTextExtents8(**display, _xftfont, - (FcChar8*)string.c_str(), string.bytes(), &info); - - return (signed) info.xOff + (_shadow ? _offset : 0); -} - - -int Font::height(void) const -{ - return (signed) _xftfont->height + (_shadow ? _offset : 0); -} - - -int Font::maxCharWidth(void) const -{ - return (signed) _xftfont->max_advance_width; -} - -}
D otk/font.hh

@@ -1,60 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __font_hh -#define __font_hh - -#include "ustring.hh" -#include "truerendercontrol.hh" - -extern "C" { -#include <X11/Xlib.h> -#define _XFT_NO_COMPAT_ // no Xft 1 API -#include <X11/Xft/Xft.h> -} - -#include <cassert> - -namespace otk { - -class Color; -class Surface; - -class Font { - /* - * static members - */ -private: - static bool _xft_init; - - int _screen_num; - - std::string _fontstring; - - bool _shadow; - unsigned char _offset; - unsigned char _tint; - - XftFont *_xftfont; - - bool createXftFont(void); - -public: - // loads an Xft font - Font(int screen_num, const std::string &fontstring, bool shadow, - unsigned char offset, unsigned char tint); - virtual ~Font(); - - inline const std::string &fontstring() const { return _fontstring; } - - int height() const; - int maxCharWidth() const; - - int measureString(const ustring &string) const; - - // The RenderControl classes use the internal data to render the fonts, but - // noone else needs it, so its private. - friend class RenderControl; -}; - -} - -#endif // __font_hh
D otk/label.cc

@@ -1,176 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "label.hh" -#include "display.hh" -#include "rendercontrol.hh" - -#include <string> - -namespace otk { - -Label::Label(int screen, EventDispatcher *ed, int bevel) - : Widget(screen, ed, Widget::Horizontal, bevel, true), - _text(""), - _font(0), - _justify_horz(RenderStyle::LeftTopJustify), - _justify_vert(RenderStyle::LeftTopJustify), - _highlight(false) -{ - styleChanged(*RenderStyle::style(screen)); -} - -Label::Label(Widget *parent) - : Widget(parent), - _text(""), - _font(0), - _justify_horz(RenderStyle::LeftTopJustify), - _justify_vert(RenderStyle::LeftTopJustify), - _highlight(false) -{ - styleChanged(*RenderStyle::style(screen())); -} - -Label::~Label() -{ -} - -void Label::setHorizontalJustify(RenderStyle::Justify j) -{ - _justify_horz = j; - refresh(); -} - -void Label::setVerticalJustify(RenderStyle::Justify j) -{ - _justify_vert = j; - refresh(); -} - -void Label::setHighlighted(bool h) -{ - _highlight = h; - styleChanged(*RenderStyle::style(screen())); - refresh(); -} - -void Label::setText(const ustring &text) -{ - bool utf = text.utf8(); - std::string s = text.c_str(); // use a normal string, for its functionality - - _parsedtext.clear(); - _text = text; - - // parse it into multiple lines - std::string::size_type p = 0; - while (p != std::string::npos) { - std::string::size_type p2 = s.find('\n', p); - std::string s(s.substr(p, (p2==std::string::npos?p2:p2-p))); - - // turn tabs into spaces (multiples of 8) - std::string::size_type t; - while ((t = s.find('\t')) != std::string::npos) - s.replace(t, 1, std::string(8 - t % 8, ' ')); - - _parsedtext.push_back(s); - _parsedtext.back().setUtf8(utf); - p = (p2==std::string::npos?p2:p2+1); - } - calcDefaultSizes(); -} - -void Label::setFont(const Font *f) -{ - _font = f; - calcDefaultSizes(); -} - -void Label::calcDefaultSizes() -{ - int longest = 0; - // find the longest line - std::vector<ustring>::iterator it, end = _parsedtext.end(); - for (it = _parsedtext.begin(); it != end; ++it) { - int length = _font->measureString(*it); - if (length < 0) continue; // lines too long get skipped - if (length > longest) longest = length; - } - setMinSize(Size(longest + borderWidth() * 2 + bevel() * 4, - _parsedtext.size() * _font->height() + borderWidth() * 2 + - bevel() * 2)); -} - -void Label::styleChanged(const RenderStyle &style) -{ - if (_highlight) { - _texture = style.labelFocusBackground(); - _forecolor = style.textFocusColor(); - } else { - _texture = style.labelUnfocusBackground(); - _forecolor = style.textUnfocusColor(); - } - if (_font != style.labelFont()) { - _font = style.labelFont(); - calcDefaultSizes(); - } -} - -void Label::renderForeground(Surface &surface) -{ - const RenderControl *control = display->renderControl(screen()); - int sidemargin = bevel() * 2; - int y = bevel(); - int w = area().width() - borderWidth() * 2 - sidemargin * 2; - int h = area().height() - borderWidth() * 2 - bevel() * 2; - - switch (_justify_vert) { - case RenderStyle::RightBottomJustify: - y += h - (_parsedtext.size() * _font->height()); - if (y < bevel()) y = bevel(); - break; - case RenderStyle::CenterJustify: - y += (h - (_parsedtext.size() * _font->height())) / 2; - if (y < bevel()) y = bevel(); - break; - case RenderStyle::LeftTopJustify: - break; - } - - if (w <= 0) return; // can't fit anything - - std::vector<ustring>::iterator it, end = _parsedtext.end(); - for (it = _parsedtext.begin(); it != end; ++it, y += _font->height()) { - ustring t = *it; // the actual text to draw - int x = sidemargin; // x coord for the text - - // find a string that will fit inside the area for text - ustring::size_type text_len = t.size(); - int length; - - do { - t.resize(text_len); - length = _font->measureString(t); - } while (length > w && text_len-- > 0); - if (length < 0) continue; // lines too long get skipped - - if (text_len <= 0) continue; // won't fit anything - - // justify the text - switch (_justify_horz) { - case RenderStyle::RightBottomJustify: - x += w - length; - break; - case RenderStyle::CenterJustify: - x += (w - length) / 2; - break; - case RenderStyle::LeftTopJustify: - break; - } - - control->drawString(surface, *_font, x, y, *_forecolor, t); - } -} - -}
D otk/label.hh

@@ -1,66 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __label_hh -#define __label_hh - -#include "widget.hh" -#include "ustring.hh" -#include "renderstyle.hh" -#include "font.hh" - -#include <vector> - -namespace otk { - -class Label : public Widget { - -public: - Label(int screen, EventDispatcher *ed, int bevel = 3); - Label(Widget *parent); - virtual ~Label(); - - inline const ustring& text(void) const { return _text; } - void setText(const ustring &text); - - virtual inline bool isHighlighted() const { return _highlight; } - virtual void setHighlighted(bool h); - - RenderStyle::Justify horizontalJustify() const { return _justify_horz; } - virtual void setHorizontalJustify(RenderStyle::Justify j); - RenderStyle::Justify verticalJustify() const { return _justify_vert; } - virtual void setVerticalJustify(RenderStyle::Justify j); - - const Font *font() const { return _font; } - virtual void setFont(const Font *f); - - virtual void styleChanged(const RenderStyle &style); - - virtual void renderForeground(Surface &surface); - -protected: - virtual void calcDefaultSizes(); - - //! The color the label will use for rendering its text - RenderColor *_forecolor; - -private: - //! Text to be displayed in the label - ustring _text; - //! Text to be displayed, parsed into its separate lines - std::vector<ustring> _parsedtext; - //! The actual text being shown, may be a subset of _text - ustring _drawtext; - //! The font the text will be rendered with - const Font *_font; - //! The horizontal justification used for drawing text - RenderStyle::Justify _justify_horz; - //! The vertical justification used for drawing text - RenderStyle::Justify _justify_vert; - //! The drawing offset for the text - int _drawx; - //! If the widget is highlighted or not - bool _highlight; -}; - -} - -#endif
D otk/messagedialog.cc

@@ -1,187 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "messagedialog.hh" -#include "assassin.hh" -#include "button.hh" -#include "label.hh" -#include "display.hh" -#include "property.hh" -#include "eventdispatcher.hh" -#include "timer.hh" - -#include <algorithm> - -namespace otk { - -class DialogButtonWidget : public Button { - MessageDialog *_dia; -public: - DialogButtonWidget(Widget *parent, MessageDialog *dia, - const DialogButton &b) - : Button(parent), - _dia(dia) - { - assert(dia); - setBevel(1); - setMaxSize(Size(0,0)); - setText(b.label()); - setHighlighted(b.isDefault()); - show(); - } - - virtual void buttonPressHandler(const XButtonEvent &e) { - // limit to the left button - if (e.button == Button1) - Button::buttonPressHandler(e); - } - virtual void clickHandler(unsigned int) { - _dia->setResult(DialogButton(text(), isHighlighted())); - _dia->hide(); - } -}; - -MessageDialog::MessageDialog(int screen, EventDispatcher *ed, ustring title, - ustring caption) - : Widget(screen, ed, Widget::Vertical), - _result("", false) -{ - init(title, caption); -} - -MessageDialog::MessageDialog(EventDispatcher *ed, ustring title, - ustring caption) - : Widget(DefaultScreen(**display), ed, Widget::Vertical), - _result("", false) -{ - init(title, caption); -} - -MessageDialog::MessageDialog(Widget *parent, ustring title, ustring caption) - : Widget(parent, Widget::Vertical), - _result("", false) -{ - init(title, caption); -} - -void MessageDialog::init(const ustring &title, const ustring &caption) -{ - _label = new Label(this); - _label->show(); - _label->setHighlighted(true); - _button_holder = new Widget(this, Widget::Horizontal); - _button_holder->show(); - _return = XKeysymToKeycode(**display, XStringToKeysym("Return")); - _escape = XKeysymToKeycode(**display, XStringToKeysym("Escape")); - - setEventMask(eventMask() | KeyPressMask); - _label->setText(caption); - if (title.utf8()) - otk::Property::set(window(), otk::Property::atoms.net_wm_name, - otk::Property::utf8, title); - otk::Property::set(window(), otk::Property::atoms.wm_name, - otk::Property::ascii, otk::ustring(title.c_str(), false)); - - // set WM Protocols on the window - Atom protocols[2]; - protocols[0] = Property::atoms.wm_protocols; - protocols[1] = Property::atoms.wm_delete_window; - XSetWMProtocols(**display, window(), protocols, 2); -} - -MessageDialog::~MessageDialog() -{ - if (visible()) hide(); - delete _button_holder; - delete _label; -} - -const DialogButton& MessageDialog::run() -{ - if (!visible()) - show(); - - while (visible()) { - dispatcher()->dispatchEvents(); - if (visible()) - Timer::dispatchTimers(); // fire pending events - } - return _result; -} - -void MessageDialog::addButton(const DialogButton &b) -{ - _button_widgets.push_back(new DialogButtonWidget(_button_holder, - this, b)); -} - -void MessageDialog::focus() -{ - if (visible()) - XSetInputFocus(**display, window(), None, CurrentTime); -} - -void MessageDialog::show() -{ - Rect r; - - if (parent()) - r = parent()->area(); - else - r = Rect(Point(0, 0), display->screenInfo(screen())->size()); - - XSizeHints size; - size.flags = PMinSize | PPosition | PWinGravity; - size.min_width = minSize().width(); - size.min_height = minSize().height(); - size.win_gravity = CenterGravity; - - Size dest = minSize(); - if (dest.width() < 200 || dest.height() < 100) { - if (dest.width() < 200 && dest.height() < 100) dest = Size(200, 100); - else if (dest.width() < 200) dest = Size(200, dest.height()); - else dest = Size(dest.width(), 100); - resize(dest); - } - - // center it above its parent - move(Point(r.x() + (r.width() - dest.width()) / 2, - r.y() + (r.height() - dest.height()) / 2)); - - XSetWMNormalHints(**display, window(), &size); - - Widget::show(); -} - -void MessageDialog::hide() -{ - Widget::hide(); - std::for_each(_button_widgets.begin(), _button_widgets.end(), - PointerAssassin()); -} - -void MessageDialog::keyPressHandler(const XKeyEvent &e) -{ - if (e.keycode == _return) { - std::vector<Button *>::const_iterator it, end = _button_widgets.end(); - for (it = _button_widgets.begin(); it != end; ++it) - if ((*it)->isHighlighted()) { - _result = DialogButton((*it)->text(), true); - hide(); - break; - } - } else if (e.keycode == _escape) { - hide(); - } -} - -void MessageDialog::clientMessageHandler(const XClientMessageEvent &e) -{ - EventHandler::clientMessageHandler(e); - if (e.message_type == Property::atoms.wm_protocols && - static_cast<Atom>(e.data.l[0]) == Property::atoms.wm_delete_window) - hide(); -} - -}
D otk/messagedialog.hh

@@ -1,66 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __messagedialog_hh -#define __messagedialog_hh - -#include "widget.hh" -#include "ustring.hh" - -#include <vector> - -namespace otk { - -class Button; -class Label; - -class DialogButton { - ustring _label; - bool _default; -public: - DialogButton(ustring label) : _label(label), _default(false) - {} - DialogButton(ustring label, bool def) : _label(label), _default(def) - {} - inline const ustring& label() const { return _label; } - inline const bool& isDefault() const { return _default; } - - bool operator==(const DialogButton &o) const { return _label == o._label; } - bool operator!=(const DialogButton &o) const { return!(_label == o._label); } -}; - -class MessageDialog : public Widget { -public: - MessageDialog(int screen, EventDispatcher *ed, ustring title, - ustring caption); - MessageDialog(EventDispatcher *ed, ustring title, ustring caption); - MessageDialog(Widget *parent, ustring title, ustring caption); - virtual ~MessageDialog(); - - virtual void addButton(const DialogButton &b); - - virtual const DialogButton& run(); - - virtual void show(); - virtual void hide(); - virtual void focus(); - - virtual const DialogButton& result() const { return _result; } - virtual void setResult(const DialogButton &result) { _result = result; } - - virtual void keyPressHandler(const XKeyEvent &e); - virtual void clientMessageHandler(const XClientMessageEvent &e); - -private: - void init(const ustring &title, const ustring &caption); - -protected: - std::vector<Button *> _button_widgets; - Label *_label; - Widget *_button_holder; - KeyCode _return; - KeyCode _escape; - DialogButton _result; -}; - -} - -#endif // __messagedialog_hh
D otk/otk.cc

@@ -1,25 +0,0 @@

-#include "display.hh" -#include "timer.hh" -#include "renderstyle.hh" -#include "property.hh" - -namespace otk { - -void initialize() -{ - new Display(); - Timer::initialize(); - RenderColor::initialize(); - RenderStyle::initialize(); - Property::initialize(); -} - -void destroy() -{ - RenderStyle::destroy(); - RenderColor::destroy(); - Timer::destroy(); - delete display; -} - -}
D otk/otk.hh

@@ -1,39 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __otk_hh -#define __otk_hh - -#include "config.h" - -#include "eventdispatcher.hh" -#include "eventhandler.hh" -#include "widget.hh" -#include "appwidget.hh" -#include "application.hh" -#include "assassin.hh" -#include "label.hh" -#include "button.hh" -#include "rendercolor.hh" -#include "display.hh" -#include "font.hh" -#include "messagedialog.hh" -#include "rendercontrol.hh" -#include "size.hh" -#include "point.hh" -#include "property.hh" -#include "rect.hh" -#include "screeninfo.hh" -#include "strut.hh" -#include "renderstyle.hh" -#include "surface.hh" -#include "rendertexture.hh" -#include "timer.hh" -#include "util.hh" -#include "ustring.hh" -#include "widget.hh" - -namespace otk { -void initialize(); -void destroy(); -} - -#endif // __otk_hh
D otk/otk.pc.in

@@ -1,11 +0,0 @@

-prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: otk -Description: Openbox Toolkit -Version: @version@ -Requires: xft -Libs: -L${libdir} -lotk -Cflags: -I${includedir}
D otk/otk_test.cc

@@ -1,36 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "application.hh" -#include "appwidget.hh" -#include "label.hh" -#include "button.hh" - -int main(int argc, char **argv) { - otk::Application app(argc, argv); - - otk::AppWidget foo(&app, otk::Widget::Vertical, 3); - otk::Label lab(&foo); - otk::Label lab2(&foo); - otk::Button but(&foo); - otk::Button but2(&foo); - - foo.resize(otk::Size(100, 150)); - - lab.setText("Hi, I'm a sexy\nlabel!!!"); - lab.setMaxSize(otk::Size(0,0)); - lab2.setText("Me too!!"); - lab2.setBorderWidth(10); - lab2.setBorderColor(otk::RenderStyle::style(app.screen())->buttonFocusColor()); - but.setText("Im not the default button..."); - but2.setText("But I AM!!"); - but2.setHighlighted(true); - - - foo.show(); - - app.run(); - - return 0; -}
D otk/point.hh

@@ -1,23 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __point_hh -#define __point_hh - -namespace otk { - -class Point { - int _x, _y; -public: - Point() : _x(0), _y(0) {} - Point(int x, int y) : _x(x), _y(y) {} - Point(const Point &p) : _x(p._x), _y(p._y) {} - - inline int x() const { return _x; } - inline int y() const { return _y; } - - bool operator==(const Point &o) const { return _x == o._x && _y == o._y; } - bool operator!=(const Point &o) const { return _x != o._x || _y != o._y; } -}; - -} - -#endif // __point_hh
D otk/property.cc

@@ -1,342 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "property.hh" -#include "display.hh" - -extern "C" { -#include <X11/Xatom.h> -} - -#include <algorithm> -#include <cassert> - -namespace otk { - -Atoms Property::atoms; - -static Atom create(char *name) { return XInternAtom(**display, name, false); } - -void Property::initialize() -{ - assert(display); - - // make sure asserts fire if there is a problem - memset(&atoms, 0, sizeof(Atoms)); - - atoms.cardinal = XA_CARDINAL; - atoms.window = XA_WINDOW; - atoms.pixmap = XA_PIXMAP; - atoms.atom = XA_ATOM; - atoms.string = XA_STRING; - atoms.utf8 = create("UTF8_STRING"); - - atoms.openbox_pid = create("_OPENBOX_PID"); - - atoms.wm_colormap_windows = create("WM_COLORMAP_WINDOWS"); - atoms.wm_protocols = create("WM_PROTOCOLS"); - atoms.wm_state = create("WM_STATE"); - atoms.wm_change_state = create("WM_CHANGE_STATE"); - atoms.wm_delete_window = create("WM_DELETE_WINDOW"); - atoms.wm_take_focus = create("WM_TAKE_FOCUS"); - atoms.wm_name = create("WM_NAME"); - atoms.wm_icon_name = create("WM_ICON_NAME"); - atoms.wm_class = create("WM_CLASS"); - atoms.wm_window_role = create("WM_WINDOW_ROLE"); - atoms.motif_wm_hints = create("_MOTIF_WM_HINTS"); - - atoms.openbox_show_root_menu = create("_OPENBOX_SHOW_ROOT_MENU"); - atoms.openbox_show_workspace_menu = create("_OPENBOX_SHOW_WORKSPACE_MENU"); - - atoms.net_supported = create("_NET_SUPPORTED"); - atoms.net_client_list = create("_NET_CLIENT_LIST"); - atoms.net_client_list_stacking = create("_NET_CLIENT_LIST_STACKING"); - atoms.net_number_of_desktops = create("_NET_NUMBER_OF_DESKTOPS"); - atoms.net_desktop_geometry = create("_NET_DESKTOP_GEOMETRY"); - atoms.net_desktop_viewport = create("_NET_DESKTOP_VIEWPORT"); - atoms.net_current_desktop = create("_NET_CURRENT_DESKTOP"); - atoms.net_desktop_names = create("_NET_DESKTOP_NAMES"); - atoms.net_active_window = create("_NET_ACTIVE_WINDOW"); - atoms.net_workarea = create("_NET_WORKAREA"); - atoms.net_supporting_wm_check = create("_NET_SUPPORTING_WM_CHECK"); -// atoms.net_virtual_roots = create("_NET_VIRTUAL_ROOTS"); - atoms.net_desktop_layout = create("_NET_DESKTOP_LAYOUT"); - atoms.net_showing_desktop = create("_NET_SHOWING_DESKTOP"); - - atoms.net_close_window = create("_NET_CLOSE_WINDOW"); - atoms.net_wm_moveresize = create("_NET_WM_MOVERESIZE"); - -// atoms.net_properties = create("_NET_PROPERTIES"); - atoms.net_wm_name = create("_NET_WM_NAME"); - atoms.net_wm_visible_name = create("_NET_WM_VISIBLE_NAME"); - atoms.net_wm_icon_name = create("_NET_WM_ICON_NAME"); - atoms.net_wm_visible_icon_name = create("_NET_WM_VISIBLE_ICON_NAME"); - atoms.net_wm_desktop = create("_NET_WM_DESKTOP"); - atoms.net_wm_window_type = create("_NET_WM_WINDOW_TYPE"); - atoms.net_wm_state = create("_NET_WM_STATE"); - atoms.net_wm_strut = create("_NET_WM_STRUT"); -// atoms.net_wm_icon_geometry = create("_NET_WM_ICON_GEOMETRY"); - atoms.net_wm_icon = create("_NET_WM_ICON"); -// atoms.net_wm_pid = create("_NET_WM_PID"); -// atoms.net_wm_handled_icons = create("_NET_WM_HANDLED_ICONS"); - atoms.net_wm_allowed_actions = create("_NET_WM_ALLOWED_ACTIONS"); - -// atoms.net_wm_ping = create("_NET_WM_PING"); - - atoms.net_wm_window_type_desktop = create("_NET_WM_WINDOW_TYPE_DESKTOP"); - atoms.net_wm_window_type_dock = create("_NET_WM_WINDOW_TYPE_DOCK"); - atoms.net_wm_window_type_toolbar = create("_NET_WM_WINDOW_TYPE_TOOLBAR"); - atoms.net_wm_window_type_menu = create("_NET_WM_WINDOW_TYPE_MENU"); - atoms.net_wm_window_type_utility = create("_NET_WM_WINDOW_TYPE_UTILITY"); - atoms.net_wm_window_type_splash = create("_NET_WM_WINDOW_TYPE_SPLASH"); - atoms.net_wm_window_type_dialog = create("_NET_WM_WINDOW_TYPE_DIALOG"); - atoms.net_wm_window_type_normal = create("_NET_WM_WINDOW_TYPE_NORMAL"); - - atoms.net_wm_moveresize_size_topleft = - create("_NET_WM_MOVERESIZE_SIZE_TOPLEFT"); - atoms.net_wm_moveresize_size_topright = - create("_NET_WM_MOVERESIZE_SIZE_TOPRIGHT"); - atoms.net_wm_moveresize_size_bottomleft = - create("_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT"); - atoms.net_wm_moveresize_size_bottomright = - create("_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT"); - atoms.net_wm_moveresize_move = - create("_NET_WM_MOVERESIZE_MOVE"); - - atoms.net_wm_action_move = create("_NET_WM_ACTION_MOVE"); - atoms.net_wm_action_resize = create("_NET_WM_ACTION_RESIZE"); - atoms.net_wm_action_minimize = create("_NET_WM_ACTION_MINIMIZE"); - atoms.net_wm_action_shade = create("_NET_WM_ACTION_SHADE"); - atoms.net_wm_action_stick = create("_NET_WM_ACTION_STICK"); - atoms.net_wm_action_maximize_horz = create("_NET_WM_ACTION_MAXIMIZE_HORZ"); - atoms.net_wm_action_maximize_vert = create("_NET_WM_ACTION_MAXIMIZE_VERT"); - atoms.net_wm_action_fullscreen = create("_NET_WM_ACTION_FULLSCREEN"); - atoms.net_wm_action_change_desktop = - create("_NET_WM_ACTION_CHANGE_DESKTOP"); - atoms.net_wm_action_close = create("_NET_WM_ACTION_CLOSE"); - - atoms.net_wm_state_modal = create("_NET_WM_STATE_MODAL"); - atoms.net_wm_state_sticky = create("_NET_WM_STATE_STICKY"); - atoms.net_wm_state_maximized_vert = create("_NET_WM_STATE_MAXIMIZED_VERT"); - atoms.net_wm_state_maximized_horz = create("_NET_WM_STATE_MAXIMIZED_HORZ"); - atoms.net_wm_state_shaded = create("_NET_WM_STATE_SHADED"); - atoms.net_wm_state_skip_taskbar = create("_NET_WM_STATE_SKIP_TASKBAR"); - atoms.net_wm_state_skip_pager = create("_NET_WM_STATE_SKIP_PAGER"); - atoms.net_wm_state_hidden = create("_NET_WM_STATE_HIDDEN"); - atoms.net_wm_state_fullscreen = create("_NET_WM_STATE_FULLSCREEN"); - atoms.net_wm_state_above = create("_NET_WM_STATE_ABOVE"); - atoms.net_wm_state_below = create("_NET_WM_STATE_BELOW"); - - atoms.net_wm_state_add = 1; - atoms.net_wm_state_remove = 0; - atoms.net_wm_state_toggle = 2; - - atoms.kde_net_system_tray_windows = create("_KDE_NET_SYSTEM_TRAY_WINDOWS"); - atoms.kde_net_wm_system_tray_window_for = - create("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR"); - atoms.kde_net_wm_window_type_override = - create("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"); - - atoms.kwm_win_icon = create("KWM_WIN_ICON"); - - atoms.rootpmapid = create("_XROOTPMAP_ID"); - atoms.esetrootid = create("ESETROOT_PMAP_ID"); - - atoms.openbox_premax = create("_OPENBOX_PREMAX"); - atoms.openbox_active_window = create("_OPENBOX_ACTIVE_WINDOW"); - atoms.openbox_restack_window = create("_OPENBOX_RESTACK_WINDOW"); -} - -void Property::set(Window win, Atom atom, Atom type, unsigned char* data, - int size, int nelements, bool append) -{ - assert(win != None); assert(atom != None); assert(type != None); - assert(nelements == 0 || (nelements > 0 && data != (unsigned char *) 0)); - assert(size == 8 || size == 16 || size == 32); - XChangeProperty(**display, win, atom, type, size, - (append ? PropModeAppend : PropModeReplace), - data, nelements); -} - -void Property::set(Window win, Atom atom, Atom type, unsigned long value) -{ - set(win, atom, type, (unsigned char*) &value, 32, 1, false); -} - -void Property::set(Window win, Atom atom, Atom type, unsigned long value[], - int elements) -{ - set(win, atom, type, (unsigned char*) value, 32, elements, false); -} - -void Property::set(Window win, Atom atom, StringType type, - const ustring &value) -{ - Atom t; - switch (type) { - case ascii: t = atoms.string; assert(!value.utf8()); break; - case utf8: t = atoms.utf8; assert(value.utf8()); break; - default: assert(false); return; // unhandled StringType - } - - // add 1 to the size to include the trailing null - set(win, atom, t, (unsigned char*) value.c_str(), 8, value.bytes() + 1, - false); -} - -void Property::set(Window win, Atom atom, StringType type, - const StringVect &strings) -{ - Atom t; - bool u; // utf8 encoded? - switch (type) { - case ascii: t = atoms.string; u = false; break; - case utf8: t = atoms.utf8; u = true; break; - default: assert(false); return; // unhandled StringType - } - - ustring value(u); - - StringVect::const_iterator it = strings.begin(); - const StringVect::const_iterator end = strings.end(); - for (; it != end; ++it) { - assert(it->utf8() == u); // the ustring is encoded correctly? - value += *it; - value += '\0'; - } - - // add 1 to the size to include the trailing null - set(win, atom, t, (unsigned char*)value.c_str(), 8, - value.bytes() + 1, false); -} - -bool Property::get(Window win, Atom atom, Atom type, unsigned long *nelements, - unsigned char **value, int size) -{ - assert(win != None); assert(atom != None); assert(type != None); - assert(size == 8 || size == 16 || size == 32); - unsigned char *c_val = 0; // value alloc'd in Xlib, must be XFree()d - Atom ret_type; - int ret_size; - unsigned long ret_bytes; - int result; - bool ret = false; - - // try get the first element - result = XGetWindowProperty(**display, win, atom, 0l, 1l, - false, AnyPropertyType, &ret_type, &ret_size, - nelements, &ret_bytes, &c_val); - ret = (result == Success && ret_type == type && ret_size == size && - *nelements > 0); - if (ret) { - 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); - } else { - // get the entire property since it is larger than one long - XFree(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. - long remain = (ret_bytes - 1)/sizeof(long) + 1 + 1; - result = XGetWindowProperty(**display, win, atom, 0l, - remain, false, type, &ret_type, &ret_size, - nelements, &ret_bytes, &c_val); - ret = (result == Success && ret_type == type && ret_size == size); - /* - If the property has changed type/size, or has grown since our first - read of it, then stop here and try again. If it shrank, then this will - still work. - */ - if (! ret) { - return get(win, atom, type, nelements, value, size); - } - - *value = new unsigned char[*nelements * size/8 + 1]; - memcpy(*value, c_val, *nelements * size/8 + 1); - } - } - if (c_val) XFree(c_val); - return ret; -} - -bool Property::get(Window win, Atom atom, Atom type, unsigned long *nelements, - unsigned long **value) -{ - return get(win, atom, type, nelements, (unsigned char**) value, 32); -} - -bool Property::get(Window win, Atom atom, Atom type, unsigned long *value) -{ - unsigned long *temp; - unsigned long num; - if (! get(win, atom, type, &num, (unsigned char **) &temp, 32)) - return false; - if (num >= 1) { - *value = temp[0]; - delete [] temp; - return true; - } - return false; -} - -bool Property::get(Window win, Atom atom, StringType type, ustring *value) -{ - unsigned long n; - StringVect s; - - if (get(win, atom, type, &n, &s) && n > 0) { - *value = s[0]; - return true; - } - return false; -} - -bool Property::get(Window win, Atom atom, StringType type, - unsigned long *nelements, StringVect *strings) -{ - Atom t; - bool u; // utf8 encoded? - switch (type) { - case ascii: t = atoms.string; u = false; break; - case utf8: t = atoms.utf8; u = true; break; - default: assert(false); return false; // unhandled StringType - } - - unsigned char *value; - unsigned long elements;; - if (!get(win, atom, t, &elements, &value, 8) || elements < 1) - return false; - - std::string s((char*)value, elements); - delete [] value; - - std::string::const_iterator it = s.begin(), end = s.end(); - unsigned long num = 0; - while(true) { - std::string::const_iterator tmp = it; // current string.begin() - it = std::find(tmp, end, '\0'); // look for null between tmp and end - strings->push_back(std::string(tmp, it)); // s[tmp:it) - strings->back().setUtf8(u); - ++num; - if (it == end) break; - ++it; - if (it == end) break; - } - - *nelements = num; - - return true; -} - - -/* - * Removes a property entirely from a window. - */ -void Property::erase(Window win, Atom atom) -{ - XDeleteProperty(**display, win, atom); -} - -}
D otk/property.hh

@@ -1,303 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __atom_hh -#define __atom_hh - -/*! @file property.hh - @brief Provides access to window properties -*/ - -#include "ustring.hh" -#include "screeninfo.hh" - -extern "C" { -#include <X11/Xlib.h> -} - -#include <vector> -#include <cassert> - -namespace otk { - -//! The atoms on the X server which this class will cache -struct Atoms { - // types - Atom cardinal; //!< The atom which represents the Cardinal data type - Atom window; //!< The atom which represents window ids - Atom pixmap; //!< The atom which represents pixmap ids - Atom atom; //!< The atom which represents atom values - Atom string; //!< The atom which represents ascii strings - Atom utf8; //!< The atom which represents utf8-encoded strings - - Atom openbox_pid; - - // window hints - Atom wm_colormap_windows; - Atom wm_protocols; - Atom wm_state; - Atom wm_delete_window; - Atom wm_take_focus; - Atom wm_change_state; - Atom wm_name; - Atom wm_icon_name; - Atom wm_class; - Atom wm_window_role; - Atom motif_wm_hints; - - Atom openbox_show_root_menu; - Atom openbox_show_workspace_menu; - - // NETWM atoms - // root window properties - Atom net_supported; - Atom net_client_list; - Atom net_client_list_stacking; - Atom net_number_of_desktops; - Atom net_desktop_geometry; - Atom net_desktop_viewport; - Atom net_current_desktop; - Atom net_desktop_names; - Atom net_active_window; - Atom net_workarea; - Atom net_supporting_wm_check; -// Atom net_virtual_roots; - Atom net_desktop_layout; - Atom net_showing_desktop; - // root window messages - Atom net_close_window; - Atom net_wm_moveresize; - // application window properties -// Atom net_properties; - Atom net_wm_name; - Atom net_wm_visible_name; - Atom net_wm_icon_name; - Atom net_wm_visible_icon_name; - Atom net_wm_desktop; - Atom net_wm_window_type; - Atom net_wm_state; - Atom net_wm_strut; -// Atom net_wm_icon_geometry; - Atom net_wm_icon; -// Atom net_wm_pid; -// Atom net_wm_handled_icons; - Atom net_wm_allowed_actions; - // application protocols -// Atom Atom net_wm_ping; - - Atom net_wm_window_type_desktop; - Atom net_wm_window_type_dock; - Atom net_wm_window_type_toolbar; - Atom net_wm_window_type_menu; - Atom net_wm_window_type_utility; - Atom net_wm_window_type_splash; - Atom net_wm_window_type_dialog; - Atom net_wm_window_type_normal; - - Atom net_wm_moveresize_size_topleft; - Atom net_wm_moveresize_size_topright; - Atom net_wm_moveresize_size_bottomleft; - Atom net_wm_moveresize_size_bottomright; - Atom net_wm_moveresize_move; - - Atom net_wm_action_move; - Atom net_wm_action_resize; - Atom net_wm_action_minimize; - Atom net_wm_action_shade; - Atom net_wm_action_stick; - Atom net_wm_action_maximize_horz; - Atom net_wm_action_maximize_vert; - Atom net_wm_action_fullscreen; - Atom net_wm_action_change_desktop; - Atom net_wm_action_close; - - Atom net_wm_state_modal; - Atom net_wm_state_sticky; - Atom net_wm_state_maximized_vert; - Atom net_wm_state_maximized_horz; - Atom net_wm_state_shaded; - Atom net_wm_state_skip_taskbar; - Atom net_wm_state_skip_pager; - Atom net_wm_state_hidden; - Atom net_wm_state_fullscreen; - Atom net_wm_state_above; - Atom net_wm_state_below; - - Atom net_wm_state_add; - Atom net_wm_state_remove; - Atom net_wm_state_toggle; - - Atom kde_net_system_tray_windows; - Atom kde_net_wm_system_tray_window_for; - Atom kde_net_wm_window_type_override; - - Atom kwm_win_icon; - - Atom rootpmapid; - Atom esetrootid; - - Atom openbox_premax; - Atom openbox_active_window; - Atom openbox_restack_window; -}; - - -//! Provides easy access to window properties. -class Property { -public: - - //! The possible types/encodings of strings - enum StringType { - ascii, //!< Standard 8-bit ascii string - utf8, //!< Utf8-encoded string -#ifndef DOXYGEN_IGNORE - NUM_STRING_TYPE -#endif - }; - - //! A list of ustrings - typedef std::vector<ustring> StringVect; - - //! The value of all atoms on the X server that exist in the - //! Atoms struct - static Atoms atoms; - -private: - //! Sets a property on a window - static void set(Window win, Atom atom, Atom type, unsigned char *data, - int size, int nelements, bool append); - //! Gets a property's value from a window - static bool get(Window win, Atom atom, Atom type, - unsigned long *nelements, unsigned char **value, - int size); - -public: - //! Initializes the Property class. - /*! - CAUTION: This function uses otk::Display, so ensure that - otk::Display::initialize has been called before initializing this class! - */ - static void initialize(); - - //! Sets a single-value property on a window to a new value - /*! - @param win The window id of the window on which to set the property's value - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - @param type The Atom value of the property type. This can be found in the - struct returned by Property::atoms. - @param value The value to set the property to - */ - static void set(Window win, Atom atom, Atom type, unsigned long value); - //! Sets an multiple-value property on a window to a new value - /*! - @param win The window id of the window on which to set the property's value - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - @param type The Atom value of the property type. This can be found in the - struct returned by Property::atoms. - @param value Any array of values to set the property to. The array must - contain <i>elements</i> number of elements - @param elements The number of elements in the <i>value</i> array - */ - static void set(Window win, Atom atom, Atom type, - unsigned long value[], int elements); - //! Sets a string property on a window to a new value - /*! - @param win The window id of the window on which to set the property's value - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - @param type A member of the Property::StringType enum that specifies the - type of the string the property is being set to - @param value The string to set the property to - */ - static void set(Window win, Atom atom, StringType type, - const ustring &value); - //! Sets a string-array property on a window to a new value - /*! - @param win The window id of the window on which to set the property's value - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - @param type A member of the Property::StringType enum that specifies the - type of the string the property is being set to - @param strings A list of strings to set the property to - */ - static void set(Window win, Atom atom, StringType type, - const StringVect &strings); - - //! Gets the value of a property on a window - /*! - @param win The window id of the window to get the property value from - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - @param type The Atom value of the property type. This can be found in the - struct returned by Property::atoms. - @param nelements When the function returns, if it returns true, this will - contain the actual number of elements retrieved.<br> - @param value If the function returns true, then this contains an array of - retrieved values for the property.<br> - The <i>value</i> is allocated inside the function and - <b>delete[]</b> value needs to be called when you are done - with it.<br> - The <i>value</i> array returned is null terminated, and has - <i>nelements</i> elements in it plus the terminating null. - @return true if retrieval of the specified property with the specified - type was successful; otherwise, false - */ - static bool get(Window win, Atom atom, Atom type, - unsigned long *nelements, unsigned long **value); - //! Gets a single element from the value of a property on a window - /*! - @param win The window id of the window to get the property value from - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - @param type The Atom value of the property type. This can be found in the - struct returned by Property::atoms. - @param value If the function returns true, then this contains the first - (and possibly only) element in the value of the specified - property. - @return true if retrieval of the specified property with the specified - type was successful; otherwise, false - */ - static bool get(Window win, Atom atom, Atom type, unsigned long *value); - //! Gets a single string from the value of a property on a window - /*! - @param win The window id of the window to get the property value from - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - @param type A member of the Property::StringType enum that specifies the - type of the string property to retrieve - @param value If the function returns true, then this contains the first - (and possibly only) string in the value of the specified - property. - @return true if retrieval of the specified property with the specified - type was successful; otherwise, false - */ - static bool get(Window win, Atom atom, StringType type, ustring *value); - //! Gets strings from the value of a property on a window - /*! - @param win The window id of the window to get the property value from - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - @param type A member of the Property::StringType enum that specifies the - type of the string property to retrieve - @param nelements When the function returns, if it returns true, this will - contain the actual number of strings retrieved.<br> - @param strings If the function returns true, then this contains all of the - strings retrieved from the property's value. - @return true if retrieval of the specified property with the specified - type was successful; otherwise, false - */ - static bool get(Window win, Atom atom, StringType type, - unsigned long *nelements, StringVect *strings); - - //! Removes a property from a window - /*! - @param win The window id of the window to remove the property from - @param atom The Atom value of the property to set. This can be found in the - struct returned by Property::atoms. - */ - static void erase(Window win, Atom atom); -}; - -} - -#endif // __atom_hh
D otk/pseudorendercontrol.cc

@@ -1,157 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "pseudorendercontrol.hh" -#include "display.hh" -#include "screeninfo.hh" -#include "surface.hh" -#include "rendertexture.hh" - -extern "C" { -#include "../src/gettext.h" -#define _(str) gettext(str) -} - -#include <cstdlib> - -namespace otk { - -PseudoRenderControl::PseudoRenderControl(int screen) - : RenderControl(screen) -{ - printf("Initializing PseudoColor RenderControl\n"); - const ScreenInfo *info = display->screenInfo(_screen); - int depth = info->depth(); - - // determine the number of colors and the bits-per-color - _bpc = 2; // XXX THIS SHOULD BE A USER OPTION - assert(_bpc >= 1); - _ncolors = 1 << (_bpc * 3); - - if (_ncolors > 1 << depth) { - fprintf(stderr, - _("PseudoRenderControl: Invalid colormap size. Resizing.\n")); - _bpc = 1 << (depth/3) >> 3; - _ncolors = 1 << (_bpc * 3); - } - - // build a color cube - _colors = new XColor[_ncolors]; -int tr, tg, tb; - int cpc = 1 << _bpc; // colors per channel - for (int n = 0, - r = 0; r < cpc; r++) - for (int g = 0; g < cpc; g++) - for (int b = 0; b < cpc; b++, n++) { - tr = (int)(((float)(r)/(float)(cpc-1)) * 0xFF); - tg = (int)(((float)(g)/(float)(cpc-1)) * 0xFF); - tb = (int)(((float)(b)/(float)(cpc-1)) * 0xFF); - _colors[n].red = tr | tr << 8; - _colors[n].green = tg | tg << 8; - _colors[n].blue = tb | tb << 8; - _colors[n].flags = DoRed|DoGreen|DoBlue; // used to track allocation - } - - // allocate the colors - for (int i = 0; i < _ncolors; i++) - if (!XAllocColor(**display, info->colormap(), &_colors[i])) - _colors[i].flags = 0; // mark it as unallocated - - // try allocate any colors that failed allocation above - - // get the allocated values from the X server (only the first 256 XXX why!?) - XColor icolors[256]; - int incolors = (((1 << depth) > 256) ? 256 : (1 << depth)); - for (int i = 0; i < incolors; i++) - icolors[i].pixel = i; - XQueryColors(**display, info->colormap(), icolors, incolors); - - // try match unallocated ones - for (int i = 0; i < _ncolors; i++) { - if (!_colors[i].flags) { // if it wasn't allocated... - unsigned long closest = 0xffffffff, close = 0; - for (int ii = 0; ii < incolors; ii++) { - // find deviations - int r = (_colors[i].red - icolors[ii].red) & 0xff; - int g = (_colors[i].green - icolors[ii].green) & 0xff; - int b = (_colors[i].blue - icolors[ii].blue) & 0xff; - // find a weighted absolute deviation - unsigned long dev = (r * r) + (g * g) + (b * b); - - if (dev < closest) { - closest = dev; - close = ii; - } - } - - _colors[i].red = icolors[close].red; - _colors[i].green = icolors[close].green; - _colors[i].blue = icolors[close].blue; - _colors[i].pixel = icolors[close].pixel; - - // try alloc this closest color, it had better succeed! - if (XAllocColor(**display, info->colormap(), &_colors[i])) - _colors[i].flags = DoRed|DoGreen|DoBlue; // mark as alloced - else - assert(false); // wtf has gone wrong, its already alloced for chissake! - } - } -} - -PseudoRenderControl::~PseudoRenderControl() -{ - printf("Destroying PseudoColor RenderControl\n"); - - unsigned long *pixels = new unsigned long [_ncolors], *p = pixels; - for (int i = 0; i < _ncolors; ++i, ++p) - *p = _colors[i].pixel; - XFreeColors(**display, display->screenInfo(_screen)->colormap(), pixels, - _ncolors, 0); - delete [] _colors; -} - -inline const XColor *PseudoRenderControl::pickColor(int r, int g, int b) const -{ - r = (r & 0xff) >> (8-_bpc); - g = (g & 0xff) >> (8-_bpc); - b = (b & 0xff) >> (8-_bpc); - return &_colors[(r << (2*_bpc)) + (g << (1*_bpc)) + b]; -} - -void PseudoRenderControl::reduceDepth(Surface &sf, XImage *im) const -{ - pixel32 *data = sf.pixelData(); - pixel32 *ret = (pixel32*)malloc(im->width * im->height * 4); - char *p = (char *)ret; - int x, y; - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - p[x] = pickColor(data[x] >> default_red_shift, - data[x] >> default_green_shift, - data[x] >> default_blue_shift)->pixel; - } - data += im->width; - p += im->bytes_per_line; - } - im->data = (char*)ret; -} - -void PseudoRenderControl::allocateColor(XColor *color) const -{ - const XColor *c = pickColor(color->red, color->blue, color->green); - - color->red = c->red; - color->green = c->green; - color->blue = c->blue; - color->pixel = c->pixel; - - if (XAllocColor(**display, display->screenInfo(_screen)->colormap(), color)) - color->flags = DoRed|DoGreen|DoBlue; // mark as alloced - else - assert(false); // wtf has gone wrong, its already alloced for chissake! - - return; -} - -}
D otk/pseudorendercontrol.hh

@@ -1,28 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __pseudorendercontrol_hh -#define __pseudorendercontrol_hh - -#include "rendercontrol.hh" - -namespace otk { - -class PseudoRenderControl : public RenderControl { -private: - int _bpc; // number of bits per color - int _ncolors; // number of allocated colors, size of the XColor array - XColor *_colors; // the valid allocated colors - - virtual void reduceDepth(Surface &sf, XImage *im) const; - - const XColor *pickColor(int r, int g, int b) const; - -public: - PseudoRenderControl(int screen); - virtual ~PseudoRenderControl(); - - virtual void allocateColor(XColor *color) const; -}; - -} - -#endif // __pseudorendercontrol_hh
D otk/rect.hh

@@ -1,39 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __rect_hh -#define __rect_hh - -#include "point.hh" -#include "size.hh" - -namespace otk { - -class Rect { - Point _p; - Size _s; -public: - Rect() : _p(), _s() {} - Rect(const Point &p, const Size &s) : _p(p), _s(s) {} - Rect(const Rect &r) : _p(r._p), _s(r._s) {} - Rect(int x, int y, int w, int h) - : _p(x, y), _s(w, h) {} - - inline int x() const { return _p.x(); } - inline int y() const { return _p.y(); } - inline int width() const { return _s.width(); } - inline int height() const { return _s.height(); } - - inline int left() const { return _p.x(); } - inline int top() const { return _p.y(); } - inline int right() const { return _p.x() + _s.width() - 1; } - inline int bottom() const { return _p.y() + _s.height() - 1; } - - inline const Point& position() const { return _p; } - inline const Size& size() const { return _s; } - - bool operator==(const Rect &o) const { return _p == o._p && _s == o._s; } - bool operator!=(const Rect &o) const { return _p != o._p || _s != o._s; } -}; - -} - -#endif // __rect_hh
D otk/rendercolor.cc

@@ -1,101 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "rendercolor.hh" -#include "display.hh" -#include "screeninfo.hh" -#include "rendercontrol.hh" - -#include <cstdio> - -namespace otk { - -std::map<unsigned long, RenderColor::CacheItem*> *RenderColor::_cache = 0; - -void RenderColor::initialize() -{ - _cache = new std::map<unsigned long, CacheItem*>[ScreenCount(**display)]; -} - -void RenderColor::destroy() -{ - delete [] _cache; -} - -RenderColor::RenderColor(int screen, unsigned char red, - unsigned char green, unsigned char blue) - : _screen(screen), - _red(red), - _green(green), - _blue(blue) -{ - create(); -} - -RenderColor::RenderColor(int screen, RGB rgb) - : _screen(screen), - _red(rgb.r), - _green(rgb.g), - _blue(rgb.b) -{ - create(); -} - -void RenderColor::create() -{ - unsigned long color = _blue | _green << 8 | _red << 16; - - // try get a gc from the cache - CacheItem *item = _cache[_screen][color]; - - if (item) { - _gc = item->gc; - _pixel = item->pixel; - ++item->count; - } else { - XGCValues gcv; - - // allocate a color and GC from the server - const ScreenInfo *info = display->screenInfo(_screen); - - XColor xcol; // convert from 0-0xff to 0-0xffff - xcol.red = (_red << 8) | _red; - xcol.green = (_green << 8) | _green; - xcol.blue = (_blue << 8) | _blue; - - display->renderControl(_screen)->allocateColor(&xcol); - - _pixel = xcol.pixel; - gcv.foreground = _pixel; - gcv.cap_style = CapProjecting; - _gc = XCreateGC(**display, info->rootWindow(), - GCForeground | GCCapStyle, &gcv); - assert(_gc); - - // insert into the cache - item = new CacheItem(_gc, _pixel); - _cache[_screen][color] = item; - ++item->count; - } -} - -RenderColor::~RenderColor() -{ - unsigned long color = _blue | _green << 8 | _red << 16; - - CacheItem *item = _cache[_screen][color]; - assert(item); // better be... - - if (--item->count <= 0) { - // remove from the cache - XFreeGC(**display, _gc); - _cache[_screen][color] = 0; - delete item; - - const ScreenInfo *info = display->screenInfo(_screen); - XFreeColors(**display, info->colormap(), &_pixel, 1, 0); - } -} - -}
D otk/rendercolor.hh

@@ -1,64 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __rendercolor_hh -#define __rendercolor_hh - -extern "C" { -#include <X11/Xlib.h> -} - -#include <map> - -namespace otk { - -struct RGB { - int r; - int g; - int b; - RGB(int red, int green, int blue) : r(red), g(green), b(blue) {} - // color is in ARGB format - RGB(unsigned long color) - : r((color >> 16) & 0xff), - g((color >> 8) & 0xff), - b((color) & 0xff) {} -}; - -class RenderColor { -private: - struct CacheItem { - GC gc; - unsigned long pixel; - int count; - CacheItem(GC g, unsigned long p) : gc(g), pixel(p), count(0) {} - }; - static std::map<unsigned long, CacheItem*> *_cache; - - int _screen; - unsigned char _red; - unsigned char _green; - unsigned char _blue; - - unsigned long _pixel; - GC _gc; - - void create(); - -public: - static void initialize(); - static void destroy(); - - RenderColor(int screen, unsigned char red, - unsigned char green, unsigned char blue); - RenderColor(int screen, RGB rgb); - virtual ~RenderColor(); - - inline int screen() const { return _screen; } - inline unsigned char red() const { return _red; } - inline unsigned char green() const { return _green; } - inline unsigned char blue() const { return _blue; } - unsigned long pixel() const { return _pixel; } - GC gc() const { return _gc; } -}; - -} - -#endif // __rendercolor_hh
D otk/rendercontrol.cc

@@ -1,596 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "rendercontrol.hh" -#include "truerendercontrol.hh" -#include "pseudorendercontrol.hh" -#include "rendertexture.hh" -#include "rendercolor.hh" -#include "renderstyle.hh" -#include "display.hh" -#include "screeninfo.hh" -#include "surface.hh" -#include "font.hh" -#include "ustring.hh" -#include "property.hh" - -extern "C" { -#ifdef HAVE_SYS_WAIT_H -# include <sys/wait.h> -#endif // HAVE_SYS_WAIT_H - -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif // HAVE_UNISTD_H - -#include "../src/gettext.h" -#define _(str) gettext(str) -} - -#include <cstdlib> - -namespace otk { - -RenderControl *RenderControl::createRenderControl(int screen) -{ - // get the visual on the screen and return the correct type of RenderControl - int vclass = display->screenInfo(screen)->visual()->c_class; - switch (vclass) { - case TrueColor: - return new TrueRenderControl(screen); - case PseudoColor: - case StaticColor: - return new PseudoRenderControl(screen); - case GrayScale: - case StaticGray: - return new PseudoRenderControl(screen); - default: - printf(_("RenderControl: Unsupported visual %d specified. Aborting.\n"), - vclass); - ::exit(1); - } -} - -RenderControl::RenderControl(int screen) - : _screen(screen) - -{ - printf("Initializing RenderControl\n"); - -} - -RenderControl::~RenderControl() -{ - printf("Destroying RenderControl\n"); -} - -void RenderControl::drawString(Surface& sf, const Font &font, int x, int y, - const RenderColor &color, - const ustring &string) const -{ - assert(sf._screen == _screen); - XftDraw *d = sf._xftdraw; - assert(d); // this means that the background hasn't been rendered yet! - - if (font._shadow) { - XftColor c; - c.color.red = 0; - c.color.green = 0; - c.color.blue = 0; - c.color.alpha = font._tint | font._tint << 8; // transparent shadow - c.pixel = BlackPixel(**display, _screen); - - if (string.utf8()) - XftDrawStringUtf8(d, &c, font._xftfont, x + font._offset, - font._xftfont->ascent + y + font._offset, - (FcChar8*)string.c_str(), string.bytes()); - else - XftDrawString8(d, &c, font._xftfont, x + font._offset, - font._xftfont->ascent + y + font._offset, - (FcChar8*)string.c_str(), string.bytes()); - } - - XftColor c; - c.color.red = color.red() | color.red() << 8; - c.color.green = color.green() | color.green() << 8; - c.color.blue = color.blue() | color.blue() << 8; - c.pixel = color.pixel(); - c.color.alpha = 0xff | 0xff << 8; // no transparency in Color yet - - if (string.utf8()) - XftDrawStringUtf8(d, &c, font._xftfont, x, font._xftfont->ascent + y, - (FcChar8*)string.c_str(), string.bytes()); - else - XftDrawString8(d, &c, font._xftfont, x, font._xftfont->ascent + y, - (FcChar8*)string.c_str(), string.bytes()); - return; -} - -void RenderControl::drawSolidBackground(Surface& sf, - const RenderTexture& texture) const -{ - assert(_screen == sf._screen); - assert(_screen == texture.color().screen()); - - if (texture.parentRelative()) return; - - sf.setPixmap(texture.color()); - - int width = sf.size().width(), height = sf.size().height(); - int left = 0, top = 0, right = width - 1, bottom = height - 1; - - if (texture.interlaced()) - for (int i = 0; i < height; i += 2) - XDrawLine(**display, sf.pixmap(), texture.interlaceColor().gc(), - 0, i, width, i); - - switch (texture.relief()) { - case RenderTexture::Raised: - switch (texture.bevel()) { - case RenderTexture::Bevel1: - XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(), - left, bottom, right, bottom); - XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(), - right, bottom, right, top); - - XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(), - left, top, right, top); - XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(), - left, bottom, left, top); - break; - case RenderTexture::Bevel2: - XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(), - left + 1, bottom - 2, right - 2, bottom - 2); - XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(), - right - 2, bottom - 2, right - 2, top + 1); - - XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(), - left + 1, top + 1, right - 2, top + 1); - XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(), - left + 1, bottom - 2, left + 1, top + 1); - break; - default: - assert(false); // unhandled RenderTexture::BevelType - } - break; - case RenderTexture::Sunken: - switch (texture.bevel()) { - case RenderTexture::Bevel1: - XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(), - left, bottom, right, bottom); - XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(), - right, bottom, right, top); - - XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(), - left, top, right, top); - XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(), - left, bottom, left, top); - break; - case RenderTexture::Bevel2: - XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(), - left + 1, bottom - 2, right - 2, bottom - 2); - XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(), - right - 2, bottom - 2, right - 2, top + 1); - - XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(), - left + 1, top + 1, right - 2, top + 1); - XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(), - left + 1, bottom - 2, left + 1, top + 1); - break; - default: - assert(false); // unhandled RenderTexture::BevelType - } - break; - case RenderTexture::Flat: - if (texture.border()) - XDrawRectangle(**display, sf.pixmap(), texture.borderColor().gc(), - left, top, right, bottom); - break; - default: - assert(false); // unhandled RenderTexture::ReliefType - } -} - -void RenderControl::drawMask(Surface &sf, const RenderColor &color, - const PixmapMask &mask) const -{ - assert(_screen == sf._screen); - assert(_screen == color.screen()); - - if (mask.mask == None) return; // no mask given - - int width = sf.size().width(), height = sf.size().height(); - - // set the clip region - int x = (width - mask.w) / 2, y = (height - mask.h) / 2; - XSetClipMask(**display, color.gc(), mask.mask); - XSetClipOrigin(**display, color.gc(), x, y); - - // fill in the clipped region - XFillRectangle(**display, sf.pixmap(), color.gc(), x, y, - x + mask.w, y + mask.h); - - // unset the clip region - XSetClipMask(**display, color.gc(), None); - XSetClipOrigin(**display, color.gc(), 0, 0); -} - -void RenderControl::drawGradientBackground( - Surface &sf, const RenderTexture &texture) const -{ - unsigned int r,g,b; - int w = sf.size().width(), h = sf.size().height(); - int off, x; - - const ScreenInfo *info = display->screenInfo(_screen); - XImage *im = XCreateImage(**display, info->visual(), info->depth(), - ZPixmap, 0, NULL, w, h, 32, 0); - im->byte_order = endian; - - switch (texture.gradient()) { - case RenderTexture::Vertical: - verticalGradient(sf, texture); - break; - case RenderTexture::Horizontal: - horizontalGradient(sf, texture); - break; - case RenderTexture::Diagonal: - diagonalGradient(sf, texture); - break; - case RenderTexture::CrossDiagonal: - crossDiagonalGradient(sf, texture); - break; - default: - printf("unhandled gradient\n"); - } - - pixel32 *data = sf.pixelData(); - pixel32 current; - - if (texture.relief() == RenderTexture::Flat && texture.border()) { - r = texture.borderColor().red(); - g = texture.borderColor().green(); - b = texture.borderColor().blue(); - current = (r << default_red_shift) - + (g << default_green_shift) - + (b << default_blue_shift); - for (off = 0, x = 0; x < w; ++x, off++) { - *(data + off) = current; - *(data + off + ((h-1) * w)) = current; - } - for (off = 0, x = 0; x < h; ++x, off++) { - *(data + (off * w)) = current; - *(data + (off * w) + w - 1) = current; - } - } - - if (texture.relief() != RenderTexture::Flat) { - if (texture.bevel() == RenderTexture::Bevel1) { - for (off = 1, x = 1; x < w - 1; ++x, off++) - highlight(data + off, - data + off + (h-1) * w, - texture.relief()==RenderTexture::Raised); - for (off = 0, x = 0; x < h; ++x, off++) - highlight(data + off * w, - data + off * w + w - 1, - texture.relief()==RenderTexture::Raised); - } - - if (texture.bevel() == RenderTexture::Bevel2) { - for (off = 2, x = 2; x < w - 2; ++x, off++) - highlight(data + off + w, - data + off + (h-2) * w, - texture.relief()==RenderTexture::Raised); - for (off = 1, x = 1; x < h-1; ++x, off++) - highlight(data + off * w + 1, - data + off * w + w - 2, - texture.relief()==RenderTexture::Raised); - } - } - - reduceDepth(sf, im); - sf.setPixmap(im); - XDestroyImage(im); -} - -void RenderControl::verticalGradient(Surface &sf, - const RenderTexture &texture) const -{ - pixel32 *data = sf.pixelData(); - pixel32 current; - float dr, dg, db; - unsigned int r,g,b; - int w = sf.size().width(), h = sf.size().height(); - - dr = (float)(texture.secondary_color().red() - texture.color().red()); - dr/= (float)h; - - dg = (float)(texture.secondary_color().green() - texture.color().green()); - dg/= (float)h; - - db = (float)(texture.secondary_color().blue() - texture.color().blue()); - db/= (float)h; - - for (int y = 0; y < h; ++y) { - r = texture.color().red() + (int)(dr * y); - g = texture.color().green() + (int)(dg * y); - b = texture.color().blue() + (int)(db * y); - current = (r << default_red_shift) - + (g << default_green_shift) - + (b << default_blue_shift); - for (int x = 0; x < w; ++x, ++data) - *data = current; - } -} - -void RenderControl::horizontalGradient(Surface &sf, - const RenderTexture &texture) const -{ - pixel32 *data = sf.pixelData(); - pixel32 current; - float dr, dg, db; - unsigned int r,g,b; - int w = sf.size().width(), h = sf.size().height(); - - dr = (float)(texture.secondary_color().red() - texture.color().red()); - dr/= (float)w; - - dg = (float)(texture.secondary_color().green() - texture.color().green()); - dg/= (float)w; - - db = (float)(texture.secondary_color().blue() - texture.color().blue()); - db/= (float)w; - - for (int x = 0; x < w; ++x, ++data) { - r = texture.color().red() + (int)(dr * x); - g = texture.color().green() + (int)(dg * x); - b = texture.color().blue() + (int)(db * x); - current = (r << default_red_shift) - + (g << default_green_shift) - + (b << default_blue_shift); - for (int y = 0; y < h; ++y) - *(data + y*w) = current; - } -} - -void RenderControl::diagonalGradient(Surface &sf, - const RenderTexture &texture) const -{ - pixel32 *data = sf.pixelData(); - pixel32 current; - float drx, dgx, dbx, dry, dgy, dby; - unsigned int r,g,b; - int w = sf.size().width(), h = sf.size().height(); - - for (int y = 0; y < h; ++y) { - drx = (float)(texture.secondary_color().red() - texture.color().red()); - dry = drx/(float)h; - drx/= (float)w; - - dgx = (float)(texture.secondary_color().green() - texture.color().green()); - dgy = dgx/(float)h; - dgx/= (float)w; - - dbx = (float)(texture.secondary_color().blue() - texture.color().blue()); - dby = dbx/(float)h; - dbx/= (float)w; - for (int x = 0; x < w; ++x, ++data) { - r = texture.color().red() + ((int)(drx * x) + (int)(dry * y))/2; - g = texture.color().green() + ((int)(dgx * x) + (int)(dgy * y))/2; - b = texture.color().blue() + ((int)(dbx * x) + (int)(dby * y))/2; - current = (r << default_red_shift) - + (g << default_green_shift) - + (b << default_blue_shift); - *data = current; - } - } -} - -void RenderControl::crossDiagonalGradient( - Surface &sf, const RenderTexture &texture) const -{ - pixel32 *data = sf.pixelData(); - pixel32 current; - float drx, dgx, dbx, dry, dgy, dby; - unsigned int r,g,b; - int w = sf.size().width(), h = sf.size().height(); - - for (int y = 0; y < h; ++y) { - drx = (float)(texture.secondary_color().red() - texture.color().red()); - dry = drx/(float)h; - drx/= (float)w; - - dgx = (float)(texture.secondary_color().green() - texture.color().green()); - dgy = dgx/(float)h; - dgx/= (float)w; - - dbx = (float)(texture.secondary_color().blue() - texture.color().blue()); - dby = dbx/(float)h; - dbx/= (float)w; - for (int x = w; x > 0; --x, ++data) { - r = texture.color().red() + ((int)(drx * (x-1)) + (int)(dry * y))/2; - g = texture.color().green() + ((int)(dgx * (x-1)) + (int)(dgy * y))/2; - b = texture.color().blue() + ((int)(dbx * (x-1)) + (int)(dby * y))/2; - current = (r << default_red_shift) - + (g << default_green_shift) - + (b << default_blue_shift); - *data = current; - } - } -} - -void RenderControl::highlight(pixel32 *x, pixel32 *y, bool raised) const -{ - int r, g, b; - - pixel32 *up, *down; - if (raised) { - up = x; - down = y; - } else { - up = y; - down = x; - } - r = (*up >> default_red_shift) & 0xFF; - r += r >> 1; - g = (*up >> default_green_shift) & 0xFF; - g += g >> 1; - b = (*up >> default_blue_shift) & 0xFF; - b += b >> 1; - if (r > 255) r = 255; - if (g > 255) g = 255; - if (b > 255) b = 255; - *up = (r << default_red_shift) + (g << default_green_shift) - + (b << default_blue_shift); - - r = (*down >> default_red_shift) & 0xFF; - r = (r >> 1) + (r >> 2); - g = (*down >> default_green_shift) & 0xFF; - g = (g >> 1) + (g >> 2); - b = (*down >> default_blue_shift) & 0xFF; - b = (b >> 1) + (b >> 2); - *down = (r << default_red_shift) + (g << default_green_shift) - + (b << default_blue_shift); -} - -void RenderControl::drawBackground(Surface& sf, - const RenderTexture &texture) const -{ - assert(_screen == sf._screen); - assert(_screen == texture.color().screen()); - - if (texture.gradient() == RenderTexture::Solid) - drawSolidBackground(sf, texture); - else - drawGradientBackground(sf, texture); -} - - -void RenderControl::drawImage(Surface &sf, int w, int h, - unsigned long *data) const -{ - pixel32 *bg = sf.pixelData(); - int c, sfw, sfh; - unsigned int i, e, bgi; - sfw = sf.size().width(); - sfh = sf.size().height(); - - if (w && h) { - // scale it - unsigned long *olddata = data; - unsigned long newdata[sfw*sfh]; - double dx = w / (double)sfw; - double dy = h / (double)sfh; - double px = 0.0; - double py = 0.0; - int iy = 0; - for (i = 0, c = 0, e = sfw*sfh; i < e; ++i) { - newdata[i] = olddata[(int)px + iy]; - if (++c >= sfw) { - c = 0; - px = 0; - py += dy; - iy = (int)py * w; - } else - px += dx; - } - data = newdata; - - // apply the alpha channel - for (i = 0, c = 0, e = sfw*sfh; i < e; ++i, ++bgi) { - unsigned char alpha = data[i] >> 24; - unsigned char r = data[i] >> 16; - unsigned char g = data[i] >> 8; - unsigned char b = data[i]; - - // background color - unsigned char bgr = bg[i] >> default_red_shift; - unsigned char bgg = bg[i] >> default_green_shift; - unsigned char bgb = bg[i] >> default_blue_shift; - - r = bgr + (((r - bgr) * alpha) >> 8); - g = bgg + (((g - bgg) * alpha) >> 8); - b = bgb + (((b - bgb) * alpha) >> 8); - - bg[i] = (r << default_red_shift) | (g << default_green_shift) | - (b << default_blue_shift); - } - } - - const ScreenInfo *info = display->screenInfo(_screen); - XImage *im = XCreateImage(**display, info->visual(), info->depth(), - ZPixmap, 0, NULL, sf.size().width(), - sf.size().height(), 32, 0); - im->byte_order = endian; - - reduceDepth(sf, im); - sf.setPixmap(im); - XDestroyImage(im); -} - -void RenderControl::drawImage(Surface &sf, Pixmap pixmap, Pixmap mask) const -{ - int junk, sfw, sfh, w, h, depth, mw, mh, mdepth; - Window wjunk; - const ScreenInfo *info = display->screenInfo(_screen); - GC mgc = 0; - - assert(pixmap != None); - - sfw = sf.size().width(); - sfh = sf.size().height(); - - XGetGeometry(**display, pixmap, &wjunk, &junk, &junk, - (unsigned int*)&w, (unsigned int*)&h, - (unsigned int*)&junk, (unsigned int*)&depth); - if (mask != None) { - XGetGeometry(**display, mask, &wjunk, &junk, &junk, - (unsigned int*)&mw, (unsigned int*)&mh, - (unsigned int*)&junk, (unsigned int*)&mdepth); - if (mw != w || mh != h || mdepth != 1) - return; - } - - Pixmap p = XCreatePixmap(**display, info->rootWindow(), sfw, sfh, - info->depth()); - Pixmap m; - if (mask == None) - m = None; - else { - m = XCreatePixmap(**display, info->rootWindow(), sfw, sfh, 1); - XGCValues gcv; - gcv.subwindow_mode = IncludeInferiors; - gcv.graphics_exposures = false; - mgc = XCreateGC(**display, m, GCGraphicsExposures | - GCSubwindowMode, &gcv); - } - - // scale it - for (int y = sfh - 1; y >= 0; --y) { - int yy = y * h / sfh; - for (int x = sfw - 1; x >= 0; --x) { - int xx = x * w / sfw; - if (depth != info->depth()) { - XCopyPlane(**display, pixmap, p, DefaultGC(**display, _screen), - xx, yy, 1, 1, x, y, 1); - } else { - XCopyArea(**display, pixmap, p, DefaultGC(**display, _screen), - xx, yy, 1, 1, x, y); - } - if (mask != None) - XCopyArea(**display, mask, m, mgc, xx, yy, 1, 1, x, y); - } - } - - XSetClipMask(**display, DefaultGC(**display, _screen), m); - XSetClipOrigin(**display, DefaultGC(**display, _screen), 0, 0); - XCopyArea(**display, p, sf.pixmap(), DefaultGC(**display, _screen), 0, 0, - sfw, sfh, 0, 0); - XSetClipMask(**display, DefaultGC(**display, _screen), None); - - XFreePixmap(**display, p); - if (m != None) XFreePixmap(**display, m); -} - -}
D otk/rendercontrol.hh

@@ -1,85 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __rendercontrol_hh -#define __rendercontrol_hh - -extern "C" { -#include <X11/Xlib.h> -#include <X11/Xutil.h> -} - -#include "surface.hh" - -namespace otk { - -class ScreenInfo; -class RenderTexture; -class Font; -class RenderColor; -class ustring; -class PixmapMask; - -class RenderControl { -protected: - int _screen; - -// bool _dither; - - RenderControl(int screen); - - inline void highlight(pixel32 *x, pixel32 *y, bool raised) const; - void verticalGradient(Surface &sf, const RenderTexture &texture) const; - void horizontalGradient(Surface &sf, const RenderTexture &texture) const; - void diagonalGradient(Surface &sf, const RenderTexture &texture) const; - void crossDiagonalGradient(Surface &sf, const RenderTexture &texture) const; - virtual void drawGradientBackground(Surface &sf, - const RenderTexture &texture) const; - virtual void drawSolidBackground(Surface& sf, - const RenderTexture& texture) const; - - //! Reduces a Surface's Surface::pixelData so that it will display correctly - //! on the screen's depth - /*! - This function allocates and sets the im->data member. The allocated memory - will be freed when XDetroyImage is called on the XImage. - */ - virtual void reduceDepth(Surface &sf, XImage *im) const = 0; - -public: - virtual ~RenderControl(); - - static RenderControl *createRenderControl(int screen); - - //! Draws a background onto a Surface, as specified by a RenderTexture - /*! - This function will overwrite the entire surface. - */ - virtual void drawBackground(Surface &sf, - const RenderTexture &texture) const; - - //! Draws an image onto the surface - /*! - This function will overwrite the entire surface.<br> - The image must be specified in 32-bit packed ARGB format. The current - background will be used for applying the alpha. - */ - virtual void drawImage(Surface &sf, int w, int h, - unsigned long *data) const; - - //! Draws an image onto the surface - virtual void drawImage(Surface &sf, Pixmap pixmap, Pixmap mask) const; - - //! Draws a string onto a Surface - virtual void drawString(Surface &sf, const Font &font, int x, int y, - const RenderColor &color, - const ustring &string) const; - - //! Draws a PixmapMask with a specified color onto a Surface - virtual void drawMask(Surface &sf, const RenderColor &color, - const PixmapMask &mask) const; - - virtual void allocateColor(XColor *color) const = 0; -}; - -} - -#endif // __rendercontrol_hh
D otk/renderstyle.cc

@@ -1,697 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "renderstyle.hh" -#include "display.hh" -#include "screeninfo.hh" - -#include <cassert> - -namespace otk { - -RenderStyle **RenderStyle::_styles = 0; -std::list<StyleNotify*> *RenderStyle::_notifies = 0; - -void RenderStyle::initialize() -{ - int screens = ScreenCount(**display); - _styles = new RenderStyle*[screens]; - for (int i = 0; i < screens; ++i) { - _styles[i] = new RenderStyle(); - defaultStyle(_styles[i], i); - } - _notifies = new std::list<StyleNotify*>[screens]; -} - -void RenderStyle::destroy() -{ - int screens = ScreenCount(**display); - for (int i = 0; i < screens; ++i) - delete _styles[i]; - delete [] _styles; - delete [] _notifies; -} - -void RenderStyle::registerNotify(int screen, StyleNotify *n) -{ - assert(screen >= 0 && screen < ScreenCount(**display)); - _notifies[screen].push_back(n); -} - -void RenderStyle::unregisterNotify(int screen, StyleNotify *n) -{ - assert(screen >= 0 && screen < ScreenCount(**display)); - _notifies[screen].remove(n); -} - -RenderStyle *RenderStyle::style(int screen) -{ - assert(screen >= 0 && screen < ScreenCount(**display)); - return _styles[screen]; -} - -bool RenderStyle::setStyle(int screen, const ustring &stylefile) -{ - RenderStyle *s = new RenderStyle(); - if (!loadStyle(s, screen, stylefile)) { - delete s; - return false; - } - delete _styles[screen]; - _styles[screen] = s; - - std::list<StyleNotify*>::iterator it, end = _notifies[screen].end(); - for (it = _notifies[screen].begin(); it != end; ++it) - (*it)->styleChanged(*s); - return true; -} - -bool RenderStyle::loadStyle(RenderStyle *s, int screen, - const ustring &stylefile) -{ - s->_screen = screen; - s->_file = stylefile; -// pick one.. -#define FIERON -//#define MERRY - -#ifdef FIERON - s->_root_args = "#272a2f"; - - s->_text_color_focus = new RenderColor(screen, 0x272a2f); - s->_text_color_unfocus = new RenderColor(screen, 0x676869); - - s->_button_color_focus = new RenderColor(screen, 0x96ba86); - s->_button_color_unfocus = new RenderColor(screen, 0x676869); - - s->_frame_border_color = new RenderColor(screen, 0x181f24); - s->_frame_border_width = 1; - - s->_client_border_color_focus = new RenderColor(screen, 0x858687); - s->_client_border_color_unfocus = new RenderColor(screen, 0x555657); - s->_client_border_width = 1; - - s->_titlebar_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Vertical, - false, - 0x858687, - 0x373a3f, - 0x0, - 0x0); - s->_titlebar_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Vertical, - false, - 0x555657, - 0x171a1f, - 0x0, - 0x0); - - s->_label_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - true, - RenderTexture::Vertical, - false, - 0x96ba86, - 0x5a724c, - 0x181f24, - 0x0); - s->_label_unfocus = new RenderTexture(screen, - false, - RenderTexture::Sunken, - RenderTexture::Bevel1, - false, - RenderTexture::CrossDiagonal, - false, - 0x555657, - 0x272a2f, - 0x0, - 0x0); - - s->_handle_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Vertical, - false, - 0x858687, - 0x373a3f, - 0x0, - 0x0); - s->_handle_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Vertical, - false, - 0x555657, - 0x171a1f, - 0x0, - 0x0); - - s->_button_unpress_focus = new RenderTexture(screen, - false, - RenderTexture::Raised, - RenderTexture::Bevel2, - false, - RenderTexture::CrossDiagonal, - false, - 0x858687, - 0x272a2f, - 0x0, - 0x0); - s->_button_unpress_unfocus = new RenderTexture(screen, - false, - RenderTexture::Raised, - RenderTexture::Bevel2, - false, - RenderTexture::CrossDiagonal, - false, - 0x555657, - 0x171a1f, - 0x0, - 0x0); - - s->_button_press_focus = new RenderTexture(screen, - false, - RenderTexture::Sunken, - RenderTexture::Bevel2, - false, - RenderTexture::CrossDiagonal, - false, - 0x96ba86, - 0x5a724c, - 0x0, - 0x0); - s->_button_press_unfocus = new RenderTexture(screen, - false, - RenderTexture::Sunken, - RenderTexture::Bevel2, - false, - RenderTexture::CrossDiagonal, - false, - 0x555657, - 0x171a1f, - 0x0, - 0x0); - - s->_grip_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Vertical, - false, - 0x96ba86, - 0x5a724c, - 0x0, - 0x0); - s->_grip_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Vertical, - false, - 0x555657, - 0x171a1f, - 0x0, - 0x0); - - s->_label_font = new Font(screen, "Arial,Sans-9:bold", true, 1, 0x40); - s->_label_justify = RightBottomJustify; - - s->_max_mask = new PixmapMask(); - s->_max_mask->w = s->_max_mask->h = 8; - { - //char data[] = { 0x7e, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0x7e }; - char data [] = {0x00, 0x00, 0x18, 0x3c, 0x66, 0x42, 0x00, 0x00 }; - s->_max_mask->mask = - XCreateBitmapFromData(**display, - display->screenInfo(screen)->rootWindow(), - data, 8, 8); - } - - s->_icon_mask = new PixmapMask(); - s->_icon_mask->w = s->_icon_mask->h = 8; - { - //char data[] = { 0x00, 0x00, 0xc3, 0xe7, 0x7e, 0x3c, 0x18, 0x00 }; - char data[] = { 0x00, 0x00, 0x42, 0x66, 0x3c, 0x18, 0x00, 0x00 }; - s->_icon_mask->mask = - XCreateBitmapFromData(**display, - display->screenInfo(screen)->rootWindow(), - data, 8, 8); - } - - s->_alldesk_mask = new PixmapMask(); - s->_alldesk_mask->w = s->_alldesk_mask->h = 8; - { - //char data[] = { 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00 }; - char data[] = { 0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00 }; - s->_alldesk_mask->mask = - XCreateBitmapFromData(**display, - display->screenInfo(screen)->rootWindow(), - data, 8, 8); - } - - s->_close_mask = new PixmapMask(); - s->_close_mask->w = s->_close_mask->h = 8; - { - //char data[] = { 0xc3, 0xe7, 0x7e, 0x3c, 0x3c, 0x7e, 0xe7, 0xc3 }; - char data[] = { 0x00, 0xc3, 0x66, 0x3c, 0x3c, 0x66, 0xc3, 0x00 }; - s->_close_mask->mask = - XCreateBitmapFromData(**display, - display->screenInfo(screen)->rootWindow(), - data, 8, 8); - } - - s->_bevel_width = 1; - s->_handle_width = 4; -#else -# ifdef MERRY - s->_root_args = "#7b756a"; - - s->_text_color_focus = new RenderColor(screen, 0xffffff); - s->_text_color_unfocus = new RenderColor(screen, 0xffffff); - - s->_button_color_focus = new RenderColor(screen, 0x222222); - s->_button_color_unfocus = new RenderColor(screen, 0x333333); - - s->_frame_border_color = new RenderColor(screen, 0x222222); - s->_frame_border_width = 1; - - s->_client_border_color_focus = new RenderColor(screen, 0x858687); - s->_client_border_color_unfocus = new RenderColor(screen, 0x555657); - s->_client_border_width = 0; - - s->_titlebar_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0xe6e6e6, - 0xe6e6e6, - 0x0, - 0x0); - s->_titlebar_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0xe6e6e6, - 0xd9d9d9, - 0x0, - 0x0); - - s->_label_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - true, - RenderTexture::Vertical, - false, - //0x6a6973, - //0x6a6973, - 0x4c59a6, - 0x5a6dbd, - 0x222222, - 0x0); - //urg this ain't so hot - s->_label_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - true, - RenderTexture::Vertical, - false, - 0xb4b2ad, - 0xc3c1bc, - 0x6a696a, - 0x0); - - - s->_handle_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Vertical, - false, - 0xe6e6e6, - 0xd9d9d9, - 0x0, - 0x0); - s->_handle_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0xe6e6e6, - 0xe6e6e6, - 0x0, - 0x0); - - - s->_button_unpress_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0xe6e6e6, - 0xe6e6e6, - 0x0, - 0x0); - s->_button_unpress_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0xe6e6e6, - 0xe6e6e6, - 0x0, - 0x0); - - s->_button_press_focus = new RenderTexture(screen, - false, - RenderTexture::Sunken, - RenderTexture::Bevel2, - false, - RenderTexture::Vertical, - false, - 0xe6e6e6, - 0xe6e6e6, - 0x0, - 0x0); - s->_button_press_unfocus = new RenderTexture(screen, - false, - RenderTexture::Sunken, - RenderTexture::Bevel2, - false, - RenderTexture::Vertical, - false, - 0xe6e6e6, - 0xe6e6e6, - 0x0, - 0x0); - - s->_grip_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Vertical, - false, - 0xe6e6e6, - 0xd9d9d9, - 0x0, - 0x0); - s->_grip_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0xe6e6e6, - 0xe6e6e6, - 0x0, - 0x0); - - s->_label_font = new Font(screen, "Arial,Sans-8", true, 1, 0x3e); - s->_label_justify = CenterJustify; - - s->_max_mask = new PixmapMask(); - s->_max_mask->w = s->_max_mask->h = 7; - { - char data [] = {0x7c, 0x44, 0x47, 0x47, 0x7f, 0x1f, 0x1f }; - s->_max_mask->mask = - XCreateBitmapFromData(**display, - display->screenInfo(screen)->rootWindow(), - data, 7, 7); - } - - s->_icon_mask = new PixmapMask(); - s->_icon_mask->w = s->_icon_mask->h = 7; - { - char data[] = { 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e }; - s->_icon_mask->mask = - XCreateBitmapFromData(**display, - display->screenInfo(screen)->rootWindow(), - data, 7, 7); - } - - s->_alldesk_mask = new PixmapMask(); - s->_alldesk_mask->w = s->_alldesk_mask->h = 7; - { - char data[] = {0x00, 0x36, 0x36, 0x00, 0x36, 0x36, 0x00 }; - s->_alldesk_mask->mask = - XCreateBitmapFromData(**display, - display->screenInfo(screen)->rootWindow(), - data, 7, 7); - } - - s->_close_mask = new PixmapMask(); - s->_close_mask->w = s->_close_mask->h = 7; - { - char data[] = { 0x22, 0x77, 0x3e, 0x1c, 0x3e, 0x77, 0x22 }; - s->_close_mask->mask = - XCreateBitmapFromData(**display, - display->screenInfo(screen)->rootWindow(), - data, 7, 7); - } - - s->_bevel_width = 1; - s->_handle_width = 3; -# else -# error 1 -# endif -#endif - - return true; -} - -void RenderStyle::defaultStyle(RenderStyle *s, int screen) -{ - s->_screen = screen; - s->_file = ""; - - s->_root_args = "#000000"; - s->_text_color_focus = new RenderColor(screen, 0xffffff); - s->_text_color_unfocus = new RenderColor(screen, 0xffffff); - s->_button_color_focus = new RenderColor(screen, 0xffffff); - s->_button_color_unfocus = new RenderColor(screen, 0xffffff); - s->_frame_border_color = new RenderColor(screen, 0); - s->_frame_border_width = 1; - s->_client_border_color_focus = new RenderColor(screen, 0); - s->_client_border_color_unfocus = new RenderColor(screen, 0); - s->_client_border_width = 1; - s->_titlebar_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - s->_titlebar_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - - s->_label_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - true, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - s->_label_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - - s->_handle_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - s->_handle_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - - s->_button_unpress_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - true, - RenderTexture::Solid, - false, - 0, 0, 0xffffff, 0); - s->_button_unpress_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - - s->_button_press_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - true, - RenderTexture::Solid, - false, - 0, 0, 0xffffff, 0); - s->_button_press_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - - s->_grip_focus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - s->_grip_unfocus = new RenderTexture(screen, - false, - RenderTexture::Flat, - RenderTexture::Bevel1, - false, - RenderTexture::Solid, - false, - 0, 0, 0, 0); - - s->_label_font = new Font(screen, "Sans-9", false, 0, 0); - s->_label_justify = LeftTopJustify; - - s->_max_mask = new PixmapMask(); - s->_max_mask->w = s->_max_mask->h = 0; - s->_max_mask->mask = None; - - s->_icon_mask = new PixmapMask(); - s->_icon_mask->w = s->_icon_mask->h = 0; - s->_icon_mask->mask = None; - - s->_alldesk_mask = new PixmapMask(); - s->_alldesk_mask->w = s->_alldesk_mask->h = 0; - s->_alldesk_mask->mask = 0; - - s->_close_mask = new PixmapMask(); - s->_close_mask->w = s->_close_mask->h = 8; - s->_close_mask->mask = 0; - - s->_bevel_width = 1; - s->_handle_width = 4; -} - -RenderStyle::~RenderStyle() -{ - assert(_text_color_focus); - delete _text_color_focus; - assert(_text_color_unfocus); - delete _text_color_unfocus; - - assert(_button_color_focus); - delete _button_color_focus; - assert(_button_color_unfocus); - delete _button_color_unfocus; - - assert(_frame_border_color); - delete _frame_border_color; - - assert(_client_border_color_focus); - delete _client_border_color_focus; - assert(_client_border_color_unfocus); - delete _client_border_color_unfocus; - - assert(_titlebar_focus); - delete _titlebar_focus; - assert(_titlebar_unfocus); - delete _titlebar_unfocus; - - assert(_label_focus); - delete _label_focus; - assert(_label_unfocus); - delete _label_unfocus; - - assert(_handle_focus); - delete _handle_focus; - assert(_handle_unfocus); - delete _handle_unfocus; - - assert(_button_unpress_focus); - delete _button_unpress_focus; - assert(_button_unpress_unfocus); - delete _button_unpress_unfocus; - assert(_button_press_focus); - delete _button_press_focus; - assert(_button_press_unfocus); - delete _button_press_unfocus; - - assert(_grip_focus); - delete _grip_focus; - assert(_grip_unfocus); - delete _grip_unfocus; - - assert(_label_font); - delete _label_font; - - assert(_max_mask); - delete _max_mask; - assert(_icon_mask); - delete _icon_mask; - assert(_alldesk_mask); - delete _alldesk_mask; - assert(_close_mask); - delete _close_mask; -} - -}
D otk/renderstyle.hh

@@ -1,157 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __renderstyle_hh -#define __renderstyle_hh - -#include "rendertexture.hh" -#include "rendercolor.hh" -#include "font.hh" -#include "ustring.hh" - -#include <list> -#include <string> - -namespace otk { - -struct PixmapMask { - Pixmap mask; - unsigned int w, h; - PixmapMask() { mask = None; w = h = 0; } -}; - -class RenderStyle; - -class StyleNotify { -public: - //! Called when the style is changed on the same screen as the handler. - virtual void styleChanged(const RenderStyle &) {} -}; - -class RenderStyle { - static RenderStyle **_styles; - static std::list<StyleNotify*> *_notifies; -public: - static void initialize(); - static void destroy(); - static void registerNotify(int screen, StyleNotify *n); - static void unregisterNotify(int screen, StyleNotify *n); - static RenderStyle *style(int screen); - static bool setStyle(int screen, const ustring &stylefile); - - enum Justify { - LeftTopJustify, - RightBottomJustify, - CenterJustify - }; - -private: - static bool loadStyle(RenderStyle *s, int screen, const ustring &stylefile); - static void defaultStyle(RenderStyle *s, int screen); - - int _screen; - ustring _file; - - std::string _root_args; - - RenderColor *_text_color_focus; - RenderColor *_text_color_unfocus; - - RenderColor *_button_color_focus; - RenderColor *_button_color_unfocus; - - RenderColor *_frame_border_color; - int _frame_border_width; - - RenderColor *_client_border_color_focus; - RenderColor *_client_border_color_unfocus; - int _client_border_width; - - RenderTexture *_titlebar_focus; - RenderTexture *_titlebar_unfocus; - - RenderTexture *_label_focus; - RenderTexture *_label_unfocus; - - RenderTexture *_handle_focus; - RenderTexture *_handle_unfocus; - - RenderTexture *_button_unpress_focus; - RenderTexture *_button_unpress_unfocus; - RenderTexture *_button_press_focus; - RenderTexture *_button_press_unfocus; - - RenderTexture *_grip_focus; - RenderTexture *_grip_unfocus; - - Font *_label_font; - Justify _label_justify; - - PixmapMask *_max_mask; - PixmapMask *_icon_mask; - PixmapMask *_alldesk_mask; - PixmapMask *_close_mask; - - int _handle_width; - int _bevel_width; - -public: - virtual ~RenderStyle(); - - inline int screen() const { return _screen; } - - inline const std::string& rootArgs() const { return _root_args; } - - inline RenderColor *textFocusColor() const { return _text_color_focus; } - inline RenderColor *textUnfocusColor() const { return _text_color_unfocus; } - - inline RenderColor *buttonFocusColor() const { return _button_color_focus; } - inline RenderColor *buttonUnfocusColor() const - { return _button_color_unfocus; } - - inline RenderColor *frameBorderColor() const { return _frame_border_color; } - inline int frameBorderWidth() const { return _frame_border_width; } - - inline RenderColor *clientBorderFocusColor() const - { return _client_border_color_focus; } - inline RenderColor *clientBorderUnfocusColor() const - { return _client_border_color_unfocus; } - inline int clientBorderWidth() const { return _client_border_width; } - - inline RenderTexture *titlebarFocusBackground() const - { return _titlebar_focus; } - inline RenderTexture *titlebarUnfocusBackground() const - { return _titlebar_unfocus; } - - inline RenderTexture *labelFocusBackground() const { return _label_focus; } - inline RenderTexture *labelUnfocusBackground() const { return _label_unfocus;} - - inline RenderTexture *handleFocusBackground() const { return _handle_focus; } - inline RenderTexture *handleUnfocusBackground() const - { return _handle_unfocus; } - - inline RenderTexture *buttonUnpressFocusBackground() const - { return _button_unpress_focus; } - inline RenderTexture *buttonUnpressUnfocusBackground() const - { return _button_unpress_unfocus; } - inline RenderTexture *buttonPressFocusBackground() const - { return _button_press_focus; } - inline RenderTexture *buttonPressUnfocusBackground() const - { return _button_press_unfocus; } - - inline RenderTexture *gripFocusBackground() const { return _grip_focus; } - inline RenderTexture *gripUnfocusBackground() const { return _grip_unfocus; } - - inline Font *labelFont() const { return _label_font; } - inline Justify labelTextJustify() const { return _label_justify; } - - inline PixmapMask *maximizeMask() const { return _max_mask; } - inline PixmapMask *iconifyMask() const { return _icon_mask; } - inline PixmapMask *alldesktopsMask() const { return _alldesk_mask; } - inline PixmapMask *closeMask() const { return _close_mask; } - - inline int handleWidth() const { return _handle_width; } - inline int bevelWidth() const { return _bevel_width; } -}; - -} - -#endif // __renderstyle_hh
D otk/rendertest.cc

@@ -1,45 +0,0 @@

-#include "config.h" - -#include "otk.hh" -#include "rendercontrol.hh" -#include "rendertexture.hh" - -extern "C" { -#include <X11/Xlib.h> -} - -#include <cstdio> - -int main(int argc, char **argv) -{ - printf("\n"); - - otk::Application app(argc, argv); - otk::AppWidget foo(&app); - foo.resize(600, 500); - - otk::RenderColor color(0, 0x96, 0xba, 0x86); - otk::RenderColor color2(0, 0x5a, 0x72, 0x4c); - otk::RenderColor colord(0, 0, 0, 0); - otk::RenderColor colorl(0, 0xff, 0xff, 0xff); - otk::RenderTexture tex(false, - otk::RenderTexture::Raised, - otk::RenderTexture::Bevel1, - false, - otk::RenderTexture::Vertical, - false, - &color, - &color2, - &colord, - &colorl, - 0, - 0); - foo.setTexture(&tex); - - foo.show(); - - app.run(); - - printf("\n"); - return 0; -}
D otk/rendertexture.hh

@@ -1,169 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __rendertexture_hh -#define __rendertexture_hh - -#include "rendercolor.hh" - -namespace otk { - -//! Superclass for all the Textures -class RenderTexture { -public: - enum ReliefType { - Flat, - Raised, - Sunken - }; - enum BevelType { - Bevel1, - Bevel2 - }; - enum GradientType { - Solid, - Horizontal, - Vertical, - Diagonal, - CrossDiagonal, - PipeCross, - Rectangle, - Pyramid, - Elliptic - }; - -private: - int _screen; - - //! If true, the texture is not rendered at all, so all options are ignored - bool _parent_relative; - //! The relief type of the texture - ReliefType _relief; - //! The way the bevel should be drawn - BevelType _bevel; - //! If a flat border is drawn on the outside, ignored for all ReliefType - //! values except ReliefType::Flat - bool _border; - //! The type of gradient to fill the texture with (if any) - GradientType _gradient; - //! If interlace lines should be drawn over the texture - bool _interlaced; - - //! The base color for the texture, the only color when the texture is solid. - //! This must always be defined - const RenderColor *_color; - //! The secondary color for a gradient texture. - //! This is only defined for gradients - const RenderColor *_secondary_color; - //! The shadow color for the bevel. This must be defined if - //! RenderTexture::_relief is not RenderTexture::ReliefType::Flat - const RenderColor *_bevel_dark_color; - //! The light color for the bevel. This must be defined if - //! RenderTexture::_relief is not RenderTexture::ReliefType::Flat - const RenderColor *_bevel_light_color; - //! The color for the flat border if RenderTexture::_border is true. This - //! must be defined if it is true - const RenderColor *_border_color; - //! The color for the interlace lines if RenderTexture. This must be defined - //! if it is true - const RenderColor *_interlace_color; - -public: - RenderTexture(int screen, - bool parent_relative, ReliefType relief, BevelType bevel, - bool border, GradientType gradient, bool interlaced, - const RGB &color, - const RGB &secondary_color, - const RGB &border_color, - const RGB &interlace_color) - : _screen(screen), - _parent_relative(parent_relative), - _relief(relief), - _bevel(bevel), - _border(border), - _gradient(gradient), - _interlaced(interlaced), - _color(new RenderColor(screen, color)), - _secondary_color(new RenderColor(screen, secondary_color)), - _bevel_dark_color(0), - _bevel_light_color(0), - _border_color(new RenderColor(screen, border_color)), - _interlace_color(new RenderColor(screen, interlace_color)) - { - if (_relief != Flat) { - unsigned char r, g, b; - - // calculate the light bevel color - r = _color->red() + _color->red() / 2; - g = _color->green() + _color->green() / 2; - b = _color->blue() + _color->blue() / 2; - // watch for wraparound - if (r < _color->red()) r = 0xff; - if (g < _color->green()) g = 0xff; - if (b < _color->blue()) b = 0xff; - _bevel_dark_color = new RenderColor(screen, r, g, b); - - // calculate the dark bevel color - r = _color->red() / 4 + _color->red() / 2; - g = _color->green() / 4 + _color->green() / 2; - b = _color->blue() / 4 + _color->blue() / 2; - _bevel_light_color = new RenderColor(screen, r, g, b); - } - - assert(_relief == Flat || (_bevel_dark_color && _bevel_light_color)); - //assert(!_border || _border_color); - //assert(!_interlaced || _interlace_color); - assert(_color); - assert(_secondary_color); - assert(_border_color); - assert(_interlace_color); - } - - virtual ~RenderTexture() { - delete _color; - delete _secondary_color; - if (_bevel_dark_color) delete _bevel_dark_color; - if (_bevel_dark_color) delete _bevel_light_color; - delete _border_color; - delete _interlace_color; - } - - //! If true, the texture is not rendered at all, so all options are ignored - inline bool parentRelative() const { return _parent_relative; } - //! The relief type of the texture - inline ReliefType relief() const { return _relief; } - //! The way the bevel should be drawn - inline BevelType bevel() const { return _bevel; } - //! If a flat border is drawn on the outside, ignored for all ReliefType - //! values except ReliefType::Flat - inline bool border() const { return _border; } - //! The type of gradient to fill the texture with (if any) - inline GradientType gradient() const { return _gradient; } - //! If interlace lines should be drawn over the texture - inline bool interlaced() const { return _interlaced; } - - //! The base color for the texture, the only color when the texture is solid. - //! This must always be defined - inline const RenderColor& color() const { return *_color; } - //! The secondary color for gradient textures. - //! This is only defined for gradients - inline const RenderColor& secondary_color() const - { return *_secondary_color; } - //! The shadow color for the bevel. This must be defined if - //! RenderTexture::_relief is not RenderTexture::ReliefType::Flat - inline const RenderColor& bevelDarkColor() const - { return *_bevel_dark_color; } - //! The light color for the bevel. This must be defined if - //! RenderTexture::)relief is not RenderTexture::ReliefType::Flat - inline const RenderColor& bevelLightColor() const - { return *_bevel_light_color; } - //! The color for the flat border if RenderTexture::_border is true. This - //! must be defined if it is true - inline const RenderColor& borderColor() const { return *_border_color; } - //! The color for the interlace lines if RenderTexture. This must be defined - //! if it is true - inline const RenderColor& interlaceColor() const - { return *_interlace_color; } -}; - -} - -#endif // __rendertexture_hh
D otk/screeninfo.cc

@@ -1,81 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -extern "C" { -#include <X11/Xlib.h> -#include <X11/Xutil.h> -} - -#include "screeninfo.hh" -#include "display.hh" -#include "util.hh" - -using std::string; - -namespace otk { - -ScreenInfo::ScreenInfo(int num) { - assert(num >= 0 && num < ScreenCount(**display)); - - _screen = num; - - _root_window = RootWindow(**display, _screen); - - _size = Size(WidthOfScreen(ScreenOfDisplay(**display, - _screen)), - HeightOfScreen(ScreenOfDisplay(**display, - _screen))); - // get the default display string and strip the screen number - string default_string = DisplayString(**display); - const string::size_type pos = default_string.rfind("."); - if (pos != string::npos) - default_string.resize(pos); - - _display_string = string("DISPLAY=") + default_string + '.' + - itostring(static_cast<unsigned long>(_screen)); - -#if 0 //def XINERAMA - _xinerama_active = False; - - if (d->hasXineramaExtensions()) { - if (d->getXineramaMajorVersion() == 1) { - // we know the version 1(.1?) protocol - - /* - in this version of Xinerama, we can't query on a per-screen basis, but - in future versions we should be able, so the 'activeness' is checked - on a pre-screen basis anyways. - */ - if (XineramaIsActive(**display)) { - /* - If Xinerama is being used, there there is only going to be one screen - present. We still, of course, want to use the screen class, but that - is why no screen number is used in this function call. There should - never be more than one screen present with Xinerama active. - */ - int num; - XineramaScreenInfo *info = XineramaQueryScreens(**display, &num); - if (num > 0 && info) { - _xinerama_areas.reserve(num); - for (int i = 0; i < num; ++i) { - _xinerama_areas.push_back(Rect(info[i].x_org, info[i].y_org, - info[i].width, info[i].height)); - } - XFree(info); - - // if we can't find any xinerama regions, then we act as if it is not - // active, even though it said it was - _xinerama_active = true; - } - } - } - } -#else - _xinerama_active = false; -#endif // XINERAMA - if (!_xinerama_active) - _xinerama_areas.push_back(Rect(Point(0, 0), _size)); -} - -}
D otk/screeninfo.hh

@@ -1,42 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __screeninfo_hh -#define __screeninfo_hh - -#include "size.hh" -#include "rect.hh" - -extern "C" { -#include <X11/Xlib.h> -} - -#include <string> -#include <vector> - -namespace otk { - -class ScreenInfo { -private: - int _screen; - std::string _display_string; - Size _size; - std::vector<Rect> _xinerama_areas; - bool _xinerama_active; - -public: - ScreenInfo(int num); - - inline Visual *visual() const { return _visual; } - inline Window rootWindow() const { return _root_window; } - inline Colormap colormap() const { return _colormap; } - inline int depth() const { return _depth; } - inline int screen() const { return _screen; } - inline const Size& size() const { return _size; } - inline const std::string& displayString() const { return _display_string; } - inline const std::vector<Rect> &xineramaAreas() const - { return _xinerama_areas; } - inline bool isXineramaActive() const { return _xinerama_active; } -}; - -} - -#endif // __screeninfo_hh
D otk/size.hh

@@ -1,25 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __size_hh -#define __size_hh - -#include <cassert> - -namespace otk { - -class Size { - int _w, _h; -public: - Size() : _w(1), _h(1) {} - Size(int w, int h) : _w(w), _h(h) { assert(_w >= 0 && _h >= 0); } - Size(const Size &s) : _w(s._w), _h(s._h) { assert(_w >= 0 && _h >= 0); } - - inline int width() const { return _w; } - inline int height() const { return _h; } - - bool operator==(const Size &o) const { return _w == o._w && _h == o._h; } - bool operator!=(const Size &o) const { return _w != o._w || _h != o._h; } -}; - -} - -#endif // __size_hh
D otk/strut.hh

@@ -1,35 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __strut_hh -#define __strut_hh - -/*! @file strut.hh - @brief The Strut struct defines a margin on 4 sides -*/ - -namespace otk { - -//! Defines a margin on 4 sides -struct Strut { - //! The margin on the top of the Strut - unsigned int top; - //! The margin on the bottom of the Strut - unsigned int bottom; - //! The margin on the left of the Strut - unsigned int left; - //! The margin on the right of the Strut - unsigned int right; - - //! Constructs a new Strut with no margins - Strut(void): top(0), bottom(0), left(0), right(0) {} - //! Constructs a new Strut with margins - Strut(int l, int t, int r, int b): top(t), bottom(b), left(l), right(r) {} - - bool operator==(const Strut &o) const { - return top == o.top && bottom == o.bottom && left == o.left && - right == o.right; - } -}; - -} - -#endif // __strut_hh
D otk/surface.cc

@@ -1,97 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "surface.hh" -#include "display.hh" -#include "screeninfo.hh" -#include "rendercolor.hh" - -extern "C" { -#include <X11/Xutil.h> -#include <cstring> -} - -namespace otk { - -Surface::Surface(int screen, const Size &size) - : _screen(screen), - _size(size), - _pixel_data(new pixel32[size.width()*size.height()]), - _pixmap(None), - _xftdraw(0) -{ -} - -Surface::~Surface() -{ - destroyObjects(); - freePixelData(); -} - -void Surface::freePixelData() -{ - if (_pixel_data) { - delete [] _pixel_data; - _pixel_data = 0; - } -} - -void Surface::setPixmap(const RenderColor &color) -{ - assert(_pixel_data); - if (_pixmap == None) - createObjects(); - - XFillRectangle(**display, _pixmap, color.gc(), 0, 0, - _size.width(), _size.height()); - - pixel32 val = (color.red() << default_red_shift) | - (color.green() << default_green_shift) | - (color.blue() << default_blue_shift); - for (unsigned int i = 0, s = _size.width() * _size.height(); i < s; ++i) - _pixel_data[i] = val; -} - -void Surface::setPixmap(XImage *image) -{ - assert(_pixel_data); - assert(image->width == _size.width()); - assert(image->height == _size.height()); - - if (_pixmap == None) - createObjects(); - - XPutImage(**display, _pixmap, DefaultGC(**display, _screen), - image, 0, 0, 0, 0, _size.width(), _size.height()); -} - -void Surface::createObjects() -{ - assert(_pixmap == None); assert(!_xftdraw); - - const ScreenInfo *info = display->screenInfo(_screen); - - _pixmap = XCreatePixmap(**display, info->rootWindow(), - _size.width(), _size.height(), info->depth()); - assert(_pixmap != None); - - _xftdraw = XftDrawCreate(**display, _pixmap, - info->visual(), info->colormap()); - assert(_xftdraw); -} - -void Surface::destroyObjects() -{ - if (_xftdraw) { - XftDrawDestroy(_xftdraw); - _xftdraw = 0; - } - - if (_pixmap != None) { - XFreePixmap(**display, _pixmap); - _pixmap = None; - } -} - -}
D otk/surface.hh

@@ -1,88 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __surface_hh -#define __surface_hh - -#include "size.hh" - -extern "C" { -#include <X11/Xlib.h> -#define _XFT_NO_COMPAT_ // no Xft 1 API -#include <X11/Xft/Xft.h> - -#ifdef HAVE_STDINT_H -# include <stdint.h> -#else -# ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> -# endif -#endif -} - -namespace otk { - -class ScreenInfo; -class RenderColor; -class RenderControl; -class TrueRenderControl; -class PseudoRenderControl; - -#ifdef HAVE_STDINT_H -typedef uint32_t pixel32; -typedef uint16_t pixel16; -#else -typedef u_int32_t pixel32; -typedef u_int16_t pixel16; -#endif /* HAVE_STDINT_H */ - -#ifdef WORDS_BIGENDIAN -const int default_red_shift=0; -const int default_green_shift=8; -const int default_blue_shift=16; -const int endian=MSBFirst; -#else -const int default_red_shift=16; -const int default_green_shift=8; -const int default_blue_shift=0; -const int endian=LSBFirst; -#endif /* WORDS_BIGENDIAN */ - -class Surface { - int _screen; - Size _size; - pixel32 *_pixel_data; - Pixmap _pixmap; - XftDraw *_xftdraw; - -protected: - void createObjects(); - void destroyObjects(); - - void setPixmap(XImage *image); - void setPixmap(const RenderColor &color); - -public: - Surface(int screen, const Size &size); - virtual ~Surface(); - - inline int screen(void) const { return _screen; } - - const Size& size() const { return _size; } - - Pixmap pixmap() const { return _pixmap; } - - pixel32 *pixelData() { return _pixel_data; } - - //! Frees the pixel data when it will no longer be needed. Only do this once - //! you have completed rendering onto the surface. - void freePixelData(); - - // The RenderControl classes use the internal objects in this class to render - // to it. Noone else needs them tho, so they are private. - friend class RenderControl; - friend class TrueRenderControl; - friend class PseudoRenderControl; -}; - -} - -#endif // __surface_hh
D otk/timer.cc

@@ -1,145 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "timer.hh" -#include "display.hh" - -extern "C" { -#ifdef HAVE_SYS_SELECT_H -# include <sys/select.h> -#endif // HAVE_SYS_SELECT_H - -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif -} - -namespace otk { - -timeval Timer::_nearest_timeout, Timer::_now; -Timer::TimerQ Timer::_q; - -void Timer::timevalAdd(timeval &a, long msec) -{ - a.tv_sec += msec / 1000; - a.tv_usec += (msec % 1000) * 1000; - a.tv_sec += a.tv_usec / 1000000; - a.tv_usec %= 1000000; -} - -bool Timer::nearestTimeout(struct timeval &tm) -{ - if (_q.empty()) - return false; - tm.tv_sec = _nearest_timeout.tv_sec - _now.tv_sec; - tm.tv_usec = _nearest_timeout.tv_usec - _now.tv_usec; - - while (tm.tv_usec < 0) { - tm.tv_usec += 1000000; - tm.tv_sec--; - } - tm.tv_sec += tm.tv_usec / 1000000; - tm.tv_usec %= 1000000; - if (tm.tv_sec < 0) - tm.tv_sec = 0; - - return true; -} - -void Timer::dispatchTimers(bool wait) -{ - fd_set selset; - int fd; - timeval next; - Timer *curr; - - gettimeofday(&_now, NULL); - _nearest_timeout = _now; - _nearest_timeout.tv_sec += 10000; - - while (!_q.empty()) { - curr = _q.top(); - /* since we overload the destructor to keep from removing from the middle - of the priority queue, set _del_me, we have to do our real delete in - here. - */ - if (curr->_del_me) { - _q.pop(); - realDelete(curr); - continue; - } - - // the queue is sorted, so if this timer shouldn't fire, none are ready - _nearest_timeout = curr->_timeout; - if (!timercmp(&_now, &_nearest_timeout, >)) - break; - - /* we set the last fired time to delay msec after the previous firing, then - re-insert. timers maintain their order and may trigger more than once - if they've waited more than one delay's worth of time. - */ - _q.pop(); - timevalAdd(curr->_last, curr->_delay); - curr->_action(curr->_data); - timevalAdd(curr->_timeout, curr->_delay); - _q.push(curr); - - /* if at least one timer fires, then don't wait on X events, as there may - already be some in the queue from the timer callbacks. - */ - wait = false; - } - - if (wait) { - // wait for the nearest trigger, or for X to do something interesting - fd = ConnectionNumber(**display); - FD_ZERO(&selset); - FD_SET(fd, &selset); - if (nearestTimeout(next)) { - select(fd + 1, &selset, NULL, NULL, &next); - } else - select(fd + 1, &selset, NULL, NULL, NULL); - } -} - -Timer::Timer(long delay, Timer::TimeoutHandler action, void *data) - : _delay(delay), - _action(action), - _data(data), - _del_me(false), - _last(_now), - _timeout(_now) -{ - timevalAdd(_timeout, delay); - _q.push(this); -} - -void Timer::operator delete(void *self) -{ - Timer *t; - t = (Timer *)self; - t->_del_me = true; -} - -void Timer::realDelete(Timer *me) -{ - ::delete me; -} - -void Timer::initialize(void) -{ - gettimeofday(&_now, NULL); - _nearest_timeout.tv_sec = 100000; - _nearest_timeout.tv_usec = 0; -} - -void Timer::destroy(void) -{ - while(!_q.empty()) { - realDelete(_q.top()); - _q.pop(); - } -} - -}
D otk/timer.hh

@@ -1,114 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __timer_hh -#define __timer_hh - -/*! @file timer.hh - @brief Contains the Timer class, used for timed callbacks. -*/ - -extern "C" { -#include <ctime> -} - -#include <queue> -#include <vector> - -namespace otk { - -//! The Timer class implements timed callbacks. -/*! - The Timer class can be used to have a callback fire after a given time - interval. A created Timer will fire repetitively until it is destroyed. -*/ -class Timer { -public: - //! Data type of Timer callback - typedef void (*TimeoutHandler)(void *data); - -private: - //! Compares two timeval structs - struct TimerCompare { - //! Compares two timeval structs - inline bool operator()(const Timer *a, const Timer *b) const { - return ((&a->_timeout)->tv_sec == (&b->_timeout)->tv_sec) ? - ((&a->_timeout)->tv_usec > (&b->_timeout)->tv_usec) : - ((&a->_timeout)->tv_sec > (&b->_timeout)->tv_sec); - } - }; - friend struct TimerCompare; // give access to _timeout for shitty compilers - - typedef - std::priority_queue<Timer*, std::vector<Timer*>, TimerCompare> TimerQ; - - //! Milliseconds between timer firings - long _delay; - //! Callback for timer expiry - TimeoutHandler _action; - //! Data sent to callback - void *_data; - //! We overload the delete operator to just set this to true - bool _del_me; - //! The time the last fire should've been at - struct timeval _last; - //! When this timer will next trigger - struct timeval _timeout; - - //! Queue of pending timers - static TimerQ _q; - //! Time next timer will expire - static timeval _nearest_timeout; - //! Time at start of current processing loop - static timeval _now; - - //! Really delete something (not just flag for later) - /*! - @param self Timer to be deleted. - */ - static void realDelete(Timer *self); - - //! Adds a millisecond delay to a timeval structure - /*! - @param a Amount of time to increment. - @param msec Number of milliseconds to increment by. - */ - static void timevalAdd(timeval &a, long msec); - -public: - //! Constructs a new running timer and queues it - /*! - @param delay Time in milliseconds between firings - @param cb The function to be called on fire. - @param data Data to be passed to the callback on fire. - */ - Timer(long delay, TimeoutHandler cb, void *data); - - //! Overloaded delete so we can leave deleted objects in queue for later reap - /*! - @param self Pointer to current instance of Timer. - */ - void operator delete(void *self); - - //! Dispatches all elligible timers, then optionally waits for X events - /*! - @param wait Whether to wait for X events after processing timers. - */ - static void dispatchTimers(bool wait = true); - - //! Returns a relative timeval (to pass select) of the next timer - /*! - @param tm Changed to hold the time until next timer. - @return true if there are any timers queued, and the timeout is being - returned in 'tm'. false if there are no timers queued. - */ - static bool nearestTimeout(struct timeval &tm); - - //! Initializes internal data before use - static void initialize(); - - //! Deletes all waiting timers - static void destroy(); -}; - -} - -#endif // __timer.hh
D otk/truerendercontrol.cc

@@ -1,114 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "truerendercontrol.hh" -#include "display.hh" -#include "screeninfo.hh" -#include "surface.hh" -#include "rendertexture.hh" - -extern "C" { -#include "../src/gettext.h" -#define _(str) gettext(str) -} - -#include <cstdlib> - -namespace otk { - -TrueRenderControl::TrueRenderControl(int screen) - : RenderControl(screen), - _red_offset(0), - _green_offset(0), - _blue_offset(0) -{ - printf("Initializing TrueColor RenderControl\n"); - - const ScreenInfo *info = display->screenInfo(_screen); - XImage *timage = XCreateImage(**display, info->visual(), info->depth(), - ZPixmap, 0, NULL, 1, 1, 32, 0); - - unsigned long red_mask, green_mask, blue_mask; - - // find the offsets for each color in the visual's masks - red_mask = timage->red_mask; - green_mask = timage->green_mask; - blue_mask = timage->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_shift = _green_shift = _blue_shift = 8; - while (red_mask) { red_mask >>= 1; _red_shift--; } - while (green_mask) { green_mask >>= 1; _green_shift--; } - while (blue_mask) { blue_mask >>= 1; _blue_shift--; } - XFree(timage); -} - -TrueRenderControl::~TrueRenderControl() -{ - printf("Destroying TrueColor RenderControl\n"); -} - -void TrueRenderControl::reduceDepth(Surface &sf, XImage *im) const -{ - // since pixel32 is the largest possible pixel size, we can share the array - int r, g, b; - int x,y; - pixel32 *data = sf.pixelData(); - pixel32 *ret = (pixel32*)malloc(im->width * im->height * 4); - pixel16 *p = (pixel16*) ret; - switch (im->bits_per_pixel) { - case 32: - if ((_red_offset != default_red_shift) || - (_blue_offset != default_blue_shift) || - (_green_offset != default_green_shift)) { - printf("cross endian conversion\n"); - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - r = (data[x] >> default_red_shift) & 0xFF; - g = (data[x] >> default_green_shift) & 0xFF; - b = (data[x] >> default_blue_shift) & 0xFF; - ret[x] = (r << _red_offset) + (g << _green_offset) + - (b << _blue_offset); - } - data += im->width; - } - } else { - memcpy(ret, data, im->width * im->height * 4); - } - break; - case 16: - for (y = 0; y < im->height; y++) { - for (x = 0; x < im->width; x++) { - r = (data[x] >> default_red_shift) & 0xFF; - r = r >> _red_shift; - g = (data[x] >> default_green_shift) & 0xFF; - g = g >> _green_shift; - b = (data[x] >> default_blue_shift) & 0xFF; - b = b >> _blue_shift; - p[x] = (r << _red_offset) + (g << _green_offset) + (b << _blue_offset); - } - data += im->width; - p += im->bytes_per_line/2; - } - break; - default: - printf("your bit depth is currently unhandled\n"); - } - im->data = (char*)ret; -} - -void TrueRenderControl::allocateColor(XColor *color) const -{ - const ScreenInfo *info = display->screenInfo(_screen); - if (!XAllocColor(**display, info->colormap(), color)) { - fprintf(stderr, "TrueRenderControl: color alloc error: rgb:%x/%x/%x\n", - color->red & 0xff, color->green & 0xff, color->blue & 0xff); - color->pixel = 0; - } -} - -}
D otk/truerendercontrol.hh

@@ -1,35 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __truerendercontrol_hh -#define __truerendercontrol_hh - -#include "rendercontrol.hh" - -#include <vector> - -namespace otk { - -class TrueRenderControl : public RenderControl { -private: - // the number of bits to shift a color value (from 0-255) to the right, to - // fit it into the the color mask (do this before the offset) - int _red_shift; - int _green_shift; - int _blue_shift; - - // the offset of each color in a color mask - int _red_offset; - int _green_offset; - int _blue_offset; - - virtual void reduceDepth(Surface &sf, XImage *im) const; - -public: - TrueRenderControl(int screen); - virtual ~TrueRenderControl(); - - virtual void allocateColor(XColor *color) const; -}; - -} - -#endif // __truerendercontrol_hh
D otk/ustring.cc

@@ -1,263 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "ustring.hh" - -#include <cassert> - -namespace otk { - -// helper functions - -// The number of bytes to skip to find the next character in the string -static const char utf8_skip[256] = { - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1 -}; - -// takes a pointer into a utf8 string and returns a unicode character for the -// first character at the pointer -unichar utf8_get_char (const char *p) -{ - unichar result = static_cast<unsigned char>(*p); - - // if its not a 7-bit ascii character - if((result & 0x80) != 0) { - // len is the number of bytes this character takes up in the string - unsigned char len = utf8_skip[result]; - result &= 0x7F >> len; - - while(--len != 0) { - result <<= 6; - result |= static_cast<unsigned char>(*++p) & 0x3F; - } - } - - return result; -} - -// takes a pointer into a string and finds its offset -static ustring::size_type utf8_ptr_to_offset(const char *str, const char *pos) -{ - ustring::size_type offset = 0; - - while (str < pos) { - str += utf8_skip[static_cast<unsigned char>(*str)]; - offset++; - } - - return offset; -} - -// takes an offset into a string and returns a pointer to it -const char *utf8_offset_to_ptr(const char *str, ustring::size_type offset) -{ - while (offset--) - str += utf8_skip[static_cast<unsigned char>(*str)]; - return str; -} - -// First overload: stop on '\0' character. -ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset) -{ - if(offset == ustring::npos) - return ustring::npos; - - const char* p = str; - - for(; offset != 0; --offset) - { - if(*p == '\0') - return ustring::npos; - - p += utf8_skip[static_cast<unsigned char>(*p)]; - } - - return (p - str); -} - -// Second overload: stop when reaching maxlen. -ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset, - ustring::size_type maxlen) -{ - if(offset == ustring::npos) - return ustring::npos; - - const char *const pend = str + maxlen; - const char* p = str; - - for(; offset != 0; --offset) - { - if(p >= pend) - return ustring::npos; - - p += utf8_skip[static_cast<unsigned char>(*p)]; - } - - return (p - str); -} - - -// ustring methods - -ustring::ustring(bool utf8) - : _utf8(utf8) -{ -} - -ustring::~ustring() -{ -} - -ustring::ustring(const ustring& other) - : _string(other._string), _utf8(other._utf8) -{ -} - -ustring& ustring::operator=(const ustring& other) -{ - _string = other._string; - _utf8 = other._utf8; - return *this; -} - -ustring::ustring(const std::string& src, bool utf8) - : _string(src), _utf8(utf8) -{ -} - -ustring::ustring(const char* src, bool utf8) - : _string(src), _utf8(utf8) -{ -} - -ustring& ustring::operator+=(const ustring& src) -{ - assert(_utf8 == src._utf8); - _string += src._string; - return *this; -} - -ustring& ustring::operator+=(const char* src) -{ - _string += src; - return *this; -} - -ustring& ustring::operator+=(char c) -{ - _string += c; - return *this; -} - -ustring::size_type ustring::size() const -{ - if (_utf8) { - const char *const pdata = _string.data(); - return utf8_ptr_to_offset(pdata, pdata + _string.size()); - } else - return _string.size(); -} - -ustring::size_type ustring::bytes() const -{ - return _string.size(); -} - -ustring::size_type ustring::capacity() const -{ - return _string.capacity(); -} - -ustring::size_type ustring::max_size() const -{ - return _string.max_size(); -} - -bool ustring::empty() const -{ - return _string.empty(); -} - -void ustring::clear() -{ - _string.erase(); -} - -ustring& ustring::erase(ustring::size_type i, ustring::size_type n) -{ - if (_utf8) { - // find a proper offset - size_type utf_i = utf8_byte_offset(_string.c_str(), i); - if (utf_i != npos) { - // if the offset is not npos, find a proper length for 'n' - size_type utf_n = utf8_byte_offset(_string.data() + utf_i, n, - _string.size() - utf_i); - _string.erase(utf_i, utf_n); - } - } else - _string.erase(i, n); - - return *this; -} - -void ustring::resize(ustring::size_type n, char c) -{ - if (_utf8) { - const size_type size_now = size(); - if(n < size_now) - erase(n, npos); - else if(n > size_now) - _string.append(n - size_now, c); - } else - _string.resize(n, c); -} - -ustring::value_type ustring::operator[](ustring::size_type i) const -{ - return utf8_get_char(utf8_offset_to_ptr(_string.data(), i)); -} - -bool ustring::operator==(const ustring &other) const -{ - return _string == other._string && _utf8 == other._utf8; -} - -bool ustring::operator==(const std::string &other) const -{ - return _string == other; -} - -bool ustring::operator==(const char *other) const -{ - return _string == other; -} - -const char* ustring::data() const -{ - return _string.data(); -} - -const char* ustring::c_str() const -{ - return _string.c_str(); -} - -bool ustring::utf8() const -{ - return _utf8; -} - -void ustring::setUtf8(bool utf8) -{ - _utf8 = utf8; -} - -}
D otk/ustring.hh

@@ -1,177 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __ustring_hh -#define __ustring_hh - -/*! @file ustring.hh - @brief Provides a simple UTF-8 encoded string -*/ - -extern "C" { - -#ifdef HAVE_STDINT_H -# include <stdint.h> -#else -# ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> -# endif -#endif - -} - -#include <string> - -namespace otk { - - -#ifdef HAVE_STDINT_H -typedef uint32_t unichar; -#else -typedef u_int32_t unichar; -#endif - - -#ifndef DOXYGEN_IGNORE - -unichar utf8_get_char(const char *p); - -#endif // DOXYGEN_IGNORE - -//! The iterator type for ustring -/*! - Note this is not a random access iterator but a bidirectional one, since all - index operations need to iterate over the UTF-8 data. Use std::advance() to - move to a certain position. - <p> - A writeable iterator isn't provided because: The number of bytes of the old - UTF-8 character and the new one to write could be different. Therefore, any - write operation would invalidate all other iterators pointing into the same - string. -*/ - -template <class T> -class ustring_Iterator -{ -public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef unichar value_type; - typedef std::string::difference_type difference_type; - //typedef value_type reference; - typedef void pointer; - - inline ustring_Iterator() {} - inline ustring_Iterator(const ustring_Iterator<std::string::iterator>& - other) : _pos(other.base()) {} - - - inline value_type operator*() const { - // get an iterator to the internal string - std::string::const_iterator pos = _pos; - return utf8_get_char(&(*pos)); - } - - - inline ustring_Iterator<T> & operator++() { - pos_ += g_utf8_skip[static_cast<unsigned char>(*pos_)]; - return *this; - } - inline ustring_Iterator<T> & operator--() { - do { --_pos; } while((*_pos & '\xC0') == '\x80'); - return *this; - } - - explicit inline ustring_Iterator(T pos) : _pos(pos) {} - inline T base() const { return _pos; } - -private: - T _pos; -}; - - -//! This class provides a simple wrapper to a std::string that can be encoded -//! as UTF-8. The ustring::utf() member specifies if the given string is UTF-8 -//! encoded. ustrings default to specifying UTF-8 encoding. -/*! - This class does <b>not</b> handle extended 8-bit ASCII charsets like - ISO-8859-1. - <p> - More info on Unicode and UTF-8 can be found here: - http://www.cl.cam.ac.uk/~mgk25/unicode.html - <p> - This does not subclass std::string, because std::string was intended to be a - final class. For instance, it does not have a virtual destructor. -*/ -class ustring { - std::string _string; - bool _utf8; - -public: - typedef std::string::size_type size_type; - typedef std::string::difference_type difference_type; - - typedef unichar value_type; - //typedef unichar & reference; - //typedef const unichar & const_reference; - - //typedef ustring_Iterator<std::string::iterator> iterator; - //typedef ustring_Iterator<std::string::const_iterator> const_iterator; - - static const size_type npos = std::string::npos; - - ustring(bool utf8 = true); - ~ustring(); - - // make new strings - - ustring(const ustring& other); - ustring& operator=(const ustring& other); - ustring(const std::string& src, bool utf8 = true); - ustring(const char* src, bool utf8 = true); - - // append to the string - - ustring& operator+=(const ustring& src); - ustring& operator+=(const char* src); - ustring& operator+=(char c); - - // sizes - - ustring::size_type size() const; - ustring::size_type bytes() const; - ustring::size_type capacity() const; - ustring::size_type max_size() const; - bool empty() const; - - // erase substrings - - void clear(); - ustring& erase(size_type i, size_type n=npos); - - // change the string's size - - void resize(size_type n, char c='\0'); - - // extract characters - - // No reference return; use replace() to write characters. - value_type operator[](size_type i) const; - - // compare strings - - bool operator==(const ustring &other) const; - bool operator==(const std::string &other) const; - bool operator==(const char *other) const; - - // internal data - - const char* data() const; - const char* c_str() const; - - // encoding - - bool utf8() const; - void setUtf8(bool utf8); -}; - -} - -#endif // __ustring_hh
D otk/util.cc

@@ -1,97 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -extern "C" { -#include <X11/Xatom.h> - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif // HAVE_UNISTD_H - -// this is not checked in configure anymore!! -//#if defined(HAVE_PROCESS_H) && defined(__EMX__) -//# include <process.h> -//#endif // HAVE_PROCESS_H __EMX__ - -#include "../src/gettext.h" -#define _(str) gettext(str) - -} - -#include <algorithm> -#include <cassert> -#include <cstdio> -#include <cstring> -#include <cstdlib> - -#include "util.hh" - -using std::string; - -namespace otk { - -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__ - if (! fork()) { - setsid(); - putenv(displaystring); - int ret = execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL); - exit(ret); - } -//#else // __EMX__ -// spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", command.c_str(), NULL); -//#endif // !__EMX__ -} - - -string itostring(unsigned long i) { - if (i == 0) - return string("0"); - - string tmp; - for (; i > 0; i /= 10) - tmp.insert(tmp.begin(), "0123456789"[i%10]); - return tmp; -} - - -string itostring(long i) { - std::string tmp = itostring( (unsigned long) std::abs(i)); - if (i < 0) - tmp.insert(tmp.begin(), '-'); - return tmp; -} - -void putenv(const std::string &data) -{ - char *c = new char[data.size() + 1]; - std::string::size_type i, max; - for (i = 0, max = data.size(); i < max; ++i) - c[i] = data[i]; - c[i] = 0; - if (::putenv(c)) { - printf(_("warning: couldn't set environment variable\n")); - perror("putenv()"); - } -} - -string basename (const string& path) { - string::size_type slash = path.rfind('/'); - if (slash == string::npos) - return path; - return path.substr(slash+1); -} - -} -
D otk/util.hh

@@ -1,32 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __util_hh -#define __util_hh - -extern "C" { -#include <X11/Xlib.h> -#include <X11/Xutil.h> -} - -#include <string> -#include <vector> - -namespace otk { - -std::string expandTilde(const std::string& s); - -void bexec(const std::string& command, const std::string& displaystring); - -std::string itostring(unsigned long i); -std::string itostring(long i); -inline std::string itostring(unsigned int i) - { return itostring((unsigned long) i); } -inline std::string itostring(int i) - { return itostring((long) i); } - -void putenv(const std::string &data); - -std::string basename(const std::string& path); - -} - -#endif // __util_hh
D otk/widget.cc

@@ -1,547 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" -#include "widget.hh" -#include "display.hh" -#include "surface.hh" -#include "rendertexture.hh" -#include "rendercolor.hh" -#include "eventdispatcher.hh" -#include "screeninfo.hh" - -#include <climits> -#include <cassert> -#include <algorithm> - -namespace otk { - -Widget::Widget(int screen, EventDispatcher *ed, Direction direction, int bevel, - bool overrideredir) - : _texture(0), - _screen(screen), - _parent(0), - _window(0), - _surface(0), - _event_mask(ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | - ExposureMask | StructureNotifyMask), - _alignment(RenderStyle::CenterJustify), - _direction(direction), - _max_size(INT_MAX, INT_MAX), - _visible(false), - _bordercolor(0), - _borderwidth(0), - _bevel(bevel), - _dirty(true), - _dispatcher(ed), - _ignore_config(0) -{ - createWindow(overrideredir); - _dispatcher->registerHandler(_window, this); -} - -Widget::Widget(Widget *parent, Direction direction, int bevel) - : _texture(0), - _screen(parent->_screen), - _parent(parent), - _window(0), - _surface(0), - _event_mask(ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | - ExposureMask | StructureNotifyMask), - _alignment(RenderStyle::CenterJustify), - _direction(direction), - _max_size(INT_MAX, INT_MAX), - _visible(false), - _bordercolor(0), - _borderwidth(0), - _bevel(bevel), - _dirty(true), - _dispatcher(parent->_dispatcher), - _ignore_config(0) -{ - assert(parent); - createWindow(false); - parent->addChild(this); - if (parent->visible()) parent->layout(); - _dispatcher->registerHandler(_window, this); - styleChanged(*RenderStyle::style(_screen)); -} - -Widget::~Widget() -{ - assert(_children.empty()); // this would be bad. theyd have a hanging _parent - - if (_surface) delete _surface; - if (_parent) _parent->removeChild(this); - - _dispatcher->clearHandler(_window); - XDestroyWindow(**display, _window); -} - -void Widget::show(bool children) -{ - if (children) { - std::list<Widget*>::iterator it , end = _children.end(); - for (it = _children.begin(); it != end; ++it) { - (*it)->show(true); - } - } - if (!_visible) { - if (_parent) _parent->calcDefaultSizes(); - else resize(_area.size()); // constrain sizes - _visible = true; - XMapWindow(**display, _window); - update(); - } -} - -void Widget::hide() -{ - if (_visible) { - _visible = false; - XUnmapWindow(**display, _window); - if (_parent) { - _parent->calcDefaultSizes(); - _parent->layout(); - } - } -} - -void Widget::setEventMask(long e) -{ - XSelectInput(**display, _window, e); - _event_mask = e; -} - -void Widget::update() -{ - if (!_visible) return; - _dirty = true; - if (_parent) { - _parent->calcDefaultSizes(); - _parent->layout(); // relay-out us and our siblings - } else { - render(); - layout(); - } -} - -void Widget::moveresize(const Rect &r) -{ - int w, h; - w = std::max(std::min(r.width(), maxSize().width()), minSize().width()); - h = std::max(std::min(r.height(), maxSize().height()), minSize().height()); - - bool sizechange = !(w == area().width() && h == area().height()); - - if (r.x() == area().x() && r.y() == area().y() && !sizechange) - return; // no change, don't cause a big layout chain to occur! - - internal_moveresize(r.x(), r.y(), w, h); - - if (sizechange) - update(); -} - -void Widget::internal_moveresize(int x, int y, int w, int h) -{ - assert(w > 0); - assert(h > 0); - assert(_borderwidth >= 0); - _dirty = true; - if (!(x == _area.x() && y == _area.y())) { - if (!(w == _area.width() && h == _area.height())) - XMoveResizeWindow(**display, _window, x, y, - w - _borderwidth * 2, - h - _borderwidth * 2); - else - XMoveWindow(**display, _window, x, y); - } else - XResizeWindow(**display, _window, w - _borderwidth*2, h - _borderwidth*2); - _ignore_config++; - - _area = Rect(x, y, w, h); -} - -void Widget::setAlignment(RenderStyle::Justify a) -{ - _alignment = a; - layout(); -} - -void Widget::createWindow(bool overrideredir) -{ - const ScreenInfo *info = display->screenInfo(_screen); - XSetWindowAttributes attrib; - unsigned long mask = CWEventMask | CWBorderPixel; - - attrib.event_mask = _event_mask; - attrib.border_pixel = (_bordercolor ? - _bordercolor->pixel(): - BlackPixel(**display, _screen)); - - if (overrideredir) { - mask |= CWOverrideRedirect; - attrib.override_redirect = true; - } - - _window = XCreateWindow(**display, (_parent ? - _parent->_window : - RootWindow(**display, _screen)), - _area.x(), _area.y(), - _area.width(), _area.height(), - _borderwidth, - info->depth(), - InputOutput, - info->visual(), - mask, - &attrib); - assert(_window != None); - ++_ignore_config; -} - -void Widget::calcDefaultSizes() -{ - std::list<Widget*>::const_iterator it, end = _children.end(); - int min_biggest = 0, max_biggest = 0; - int min_sum = _bevel + _borderwidth * 2; - int max_sum = _bevel + _borderwidth * 2; - bool fullmax = false; - - for (it = _children.begin(); it != end; ++it) { - const otk::Size &min = (*it)->minSize(); - const otk::Size &max = (*it)->maxSize(); - if (_direction == Horizontal) { - if (min.height() > min_biggest) min_biggest = min.height(); - if (max.height() > max_biggest) max_biggest = max.height(); - min_sum += _bevel + min.width(); - if (max.width() == INT_MAX) - fullmax = true; - else if (!fullmax) - max_sum += _bevel + max.width(); - } else { - if (min.width() > min_biggest) min_biggest = min.width(); - if (max.width() > max_biggest) max_biggest = max.width(); - min_sum += _bevel + min.height(); - if (max.height() == INT_MAX) - fullmax = true; - else if (!fullmax) - max_sum += _bevel + max.height(); - } - } - if (_direction == Horizontal) { - _min_size = otk::Size(min_sum + (_bevel + _borderwidth) * 2, - min_biggest + (_bevel + _borderwidth) * 2); - _max_size = otk::Size((fullmax ? INT_MAX : - max_sum + (_bevel + _borderwidth) * 2), - max_biggest); - } else { - _min_size = otk::Size(min_biggest + (_bevel + _borderwidth) * 2, - min_sum + (_bevel + _borderwidth) * 2); - _max_size = otk::Size(max_biggest, (fullmax ? INT_MAX : max_sum + - (_bevel + _borderwidth) * 2)); - } - update(); -} - -void Widget::setBorderWidth(int w) -{ - assert(w >= 0); - if (!parent()) return; // top-level windows cannot have borders - if (w == borderWidth()) return; // no change - - _borderwidth = w; - XSetWindowBorderWidth(**display, _window, _borderwidth); - - calcDefaultSizes(); - update(); -} - -void Widget::setMinSize(const Size &s) -{ - _min_size = s; - update(); -} - -void Widget::setMaxSize(const Size &s) -{ - _max_size = s; - update(); -} - -void Widget::setBorderColor(const RenderColor *c) -{ - _bordercolor = c; - XSetWindowBorder(**otk::display, _window, - c ? c->pixel() : BlackPixel(**otk::display, _screen)); -} - -void Widget::setBevel(int b) -{ - _bevel = b; - calcDefaultSizes(); - layout(); -} - -void Widget::layout() -{ - if (_children.empty() || !_visible) return; - if (_direction == Horizontal) - layoutHorz(); - else - layoutVert(); -} - -void Widget::layoutHorz() -{ - std::list<Widget*>::iterator it, end; - - // work with just the visible children - std::list<Widget*> visible; - for (it = _children.begin(), end = _children.end(); it != end; ++it) - if ((*it)->visible()) - visible.push_back(*it); - - if (visible.empty()) return; - - int x, y, w, h; // working area - x = y = _bevel; - w = _area.width() - _borderwidth * 2 - _bevel * 2; - h = _area.height() - _borderwidth * 2 - _bevel * 2; - if (w < 0 || h < 0) return; // not worth laying anything out! - - int free = w - (visible.size() - 1) * _bevel; - if (free < 0) free = 0; - int each; - - std::list<Widget*> adjustable; - - // find the 'free' space, and how many children will be using it - for (it = visible.begin(), end = visible.end(); it != end; ++it) { - free -= (*it)->minSize().width(); - if (free < 0) free = 0; - if ((*it)->maxSize().width() - (*it)->minSize().width() > 0) - adjustable.push_back(*it); - } - // some widgets may have max widths that restrict them, find the 'true' - // amount of free space after these widgets are not included - if (!adjustable.empty()) { - do { - each = free / adjustable.size(); - for (it = adjustable.begin(), end = adjustable.end(); it != end;) { - std::list<Widget*>::iterator next = it; ++next; - int m = (*it)->maxSize().width() - (*it)->minSize().width(); - if (m > 0 && m < each) { - free -= m; - if (free < 0) free = 0; - adjustable.erase(it); - break; // if one is found to be fixed, then the free space needs to - // change, and the rest need to be reexamined - } - it = next; - } - } while (it != end && !adjustable.empty()); - } - - // place/size the widgets - if (!adjustable.empty()) - each = free / adjustable.size(); - else - each = 0; - for (it = visible.begin(), end = visible.end(); it != end; ++it) { - int w; - // is the widget adjustable? - std::list<Widget*>::const_iterator - found = std::find(adjustable.begin(), adjustable.end(), *it); - if (found != adjustable.end()) { - // adjustable - w = (*it)->minSize().width() + each; - } else { - // fixed - w = (*it)->minSize().width(); - } - // align it vertically - int yy = y; - int hh = std::max(std::min(h, (*it)->_max_size.height()), - (*it)->_min_size.height()); - if (hh < h) { - switch(_alignment) { - case RenderStyle::RightBottomJustify: - yy += h - hh; - break; - case RenderStyle::CenterJustify: - yy += (h - hh) / 2; - break; - case RenderStyle::LeftTopJustify: - break; - } - } - (*it)->internal_moveresize(x, yy, w, hh); - (*it)->render(); - (*it)->layout(); - x += w + _bevel; - } -} - -void Widget::layoutVert() -{ - std::list<Widget*>::iterator it, end; - - // work with just the visible children - std::list<Widget*> visible; - for (it = _children.begin(), end = _children.end(); it != end; ++it) - if ((*it)->visible()) - visible.push_back(*it); - - if (visible.empty()) return; - - int x, y, w, h; // working area - x = y = _bevel; - w = _area.width() - _borderwidth * 2 - _bevel * 2; - h = _area.height() - _borderwidth * 2 - _bevel * 2; - if (w < 0 || h < 0) return; // not worth laying anything out! - - int free = h - (visible.size() - 1) * _bevel; - if (free < 0) free = 0; - int each; - - std::list<Widget*> adjustable; - - // find the 'free' space, and how many children will be using it - for (it = visible.begin(), end = visible.end(); it != end; ++it) { - free -= (*it)->minSize().height(); - if (free < 0) free = 0; - if ((*it)->maxSize().height() - (*it)->minSize().height() > 0) - adjustable.push_back(*it); - } - // some widgets may have max heights that restrict them, find the 'true' - // amount of free space after these widgets are not included - if (!adjustable.empty()) { - do { - each = free / adjustable.size(); - for (it = adjustable.begin(), end = adjustable.end(); it != end;) { - std::list<Widget*>::iterator next = it; ++next; - int m = (*it)->maxSize().height() - (*it)->minSize().height(); - if (m > 0 && m < each) { - free -= m; - if (free < 0) free = 0; - adjustable.erase(it); - break; // if one is found to be fixed, then the free space needs to - // change, and the rest need to be reexamined - } - it = next; - } - } while (it != end && !adjustable.empty()); - } - - // place/size the widgets - if (!adjustable.empty()) - each = free / adjustable.size(); - else - each = 0; - for (it = visible.begin(), end = visible.end(); it != end; ++it) { - int h; - // is the widget adjustable? - std::list<Widget*>::const_iterator - found = std::find(adjustable.begin(), adjustable.end(), *it); - if (found != adjustable.end()) { - // adjustable - h = (*it)->minSize().height() + each; - } else { - // fixed - h = (*it)->minSize().height(); - } - // align it horizontally - int xx = x; - int ww = std::max(std::min(w, (*it)->_max_size.width()), - (*it)->_min_size.width()); - if (ww < w) { - switch(_alignment) { - case RenderStyle::RightBottomJustify: - xx += w - ww; - break; - case RenderStyle::CenterJustify: - xx += (w - ww) / 2; - break; - case RenderStyle::LeftTopJustify: - break; - } - } - (*it)->internal_moveresize(xx, y, ww, h); - (*it)->render(); - (*it)->layout(); - y += h + _bevel; - } -} - -void Widget::render() -{ - if (!_dirty) return; - if (!_texture) { - // set a solid color as the default background - XSetWindowBackground(**display, _window, - RenderStyle::style(_screen)-> - titlebarUnfocusBackground()->color().pixel()); - return; - } - if (_borderwidth * 2 > _area.width() || - _borderwidth * 2 > _area.height()) - return; // no surface to draw on - - Surface *s = new Surface(_screen, Size(_area.width() - _borderwidth * 2, - _area.height() - _borderwidth * 2)); - display->renderControl(_screen)->drawBackground(*s, *_texture); - - renderForeground(*s); // for inherited types to render onto the _surface - - XSetWindowBackgroundPixmap(**display, _window, s->pixmap()); - XClearWindow(**display, _window); - - // delete the old surface *after* its pixmap isn't in use anymore - if (_surface) delete _surface; - - s->freePixelData(); // done rendering with this surface - _surface = s; - - _dirty = false; -} - -void Widget::renderChildren() -{ - std::list<Widget*>::iterator it, end = _children.end(); - for (it = _children.begin(); it != end; ++it) - (*it)->render(); -} - -void Widget::styleChanged(const RenderStyle &) -{ - refresh(); -} - -void Widget::exposeHandler(const XExposeEvent &e) -{ - EventHandler::exposeHandler(e); - XClearArea(**display, _window, e.x, e.y, e.width, e.height, false); -} - -void Widget::configureHandler(const XConfigureEvent &e) -{ - if (_ignore_config) { - _ignore_config--; - } else { - // only interested in these for top level windows - if (_parent) return; - - XEvent ev; - ev.xconfigure.width = e.width; - ev.xconfigure.height = e.height; - while (XCheckTypedWindowEvent(**display, window(), ConfigureNotify, &ev)); - - if (!(ev.xconfigure.width == area().width() && - ev.xconfigure.height == area().height())) { - _area = Rect(_area.position(), Size(e.width, e.height)); - update(); - } - } -} - -}
D otk/widget.hh

@@ -1,141 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __widget_hh -#define __widget_hh - -#include "eventhandler.hh" -#include "rect.hh" -#include "renderstyle.hh" - -#include <list> -#include <algorithm> -#include <cassert> - -namespace otk { - -class Surface; -class RenderTexture; -class RenderColor; -class EventDispatcher; - -class Widget : public EventHandler, public StyleNotify { -public: - enum Direction { Horizontal, Vertical }; - - Widget(int screen, EventDispatcher *ed, Direction direction = Horizontal, - int bevel = 3, bool overrideredir = false); - Widget(Widget *parent, Direction direction = Horizontal, int bevel = 3); - virtual ~Widget(); - - inline int screen() const { return _screen; } - inline Window window() const { return _window; } - inline Widget *parent() const { return _parent; } - inline Direction direction() const { return _direction; } - - inline RenderStyle::Justify alignment() const { return _alignment; } - void setAlignment(RenderStyle::Justify a); - - inline long eventMask() const { return _event_mask; } - virtual void setEventMask(long e); - - inline const Rect& area() const { return _area; } - inline Rect usableArea() const { return Rect(_area.position(), - Size(_area.width() - - _borderwidth * 2, - _area.height() - - _borderwidth * 2));} - inline const Size& minSize() const { return _min_size; } - inline const Size& maxSize() const { return _max_size; } - virtual void setMaxSize(const Size &s); - - virtual void show(bool children = false); - virtual void hide(); - inline bool visible() const { return _visible; } - - virtual void update(); - virtual void refresh() { if (_visible) { _dirty = true; render(); } } - - virtual void setBevel(int b); - inline int bevel() const { return _bevel; } - - void move(const Point &p) - { moveresize(Rect(p, _area.size())); } - void resize(const Size &s) - { moveresize(Rect(_area.position(), s)); } - /*! - When a widget has a parent, this won't change the widget directly, but will - just cause the parent to re-layout all its children. - */ - virtual void moveresize(const Rect &r); - - inline const RenderColor *borderColor() const { return _bordercolor; } - virtual void setBorderColor(const RenderColor *c); - - inline int borderWidth() const { return _borderwidth; } - virtual void setBorderWidth(int w); - - const std::list<Widget*>& children() const { return _children; } - - virtual void exposeHandler(const XExposeEvent &e); - virtual void configureHandler(const XConfigureEvent &e); - virtual void styleChanged(const RenderStyle &style); - -protected: - virtual void addChild(Widget *w) { assert(w); _children.push_back(w); } - virtual void removeChild(Widget *w) { assert(w); _children.remove(w); } - - //! Find the default min/max sizes for the widget. Useful after the in-use - //! style has changed. - virtual void calcDefaultSizes(); - - virtual void setMinSize(const Size &s); - - //! Arrange the widget's children - virtual void layout(); - virtual void layoutHorz(); - virtual void layoutVert(); - virtual void render(); - virtual void renderForeground(Surface&) {}; - virtual void renderChildren(); - - void createWindow(bool overrideredir); - - RenderTexture *_texture; - - EventDispatcher *dispatcher() const { return _dispatcher; } - -private: - void internal_moveresize(int x, int y, int w, int h); - - int _screen; - Widget *_parent; - Window _window; - Surface *_surface; - long _event_mask; - - RenderStyle::Justify _alignment; - Direction _direction; - Rect _area; - //! This size is the size *inside* the border, so they won't match the - //! actual size of the widget - Size _min_size; - //! This size is the size *inside* the border, so they won't match the - //! actual size of the widget - Size _max_size; - - bool _visible; - - const RenderColor *_bordercolor; - int _borderwidth; - int _bevel; - bool _dirty; - - std::list<Widget*> _children; - - EventDispatcher *_dispatcher; - - int _ignore_config; -}; - -} - -#endif // __widget_hh
D python/.cvsignore

@@ -1,2 +0,0 @@

-Makefile -Makefile.in
D python/Makefile.am

@@ -1,11 +0,0 @@

-scriptdir=$(libdir)/openbox/python - -SUBDIRS = - -script_PYTHON = rc.py keymap.py buttonmap.py config.py motion.py \ - historyplacement.py windowplacement.py stackedcycle.py focus.py - -MAINTAINERCLEANFILES= Makefile.in - -distclean-local: - $(RM) *\~ *.orig *.rej .\#*
D python/buttonmap.py

@@ -1,76 +0,0 @@

-from input import Pointer - -def set(map): - """Set your buttonmap. Functions in the button map should all take a single - argument, a Client object, except for functions for Action_Motion events, - who should take 2 arguments, a PointerData object and a Client object.""" - global _press_map, _release_map, _click_map, _doubleclick_map, _motion_map - Pointer.clearBinds() - _press_map = [] - _release_map = [] - _click_map = [] - _doubleclick_map = [] - _motion_map = [] - for button, context, action, func in map: - if (action == Pointer.Action_Press): - _press_map.append((button, context, func)) - mapfunc = press_run - if (action == Pointer.Action_Release): - _release_map.append((button, context, func)) - mapfunc = release_run - if (action == Pointer.Action_Click): - _click_map.append((button, context, func)) - mapfunc = click_run - if (action == Pointer.Action_DoubleClick): - _doubleclick_map.append((button, context, func)) - mapfunc = doubleclick_run - if (action == Pointer.Action_Motion): - _motion_map.append((button, context, func)) - mapfunc = motion_run - Pointer.bind(button, context, action, mapfunc) - -def press_run(ptrdata, client): - """Run a button press event through the buttonmap""" - button = ptrdata.button - context = ptrdata.context - for but, cont, func in _press_map: - if (but == button and cont == context): - func(client) - -def release_run(ptrdata, client): - """Run a button release event through the buttonmap""" - button = ptrdata.button - context = ptrdata.context - for but, cont, func in _release_map: - if (but == button and cont == context): - func(client) - -def click_run(ptrdata, client): - """Run a button click event through the buttonmap""" - button = ptrdata.button - context = ptrdata.context - for but, cont, func in _click_map: - if (but == button and cont == context): - func(client) - -def doubleclick_run(ptrdata, client): - """Run a button doubleclick event through the buttonmap""" - button = ptrdata.button - context = ptrdata.context - for but, cont, func in _doubleclick_map: - if (but == button and cont == context): - func(client) - -def motion_run(ptrdata, client): - """Run a pointer motion event through the buttonmap""" - button = ptrdata.button - context = ptrdata.context - for but, cont, func in _motion_map: - if (but == button and cont == context): - func(ptrdata, client) - -_press_map = () -_release_map = () -_click_map = () -_doubleclick_map = () -_motion_map = ()
D python/config.py

@@ -1,190 +0,0 @@

-# Openbox's config system. Please use the defined functions instead of -# accessing the internal data structures directly, for the sake of us all. - -def add(modulename, name, friendlyname, description, type, default, - **keywords): - """Add a variable to the configuration system. - - Add a variable to the configuration system for a module. - modulename - The name of the module, e.g. 'focus' - name - The name of the variable, e.g. 'my_variable' - friendlyname - The user-friendly name of the variable, e.g. 'My Variable' - description - The detailed destription of the variable, e.g. 'Does Things' - type - The type of the variable, one of: - - 'boolean' - - 'enum' - - 'integer' - - 'string' - - 'file' - - 'function' - - 'object' - default - The default value for the variable, e.g. 300 - keywords - Extra keyword=value pairs to further define the variable. These - can be: - - For 'enum' types: - - options : A list of possible options for the variable. - This *must* be set for all enum variables. - - For 'integer' types: - - min : The minimum value for the variable. - - max : The maximum value for the variable. - """ - modulename = str(modulename).lower() - name = str(name).lower() - friendlyname = str(friendlyname) - description = str(description) - type = str(type).lower() - - # make sure the sub-dicts exist - try: - _settings[modulename] - try: - _settings[modulename][name] - except KeyError: - _settings[modulename][name] = {} - except KeyError: - _settings[modulename] = {} - _settings[modulename][name] = {} - - # add the keywords first as they are used for the tests in set() - for key,value in zip(keywords.keys(), keywords.values()): - _settings[modulename][name][key] = value - - _settings[modulename][name]['name'] = friendlyname - _settings[modulename][name]['description'] = description - _settings[modulename][name]['type'] = type - _settings[modulename][name]['default'] = default - - # put it through the tests - try: - set(modulename, name, default) - except: - del _settings[modulename][name] - import sys - raise sys.exc_info()[0], sys.exc_info()[1] # re-raise it - -def set(modulename, name, value): - """Set a variable's value. - - Sets the value for a variable of the specified module. - modulename - The name of the module, e.g. 'focus' - name - The name of the variable, e.g. 'my_variable' - value - The new value for the variable. - """ - modulename = str(modulename).lower() - name = str(name).lower() - - # proper value checking for 'boolean's - if _settings[modulename][name]['type'] == 'boolean': - if not (value == 0 or value == 1): - raise ValueError, 'Attempted to set ' + name + ' to a value of '+\ - str(value) + ' but boolean variables can only contain 0 or'+\ - ' 1.' - - # proper value checking for 'enum's - elif _settings[modulename][name]['type'] == 'enum': - options = _settings[modulename][name]['options'] - if not value in options: - raise ValueError, 'Attempted to set ' + name + ' to a value of '+\ - str(value) + ' but this is not one of the possible values '+\ - 'for this enum variable. Possible values are: ' +\ - str(options) + "." - - # min/max checking for 'integer's - elif _settings[modulename][name]['type'] == 'integer': - try: - min = _settings[modulename][name]['min'] - if value < min: - raise ValueError, 'Attempted to set ' + name + ' to a value '+\ - ' of ' + str(value) + ' but it has a minimum value ' +\ - ' of ' + str(min) + '.' - except KeyError: pass - try: - max = _settings[modulename][name]['max'] - if value > max: - raise ValueError, 'Attempted to set ' + name + ' to a value '+\ - ' of ' + str(value) + ' but it has a maximum value ' +\ - ' of ' + str(min) + '.' - except KeyError: pass - - _settings[modulename][name]['value'] = value - -def reset(modulename, name): - """Reset a variable to its default value. - - Resets the value for a variable in the specified module back to its - original (default) value. - modulename - The name of the module, e.g. 'focus' - name - The name of the variable, e.g. 'my_variable' - """ - modulename = str(modulename).lower() - name = str(name).lower() - _settings[modulename][name]['value'] = \ - _settings[modulename][name]['default'] - -def get(modulename, name): - """Returns the value of a variable. - - Returns the current value for a variable in the specified module. - modulename - The name of the module, e.g. 'focus' - name - The name of the variable, e.g. 'my variable' - """ - modulename = str(modulename).lower() - name = str(name).lower() - return _settings[modulename][name]['value'] - -#---------------------------- Internals --------------------------- - -"""The main configuration dictionary, which holds sub-dictionaries for each - module. - - The format for entries in here like this (for a string): - _settings['modulename']['varname']['name'] = 'Text Label' - _settings['modulename']['varname']['description'] = 'Does this' - _settings['modulename']['varname']['type'] = 'string' - _settings['modulename']['varname']['default'] = 'Foo' - _settings['modulename']['varname']['value'] = 'Foo' - # 'value' should always be initialized to the same - # value as the 'default' field! - - Here's an example of an enum: - _settings['modulename']['varname']['name'] = 'My Enum Variable' - _settings['modulename']['varname']['description'] = 'Does Enum-like things.' - _settings['modulename']['varname']['type'] = 'enum' - _settings['modulename']['varname']['default'] = \ - _settings['modulename']['varname']['value'] = [ 'Blue', 'Green', 'Pink' ] - - And Here's an example of an integer with bounds: - _settings['modulename']['varname']['name'] = 'A Bounded Integer' - _settings['modulename']['varname']['description'] = 'A fierce party animal!' - _settings['modulename']['varname']['type'] = 'integer' - _settings['modulename']['varname']['default'] = \ - _settings['modulename']['varname']['value'] = 0 - _settings['modulename']['varname']['min'] = 0 - _settings['modulename']['varname']['max'] = 49 - - Hopefully you get the idea. - """ -_settings = {} - -"""Valid values for a variable's type.""" -_types = [ 'boolean', # Boolean types can only hold a value of 0 or 1. - - 'enum', # Enum types hold a value from a list of possible values. - # An 'options' field *must* be provided for enums, - # containing a list of possible values for the variable. - - 'integer', # Integer types hold a single number, as well as a 'min' - # and 'max' property. - # If the 'min' or 'max' is ignore then bounds checking - # will not be performed in that direction. - - 'string', # String types hold a text string. - - 'file', # File types hold a file object. - - 'function',# Function types hold any callable object. - - 'object' # Object types can hold any python object. - ]; - -print "Loaded config.py"
D python/focus.py

@@ -1,66 +0,0 @@

-########################################################################### -### Functions for helping out with your window focus. ### -########################################################################### - -import config, ob, hooks - -export_functions = () - -config.add('focus', - 'avoid_skip_taskbar', - 'Avoid SkipTaskbar Windows', - "Don't focus windows which have requested to not be displayed " + \ - "in taskbars. You will still be able to focus the windows, but " + \ - "not through cycling, and they won't be focused as a fallback " + \ - "if 'Focus Fallback' is enabled.", - 'boolean', - 1) - -config.add('focus', - 'fallback', - 'Focus Fallback', - "Send focus somewhere when nothing is left with the focus, if " + \ - "possible.", - 'boolean', - 1) - -# maintain a list of clients, stacked in focus order -_clients = [] -_skip = 0 - -def focusable(client, desktop): - if not client.normal(): return False - if not (client.canFocus() or client.focusNotify()): return False - if client.iconic(): return False - if config.get('focus', 'avoid_skip_taskbar') and \ - client.skipTaskbar(): return False - - desk = client.desktop() - if not (desk == 0xffffffff or desk == desktop): return False - - return True - -def _focused(client): - global _clients, _skip - - if _skip: - _skip -= 1 - return - - if client: - # move it to the top - _clients.remove(client) - _clients.insert(0, client) - elif config.get('focus', 'fallback'): - # pass around focus - desktop = ob.Openbox.desktop() - for c in _clients: - if focusable(c, desktop): - c.focus() - break - -hooks.managed.append(lambda c: _clients.append(c)) -hooks.closed.append(lambda c: _clients.remove(c)) -hooks.focused.append(_focused) - -print "Loaded focus.py"
D python/historyplacement.py

@@ -1,164 +0,0 @@

-############################################################################## -### The history window placement algorithm. ebind historyplacement.place ### -### to the ob.EventAction.PlaceWindow event to use it. ### -############################################################################## - -import windowplacement, config, hooks - -def place(data): - """Place a window usingthe history placement algorithm.""" - _place(data) - -export_functions = place - -############################################################################## - -config.add('historyplacement', - 'ignore_requested_positions', - 'Ignore Requested Positions', - "When true, the placement algorithm will attempt to place " + \ - "windows even when they request a position (like XMMS can)." + \ - "Note this only applies to 'normal' windows, not to special " + \ - "cases like desktops and docks.", - 'boolean', - 0) -config.add('historyplacement', - 'dont_duplicate', - "Don't Diplicate", - "When true, if 2 copies of the same match in history are to be " + \ - "placed before one of them is closed (so it would be placed " + \ - "over-top of the last one), this will cause the second window to "+\ - "not be placed via history, and the 'Fallback Algorithm' will be "+\ - "used instead.", - 'boolean', - 1) -config.add('historyplacement', - 'filename', - 'History Database Filename', - "The name of the file where history data will be stored. The " + \ - "number of the screen is appended onto this name. The file will " +\ - "be placed in ~/.openbox/.", - 'string', - 'historydb') -config.add('historyplacement', - 'fallback', - 'Fallback Algorithm', - "The window placement algorithm that will be used when history " + \ - "placement does not have a place for the window.", - 'enum', - windowplacement.random, - options = windowplacement.export_functions) - -########################################################################### - -########################################################################### -### Internal stuff, should not be accessed outside the module. ### -########################################################################### - -import ob, os, string - -_data = [] - -class _State: - def __init__(self, resname, resclass, role, x, y): - self.resname = resname - self.resclass = resclass - self.role = role - self.x = x - self.y = y - self.placed = 0 - def __eq__(self, other): - if self.resname == other.resname and \ - self.resclass == other.resclass and \ - self.role == other.role: - return 1 - return 0 - -def _load(): - global _data - try: - file = open(os.environ['HOME'] + '/.openbox/' + \ - config.get('historyplacement', 'filename') + \ - "." + str(ob.Openbox.screenNumber()), 'r') - # read data - for line in file.readlines(): - line = line[:-1] # drop the '\n' - try: - s = string.split(line, '\0') - state = _State(s[0], s[1], s[2], - int(s[3]), int(s[4])) - - _data.append(state) - - except ValueError: pass - except IndexError: pass - file.close() - except IOError: pass - -def _save(): - file = open(os.environ['HOME'] + '/.openbox/'+ \ - config.get('historyplacement', 'filename') + \ - "." + str(ob.Openbox.screenNumber()), 'w') - if file: - for i in _data: - file.write(i.resname + '\0' + - i.resclass + '\0' + - i.role + '\0' + - str(i.x) + '\0' + - str(i.y) + '\n') - file.close() - -def _create_state(client): - area = client.area() - return _State(client.resName(), client.resClass(), - client.role(), area[0], area[1]) - -def _place(client): - state = _create_state(client) - try: - print "looking for : " + state.resname + " : " + \ - state.resclass + " : " + state.role - try: - i = _data.index(state) - except ValueError: - print "No match in history" - else: - coords = _data[i] # get the equal element - print "Found in history ("+str(coords.x)+","+\ - str(coords.y)+")" - if not (config.get('historyplacement', 'dont_duplicate') \ - and coords.placed): - coords.placed = 1 - if ob.Openbox.state() != ob.State.Starting: -# if not (config.get('historyplacement', 'ignore_requested_positions') \ -# and data.client.normal()): -# if data.client.positionRequested(): return - ca = client.area() - client.setArea((coords.x, coords.y, ca[2], ca[3])) - return - else: - print "Already placed another window there" - except TypeError: - pass - fallback = config.get('historyplacement', 'fallback') - if fallback: fallback(client) - -def _save_window(client): - global _data - state = _create_state(client) - print "looking for : " + state.resname + " : " + state.resclass + \ - " : " + state.role - - try: - print "replacing" - i = _data.index(state) - _data[i] = state # replace it - except ValueError: - print "appending" - _data.append(state) - -hooks.startup.append(_load) -hooks.shutdown.append(_save) -hooks.closed.append(_save_window) - -print "Loaded historyplacement.py"
D python/keymap.py

@@ -1,17 +0,0 @@

-from input import Keyboard - -def set(map): - """Set your keymap""" - global _map - Keyboard.clearBinds() - for key, func in map: - Keyboard.bind(key, run) - _map = map - -def run(keydata, client): - """Run a key press event through the keymap""" - for key, func in _map: - if (keydata.keychain == key): - func(keydata, client) - -_map = ()
D python/motion.py

@@ -1,81 +0,0 @@

-import config, hooks, ob -from input import Pointer - -config.add('motion', - 'edge_resistance', - 'Edge Resistance', - "The amount of resistance to provide to moving a window past a " + \ - "screen boundary. Specify a value of 0 to disable edge resistance.", - 'integer', - 10, - min = 0) - -def move(ptrdata, client): - def mymove(ptrdata, client): - global _moving, _last_pos - if ptrdata.action == Pointer.Action_Release: - _moveclient.setArea(_moveclient.area(), True) # finalize the move - _moving = False - Pointer.ungrab() - elif ptrdata.action == Pointer.Action_Motion: - pos = ptrdata.pos - - x = _pcarea[0] + pos[0] - _presspos[0] - y = _pcarea[1] + pos[1] - _presspos[1] - - resist = config.get('motion', 'edge_resistance') - if resist: - ca = _moveclient.area() - w, h = ca[2], ca[3] - # use the area based on the struts - sa = ob.Openbox.screenArea(_moveclient.desktop()) - l, t = sa[0], sa[1] - r = l+ sa[2] - w - b = t+ sa[3] - h - # left screen edge - if _last_pos[0] >= pos[0] and x < l and x >= l - resist: - x = l - # right screen edge - if _last_pos[0] <= pos[0] and x > r and x <= r + resist: - x = r - # top screen edge - if _last_pos[1] >= pos[1] and y < t and y >= t - resist: - y = t - # right screen edge - if _last_pos[1] <= pos[1] and y > b and y <= b + resist: - y = b - - _moveclient.setArea((x, y, _pcarea[2], _pcarea[3]), False) - _last_pos = pos - - global _last_pos, _moving, _pcarea, _presspos, _moveclient - if not _moving: - _moving = True - _pcarea = ptrdata.pressclientarea - _presspos = ptrdata.presspos - _last_pos = _presspos - _moveclient = client - Pointer.grab(mymove) - mymove(ptrdata, client) - -def resize(ptrdata, client): - x, y = ptrdata.pos - px, py = ptrdata.presspos - cx, cy, cw, ch = ptrdata.pressclientarea - dx = x - px - dy = y - py - if px < cx + cw / 2: # left side - dx *= -1 - cx -= dx - if py < cy + ch / 2: # top side - dy *= -1 - cy -= dy - cw += dx - ch += dy - client.setArea((cx, cy, cw, ch)) - -_moving = False -_moveclient = 0 -_last_pos = () -_pcarea = () -_presspos = ()
D python/rc.py

@@ -1,124 +0,0 @@

-import hooks, ob, keymap, buttonmap, os, sys, input, motion, historyplacement -import stackedcycle -from input import Pointer - -hooks.managed.append(historyplacement.place) -#import windowplacement -#hooks.managed.append(windowplacement.random) - -_grab = 0 -def printshit(keydata, client): - global _grab - print "shit" - _grab = not _grab - print _grab - def gfunc(data, client=None): pass - if _grab: - input.Keyboard.grab(gfunc) - input.Pointer.grab(gfunc) - else: - input.Keyboard.ungrab() - input.Pointer.ungrab() - -def myexec(prog): - print "execing: ", prog - if (os.fork() == 0): - try: - os.setsid() - os.execl("/bin/sh", "/bin/sh", "-c", prog) - except: - print str(sys.exc_info()[0]) + ": " + str(sys.exc_info()[1]) - try: - print "failed to execute '" + prog + "'" - except: - print str(sys.exc_info()[0]) + ": " + str(sys.exc_info()[1]) - os._exit(0) - -def myactivate(c): - if ob.Openbox.showingDesktop(): - ob.Openbox.setShowingDesktop(False) - if c.iconic(): - c.setIconic(False) - elif not c.visible(): - # if its not visible for other reasons, then don't mess with it - return - if c.shaded(): - c.setShaded(False) - c.focus() - c.raiseWindow() - -hooks.requestactivate.append(myactivate) - -def myfocus(c): - if c and c.normal(): c.focus() - -#hooks.showwindow.append(myfocus) -hooks.pointerenter.append(myfocus) - -hooks.visible.append(myfocus) - -mykmap=((("C-a", "d"), printshit), - (("C-Tab",), stackedcycle.next), - (("C-S-Tab",), stackedcycle.previous), - (("Mod1-1",), lambda k,c: ob.Openbox.setDesktop(1)), - (("Mod1-2",), lambda k,c: ob.Openbox.setDesktop(2)), - (("Mod1-3",), lambda k,c: ob.Openbox.setDesktop(3)), - (("Mod1-4",), lambda k,c: ob.Openbox.setDesktop(4)), - (("Mod1-C-Left",), lambda k,c: ob.Openbox.setPreviousDesktop() or c.setDesktop(ob.Openbox.desktop())), - (("Mod1-C-Right",), lambda k,c: ob.Openbox.setNextDesktop() or c.setDesktop(ob.Openbox.desktop())), - (("Mod1-Left",), lambda k,c: ob.Openbox.setPreviousDesktop()), - (("Mod1-Right",), lambda k,c: ob.Openbox.setNextDesktop()), - (("C-space",), lambda k,c: myexec("xterm"))) -keymap.set(mykmap) - -def mytogglesticky(client): - if client.desktop() == 0xffffffff: d = ob.Openbox.desktop() - else: d = 0xffffffff - client.setDesktop(d) - -mybmap=(("1", "maximize", Pointer.Action_Click, - lambda c: c.setMaximized(not c.maximized())), - ("2", "maximize", Pointer.Action_Click, - lambda c: c.setMaximizedVert(not c.maximizedVert())), - ("3", "maximize", Pointer.Action_Click, - lambda c: c.setMaximizedHorz(not c.maximizedHorz())), - ("1", "alldesktops", Pointer.Action_Click, mytogglesticky), - ("1", "iconify", Pointer.Action_Click, - lambda c: c.setIconic(True)), - ("1", "icon", Pointer.Action_DoubleClick, ob.Client.close), - ("1", "close", Pointer.Action_Click, ob.Client.close), - ("1", "titlebar", Pointer.Action_Motion, motion.move), - ("1", "handle", Pointer.Action_Motion, motion.move), - ("Mod1-1", "frame", Pointer.Action_Click, ob.Client.raiseWindow), - ("Mod1-1", "frame", Pointer.Action_Motion, motion.move), - ("1", "titlebar", Pointer.Action_Press, ob.Client.raiseWindow), - ("1", "handle", Pointer.Action_Press, ob.Client.raiseWindow), - ("1", "client", Pointer.Action_Press, ob.Client.raiseWindow), - ("2", "titlebar", Pointer.Action_Press, ob.Client.lowerWindow), - ("2", "handle", Pointer.Action_Press, ob.Client.lowerWindow), - ("Mod1-3", "frame", Pointer.Action_Click, ob.Client.lowerWindow), - ("Mod1-3", "frame", Pointer.Action_Motion, motion.resize), - ("1", "blcorner", Pointer.Action_Motion, motion.resize), - ("1", "brcorner", Pointer.Action_Motion, motion.resize), - ("1", "titlebar", Pointer.Action_Press, ob.Client.focus), - ("1", "handle", Pointer.Action_Press, ob.Client.focus), - ("1", "client", Pointer.Action_Press, ob.Client.focus), - ("1", "titlebar", Pointer.Action_DoubleClick, - lambda c: c.setShaded(not c.shaded())), - ("4", "titlebar", Pointer.Action_Click, - lambda c: c.setShaded(True)), - ("5", "titlebar", Pointer.Action_Click, - lambda c: c.setShaded(False)), - ("4", "root", Pointer.Action_Click, - lambda c: ob.Openbox.setNextDesktop()), - ("5", "root", Pointer.Action_Click, - lambda c: ob.Openbox.setPreviousDesktop()), - ("Mod1-4", "frame", Pointer.Action_Click, - lambda c: ob.Openbox.setNextDesktop()), - ("Mod1-5", "frame", Pointer.Action_Click, - lambda c: ob.Openbox.setPreviousDesktop()), - ("Mod1-4", "root", Pointer.Action_Click, - lambda c: ob.Openbox.setNextDesktop()), - ("Mod1-5", "root", Pointer.Action_Click, - lambda c: ob.Openbox.setPreviousDesktop())) -buttonmap.set(mybmap)
D python/stackedcycle.py

@@ -1,216 +0,0 @@

-import ob, config, hooks, focus -from input import Pointer, Keyboard - -config.add('stackedcycle', - 'activate_while_cycling', - 'Activate While Cycling', - "If this is True then windows will be activated as they are" + \ - "highlighted in the cycling list (except iconified windows).", - 'boolean', - True) - -config.add('stackedcycle', - 'raise_window', - 'Raise After Cycling', - "If this is True, the selected window will be raised as well as " +\ - "focused.", - 'boolean', - True) - -config.add('stackedcycle', - 'include_all_desktops', - 'Include Windows From All Desktops', - "If this is True then windows from all desktops will be included" +\ - " in the stacking list.", - 'boolean', - False) - -config.add('stackedcycle', - 'include_icons', - 'Include Icons', - "If this is True then windows which are iconified on the current" +\ - " desktop will be included in the stacking list.", - 'boolean', - False) - -config.add('stackedcycle', - 'include_icons_all_desktops', - 'Include Icons From All Desktops', - "If this is True then windows which are iconified from all " +\ - "desktops will be included in the stacking list (if Include Icons"+\ - " is also True).", - 'boolean', - True) - -config.add('stackedcycle', - 'include_omnipresent', - 'Include Omnipresent Windows', - "If this is True then windows which are on all-desktops at once " +\ - "will be included in the stacking list.", - 'boolean', - True) - -def next(keydata, client): _cycle(keydata, client, True) -def previous(keydata, client): _cycle(keydata, client, False) - -def _shouldAdd(client): - """Determines if a client should be added to the cycling list.""" - curdesk = ob.Openbox.desktop() - desk = client.desktop() - - if not (client.normal() and client.canFocus()): return False - if config.get('focus', 'avoid_skip_taskbar') and client.skipTaskbar(): - return False - - if client.iconic(): - if config.get('stackedcycle', 'include_icons'): - if config.get('stackedcycle', 'include_icons_all_desktops'): - return True - if desk == curdesk: return True - return False - if config.get('stackedcycle', 'include_omnipresent') and \ - desk == 0xffffffff: return True - if config.get('stackedcycle', 'include_all_desktops'): return True - if desk == curdesk: return True - - return False - -def _populateItems(): - global _items - # get the list of clients, keeping iconic windows at the bottom - _items = [] - iconic_clients = [] - for c in focus._clients: - if _shouldAdd(c): - if c.iconic(): iconic_clients.append(c) - else: _items.append(c) - _items.extend(iconic_clients) - -def _populate(): - global _pos, _items - try: - current = _items[_pos] - except IndexError: - current = None - oldpos = _pos - _pos = -1 - - _populateItems() - - i = 0 - for item in _items: - # current item might have shifted after a populateItems() - # call, so we need to do this test. - if current == item: - _pos = i - i += 1 - - # The item we were on might be gone entirely - if _pos < 0: - # try stay at the same spot in the menu - if oldpos >= len(_items): - _pos = len(_items) - 1 - else: - _pos = oldpos - - -def _activate(final): - """ - Activates (focuses and, if the user requested it, raises a window). - If final is True, then this is the very last window we're activating - and the user has finished cycling. - """ - print "_activate" - try: - client = _items[_pos] - except IndexError: return # empty list - print client - - # move the to client's desktop if required - if not (client.iconic() or client.desktop() == 0xffffffff or \ - client.desktop() == ob.Openbox.desktop()): - ob.Openbox.setDesktop(client.desktop()) - - if final or not client.iconic(): - if final: r = config.get('stackedcycle', 'raise_window') - else: r = False - client.focus(True) - if final and client.shaded(): client.setShaded(False) - print "final", final, "raising", r - if r: client.raiseWindow() - if not final: - focus._skip += 1 - -def _cycle(keydata, client, forward): - global _cycling, _state, _pos, _inititem, _items - - if not _cycling: - _items = [] # so it doesnt try start partway through the list - _populate() - - if not _items: return # don't bother doing anything - - Keyboard.grab(_grabfunc) - # the pointer grab causes pointer events during the keyboard grab - # to go away, which means we don't get enter notifies when the - # popup disappears, screwing up the focus - Pointer.grabPointer(True) - - _cycling = True - _state = keydata.state - _pos = 0 - _inititem = _items[_pos] - - if forward: - _pos += 1 - else: - _pos -= 1 - # wrap around - if _pos < 0: _pos = len(_items) - 1 - elif _pos >= len(_items): _pos = 0 - if config.get('stackedcycle', 'activate_while_cycling'): - _activate(False) # activate, but dont deiconify/unshade/raise - -def _grabfunc(keydata, client): - global _cycling - - done = False - notreverting = True - # have all the modifiers this started with been released? - if not _state & keydata.state: - done = True - elif keydata.press: - # has Escape been pressed? - if keydata.keychain == "Escape": - done = True - notreverting = False - # revert - try: - _pos = _items.index(_inititem) - except: - _pos = -1 - # has Enter been pressed? - elif keydata.keychain == "Return": - done = True - - if done: - # activate, and deiconify/unshade/raise - _activate(notreverting) - _cycling = False - Keyboard.ungrab() - Pointer.grabPointer(False) - - -_cycling = False -_pos = 0 -_inititem = None -_items = [] -_state = 0 - -def _newwin(data): - if _cycling: _populate() -def _closewin(data): - if _cycling: _populate() - -hooks.managed.append(_newwin) -hooks.closed.append(_closewin)
D python/windowplacement.py

@@ -1,50 +0,0 @@

-############################################################################ -### Window placement algorithms, choose one of these and ebind it to the ### -### ob.EventAction.PlaceWindow event. ### -### ### -### Also see historyplacement.py for the history placement module which ### -### provides an algorithm that can be used in place of, or alongside, ### -### these. ### -############################################################################ - -import ob -from random import Random - -def random(client): - """Place windows randomly around the screen.""" - if ob.Openbox.state() == ob.State.Starting: return - #if data.client.positionRequested(): return - cx, cy, cw, ch = client.area() - sx, sy, sw, sh = ob.Openbox.screenArea(client.desktop()) - xr = sw - cw - 1 # x range - yr = sh - ch - 1 # y range - if xr <= 0: x = 0 - else: x = Random().randrange(sx, xr) - if yr <= 0: y = 0 - else: y = Random().randrange(sy, yr) - client.setArea((x, y, cw, ch)) - -def cascade(client): - """Place windows in a cascading order from top-left to bottom-right.""" - if ob.Openbox.state() == ob.State.Starting: return - #if data.client.positionRequested(): return - cx, cy, cw, ch = client.area() - sx, sy, sw, sh = ob.Openbox.screenArea(client.desktop()) - width = sw - cw - height = sh - ch - global _cascade_x, _cascade_y - if _cascade_x < sx or _cascade_y < sy or \ - _cascade_x >= width or _cascade_y >= height: - _cascade_x = sx - _cascade_y = sy - client.setArea((_cascade_x, _cascade_y, cw, ch)) - frame_size = client.frameSize() - _cascade_x += frame_size[1] - _cascade_y += frame_size[1] - -_cascade_x = 0 -_cascade_y = 0 - -export_functions = random, cascade - -print "Loaded windowplacement.py"
D scripts/.cvsignore

@@ -1,2 +0,0 @@

-Makefile -Makefile.in
D scripts/Makefile.am

@@ -1,10 +0,0 @@

-scriptdir = $(libdir)/openbox/python -MAINTAINERCLEANFILES = Makefile.in -script_PYTHON = config.py defaults.py focus.py callbacks.py \ - focusmodel.py windowplacement.py behavior.py motion.py \ - historyplacement.py cycle.py - -distclean-local: - $(RM) *\~ .\#* -uninstall-am: - rmdir -p $(scriptdir)
D scripts/behavior.py

@@ -1,115 +0,0 @@

-############################################################################### -### Functions for setting up some default behaviors. This includes the ### -### default bindings for clicking on various parts of a window, the ### -### titlebar buttons, and bindings for the scroll wheel on your mouse. ### -############################################################################### - -import ob -import callbacks -import motion - -def setup_window_clicks(): - """Sets up the default bindings for various mouse buttons for various - contexts. - This includes: - * Alt-left drag anywhere on a window will move it - * Alt-right drag anywhere on a window will resize it - * Left drag on a window's titlebar/handle will move it - * Left drag on a window's handle grips will resize it - * Alt-left press anywhere on a window's will raise it to the front of - its stacking layer. - * Left press on a window's titlebar/handle will raise it to the front - of its stacking layer. - * Alt-middle click anywhere on a window's will lower it to the bottom - of its stacking layer. - * Middle click on a window's titlebar/handle will lower it to the - bottom of its stacking layer. - * Double-left click on a window's titlebar will toggle shading it - """ - ob.mbind("A-Left", ob.MouseContext.Frame, - ob.MouseAction.Motion, motion.move) - ob.mbind("A-Left", ob.MouseContext.Frame, - ob.MouseAction.Release, motion.end_move) - ob.mbind("Left", ob.MouseContext.Titlebar, - ob.MouseAction.Motion, motion.move) - ob.mbind("Left", ob.MouseContext.Titlebar, - ob.MouseAction.Release, motion.end_move) - ob.mbind("Left", ob.MouseContext.Handle, - ob.MouseAction.Motion, motion.move) - ob.mbind("Left", ob.MouseContext.Handle, - ob.MouseAction.Release, motion.end_move) - - ob.mbind("A-Right", ob.MouseContext.Frame, - ob.MouseAction.Motion, motion.resize) - ob.mbind("A-Right", ob.MouseContext.Frame, - ob.MouseAction.Release, motion.end_resize) - ob.mbind("Left", ob.MouseContext.Grip, - ob.MouseAction.Motion, motion.resize) - ob.mbind("Left", ob.MouseContext.Grip, - ob.MouseAction.Release, motion.end_resize) - - ob.mbind("Left", ob.MouseContext.Titlebar, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("Left", ob.MouseContext.Handle, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("A-Left", ob.MouseContext.Frame, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("A-Middle", ob.MouseContext.Frame, - ob.MouseAction.Click, callbacks.lower_win) - ob.mbind("Middle", ob.MouseContext.Titlebar, - ob.MouseAction.Click, callbacks.lower_win) - ob.mbind("Middle", ob.MouseContext.Handle, - ob.MouseAction.Click, callbacks.lower_win) - - ob.mbind("Left", ob.MouseContext.Titlebar, - ob.MouseAction.DoubleClick, callbacks.toggle_shade) - -def setup_window_buttons(): - """Sets up the default behaviors for the buttons in the window titlebar.""" - ob.mbind("Left", ob.MouseContext.AllDesktopsButton, - ob.MouseAction.Click, callbacks.toggle_all_desktops) - ob.mbind("Left", ob.MouseContext.CloseButton, - ob.MouseAction.Click, callbacks.close) - ob.mbind("Left", ob.MouseContext.IconifyButton, - ob.MouseAction.Click, callbacks.iconify) - ob.mbind("Left", ob.MouseContext.MaximizeButton, - ob.MouseAction.Click, callbacks.toggle_maximize) - ob.mbind("Middle", ob.MouseContext.MaximizeButton, - ob.MouseAction.Click, callbacks.toggle_maximize_vert) - ob.mbind("Right", ob.MouseContext.MaximizeButton, - ob.MouseAction.Click, callbacks.toggle_maximize_horz) - -def setup_scroll(): - """Sets up the default behaviors for the mouse scroll wheel. - This includes: - * scrolling on a window titlebar will shade/unshade it - * alt-scrolling anywhere will switch to the next/previous desktop - * control-alt-scrolling on a window will send it to the next/previous - desktop, and switch to the desktop with the window - """ - ob.mbind("Up", ob.MouseContext.Titlebar, - ob.MouseAction.Click, callbacks.shade) - ob.mbind("Down", ob.MouseContext.Titlebar, - ob.MouseAction.Click, callbacks.unshade) - - ob.mbind("A-Up", ob.MouseContext.Frame, - ob.MouseAction.Click, callbacks.next_desktop) - ob.mbind("A-Up", ob.MouseContext.Root, - ob.MouseAction.Click, callbacks.next_desktop) - ob.mbind("Up", ob.MouseContext.Root, - ob.MouseAction.Click, callbacks.next_desktop) - ob.mbind("A-Down", ob.MouseContext.Frame, - ob.MouseAction.Click, callbacks.prev_desktop) - ob.mbind("A-Down", ob.MouseContext.Root, - ob.MouseAction.Click, callbacks.prev_desktop) - ob.mbind("Down", ob.MouseContext.Root, - ob.MouseAction.Click, callbacks.prev_desktop) - - ob.mbind("C-A-Up", ob.MouseContext.Frame, - ob.MouseAction.Click, callbacks.send_to_next_desktop) - ob.mbind("C-A-Down", ob.MouseContext.Frame, - ob.MouseAction.Click, callbacks.send_to_prev_desktop) - -export_functions = setup_window_clicks, setup_window_buttons, setup_scroll - -print "Loaded behavior.py"
D scripts/callbacks.py

@@ -1,284 +0,0 @@

-############################################################################ -### Functions that can be used as callbacks for mouse/keyboard bindings ### -############################################################################ - -import ob -import otk - -def iconify(data): - """Iconifies the window on which the event occured""" - if not data.client: return - data.client.iconify(1) - -def restore(data): - """Un-iconifies the window on which the event occured, but does not focus - if. If you want to focus the window too, it is recommended that you - use the activate() function.""" - if not data.client: return - data.client.iconify(0) - -def close(data): - """Closes the window on which the event occured""" - if not data.client: return - data.client.close() - -def focus(data): - """Focuses the window on which the event occured""" - if not data.client: return - # !normal windows dont get focus from window enter events - if data.action == ob.EventAction.EnterWindow and not data.client.normal(): - return - data.client.focus() - -def raise_win(data): - """Raises the window on which the event occured""" - if not data.client: return - data.client.raiseWindow() - -def lower_win(data): - """Lowers the window on which the event occured""" - if not data.client: return - data.client.lowerWindow() - -def toggle_maximize(data): - """Toggles the maximized status of the window on which the event occured""" - if not data.client: return - data.client.maximize(not (data.client.maxHorz() or data.client.maxVert())) - -def toggle_maximize_horz(data): - """Toggles the horizontal maximized status of the window on which the event - occured""" - if not data.client: return - data.client.maximizeHorizontal(not data.client.maxHorz()) - -def toggle_maximize_vert(data): - """Toggles the vertical maximized status of the window on which the event - occured""" - if not data.client: return - data.client.maximizeVertical(not data.client.maxVert()) - -def maximize(data): - """Maximizes the window on which the event occured""" - if not data.client: return - data.client.maximize(1) - -def maximize_horz(data): - """Horizontally maximizes the window on which the event occured""" - if not data.client: return - data.client.maximizeHorizontal(1) - -def maximize_vert(data): - """Vertically maximizes the window on which the event occured""" - if not data.client: return - data.client.maximizeVertical(1) - -def unmaximize(data): - """Unmaximizes the window on which the event occured""" - if not data.client: return - data.client.maximize(0) - -def unmaximize_horz(data): - """Horizontally unmaximizes the window on which the event occured""" - if not data.client: return - data.client.maximizeHorizontal(0) - -def unmaximize_vert(data): - """Vertically unmaximizes the window on which the event occured""" - if not data.client: return - data.client.maximizeVertical(0) - -def toggle_shade(data): - """Toggles the shade status of the window on which the event occured""" - if not data.client: return - data.client.shade(not data.client.shaded()) - -def shade(data): - """Shades the window on which the event occured""" - if not data.client: return - data.client.shade(1) - -def unshade(data): - """Unshades the window on which the event occured""" - if not data.client: return - data.client.shade(0) - -def change_desktop(data, num): - """Switches to a specified desktop""" - ob.openbox.screen(data.screen).changeDesktop(num) - -def show_desktop(data, show=1): - """Shows and focuses the desktop, hiding any client windows. Optionally, - if show is zero, this will hide the desktop, leaving show-desktop - mode.""" - ob.openbox.screen(data.screen).showDesktop(show) - -def hide_desktop(data): - """Hides the desktop, re-showing the client windows. Leaves show-desktop - mode.""" - show_desktop(data, 0) - -def toggle_show_desktop(data): - """Requests the Openbox to show the desktop, hiding the client windows, or - redisplay the clients.""" - screen = ob.openbox.screen(data.screen) - screen.showDesktop(not screen.showingDesktop()) - -def next_desktop(data, no_wrap=0): - """Switches to the next desktop, optionally (by default) cycling around to - the first when going past the last.""" - screen = ob.openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - if (d < (n-1)): - d = d + 1 - elif not no_wrap: - d = 0 - change_desktop(data, d) - -def prev_desktop(data, no_wrap=0): - """Switches to the previous desktop, optionally (by default) cycling around - to the last when going past the first.""" - screen = ob.openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - if (d > 0): - d = d - 1 - elif not no_wrap: - d = n - 1 - change_desktop(data, d) - -def up_desktop(data, num=1): - """Switches to the desktop vertically above the current one. This is based - on the desktop layout chosen by an EWMH compliant pager. Optionally, num - can be specified to move more than one row at a time.""" - screen = ob.openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - l = screen.desktopLayout() - - target = d - num * l.columns - if target < 0: - target += l.rows * l.columns - while target >= n: - target -= l.columns - change_desktop(data, target) - -def down_desktop(data, num=1): - """Switches to the desktop vertically below the current one. This is based - on the desktop layout chosen by an EWMH compliant pager. Optionally, num - can be specified to move more than one row at a time.""" - screen = ob.openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - l = screen.desktopLayout() - - target = d + num * l.columns - if target >= n: - target -= l.rows * l.columns - while target < 0: - target += l.columns - change_desktop(data, target) - -def left_desktop(data, num=1): - """Switches to the desktop horizotally left of the current one. This is - based on the desktop layout chosen by an EWMH compliant pager. - Optionally, num can be specified to move more than one column at a - time.""" - screen = ob.openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - l = screen.desktopLayout() - - rowstart = d - d % l.columns - target = d - num - while target < rowstart: - target += l.columns - change_desktop(data, target) - -def right_desktop(data, num=1): - """Switches to the desktop horizotally right of the current one. This is - based on the desktop layout chosen by an EWMH compliant pager. - Optionally, num can be specified to move more than one column at a - time.""" - screen = ob.openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - l = screen.desktopLayout() - - rowstart = d - d % l.columns - target = d + num - while target >= rowstart + l.columns: - target -= l.columns - change_desktop(data, target) - -def send_to_desktop(data, num): - """Sends a client to a specified desktop""" - if not data.client: return - data.client.setDesktop(num) - -def toggle_all_desktops(data): - """Toggles between sending a client to all desktops and to the current - desktop.""" - if not data.client: return - if not data.client.desktop() == 0xffffffff: - send_to_desktop(data, 0xffffffff) - else: - send_to_desktop(data, ob.openbox.screen(data.screen).desktop()) - -def send_to_all_desktops(data): - """Sends a client to all desktops""" - if not data.client: return - send_to_desktop(data, 0xffffffff) - -def send_to_next_desktop(data, no_wrap=0, follow=1): - """Sends a window to the next desktop, optionally (by default) cycling - around to the first when going past the last. Also optionally moving to - the new desktop after sending the window.""" - if not data.client: return - screen = ob.openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - if (d < (n-1)): - d = d + 1 - elif not no_wrap: - d = 0 - send_to_desktop(data, d) - if follow: - change_desktop(data, d) - -def send_to_prev_desktop(data, no_wrap=0, follow=1): - """Sends a window to the previous desktop, optionally (by default) cycling - around to the last when going past the first. Also optionally moving to - the new desktop after sending the window.""" - if not data.client: return - screen = ob.openbox.screen(data.screen) - d = screen.desktop() - n = screen.numDesktops() - if (d > 0): - d = d - 1 - elif not no_wrap: - d = n - 1 - send_to_desktop(data, d) - if follow: - change_desktop(data, d) - -def restart(data=0, other = ""): - """Restarts Openbox, optionally starting another window manager.""" - ob.openbox.restart(other) - -def exit(data=0): - """Exits Openbox.""" - ob.openbox.shutdown() - -export_functions = iconify, restore, close, focus, raise_win, lower_win, \ - toggle_maximize, toggle_maximize_horz, \ - toggle_maximize_vert, maximize, maximize_horz, \ - maximize_vert, unmaximize, unmaximize_horz, \ - unmaximize_vert, toggle_shade, shade, unshade, \ - change_desktop, show_desktop, hide_desktop, \ - toggle_show_desktop, next_desktop, prev_desktop, \ - up_desktop, down_desktop, left_desktop, right_desktop, \ - send_to_desktop, toggle_all_desktops, send_to_all_desktops,\ - send_to_next_desktop, send_to_prev_desktop, restart, exit - -print "Loaded callbacks.py"
D scripts/config.py

@@ -1,244 +0,0 @@

-# Openbox's config system. Please use the defined functions instead of -# accessing the internal data structures directly, for the sake of us all. - -import ob - -def add(modulename, name, friendlyname, description, type, default, - **keywords): - """Add a variable to the configuration system. - - Add a variable to the configuration system for a module. - modulename - The name of the module, e.g. 'focus' - name - The name of the variable, e.g. 'my_variable' - friendlyname - The user-friendly name of the variable, e.g. 'My Variable' - description - The detailed destription of the variable, e.g. 'Does Things' - type - The type of the variable, one of: - - 'boolean' - - 'enum' - - 'integer' - - 'string' - - 'file' - - 'function' - - 'object' - default - The default value for the variable, e.g. 300 - keywords - Extra keyword=value pairs to further define the variable. These - can be: - - For 'enum' types: - - options : A list of possible options for the variable. - This *must* be set for all enum variables. - - For 'integer' types: - - min : The minimum value for the variable. - - max : The maximum value for the variable. - """ - modulename = str(modulename).lower() - name = str(name).lower() - friendlyname = str(friendlyname) - description = str(description) - type = str(type).lower() - - # make sure the sub-dicts exist - try: - _settings[modulename] - try: - _settings[modulename][name] - except KeyError: - _settings[modulename][name] = {} - except KeyError: - _settings[modulename] = {} - _settings[modulename][name] = {} - - # add the keywords first as they are used for the tests in set() - for key,value in zip(keywords.keys(), keywords.values()): - _settings[modulename][name][key] = value - - _settings[modulename][name]['name'] = friendlyname - _settings[modulename][name]['description'] = description - _settings[modulename][name]['type'] = type - _settings[modulename][name]['default'] = default - - # put it through the tests - try: - set(modulename, name, default) - except: - del _settings[modulename][name] - import sys - raise sys.exc_info()[0], sys.exc_info()[1] # re-raise it - -def set(modulename, name, value): - """Set a variable's value. - - Sets the value for a variable of the specified module. - modulename - The name of the module, e.g. 'focus' - name - The name of the variable, e.g. 'my_variable' - value - The new value for the variable. - """ - modulename = str(modulename).lower() - name = str(name).lower() - - # proper value checking for 'boolean's - if _settings[modulename][name]['type'] == 'boolean': - if not (value == 0 or value == 1): - raise ValueError, 'Attempted to set ' + name + ' to a value of '+\ - str(value) + ' but boolean variables can only contain 0 or'+\ - ' 1.' - - # proper value checking for 'enum's - elif _settings[modulename][name]['type'] == 'enum': - options = _settings[modulename][name]['options'] - if not value in options: - raise ValueError, 'Attempted to set ' + name + ' to a value of '+\ - str(value) + ' but this is not one of the possible values '+\ - 'for this enum variable. Possible values are: ' +\ - str(options) + "." - - # min/max checking for 'integer's - elif _settings[modulename][name]['type'] == 'integer': - try: - min = _settings[modulename][name]['min'] - if value < min: - raise ValueError, 'Attempted to set ' + name + ' to a value '+\ - ' of ' + str(value) + ' but it has a minimum value ' +\ - ' of ' + str(min) + '.' - except KeyError: pass - try: - max = _settings[modulename][name]['max'] - if value > max: - raise ValueError, 'Attempted to set ' + name + ' to a value '+\ - ' of ' + str(value) + ' but it has a maximum value ' +\ - ' of ' + str(min) + '.' - except KeyError: pass - - _settings[modulename][name]['value'] = value - -def reset(modulename, name): - """Reset a variable to its default value. - - Resets the value for a variable in the specified module back to its - original (default) value. - modulename - The name of the module, e.g. 'focus' - name - The name of the variable, e.g. 'my_variable' - """ - modulename = str(modulename).lower() - name = str(name).lower() - _settings[modulename][name]['value'] = \ - _settings[modulename][name]['default'] - -def get(modulename, name): - """Returns the value of a variable. - - Returns the current value for a variable in the specified module. - modulename - The name of the module, e.g. 'focus' - name - The name of the variable, e.g. 'my variable' - """ - modulename = str(modulename).lower() - name = str(name).lower() - return _settings[modulename][name]['value'] - -#---------------------------- Internals --------------------------- - -"""The main configuration dictionary, which holds sub-dictionaries for each - module. - - The format for entries in here like this (for a string): - _settings['modulename']['varname']['name'] = 'Text Label' - _settings['modulename']['varname']['description'] = 'Does this' - _settings['modulename']['varname']['type'] = 'string' - _settings['modulename']['varname']['default'] = 'Foo' - _settings['modulename']['varname']['value'] = 'Foo' - # 'value' should always be initialized to the same - # value as the 'default' field! - - Here's an example of an enum: - _settings['modulename']['varname']['name'] = 'My Enum Variable' - _settings['modulename']['varname']['description'] = 'Does Enum-like things.' - _settings['modulename']['varname']['type'] = 'enum' - _settings['modulename']['varname']['default'] = \ - _settings['modulename']['varname']['value'] = [ 'Blue', 'Green', 'Pink' ] - - And Here's an example of an integer with bounds: - _settings['modulename']['varname']['name'] = 'A Bounded Integer' - _settings['modulename']['varname']['description'] = 'A fierce party animal!' - _settings['modulename']['varname']['type'] = 'integer' - _settings['modulename']['varname']['default'] = \ - _settings['modulename']['varname']['value'] = 0 - _settings['modulename']['varname']['min'] = 0 - _settings['modulename']['varname']['max'] = 49 - - Hopefully you get the idea. - """ -_settings = {} - -"""Valid values for a variable's type.""" -_types = [ 'boolean', # Boolean types can only hold a value of 0 or 1. - - 'enum', # Enum types hold a value from a list of possible values. - # An 'options' field *must* be provided for enums, - # containing a list of possible values for the variable. - - 'integer', # Integer types hold a single number, as well as a 'min' - # and 'max' property. - # If the 'min' or 'max' is ignore then bounds checking - # will not be performed in that direction. - - 'string', # String types hold a text string. - - 'file', # File types hold a file object. - - 'function',# Function types hold any callable object. - - 'object' # Object types can hold any python object. - ]; - - - - - - - - - - - - - - - - - -############################################################################# -### Options that can be changed to adjust the behavior of Openbox. ### -############################################################################# - -THEME = "/usr/local/share/openbox/styles/fieron2" -"""The theme used to decorate everything.""" - -#TITLEBAR_LAYOUT = [ "icon", "title", "alldesktops", "iconify", "maximize", "close" ] -TITLEBAR_LAYOUT = "DITMC" -"""The layout of the buttons/label on client titlebars, can be made up of the -following: - I - iconify button - L - text label - M - maximize button, - D - all-desktops button - C - close button -If no 'L' is included in the string, one will be added to the end by -Openbox.""" - -DOUBLE_CLICK_DELAY = 300 -"""The number of milliseconds in which 2 clicks are perceived as a -double-click.""" - -DRAG_THRESHOLD = 3 -"""The amount of pixels that you have to drag the mouse before motion events -will start occuring.""" - -DESKTOP_NAMES = ["one", "two", "three", "four", "five", "six", "seven", \ - "eight", "nine", "ten", "eleven", "twelve"] -"""The name of each desktop.""" - -NUMBER_OF_DESKTOPS = 4 -"""The number of desktops/workspaces which can be scrolled between.""" - -############################################################################# - -print "Loaded config.py"
D scripts/cycle.py

@@ -1,473 +0,0 @@

-import ob, otk, config -class _Cycle: - """ - This is a basic cycling class for anything, from xOr's stackedcycle.py, - that pops up a cycling menu when there's more than one thing to be cycled - to. - An example of inheriting from and modifying this class is _CycleWindows, - which allows users to cycle around windows. - - This class could conceivably be used to cycle through anything -- desktops, - windows of a specific class, XMMS playlists, etc. - """ - - """This specifies a rough limit of characters for the cycling list titles. - Titles which are larger will be chopped with an elipsis in their - center.""" - TITLE_SIZE_LIMIT = 80 - - """If this is non-zero then windows will be activated as they are - highlighted in the cycling list (except iconified windows).""" - ACTIVATE_WHILE_CYCLING = 0 - - """If this is true, we start cycling with the next (or previous) thing - selected.""" - START_WITH_NEXT = 1 - - """If this is true, a popup window will be displayed with the options - while cycling.""" - SHOW_POPUP = 1 - - def __init__(self): - """Initialize an instance of this class. Subclasses should - do any necessary event binding in their constructor as well. - """ - self.cycling = 0 # internal var used for going through the menu - self.items = [] # items to cycle through - - self.widget = None # the otk menu widget - self.menuwidgets = [] # labels in the otk menu widget TODO: RENAME - - def createPopup(self): - """Creates the cycling popup menu. - """ - self.widget = otk.Widget(self.screen.number(), ob.openbox, - otk.Widget.Vertical, 0, 1) - - def destroyPopup(self): - """Destroys (or rather, cleans up after) the cycling popup menu. - """ - self.menuwidgets = [] - self.widget = 0 - - def populateItems(self): - """Populate self.items with the appropriate items that can currently - be cycled through. self.items may be cleared out before this - method is called. - """ - pass - - def menuLabel(self, item): - """Return a string indicating the menu label for the given item. - Don't worry about title truncation. - """ - pass - - def itemEqual(self, item1, item2): - """Compare two items, return 1 if they're "equal" for purposes of - cycling, and 0 otherwise. - """ - # suggestion: define __eq__ on item classes so that this works - # in the general case. :) - return item1 == item2 - - def populateLists(self): - """Populates self.items and self.menuwidgets, and then shows and - positions the cycling popup. You probably shouldn't mess with - this function; instead, see populateItems and menuLabel. - """ - self.widget.hide() - - try: - current = self.items[self.menupos] - except IndexError: - current = None - oldpos = self.menupos - self.menupos = -1 - - self.items = [] - self.populateItems() - - # make the widgets - i = 0 - self.menuwidgets = [] - for i in range(len(self.items)): - c = self.items[i] - - w = otk.Label(self.widget) - # current item might have shifted after a populateItems() - # call, so we need to do this test. - if current and self.itemEqual(c, current): - self.menupos = i - w.setHilighted(1) - self.menuwidgets.append(w) - - t = self.menuLabel(c) - # TODO: maybe subclasses will want to truncate in different ways? - if len(t) > self.TITLE_SIZE_LIMIT: # limit the length of titles - t = t[:self.TITLE_SIZE_LIMIT / 2 - 2] + "..." + \ - t[0 - self.TITLE_SIZE_LIMIT / 2 - 2:] - w.setText(t) - - # The item we were on might be gone entirely - if self.menupos < 0: - # try stay at the same spot in the menu - if oldpos >= len(self.items): - self.menupos = len(self.items) - 1 - else: - self.menupos = oldpos - - # find the size for the popup - width = 0 - height = 0 - for w in self.menuwidgets: - size = w.minSize() - if size.width() > width: width = size.width() - height += size.height() - - # show or hide the list and its child widgets - if len(self.items) > 1: - size = self.screen.size() - self.widget.moveresize(otk.Rect((size.width() - width) / 2, - (size.height() - height) / 2, - width, height)) - if self.SHOW_POPUP: self.widget.show(1) - - def activateTarget(self, final): - """Activates (focuses and, if the user requested it, raises a window). - If final is true, then this is the very last window we're activating - and the user has finished cycling. - """ - pass - - def setDataInfo(self, data): - """Retrieve and/or calculate information when we start cycling, - preferably caching it. Data is what's given to callback functions. - """ - self.screen = ob.openbox.screen(data.screen) - - def chooseStartPos(self): - """Set self.menupos to a number between 0 and len(self.items) - 1. - By default the initial menupos is 0, but this can be used to change - it to some other position.""" - pass - - def cycle(self, data, forward): - """Does the actual job of cycling through windows. data is a callback - parameter, while forward is a boolean indicating whether the - cycling goes forwards (true) or backwards (false). - """ - - initial = 0 - - if not self.cycling: - ob.kgrab(data.screen, self.grabfunc) - # the pointer grab causes pointer events during the keyboard grab - # to go away, which means we don't get enter notifies when the - # popup disappears, screwing up the focus - ob.mgrab(data.screen) - - self.cycling = 1 - self.state = data.state - self.menupos = 0 - - self.setDataInfo(data) - - self.createPopup() - self.items = [] # so it doesnt try start partway through the list - self.populateLists() - - self.chooseStartPos() - self.initpos = self.menupos - - initial = 1 - - if not self.items: return # don't bother doing anything - - self.menuwidgets[self.menupos].setHighlighted(0) - - if initial and not self.START_WITH_NEXT: - pass - else: - if forward: - self.menupos += 1 - else: - self.menupos -= 1 - # wrap around - if self.menupos < 0: self.menupos = len(self.items) - 1 - elif self.menupos >= len(self.items): self.menupos = 0 - self.menuwidgets[self.menupos].setHighlighted(1) - if self.ACTIVATE_WHILE_CYCLING: - self.activateTarget(0) # activate, but dont deiconify/unshade/raise - - def grabfunc(self, data): - """A callback method that grabs away all keystrokes so that navigating - the cycling menu is possible.""" - done = 0 - notreverting = 1 - # have all the modifiers this started with been released? - if not self.state & data.state: - done = 1 - elif data.action == ob.KeyAction.Press: - # has Escape been pressed? - if data.key == "Escape": - done = 1 - notreverting = 0 - # revert - self.menupos = self.initpos - # has Enter been pressed? - elif data.key == "Return": - done = 1 - - if done: - # activate, and deiconify/unshade/raise - self.activateTarget(notreverting) - self.destroyPopup() - self.cycling = 0 - ob.kungrab() - ob.mungrab() - - def next(self, data): - """Focus the next window.""" - self.cycle(data, 1) - - def previous(self, data): - """Focus the previous window.""" - self.cycle(data, 0) - -#---------------------- Window Cycling -------------------- -import focus -class _CycleWindows(_Cycle): - """ - This is a basic cycling class for Windows. - - An example of inheriting from and modifying this class is - _ClassCycleWindows, which allows users to cycle around windows of a certain - application name/class only. - - This class has an underscored name because I use the singleton pattern - (so CycleWindows is an actual instance of this class). This doesn't have - to be followed, but if it isn't followed then the user will have to create - their own instances of your class and use that (not always a bad thing). - - An example of using the CycleWindows singleton: - - from cycle import CycleWindows - CycleWindows.INCLUDE_ICONS = 0 # I don't like cycling to icons - ob.kbind(["A-Tab"], ob.KeyContext.All, CycleWindows.next) - ob.kbind(["A-S-Tab"], ob.KeyContext.All, CycleWindows.previous) - """ - - """If this is non-zero then windows from all desktops will be included in - the stacking list.""" - INCLUDE_ALL_DESKTOPS = 0 - - """If this is non-zero then windows which are iconified on the current - desktop will be included in the stacking list.""" - INCLUDE_ICONS = 1 - - """If this is non-zero then windows which are iconified from all desktops - will be included in the stacking list.""" - INCLUDE_ICONS_ALL_DESKTOPS = 1 - - """If this is non-zero then windows which are on all-desktops at once will - be included.""" - INCLUDE_OMNIPRESENT = 1 - - """A better default for window cycling than generic cycling.""" - ACTIVATE_WHILE_CYCLING = 1 - - """When cycling focus, raise the window chosen as well as focusing it.""" - RAISE_WINDOW = 1 - - def __init__(self): - _Cycle.__init__(self) - - def newwindow(data): - if self.cycling: self.populateLists() - def closewindow(data): - if self.cycling: self.populateLists() - - ob.ebind(ob.EventAction.NewWindow, newwindow) - ob.ebind(ob.EventAction.CloseWindow, closewindow) - - def shouldAdd(self, client): - """Determines if a client should be added to the cycling list.""" - curdesk = self.screen.desktop() - desk = client.desktop() - - if not client.normal(): return 0 - if not (client.canFocus() or client.focusNotify()): return 0 - if config.get('focus', 'avoid_skip_taskbar') and client.skipTaskbar(): - return 0 - - if client.iconic(): - if self.INCLUDE_ICONS: - if self.INCLUDE_ICONS_ALL_DESKTOPS: return 1 - if desk == curdesk: return 1 - return 0 - if self.INCLUDE_OMNIPRESENT and desk == 0xffffffff: return 1 - if self.INCLUDE_ALL_DESKTOPS: return 1 - if desk == curdesk: return 1 - - return 0 - - def populateItems(self): - # get the list of clients, keeping iconic windows at the bottom - iconic_clients = [] - for c in focus._clients: - if self.shouldAdd(c): - if c.iconic(): iconic_clients.append(c) - else: self.items.append(c) - self.items.extend(iconic_clients) - - def menuLabel(self, client): - if client.iconic(): t = '[' + client.iconTitle() + ']' - else: t = client.title() - - if self.INCLUDE_ALL_DESKTOPS: - d = client.desktop() - if d == 0xffffffff: d = self.screen.desktop() - t = self.screen.desktopNames()[d] + " - " + t - - return t - - def itemEqual(self, client1, client2): - return client1.window() == client2.window() - - def activateTarget(self, final): - """Activates (focuses and, if the user requested it, raises a window). - If final is true, then this is the very last window we're activating - and the user has finished cycling.""" - try: - client = self.items[self.menupos] - except IndexError: return # empty list - - # move the to client's desktop if required - if not (client.iconic() or client.desktop() == 0xffffffff or \ - client.desktop() == self.screen.desktop()): - self.screen.changeDesktop(client.desktop()) - - # send a net_active_window message for the target - if final or not client.iconic(): - if final: r = self.RAISE_WINDOW - else: r = 0 - client.focus(final, r) - if not final: - focus._skip += 1 - -# The singleton. -CycleWindows = _CycleWindows() - -#---------------------- Window Cycling -------------------- -import focus -class _CycleWindowsLinear(_CycleWindows): - """ - This class is an example of how to inherit from and make use of the - _CycleWindows class. This class also uses the singleton pattern. - - An example of using the CycleWindowsLinear singleton: - - from cycle import CycleWindowsLinear - CycleWindows.ALL_DESKTOPS = 1 # I want all my windows in the list - ob.kbind(["A-Tab"], ob.KeyContext.All, CycleWindowsLinear.next) - ob.kbind(["A-S-Tab"], ob.KeyContext.All, CycleWindowsLinear.previous) - """ - - """When cycling focus, raise the window chosen as well as focusing it.""" - RAISE_WINDOW = 0 - - """If this is true, a popup window will be displayed with the options - while cycling.""" - SHOW_POPUP = 0 - - def __init__(self): - _CycleWindows.__init__(self) - - def shouldAdd(self, client): - """Determines if a client should be added to the cycling list.""" - curdesk = self.screen.desktop() - desk = client.desktop() - - if not client.normal(): return 0 - if not (client.canFocus() or client.focusNotify()): return 0 - if config.get('focus', 'avoid_skip_taskbar') and client.skipTaskbar(): - return 0 - - if client.iconic(): return 0 - if self.INCLUDE_OMNIPRESENT and desk == 0xffffffff: return 1 - if self.INCLUDE_ALL_DESKTOPS: return 1 - if desk == curdesk: return 1 - - return 0 - - def populateItems(self): - # get the list of clients, keeping iconic windows at the bottom - iconic_clients = [] - for c in self.screen.clients: - if self.shouldAdd(c): - self.items.append(c) - - def chooseStartPos(self): - if focus._clients: - t = focus._clients[0] - for i,c in zip(range(len(self.items)), self.items): - if self.itemEqual(c, t): - self.menupos = i - break - - def menuLabel(self, client): - t = client.title() - - if self.INCLUDE_ALL_DESKTOPS: - d = client.desktop() - if d == 0xffffffff: d = self.screen.desktop() - t = self.screen.desktopNames()[d] + " - " + t - - return t - -# The singleton. -CycleWindowsLinear = _CycleWindowsLinear() - -#----------------------- Desktop Cycling ------------------ -class _CycleDesktops(_Cycle): - """ - Example of usage: - - from cycle import CycleDesktops - ob.kbind(["W-d"], ob.KeyContext.All, CycleDesktops.next) - ob.kbind(["W-S-d"], ob.KeyContext.All, CycleDesktops.previous) - """ - class Desktop: - def __init__(self, name, index): - self.name = name - self.index = index - def __eq__(self, other): - return other.index == self.index - - def __init__(self): - _Cycle.__init__(self) - - def populateItems(self): - names = self.screen.desktopNames() - num = self.screen.numDesktops() - for n, i in zip(names[:num], range(num)): - self.items.append(_CycleDesktops.Desktop(n, i)) - - def menuLabel(self, desktop): - return desktop.name - - def chooseStartPos(self): - self.menupos = self.screen.desktop() - - def activateTarget(self, final): - # TODO: refactor this bit - try: - desktop = self.items[self.menupos] - except IndexError: return - - self.screen.changeDesktop(desktop.index) - -CycleDesktops = _CycleDesktops() - -print "Loaded cycle.py"
D scripts/defaults.py

@@ -1,78 +0,0 @@

-import ob # base module -import focus # add some default focus handling and cycling functions -import focusmodel # default focus models -import behavior # defines default behaviors for interaction with windows -import callbacks # a lib of functions that can be used as binding callbacks -import windowplacement # use a routine in here to place windows -import historyplacement # history window placement - -# try focus something when nothing is focused -focus.FALLBACK = 1 - -# choose a default focus model -focusmodel.setup_click_focus() # use focusmodel.setup_sloppy_focus() instead to - # make focus follow the cursor, or bind things - # in some way like these functions do to make - # your own custom focus model. -# set up the mouse buttons -behavior.setup_window_clicks() -behavior.setup_window_buttons() -behavior.setup_scroll() - -# my window placement algorithm -#ob.ebind(ob.EventAction.PlaceWindow, windowplacement.random) -ob.ebind(ob.EventAction.PlaceWindow, historyplacement.place) -# don't place terminals by history placement (xterm,aterm,rxvt) -def histplace(data): - if data.client.appClass() == "XTerm": return 0 - return 1 -historyplacement.CONFIRM_CALLBACK = histplace - - -# run xterm from root clicks -ob.mbind("Left", ob.MouseContext.Root, ob.MouseAction.Click, - lambda(d): ob.execute("xterm", d.screen)) - -ob.kbind(["A-F4"], ob.KeyContext.All, callbacks.close) - -ob.kbind(["W-d"], ob.KeyContext.All, callbacks.toggle_show_desktop) - -# focus bindings - -from cycle import CycleWindows -ob.kbind(["A-Tab"], ob.KeyContext.All, CycleWindows.next) -ob.kbind(["A-S-Tab"], ob.KeyContext.All, CycleWindows.previous) - -# if you want linear cycling instead of stacked cycling, comment out the two -# bindings above, and use these instead. -#from cycle import CycleWindowsLinear -#ob.kbind(["A-Tab"], ob.KeyContext.All, CycleWindows.next) -#ob.kbind(["A-S-Tab"], ob.KeyContext.All, CycleWindows.previous) - -from cycle import CycleDesktops -ob.kbind(["C-Tab"], ob.KeyContext.All, CycleDesktops.next) -ob.kbind(["C-S-Tab"], ob.KeyContext.All, CycleDesktops.previous) - -# desktop changing bindings -ob.kbind(["C-1"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 0)) -ob.kbind(["C-2"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 1)) -ob.kbind(["C-3"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 2)) -ob.kbind(["C-4"], ob.KeyContext.All, lambda(d): callbacks.change_desktop(d, 3)) -ob.kbind(["C-A-Right"], ob.KeyContext.All, - lambda(d): callbacks.right_desktop(d)) -ob.kbind(["C-A-Left"], ob.KeyContext.All, - lambda(d): callbacks.left_desktop(d)) -ob.kbind(["C-A-Up"], ob.KeyContext.All, - lambda(d): callbacks.up_desktop(d)) -ob.kbind(["C-A-Down"], ob.KeyContext.All, - lambda(d): callbacks.down_desktop(d)) - -ob.kbind(["C-S-A-Right"], ob.KeyContext.All, - lambda(d): callbacks.send_to_next_desktop(d)) -ob.kbind(["C-S-A-Left"], ob.KeyContext.All, - lambda(d): callbacks.send_to_prev_desktop(d)) - -# focus new windows -ob.ebind(ob.EventAction.NewWindow, callbacks.focus) - -print "Loaded defaults.py"
D scripts/focus.py

@@ -1,89 +0,0 @@

-########################################################################### -### Functions for helping out with your window focus. ### -########################################################################### - -import config, ob - -export_functions = () - -config.add('focus', - 'avoid_skip_taskbar', - 'Avoid SkipTaskbar Windows', - "Don't focus windows which have requested to not be displayed " + \ - "in taskbars. You will still be able to focus the windows, but " + \ - "not through cycling, and they won't be focused as a fallback " + \ - "if 'Focus Fallback' is enabled.", - 'boolean', - 1) - -config.add('focus', - 'fallback', - 'Focus Fallback', - "Send focus somewhere when nothing is left with the focus, if " + \ - "possible.", - 'boolean', - 1) - -# maintain a list of clients, stacked in focus order -_clients = [] -_skip = 0 - -def _focusable(client, desktop): - if not client.normal(): return 0 - if not (client.canFocus() or client.focusNotify()): return 0 - if client.iconic(): return 0 - if config.get('focus', 'avoid_skip_taskbar') and \ - client.skipTaskbar(): return 0 - - desk = client.desktop() - if not (desk == 0xffffffff or desk == desktop): return 0 - - return 1 - -def _remove(client): - """This function exists because Swig pointers don't define a __eq__ - function, so list.remove(ptr) does not work.""" - win = client.window() - for i in range(len(_clients)): - if _clients[i].window() == win: - _clients.pop(i) - return - raise ValueError("_remove(x): x not in _clients list.") - -def _focused(data): - global _clients, _skip - - if _skip: - _skip -= 1 - return - - if data.client: - # move it to the top - try: - _remove(data.client) - except ValueError: pass # happens if _focused comes before _newwindow - _clients.insert(0, data.client) - elif config.get('focus', 'fallback'): - # pass around focus - desktop = ob.openbox.screen(data.screen).desktop() - for c in _clients: - if _focusable(c, desktop): - c.focus() - break - -def _newwindow(data): - # make sure its not already in the list - win = data.client.window() - for i in range(len(_clients)): - if _clients[i].window() == win: - return - _clients.append(data.client) - -def _closewindow(data): - _remove(data.client) - -ob.ebind(ob.EventAction.NewWindow, _newwindow) -ob.ebind(ob.EventAction.CloseWindow, _closewindow) -ob.ebind(ob.EventAction.Focus, _focused) - -print "Loaded focus.py"
D scripts/focusmodel.py

@@ -1,61 +0,0 @@

-############################################################################### -### Functions for setting up some default focus models. ### -############################################################################### - -import ob -import callbacks - -def setup_click_focus(click_raise = 1): - """Sets up for focusing windows by clicking on or in the window. - Optionally, clicking on or in a window can raise the window to the - front of its stacking layer.""" - ob.mbind("Left", ob.MouseContext.Titlebar, - ob.MouseAction.Press, callbacks.focus) - ob.mbind("Left", ob.MouseContext.Handle, - ob.MouseAction.Press, callbacks.focus) - ob.mbind("Left", ob.MouseContext.Grip, - ob.MouseAction.Press, callbacks.focus) - ob.mbind("Left", ob.MouseContext.Window, - ob.MouseAction.Press, callbacks.focus) - ob.mbind("Middle", ob.MouseContext.Window, - ob.MouseAction.Press, callbacks.focus) - ob.mbind("A-Left", ob.MouseContext.Frame, - ob.MouseAction.Press, callbacks.focus) - if click_raise: - ob.mbind("Left", ob.MouseContext.Titlebar, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("Left", ob.MouseContext.Handle, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("Left", ob.MouseContext.Grip, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("Left", ob.MouseContext.Window, - ob.MouseAction.Press, callbacks.raise_win) - -def setup_sloppy_focus(click_focus = 1, click_raise = 0): - """Sets up for focusing windows when the mouse pointer enters them. - Optionally, clicking on or in a window can focus it if your pointer - ends up inside a window without focus. Also, optionally, clicking on or - in a window can raise the window to the front of its stacking layer.""" - ob.ebind(ob.EventAction.EnterWindow, callbacks.focus) - if click_focus: - ob.mbind("Left", ob.MouseContext.Titlebar, - ob.MouseAction.Press, callbacks.focus) - ob.mbind("Left", ob.MouseContext.Handle, - ob.MouseAction.Press, callbacks.focus) - ob.mbind("Left", ob.MouseContext.Grip, - ob.MouseAction.Press, callbacks.focus) - ob.mbind("Left", ob.MouseContext.Window, - ob.MouseAction.Press, callbacks.focus) - if click_raise: - ob.mbind("Left", ob.MouseContext.Titlebar, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("Left", ob.MouseContext.Handle, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("Left", ob.MouseContext.Grip, - ob.MouseAction.Press, callbacks.raise_win) - ob.mbind("Left", ob.MouseContext.Window, - ob.MouseAction.Press, callbacks.raise_win) - -export_functions = setup_click_focus, setup_sloppy_focus - -print "Loaded focusmodel.py"
D scripts/historyplacement.py

@@ -1,185 +0,0 @@

-############################################################################## -### The history window placement algorithm. ebind historyplacement.place ### -### to the ob.EventAction.PlaceWindow event to use it. ### -############################################################################## - -import windowplacement, config - -def place(data): - """Place a window usingthe history placement algorithm.""" - _place(data) - -export_functions = place - -############################################################################## - -config.add('historyplacement', - 'ignore_requested_positions', - 'Ignore Requested Positions', - "When true, the placement algorithm will attempt to place " + \ - "windows even when they request a position (like XMMS can)." + \ - "Note this only applies to 'normal' windows, not to special " + \ - "cases like desktops and docks.", - 'boolean', - 0) -config.add('historyplacement', - 'dont_duplicate', - "Don't Diplicate", - "When true, if 2 copies of the same match in history are to be " + \ - "placed before one of them is closed (so it would be placed " + \ - "over-top of the last one), this will cause the second window to "+\ - "not be placed via history, and the 'Fallback Algorithm' will be "+\ - "used instead.", - 'boolean', - 1) -config.add('historyplacement', - 'filename', - 'History Database Filename', - "The name of the file where history data will be stored. The " + \ - "number of the screen is appended onto this name. The file will " +\ - "be placed in ~/.openbox/.", - 'string', - 'historydb') -config.add('historyplacement', - 'fallback', - 'Fallback Algorithm', - "The window placement algorithm that will be used when history " + \ - "placement does not have a place for the window.", - 'enum', - windowplacement.random, - options = windowplacement.export_functions) - -########################################################################### - -########################################################################### -### Internal stuff, should not be accessed outside the module. ### -########################################################################### - -import otk -import ob -import os -import string - -_data = [] - -class _state: - def __init__(self, appname, appclass, role, x, y): - self.appname = appname - self.appclass = appclass - self.role = role - self.x = x - self.y = y - self.placed = 0 - def __eq__(self, other): - if self.appname == other.appname and \ - self.appclass == other.appclass and \ - self.role == other.role: - return 1 - return 0 - -def _load(data): - global _data - try: - file = open(os.environ['HOME'] + '/.openbox/' + \ - config.get('historyplacement', 'filename') + \ - "." + str(data.screen), 'r') - # read data - for line in file.readlines(): - line = line[:-1] # drop the '\n' - try: - s = string.split(line, '\0') - state = _state(s[0], s[1], s[2], - string.atoi(s[3]), string.atoi(s[4])) - - while len(_data)-1 < data.screen: - _data.append([]) - _data[data.screen].append(state) - - except ValueError: pass - except IndexError: pass - file.close() - except IOError: pass - -def _save(data): - global _data - file = open(os.environ['HOME']+'/.openbox/'+ \ - config.get('historyplacement', 'filename') + \ - "." + str(data.screen), 'w') - if file: - while len(_data)-1 < data.screen: - _data.append([]) - for i in _data[data.screen]: - file.write(i.appname + '\0' + - i.appclass + '\0' + - i.role + '\0' + - str(i.x) + '\0' + - str(i.y) + '\n') - file.close() - -def _create_state(data): - global _data - area = data.client.area() - return _state(data.client.appName(), data.client.appClass(), - data.client.role(), area.x(), area.y()) - -def _find(screen, state): - global _data - try: - return _data[screen].index(state) - except ValueError: - return -1 - except IndexError: - while len(_data)-1 < screen: - _data.append([]) - return _find(screen, state) # try again - -def _place(data): - global _data - if data.client: - if not (config.get('historyplacement', 'ignore_requested_positions') \ - and data.client.normal()): - if data.client.positionRequested(): return - state = _create_state(data) - try: - print "looking for : " + state.appname + " : " + \ - state.appclass + " : " + state.role - - i = _find(data.screen, state) - if i >= 0: - coords = _data[data.screen][i] - print "Found in history ("+str(coords.x)+","+\ - str(coords.y)+")" - if not (config.get('historyplacement', 'dont_duplicate') \ - and coords.placed): - data.client.move(coords.x, coords.y) - coords.placed = 1 - return - else: - print "Already placed another window there" - else: - print "No match in history" - except TypeError: - pass - fallback = config.get('historyplacement', 'fallback') - if fallback: fallback(data) - -def _save_window(data): - global _data - if data.client: - state = _create_state(data) - print "looking for : " + state.appname + " : " + state.appclass + \ - " : " + state.role - - i = _find(data.screen, state) - if i >= 0: - print "replacing" - _data[data.screen][i] = state # replace it - else: - print "appending" - _data[data.screen].append(state) - -ob.ebind(ob.EventAction.CloseWindow, _save_window) -ob.ebind(ob.EventAction.Startup, _load) -ob.ebind(ob.EventAction.Shutdown, _save) - -print "Loaded historyplacement.py"
D scripts/motion.py

@@ -1,348 +0,0 @@

-############################################################################ -### Functions that provide callbacks for motion events to move and ### -### resize windows. ### -############################################################################ - -def move(data): - """Moves the window interactively. This should only be used with - MouseAction.Motion events. If 'Coords Popup for Moving' or 'Rubberband - Mode for Moving' is enabled, then the end_move function needs to be - bound as well.""" - _move(data) - -def end_move(data): - """Complete the interactive move of a window.""" - _end_move(data) - -def resize(data): - """Resizes the window interactively. This should only be used with - MouseMotion events. If 'Coords Popup for Resizing' or 'Rubberband Mode - for Resizing' is enabled, then the end_resize function needs to be - bound as well.""" - _resize(data) - -def end_resize(data): - """Complete the interactive resize of a window.""" - _end_resize(data) - -export_functions = move, end_move, resize, end_resize - -############################################################################# - -import config - -config.add('motion', - 'edge_resistance', - 'Edge Resistance', - "The amount of resistance to provide to moving a window past a " + \ - "screen boundary. Specify a value of 0 to disable edge resistance.", - 'integer', - 10, - min = 0) -config.add('motion', - 'popup_in_window', - 'Coords Popup In Window', - "When this is true, the coordinates popups will be placed " + \ - "relative to the window being moved/resized. When false, they " + \ - "will appear relative to the entire screen.", - 'boolean', - 0) -config.add('motion', - 'popup_centered', - 'Coords Popup Centered', - "When this is true, the coordinates popups will be centered " + \ - "relative to the window or screen (see 'Coords Popup In " + \ - "Window'). When false, they will be placed based upon the " + \ - "'Coords Popup Position' options.", - 'boolean', - 1) -config.add('motion', - 'popup_coords_x', - 'Coords Popup Position - X', - "When 'Coords Popup Centered' is false, this position will be " + \ - "used to place the coordinates popups. The popups will be " + \ - "placed relative to the window or the screen (see 'Coords " + \ - "Popup In Window'). A value of 0 would place it at the left " + \ - "edge, while a value of -1 would place it at the right edge. " + \ - "This value behaves similarly to those passed to the -geometry " + \ - "flag of many applications.", - 'integer', - 0) -config.add('motion', - 'popup_coords_y', - 'Coords Popup Position - Y', - "When 'Coords Popup Centered' is false, this position will be " + \ - "used to place the coordinates popups. The popups will be " + \ - "placed relative to the window or the screen (see 'Coords Popup " +\ - "In Window'). A value of 0 would place it at the top edge, " + \ - "while a value of -1 would place it at the bottom edge. This " + \ - "value behaves similarly to those passed to the -geometry flag " + \ - "of many applications.", - 'integer', - 0) -config.add('motion', - 'move_popup', - 'Coords Popup for Moving', - "Option to display a coordinates popup when moving windows.", - 'boolean', - 1) -config.add('motion', - 'move_rubberband', - 'Rubberband Mode for Moving', - "NOT IMPLEMENTED (yet?)\n"+\ - "Display an outline while moving instead of moving the actual " + \ - "window, until the move is completed. Good for slower systems.", - 'boolean', - 0) -config.add('motion', - 'resize_popup', - 'Coords Popup for Resizing', - "Option to display a coordinates popup when resizing windows.", - 'boolean', - 1) -config.add('motion', - 'resize_rubberband', - 'Rubberband Mode for Resizing', - "NOT IMPLEMENTED (yet?)\n"+\ - "Display an outline while resizing instead of resizing the " + \ - "actual window, until the resize is completed. Good for slower " + \ - "systems.", - 'boolean', - 0) -config.add('motion', - 'resize_nearest', - 'Resize Nearest Corner', - "When true, resizing will occur from the corner nearest where " + \ - "the mouse is. When false resizing will always occur from the " + \ - "bottom right corner.", - 'boolean', - 1) - -########################################################################### -### Internal stuff, should not be accessed outside the module. ### -########################################################################### - -import ob -import otk - -_popwidget = 0 - -# motion state -_inmove = 0 -_inresize = 0 - -# last motion data -_cx = 0 -_cy = 0 -_cw = 0 -_ch = 0 -_px = 0 -_py = 0 -_dx = 0 -_dy = 0 -_client = 0 -_screen = 0 - -_motion_mask = 0 - -def _place_popup(): - if config.get('motion', 'popup_in_window'): - # use the actual client's area, not the frame's - area = _client.frame.area() - size = _client.frame.size() - area = otk.Rect(area.x() + size.left, area.y() + size.top, - area.width() - size.left - size.right, - area.height() - size.top - size.bottom) - else: - area = otk.Rect(otk.Point(0, 0), ob.openbox.screen(_screen).size()) - size = _popwidget.minSize() - if config.get('motion', 'popup_centered'): - x = area.position().x() + (area.size().width() - size.width()) / 2 - y = area.position().y() + (area.size().height() - size.height()) / 2 - else: - x = config.get('motion', 'popup_coords_x') - y = config.get('motion', 'popup_coords_y') - if x < 0: x += area.width() - size.width() + 1 - if y < 0: y += area.width() - size.height() + 1 - x += area.position().x() - y += area.position().y() - _popwidget.moveresize(otk.Rect(x, y, size.width(), size.height())) - -def _motion_grab(data): - global _motion_mask, _inmove, _inresize; - - # are all the modifiers this started with still pressed? - if not _motion_mask & data.state: - if _inmove: - _end_move(data) - elif _inresize: - _end_resize(data) - else: - raise RuntimeError - -_last_x = 0 -_last_y = 0 - -def _do_move(final): - global _screen, _client, _cx, _cy, _dx, _dy - - # get destination x/y for the *frame* - x = _cx + _dx + _client.frame.area().x() - _client.area().x() - y = _cy + _dy + _client.frame.area().y() - _client.area().y() - - global _last_x, _last_y - resist = config.get('motion', 'edge_resistance') - if resist: - fs = _client.frame.size() - w = _client.area().width() + fs.left + fs.right - h = _client.area().height() + fs.top + fs.bottom - # use the area based on the struts - area = ob.openbox.screen(_screen).area(_client.desktop()) - l = area.left() - r = area.right() - w + 1 - t = area.top() - b = area.bottom() - h + 1 - # left screen edge - if _last_x > x and x < l and x >= l - resist: - x = l - # right screen edge - if _last_x < x and x > r and x <= r + resist: - x = r - # top screen edge - if _last_y > y and y < t and y >= t - resist: - y = t - # right screen edge - if _last_y < y and y > b and y <= b + resist: - y = b - - global _inmove - if not _inmove: - _last_x = 0 - _last_y = 0 - else: - _last_x = x - _last_y = y - - if not final and config.get('motion', 'move_rubberband'): - # XXX draw the outline ... - pass - else: - _client.move(x, y, final) - - if config.get('motion', 'move_popup'): - global _popwidget - text = "X: " + str(x) + " Y: " + str(y) - if not _popwidget: - _popwidget = otk.Label(_screen, ob.openbox) - _popwidget.setHighlighted(1) - _popwidget.setText(text) - _place_popup() - _popwidget.show() - -def _move(data): - if not data.client: return - - # not-normal windows dont get moved - if not data.client.normal(): return - - global _screen, _client, _cx, _cy, _dx, _dy, _motion_mask - _screen = data.screen - _client = data.client - _cx = data.press_clientx - _cy = data.press_clienty - _dx = data.xroot - data.pressx - _dy = data.yroot - data.pressy - _motion_mask = data.state - _do_move(0) - global _inmove - if not _inmove: - ob.kgrab(_screen, _motion_grab) - _inmove = 1 - -def _end_move(data): - global _inmove, _popwidget - if _inmove: - _do_move(1) - _inmove = 0 - _popwidget = 0 - ob.kungrab() - -def _do_resize(final): - global _screen, _client, _cx, _cy, _cw, _ch, _px, _py, _dx, _dy - - dx = _dx - dy = _dy - - # pick a corner to anchor - if not (config.get('motion', 'resize_nearest') or - _context == ob.MouseContext.Grip): - corner = ob.Client.TopLeft - else: - x = _px - _cx - y = _py - _cy - if y < _ch / 2: - if x < _cw / 2: - corner = ob.Client.BottomRight - dx *= -1 - else: - corner = ob.Client.BottomLeft - dy *= -1 - else: - if x < _cw / 2: - corner = ob.Client.TopRight - dx *= -1 - else: - corner = ob.Client.TopLeft - - w = _cw + dx - h = _ch + dy - - if not final and config.get('motion', 'resize_rubberband'): - # XXX draw the outline ... - pass - else: - _client.resize(corner, w, h) - - if config.get('motion', 'resize_popup'): - global _popwidget - ls = _client.logicalSize() - text = "W: " + str(ls.width()) + " H: " + str(ls.height()) - if not _popwidget: - _popwidget = otk.Label(_screen, ob.openbox) - _popwidget.setHighlighted(1) - _popwidget.setText(text) - _place_popup() - _popwidget.show() - -def _resize(data): - if not data.client: return - - # not-normal windows dont get resized - if not data.client.normal(): return - - global _screen, _client, _cx, _cy, _cw, _ch, _px, _py, _dx, _dy - global _motion_mask - _screen = data.screen - _client = data.client - _cx = data.press_clientx - _cy = data.press_clienty - _cw = data.press_clientwidth - _ch = data.press_clientheight - _px = data.pressx - _py = data.pressy - _dx = data.xroot - _px - _dy = data.yroot - _py - _motion_mask = data.state - _do_resize(0) - global _inresize - if not _inresize: - ob.kgrab(_screen, _motion_grab) - _inresize = 1 - -def _end_resize(data): - global _inresize, _popwidget - if _inresize: - _do_resize(1) - _inresize = 0 - _popwidget = 0 - ob.kungrab()
D scripts/windowplacement.py

@@ -1,50 +0,0 @@

-############################################################################ -### Window placement algorithms, choose one of these and ebind it to the ### -### ob.EventAction.PlaceWindow event. ### -### ### -### Also see historyplacement.py for the history placement module which ### -### provides an algorithm that can be used in place of, or alongside, ### -### these. ### -############################################################################ - -import otk, ob, random - -_rand = random.Random() - -def random(data): - """Place windows randomly around the screen.""" - if not data.client: return - if data.client.positionRequested(): return - client_area = data.client.frame.area() - screen_area = ob.openbox.screen(data.screen).area(data.client.desktop()) - width = screen_area.width() - client_area.width() - height = screen_area.height() - client_area.height() - global _rand - x = _rand.randrange(screen_area.x(), width-1) - y = _rand.randrange(screen_area.y(), height-1) - data.client.move(x, y) - -_cascade_x = 0 -_cascade_y = 0 - -def cascade(data): - """Place windows in a cascading order from top-left to bottom-right.""" - if not data.client: return - if data.client.positionRequested(): return - client_area = data.client.frame.area() - screen_area = ob.openbox.screen(data.screen).area(data.client.desktop()) - width = screen_area.width() - client_area.width() - height = screen_area.height() - client_area.height() - global _cascade_x, _cascade_y - if _cascade_x < screen_area.x() or _cascade_y < screen_area.y() or \ - _cascade_x >= width or _cascade_y >= height: - _cascade_x = screen_area.x() - _cascade_y = screen_area.y() - data.client.move(_cascade_x, _cascade_y) - frame_size = data.client.frame.size() - _cascade_x += frame_size.top - _cascade_y += frame_size.top - -export_functions = random, cascade - -print "Loaded windowplacement.py"
D src/.cvsignore

@@ -1,5 +0,0 @@

-Makefile -Makefile.in -openbox3 -.deps -.libs
D src/Makefile.am

@@ -1,26 +0,0 @@

-localedir=$(datadir)/locale -scriptdir = $(libdir)/openbox/python -DEFAULT_MENU=$(pkgdatadir)/menu -DEFAULT_STYLE=$(pkgdatadir)/styles/mbdtex - -CPPFLAGS=$(XFT_CFLAGS) $(PYTHON_CFLAGS) @CPPFLAGS@ \ --DDEFAULTMENU=\"$(DEFAULT_MENU)\" \ --DDEFAULTSTYLE=\"$(DEFAULT_STYLE)\" \ --DLOCALEDIR=\"$(localedir)\" \ --DSCRIPTDIR=\"$(scriptdir)\" - -LIBS=$(XFT_LIBS) $(PYTHON_LIBS) @LIBS@ $(SWIG_PYTHON_LIB) - -bin_PROGRAMS= openbox3 - -openbox3_LDADD=-L../otk -lotk @LIBINTL@ -openbox3_LDFLAGS=-export-dynamic -openbox3_SOURCES= actions.cc client.cc frame.cc openbox.cc screen.cc \ - main.cc python.cc bindings.cc config.cc -noinst_HEADERS= actions.hh bindings.hh client.hh frame.hh openbox.hh \ - python.hh screen.hh config.hh - -MAINTAINERCLEANFILES= Makefile.in - -distclean-local: - $(RM) *\~ *.orig *.rej .\#*
D src/actions.cc

@@ -1,351 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "actions.hh" -#include "openbox.hh" -#include "client.hh" -#include "frame.hh" -#include "screen.hh" -#include "python.hh" -#include "bindings.hh" -#include "otk/display.hh" - -#include <cstdio> -#include <algorithm> - -namespace ob { - -Actions::Actions() - : _dragging(false) -{ -} - - -Actions::~Actions() -{ -} - - -void Actions::buttonPressHandler(const XButtonEvent &e) -{ - otk::EventHandler::buttonPressHandler(e); - - MouseContext::MC context; - EventHandler *h = openbox->findHandler(e.window); - Frame *f = dynamic_cast<Frame*>(h); - if (f) - context= f->mouseContext(e.window); - else if (dynamic_cast<Client*>(h)) - context = MouseContext::Window; - else if (dynamic_cast<Screen*>(h)) - context = MouseContext::Root; - else - return; // not a valid mouse context - - if (_press.button) { - unsigned int mask; - switch(_press.button) { - case Button1: mask = Button1Mask; break; - case Button2: mask = Button2Mask; break; - case Button3: mask = Button3Mask; break; - case Button4: mask = Button4Mask; break; - case Button5: mask = Button5Mask; break; - default: mask = 0; // on other buttons we have to assume its not pressed... - } - // was the button released but we didnt get the event? (pointergrabs cause - // this) - if (!(e.state & mask)) - _press.button = 0; - } - - // run the PRESS python hook - // kill off the Button1Mask etc, only want the modifiers - unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask | - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask); - int screen; - Client *c = openbox->findClient(e.window); - if (c) - screen = c->screen(); - else - screen = otk::display->findScreen(e.root)->screen(); - MouseData data(screen, c, e.time, state, e.button, context, - MouseAction::Press); - openbox->bindings()->fireButton(&data); - - if (_press.button) return; // won't count toward CLICK events - - _press.win = e.window; - _press.button = e.button; - _press.pos = otk::Point(e.x_root, e.y_root); - if (c) - _press.clientarea = c->area(); - - printf("press queue %u pressed %u\n", _press.button, e.button); - - if (context == MouseContext::Window) { - /* - Because of how events are grabbed on the client window, we can't get - ButtonRelease events, so instead we simply manufacture them here, so that - clicks/doubleclicks etc still work. - */ - //XButtonEvent ev = e; - //ev.type = ButtonRelease; - buttonReleaseHandler(e); - } -} - - -void Actions::buttonReleaseHandler(const XButtonEvent &e) -{ - otk::EventHandler::buttonReleaseHandler(e); - - MouseContext::MC context; - EventHandler *h = openbox->findHandler(e.window); - Frame *f = dynamic_cast<Frame*>(h); - if (f) - context= f->mouseContext(e.window); - else if (dynamic_cast<Client*>(h)) - context = MouseContext::Window; - else if (dynamic_cast<Screen*>(h)) - context = MouseContext::Root; - else - return; // not a valid mouse context - - // run the RELEASE python hook - // kill off the Button1Mask etc, only want the modifiers - unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask | - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask); - int screen; - Client *c = openbox->findClient(e.window); - if (c) - screen = c->screen(); - else - screen = otk::display->findScreen(e.root)->screen(); - MouseData data(screen, c, e.time, state, e.button, context, - MouseAction::Release); - openbox->bindings()->fireButton(&data); - - // not for the button we're watching? - if (_press.button != e.button) return; - - _press.button = 0; - _dragging = false; - - // find the area of the window - XWindowAttributes attr; - if (!XGetWindowAttributes(**otk::display, e.window, &attr)) return; - - // if not on the window any more, it isnt a CLICK - if (!(e.same_screen && e.x >= 0 && e.y >= 0 && - e.x < attr.width && e.y < attr.height)) - return; - - // run the CLICK python hook - data.action = MouseAction::Click; - openbox->bindings()->fireButton(&data); - - long dblclick = 0; - python_get_long("double_click_delay", &dblclick); - if (e.time - _release.time < (unsigned)dblclick && - _release.win == e.window && _release.button == e.button) { - - // run the DOUBLECLICK python hook - data.action = MouseAction::DoubleClick; - openbox->bindings()->fireButton(&data); - - // reset so you cant triple click for 2 doubleclicks - _release.win = 0; - _release.button = 0; - _release.time = 0; - } else { - // save the button release, might be part of a double click - _release.win = e.window; - _release.button = e.button; - _release.time = e.time; - } -} - - -void Actions::enterHandler(const XCrossingEvent &e) -{ - otk::EventHandler::enterHandler(e); - - // run the ENTER python hook - int screen; - Client *c = openbox->findClient(e.window); - if (c) - screen = c->screen(); - else - screen = otk::display->findScreen(e.root)->screen(); - EventData data(screen, c, EventAction::EnterWindow, e.state); - openbox->bindings()->fireEvent(&data); -} - - -void Actions::leaveHandler(const XCrossingEvent &e) -{ - otk::EventHandler::leaveHandler(e); - - // run the LEAVE python hook - int screen; - Client *c = openbox->findClient(e.window); - if (c) - screen = c->screen(); - else - screen = otk::display->findScreen(e.root)->screen(); - EventData data(screen, c, EventAction::LeaveWindow, e.state); - openbox->bindings()->fireEvent(&data); -} - - -void Actions::keyPressHandler(const XKeyEvent &e) -{ - otk::EventHandler::keyPressHandler(e); - - // kill off the Button1Mask etc, only want the modifiers - unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask | - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask); - - // add to the state the mask of the modifier being pressed, if it is - // a modifier key being pressed (this is a little ugly..) - const XModifierKeymap *map = otk::display->modifierMap(); - const int mask_table[] = { - ShiftMask, LockMask, ControlMask, Mod1Mask, - Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask - }; - KeyCode *kp = map->modifiermap; - for (int i = 0, n = sizeof(mask_table)/sizeof(mask_table[0]); i < n; ++i) { - for (int k = 0; k < map->max_keypermod; ++k) { - if (*kp == e.keycode) { // found the keycode - state |= mask_table[i]; // add the mask for it - i = n; // cause the first loop to break; - break; // get outta here! - } - ++kp; - } - } - - openbox->bindings()-> - fireKey(otk::display->findScreen(e.root)->screen(), - state, e.keycode, e.time, KeyAction::Press); -} - - -void Actions::keyReleaseHandler(const XKeyEvent &e) -{ - otk::EventHandler::keyReleaseHandler(e); - - // kill off the Button1Mask etc, only want the modifiers - unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask | - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask); - - // remove from the state the mask of the modifier being released, if it is - // a modifier key being released (this is a little ugly..) - const XModifierKeymap *map = otk::display->modifierMap(); - const int mask_table[] = { - ShiftMask, LockMask, ControlMask, Mod1Mask, - Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask - }; - KeyCode *kp = map->modifiermap; - for (int i = 0, n = sizeof(mask_table)/sizeof(mask_table[0]); i < n; ++i) { - for (int k = 0; k < map->max_keypermod; ++k) { - if (*kp == e.keycode) { // found the keycode - state &= ~mask_table[i]; // remove the mask for it - i = n; // cause the first loop to break; - break; // get outta here! - } - ++kp; - } - } - - openbox->bindings()-> - fireKey(otk::display->findScreen(e.root)->screen(), - state, e.keycode, e.time, KeyAction::Release); -} - - -void Actions::motionHandler(const XMotionEvent &e) -{ - otk::EventHandler::motionHandler(e); - - if (!e.same_screen) return; // this just gets stupid - - if (e.window != _press.win) return; - - MouseContext::MC context; - EventHandler *h = openbox->findHandler(e.window); - Frame *f = dynamic_cast<Frame*>(h); - if (f) - context= f->mouseContext(e.window); - else if (dynamic_cast<Client*>(h)) - context = MouseContext::Window; - else if (dynamic_cast<Screen*>(h)) - context = MouseContext::Root; - else - return; // not a valid mouse context - - int x_root = e.x_root, y_root = e.y_root; - - // compress changes to a window into a single change - XEvent ce; - while (XCheckTypedWindowEvent(**otk::display, e.window, e.type, &ce)) { - x_root = ce.x_root; - y_root = ce.y_root; - } - - int screen; - Client *c = openbox->findClient(e.window); - if (c) - screen = c->screen(); - else - screen = otk::display->findScreen(e.root)->screen(); - - if (!_dragging) { - int dx = x_root - _press.pos.x(); - int dy = y_root - _press.pos.y(); - long threshold = 0; - python_get_long("drag_threshold", &threshold); - if (!(std::abs(dx) >= threshold || std::abs(dy) >= threshold)) - return; // not at the threshold yet - } - _dragging = true; // in a drag now - - // check if the movement is more than the threshold - - // run the MOTION python hook - // kill off the Button1Mask etc, only want the modifiers - unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask | - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask); - unsigned int button = _press.button; - MouseData data(screen, c, e.time, state, button, context, - MouseAction::Motion, x_root, y_root, - _press.pos, _press.clientarea); - openbox->bindings()->fireButton(&data); -} - -#ifdef XKB -void Actions::xkbHandler(const XkbEvent &e) -{ - Window w; - int screen; - - otk::EventHandler::xkbHandler(e); - - switch (((XkbAnyEvent*)&e)->xkb_type) { - case XkbBellNotify: - w = ((XkbBellNotifyEvent*)&e)->window; - Client *c = openbox->findClient(w); - if (c) - screen = c->screen(); - else - screen = openbox->focusedScreen()->number(); - EventData data(screen, c, EventAction::Bell, 0); - openbox->bindings()->fireEvent(&data); - break; - } -} -#endif // XKB - -} -
D src/actions.hh

@@ -1,79 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __actions_hh -#define __actions_hh - -/*! @file actions.hh - @brief The action interface for user-available actions -*/ - -#include "otk/point.hh" -#include "otk/rect.hh" -#include "otk/eventhandler.hh" - -extern "C" { -#include <X11/Xlib.h> -#include <Python.h> -} - -#include <map> - -namespace ob { - -//! The action interface for user-available actions -/*! - When these actions are fired, hooks to the guile engine are fired so that - guile code is run. -*/ -class Actions : public otk::EventHandler { -public: -#ifndef SWIG // get rid of a swig warning - struct ButtonReleaseAction { - Window win; - unsigned int button; - Time time; - ButtonReleaseAction() { win = 0; button = 0; time = 0; } - }; - - struct ButtonPressAction { - Window win; - unsigned int button; - otk::Point pos; - otk::Rect clientarea; - ButtonPressAction() { button = 0; } - }; -#endif // SWIG -private: - //! The last button release processed for CLICKs - ButtonReleaseAction _release; - //! The last button press processed for CLICKs - ButtonPressAction _press; - //! This is set to true once a drag has started and false when done to make - //! sure the threshold isnt checked anymore once a drag is underway - bool _dragging; - -public: - //! Constructs an Actions object - Actions(); - //! Destroys the Actions object - virtual ~Actions(); - - virtual void buttonPressHandler(const XButtonEvent &e); - virtual void buttonReleaseHandler(const XButtonEvent &e); - - virtual void enterHandler(const XCrossingEvent &e); - virtual void leaveHandler(const XCrossingEvent &e); - - virtual void keyPressHandler(const XKeyEvent &e); - virtual void keyReleaseHandler(const XKeyEvent &e); - - virtual void motionHandler(const XMotionEvent &e); - -#ifdef XKB - virtual void xkbHandler(const XkbEvent &e); -#endif // XKB - -}; - -} - -#endif // __actions_hh
D src/bindings.cc

@@ -1,655 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "bindings.hh" -#include "screen.hh" -#include "openbox.hh" -#include "client.hh" -#include "frame.hh" -#include "otk/display.hh" - -extern "C" { -#include <X11/Xlib.h> - -#include "gettext.h" -#define _(str) gettext(str) -} - -#include <cstdlib> -#include <algorithm> - -namespace ob { - -static bool buttonvalue(const std::string &button, unsigned int *val) -{ - if (button == "Left") - *val = 1; - else if (button == "Middle") - *val = 2; - else if (button == "Right") - *val = 3; - else if (button == "Up") - *val = 4; - else if (button == "Down") - *val = 5; - else { - // try convert to number - int i = atoi(button.c_str()); - if (i <= 0) - return false; - *val = i; - } - return true; -} - -static bool modvalue(const std::string &mod, unsigned int *val) -{ - if (mod == "C") { // control - *val |= ControlMask; - } else if (mod == "S") { // shift - *val |= ShiftMask; - } else if (mod == "A" || // alt/mod1 - mod == "M" || - mod == "Mod1" || - mod == "M1") { - *val |= Mod1Mask; - } else if (mod == "Mod2" || // mod2 - mod == "M2") { - *val |= Mod2Mask; - } else if (mod == "Mod3" || // mod3 - mod == "M3") { - *val |= Mod3Mask; - } else if (mod == "W" || // windows/mod4 - mod == "Mod4" || - mod == "M4") { - *val |= Mod4Mask; - } else if (mod == "Mod5" || // mod5 - mod == "M5") { - *val |= Mod5Mask; - } else { // invalid - return false; - } - return true; -} - -bool Bindings::translate(const std::string &str, Binding &b,bool askey) const -{ - // parse out the base key name - std::string::size_type keybegin = str.find_last_of('-'); - keybegin = (keybegin == std::string::npos) ? 0 : keybegin + 1; - std::string key(str, keybegin); - - // parse out the requested modifier keys - unsigned int modval = 0; - std::string::size_type begin = 0, end; - while (begin != keybegin) { - end = str.find_first_of('-', begin); - - std::string mod(str, begin, end-begin); - if (!modvalue(mod, &modval)) { - printf(_("Invalid modifier element in key binding: %s\n"), mod.c_str()); - return false; - } - - begin = end + 1; - } - - // set the binding - b.modifiers = modval; - if (askey) { - KeySym sym = XStringToKeysym(const_cast<char *>(key.c_str())); - if (sym == NoSymbol) { - printf(_("Invalid Key name in key binding: %s\n"), key.c_str()); - return false; - } - if (!(b.key = XKeysymToKeycode(**otk::display, sym))) - printf(_("No valid keycode for Key in key binding: %s\n"), key.c_str()); - return b.key != 0; - } else { - return buttonvalue(key, &b.key); - } -} - -static void destroytree(KeyBindingTree *tree) -{ - while (tree) { - KeyBindingTree *c = tree->first_child; - delete tree; - tree = c; - } -} - -KeyBindingTree *Bindings::buildtree(const StringVect &keylist, - KeyCallback callback, void *data) const -{ - if (keylist.empty()) return 0; // nothing in the list.. return 0 - - KeyBindingTree *ret = 0, *p; - - StringVect::const_reverse_iterator it, end = keylist.rend(); - for (it = keylist.rbegin(); it != end; ++it) { - p = ret; - ret = new KeyBindingTree(); - if (!p) { - // this is the first built node, the bottom node of the tree - ret->chain = false; - ret->callbacks.push_back(KeyCallbackData(callback, data)); - } - ret->first_child = p; - if (!translate(*it, ret->binding)) { - destroytree(ret); - ret = 0; - break; - } - } - return ret; -} - - -Bindings::Bindings() - : _curpos(&_keytree), - _resetkey(0,0), - _timer((otk::Timer *) 0), - _keybgrab_callback(0, 0), - _grabbed(0) -{ - setResetKey("C-g"); // set the default reset key -} - - -Bindings::~Bindings() -{ - if (_timer) - delete _timer; - if (_grabbed) { - _grabbed = false; - XUngrabKeyboard(**otk::display, CurrentTime); - } - removeAllKeys(); - //removeAllButtons(); // this is done by each client as they are unmanaged - removeAllEvents(); -} - - -void Bindings::assimilate(KeyBindingTree *node) -{ - KeyBindingTree *a, *b, *tmp, *last; - - if (!_keytree.first_child) { - // there are no nodes at this level yet - _keytree.first_child = node; - } else { - a = _keytree.first_child; - last = a; - b = node; - while (a) { - last = a; - if (a->binding != b->binding) { - a = a->next_sibling; - } else { - tmp = b; - b = b->first_child; - delete tmp; - a = a->first_child; - } - } - if (last->binding != b->binding) - last->next_sibling = b; - else { - last->first_child = b->first_child; - delete b; - } - } -} - - -KeyBindingTree *Bindings::find(KeyBindingTree *search, - bool *conflict) const { - *conflict = false; - KeyBindingTree *a, *b; - a = _keytree.first_child; - b = search; - while (a && b) { - if (a->binding != b->binding) { - a = a->next_sibling; - } else { - if (a->chain == b->chain) { - if (!a->chain) { - // found it! (return the actual id, not the search's) - return a; - } - } else { - *conflict = true; - return 0; // the chain status' don't match (conflict!) - } - b = b->first_child; - a = a->first_child; - } - } - return 0; // it just isn't in here -} - - -bool Bindings::addKey(const StringVect &keylist, KeyCallback callback, - void *data) -{ - KeyBindingTree *tree, *t; - bool conflict; - - if (!(tree = buildtree(keylist, callback, data))) - return false; // invalid binding requested - - t = find(tree, &conflict); - if (conflict) { - // conflicts with another binding - destroytree(tree); - return false; - } - - if (t) { - // already bound to something - t->callbacks.push_back(KeyCallbackData(callback, data)); - destroytree(tree); - } else { - // grab the server here to make sure no key pressed go missed - otk::display->grab(); - grabKeys(false); - - // assimilate this built tree into the main tree - assimilate(tree); // assimilation destroys/uses the tree - - grabKeys(true); - otk::display->ungrab(); - } - - return true; -} - -/* -bool Bindings::removeKey(const StringVect &keylist, KeyCallback callback, void *data) -{ - assert(false); // XXX: function not implemented yet - - KeyBindingTree *tree; - bool conflict; - - if (!(tree = buildtree(keylist, 0))) - return false; // invalid binding requested - - KeyBindingTree *t = find(tree, &conflict); - if (t) { - KeyCallbackList::iterator it = std::find(t->callbacks.begin(), - t->callbacks.end(), - callback); - if (it != t->callbacks.end()) { - // grab the server here to make sure no key pressed go missed - otk::display->grab(); - grabKeys(false); - - _curpos = &_keytree; - - // XXX do shit here ... - Py_XDECREF(*it); - - grabKeys(true); - otk::display->ungrab(); - - return true; - } - } - return false; -} -*/ - -void Bindings::setResetKey(const std::string &key) -{ - Binding b(0, 0); - if (translate(key, b)) { - _resetkey.key = b.key; - _resetkey.modifiers = b.modifiers; - } -} - - -static void remove_branch(KeyBindingTree *first) -{ - KeyBindingTree *p = first; - - while (p) { - if (p->first_child) - remove_branch(p->first_child); - KeyBindingTree *s = p->next_sibling; - while(!p->callbacks.empty()) { - p->callbacks.pop_front(); - } - delete p; - p = s; - } -} - - -void Bindings::removeAllKeys() -{ - grabKeys(false); - if (_keytree.first_child) { - remove_branch(_keytree.first_child); - _keytree.first_child = 0; - } - grabKeys(true); -} - - -void Bindings::grabKeys(bool grab) -{ - for (int i = 0; i < ScreenCount(**otk::display); ++i) { - Screen *sc = openbox->screen(i); - if (!sc) continue; // not a managed screen - Window root = otk::display->screenInfo(i)->rootWindow(); - if (!grab) { - otk::display->ungrabAllKeys(root); - continue; - } - KeyBindingTree *p = _keytree.first_child; - while (p) { - otk::display->grabKey(p->binding.key, p->binding.modifiers, - root, false, GrabModeAsync, GrabModeSync, - false); - p = p->next_sibling; - } - } -} - - -bool Bindings::grabKeyboard(int screen, KeyCallback callback, void *data) -{ - assert(callback); - if (_keybgrab_callback.callback) return false; // already grabbed - - if (!openbox->screen(screen)) - return false; // the screen is not managed - - Window root = otk::display->screenInfo(screen)->rootWindow(); - if (XGrabKeyboard(**otk::display, root, false, GrabModeAsync, - GrabModeAsync, CurrentTime)) - return false; - _keybgrab_callback.callback = callback; - _keybgrab_callback.data = data; - return true; -} - - -void Bindings::ungrabKeyboard() -{ - if (!_keybgrab_callback.callback) return; // not grabbed - - _keybgrab_callback = KeyCallbackData(0, 0); - if (!_grabbed) /* don't release out from under keychains */ - XUngrabKeyboard(**otk::display, CurrentTime); - XUngrabPointer(**otk::display, CurrentTime); -} - - -bool Bindings::grabPointer(int screen) -{ - if (!openbox->screen(screen)) - return false; // the screen is not managed - - Window root = otk::display->screenInfo(screen)->rootWindow(); - XGrabPointer(**otk::display, root, false, 0, GrabModeAsync, - GrabModeAsync, None, None, CurrentTime); - return true; -} - - -void Bindings::ungrabPointer() -{ - XUngrabPointer(**otk::display, CurrentTime); -} - - -void Bindings::fireKey(int screen, unsigned int modifiers, unsigned int key, - Time time, KeyAction::KA action) -{ - if (_keybgrab_callback.callback) { - Client *c = openbox->focusedClient(); - KeyData data(screen, c, time, modifiers, key, action); - _keybgrab_callback.fire(&data); - } - - // KeyRelease events only occur during keyboard grabs - if (action == KeyAction::Release) return; - - if (key == _resetkey.key && modifiers == _resetkey.modifiers) { - resetChains(this); - XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime); - } else { - KeyBindingTree *p = _curpos->first_child; - while (p) { - if (p->binding.key == key && p->binding.modifiers == modifiers) { - if (p->chain) { - if (_timer) - delete _timer; - _timer = new otk::Timer(5000, // 5 second timeout - (otk::Timer::TimeoutHandler)resetChains, - this); - if (!_grabbed && !_keybgrab_callback.callback) { - Window root = otk::display->screenInfo(screen)->rootWindow(); - //grab should never fail because we should have a sync grab at - //this point - XGrabKeyboard(**otk::display, root, 0, GrabModeAsync, - GrabModeSync, CurrentTime); - } - _grabbed = true; - _curpos = p; - XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime); - } else { - Client *c = openbox->focusedClient(); - KeyData data(screen, c, time, modifiers, key, action); - KeyCallbackList::iterator it, end = p->callbacks.end(); - for (it = p->callbacks.begin(); it != end; ++it) - it->fire(&data); - XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime); - resetChains(this); - } - break; - } - p = p->next_sibling; - } - } -} - -void Bindings::resetChains(Bindings *self) -{ - if (self->_timer) { - delete self->_timer; - self->_timer = (otk::Timer *) 0; - } - self->_curpos = &self->_keytree; - if (self->_grabbed) { - self->_grabbed = false; - if (!self->_keybgrab_callback.callback) - XUngrabKeyboard(**otk::display, CurrentTime); - } -} - - -bool Bindings::addButton(const std::string &but, MouseContext::MC context, - MouseAction::MA action, MouseCallback callback, - void *data) -{ - assert(context >= 0 && context < MouseContext::NUM_MOUSE_CONTEXT); - assert(action >= 0 && action < MouseAction::NUM_MOUSE_ACTION); - - Binding b(0,0); - if (!translate(but, b, false)) - return false; - - ButtonBindingList::iterator it, end = _buttons[context].end(); - - // look for a duplicate binding - for (it = _buttons[context].begin(); it != end; ++it) - if ((*it)->binding.key == b.key && - (*it)->binding.modifiers == b.modifiers) { - break; - } - - ButtonBinding *bind; - - // the binding didnt exist yet, add it - if (it == end) { - bind = new ButtonBinding(); - bind->binding.key = b.key; - bind->binding.modifiers = b.modifiers; - _buttons[context].push_back(bind); - // grab the button on all clients - for (int sn = 0; sn < ScreenCount(**otk::display); ++sn) { - Screen *s = openbox->screen(sn); - if (!s) continue; // not managed - Client::List::iterator c_it, c_end = s->clients.end(); - for (c_it = s->clients.begin(); c_it != c_end; ++c_it) { - grabButton(true, bind->binding, context, *c_it); - } - } - } else - bind = *it; - bind->callbacks[action].push_back(MouseCallbackData(callback, data)); - return true; -} - -void Bindings::removeAllButtons() -{ - for (int i = 0; i < MouseContext::NUM_MOUSE_CONTEXT; ++i) { - ButtonBindingList::iterator it, end = _buttons[i].end(); - for (it = _buttons[i].begin(); it != end; ++it) { - for (int a = 0; a < MouseAction::NUM_MOUSE_ACTION; ++a) { - while (!(*it)->callbacks[a].empty()) { - (*it)->callbacks[a].pop_front(); - } - } - // ungrab the button on all clients - for (int sn = 0; sn < ScreenCount(**otk::display); ++sn) { - Screen *s = openbox->screen(sn); - if (!s) continue; // not managed - Client::List::iterator c_it, c_end = s->clients.end(); - for (c_it = s->clients.begin(); c_it != c_end; ++c_it) { - grabButton(false, (*it)->binding, (MouseContext::MC)i, *c_it); - } - } - } - } -} - -void Bindings::grabButton(bool grab, const Binding &b, - MouseContext::MC context, Client *client) -{ - Window win; - int mode = GrabModeAsync; - unsigned int mask; - switch(context) { - case MouseContext::Frame: - win = client->frame->window(); - mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask; - break; - case MouseContext::Window: - win = client->frame->plate(); - mode = GrabModeSync; // this is handled in fireButton - mask = ButtonPressMask; // can't catch more than this with Sync mode - // the release event is manufactured by the - // master buttonPressHandler - break; - default: - // any other elements already get button events, don't grab on them - return; - } - if (grab) - otk::display->grabButton(b.key, b.modifiers, win, false, mask, mode, - GrabModeAsync, None, None, false); - else - otk::display->ungrabButton(b.key, b.modifiers, win); -} - -void Bindings::grabButtons(bool grab, Client *client) -{ - for (int i = 0; i < MouseContext::NUM_MOUSE_CONTEXT; ++i) { - ButtonBindingList::iterator it, end = _buttons[i].end(); - for (it = _buttons[i].begin(); it != end; ++it) - grabButton(grab, (*it)->binding, (MouseContext::MC)i, client); - } -} - -void Bindings::fireButton(MouseData *data) -{ - if (data->context == MouseContext::Window) { - // Replay the event, so it goes to the client - XAllowEvents(**otk::display, ReplayPointer, data->time); - } - - ButtonBindingList::iterator it, end = _buttons[data->context].end(); - for (it = _buttons[data->context].begin(); it != end; ++it) - if ((*it)->binding.key == data->button && - (*it)->binding.modifiers == data->state) { - MouseCallbackList::iterator c_it, - c_end = (*it)->callbacks[data->action].end(); - for (c_it = (*it)->callbacks[data->action].begin(); - c_it != c_end; ++c_it) - c_it->fire(data); - } -} - - -bool Bindings::addEvent(EventAction::EA action, EventCallback callback, - void *data) -{ - if (action < 0 || action >= EventAction::NUM_EVENT_ACTION) { - return false; - } -#ifdef XKB - if (action == EventAction::Bell && _eventlist[action].empty()) - XkbSelectEvents(**otk::display, XkbUseCoreKbd, - XkbBellNotifyMask, XkbBellNotifyMask); -#endif // XKB - _eventlist[action].push_back(EventCallbackData(callback, data)); - return true; -} - -bool Bindings::removeEvent(EventAction::EA action, EventCallback callback, - void *data) -{ - if (action < 0 || action >= EventAction::NUM_EVENT_ACTION) { - return false; - } - - EventCallbackList::iterator it = std::find(_eventlist[action].begin(), - _eventlist[action].end(), - EventCallbackData(callback, - data)); - if (it != _eventlist[action].end()) { - _eventlist[action].erase(it); -#ifdef XKB - if (action == EventAction::Bell && _eventlist[action].empty()) - XkbSelectEvents(**otk::display, XkbUseCoreKbd, - XkbBellNotifyMask, 0); -#endif // XKB - return true; - } - return false; -} - -void Bindings::removeAllEvents() -{ - for (int i = 0; i < EventAction::NUM_EVENT_ACTION; ++i) { - while (!_eventlist[i].empty()) { - _eventlist[i].pop_front(); - } - } -} - -void Bindings::fireEvent(EventData *data) -{ - EventCallbackList::iterator c_it, c_end = _eventlist[data->action].end(); - for (c_it = _eventlist[data->action].begin(); c_it != c_end; ++c_it) - c_it->fire(data); -} - -}
D src/bindings.hh

@@ -1,186 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __binding_hh -#define __binding_hh - -/*! @file bindings.hh - @brief I dunno.. some binding stuff? -*/ - -#include "actions.hh" -#include "python.hh" -#include "otk/timer.hh" - -#include <string> -#include <list> -#include <vector> - -namespace ob { - -class Client; - -struct MouseCallbackData { - MouseCallback callback; - void *data; - MouseCallbackData(MouseCallback c, void *d) : callback(c), data(d) {} - void fire(MouseData *d) { callback(d, data); } - bool operator==(const MouseCallbackData &other) { return (callback == - other.callback && - data == - other.data); } -}; - -struct KeyCallbackData { - KeyCallback callback; - void *data; - KeyCallbackData(KeyCallback c, void *d) : callback(c), data(d) {} - void fire(KeyData *d) { callback(d, data); } - bool operator==(const KeyCallbackData &other) { return (callback == - other.callback && - data == - other.data); } -}; - -struct EventCallbackData { - EventCallback callback; - void *data; - EventCallbackData(EventCallback c, void *d) : callback(c), data(d) {} - void fire(EventData *d) { callback(d, data); } - bool operator==(const EventCallbackData &other) { return (callback == - other.callback && - data == - other.data); } -}; - -typedef std::list<MouseCallbackData> MouseCallbackList; -typedef std::list<KeyCallbackData> KeyCallbackList; -typedef std::list<EventCallbackData> EventCallbackList; - -typedef struct Binding { - unsigned int modifiers; - unsigned int key; - - bool operator==(struct Binding &b2) { return key == b2.key && - modifiers == b2.modifiers; } - bool operator!=(struct Binding &b2) { return key != b2.key || - modifiers != b2.modifiers; } - Binding(unsigned int mod, unsigned int k) { modifiers = mod; key = k; } -} Binding; - -typedef struct KeyBindingTree { - Binding binding; - KeyCallbackList callbacks; // the callbacks given for the binding in add() - bool chain; // true if this is a chain to another key (not an action) - - struct KeyBindingTree *next_sibling; // the next binding in the tree at the same - // level - struct KeyBindingTree *first_child; // the first child of this binding (next - // binding in a chained sequence). - KeyBindingTree() : binding(0, 0) { - chain = true; next_sibling = first_child = 0; - } -} KeyBindingTree; - -typedef struct ButtonBinding { - Binding binding; - MouseCallbackList callbacks[MouseAction::NUM_MOUSE_ACTION]; - ButtonBinding() : binding(0, 0) {} -}; - -class Bindings { -public: - //! A list of strings - typedef std::vector<std::string> StringVect; - -private: - // root node of the tree (this doesn't have siblings!) - KeyBindingTree _keytree; - KeyBindingTree *_curpos; // position in the keytree - - Binding _resetkey; // the key which resets the key chain status - - otk::Timer *_timer; - - KeyBindingTree *find(KeyBindingTree *search, bool *conflict) const; - KeyBindingTree *buildtree(const StringVect &keylist, - KeyCallback callback, void *data) const; - void assimilate(KeyBindingTree *node); - - static void resetChains(Bindings *self); // the timer's timeout function - - typedef std::list <ButtonBinding*> ButtonBindingList; - ButtonBindingList _buttons[MouseContext::NUM_MOUSE_CONTEXT]; - - void grabButton(bool grab, const Binding &b, MouseContext::MC context, - Client *client); - - EventCallbackList _eventlist[EventAction::NUM_EVENT_ACTION]; - - KeyCallbackData _keybgrab_callback; - - bool _grabbed; - -public: - //! Initializes an Bindings object - Bindings(); - //! Destroys the Bindings object - virtual ~Bindings(); - - //! Translates a binding string into the actual Binding - bool translate(const std::string &str, Binding &b, bool askey = true) const; - - //! Adds a new key binding - /*! - A binding will fail to be added if the binding already exists (as part of - a chain or not), or if any of the strings in the keylist are invalid. - @return true if the binding could be added; false if it could not. - */ - bool addKey(const StringVect &keylist, KeyCallback callback, void *data); - - ////! Removes a key binding - ///*! - // @return The callbackid of the binding, or '< 0' if there was no binding to - // be removed. - //*/ - //bool removeKey(const StringVect &keylist, KeyCallback callback, void *data); - - //! Removes all key bindings - void removeAllKeys(); - - void fireKey(int screen, unsigned int modifiers,unsigned int key, Time time, - KeyAction::KA action); - - void setResetKey(const std::string &key); - - void grabKeys(bool grab); - - bool grabKeyboard(int screen, KeyCallback callback, void *data); - void ungrabKeyboard(); - - bool grabPointer(int screen); - void ungrabPointer(); - - bool addButton(const std::string &but, MouseContext::MC context, - MouseAction::MA action, MouseCallback callback, void *data); - - void grabButtons(bool grab, Client *client); - - //! Removes all button bindings - void removeAllButtons(); - - void fireButton(MouseData *data); - - //! Bind a callback for an event - bool addEvent(EventAction::EA action, EventCallback callback, void *data); - - //! Unbind the callback function from an event - bool removeEvent(EventAction::EA action, EventCallback callback, void *data); - - //! Remove all callback functions - void removeAllEvents(); - - void fireEvent(EventData *data); -}; - -} - -#endif // __binding_hh
D src/client.cc

@@ -1,2014 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "client.hh" -#include "frame.hh" -#include "screen.hh" -#include "openbox.hh" -#include "bindings.hh" -#include "otk/display.hh" -#include "otk/property.hh" - -extern "C" { -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> - -#include "gettext.h" -#define _(str) gettext(str) -} - -#include <cstring> // for memcpy -#include <climits> -#include <cassert> -#include <algorithm> - -namespace ob { - -Client::Client(int screen, Window window) - : otk::EventHandler(), - frame(0), _screen(screen), _window(window) -{ - assert(screen >= 0); - assert(window); - - ignore_unmaps = 0; - - // update EVERYTHING the first time!! - - // defaults - _wmstate = NormalState; - _focused = false; - _transient_for = 0; - _layer = Layer_Normal; - _urgent = false; - _positioned = false; - _disabled_decorations = 0; - _group = None; - _desktop = 0; - _nicons = 0; - - getArea(); - getDesktop(); - getState(); // do this before updateTransientFor! (for _modal) - getShaped(); - - updateTransientFor(); - getMwmHints(); - getType(); // this can change the mwmhints for special cases - - updateProtocols(); - - getGravity(); // get the attribute gravity - updateNormalHints(); // this may override the attribute gravity - - // got the type, the mwmhints, the protocols, and the normal hints (min/max - // sizes), so we're ready to set up - // the decorations/functions - setupDecorAndFunctions(); - - // also get the initial_state and set _iconic if we aren't "starting" - // when we're "starting" that means we should use whatever state was already - // on the window over the initial map state, because it was already mapped - updateWMHints(openbox->state() != Openbox::State_Starting); - updateTitle(); - updateIconTitle(); - updateClass(); - updateStrut(); - updateIcons(); - updateKwmIcon(); - - // this makes sure that these windows appear on all desktops - if (/*_type == Type_Dock ||*/ _type == Type_Desktop) - _desktop = 0xffffffff; - - // set the desktop hint, to make sure that it always exists, and to reflect - // any changes we've made here - otk::Property::set(_window, otk::Property::atoms.net_wm_desktop, - otk::Property::atoms.cardinal, (unsigned)_desktop); - changeState(); -} - - -Client::~Client() -{ - assert(_nicons > 0); // there should always be a default.. - for (int j = 0; j < _nicons; ++j) - delete [] _icons[j].data; - delete [] _icons; - - // clean up childrens' references - while (!_transients.empty()) { - _transients.front()->_transient_for = 0; - _transients.pop_front(); - } - - // clean up parents reference to this - if (_transient_for) - _transient_for->_transients.remove(this); // remove from old parent - - if (openbox->state() != Openbox::State_Exiting) { - // these values should not be persisted across a window unmapping/mapping - otk::Property::erase(_window, otk::Property::atoms.net_wm_desktop); - otk::Property::erase(_window, otk::Property::atoms.net_wm_state); - } else { - // if we're left in an iconic state, the client wont be mapped. this is - // bad, since we will no longer be managing the window on restart - if (_iconic) - XMapWindow(**otk::display, _window); - } -} - - -bool Client::validate() const -{ - XSync(**otk::display, false); // get all events on the server - - XEvent e; - if (XCheckTypedWindowEvent(**otk::display, _window, DestroyNotify, &e) || - XCheckTypedWindowEvent(**otk::display, _window, UnmapNotify, &e)) { - XPutBackEvent(**otk::display, &e); - return false; - } - - return true; -} - - -void Client::getGravity() -{ - XWindowAttributes wattrib; - Status ret; - - ret = XGetWindowAttributes(**otk::display, _window, &wattrib); - assert(ret != BadWindow); - _gravity = wattrib.win_gravity; -} - - -void Client::getDesktop() -{ - // defaults to the current desktop - _desktop = openbox->screen(_screen)->desktop(); - unsigned int d; - - if (otk::Property::get(_window, otk::Property::atoms.net_wm_desktop, - otk::Property::atoms.cardinal, - (long unsigned*)&d)) { - if (d >= openbox->screen(_screen)->numDesktops() && - d != 0xffffffff) - d = openbox->screen(_screen)->numDesktops() - 1; - _desktop = d; -#ifdef DEBUG -// printf("Window requested desktop: %ld\n", _desktop); -#endif - } -} - - -void Client::getType() -{ - _type = (WindowType) -1; - - unsigned long *val; - unsigned long num; - if (otk::Property::get(_window, otk::Property::atoms.net_wm_window_type, - otk::Property::atoms.atom, &num, &val)) { - // use the first value that we know about in the array - for (unsigned long i = 0; i < num; ++i) { - if (val[i] == otk::Property::atoms.net_wm_window_type_desktop) - _type = Type_Desktop; - else if (val[i] == otk::Property::atoms.net_wm_window_type_dock) - _type = Type_Dock; - else if (val[i] == otk::Property::atoms.net_wm_window_type_toolbar) - _type = Type_Toolbar; - else if (val[i] == otk::Property::atoms.net_wm_window_type_menu) - _type = Type_Menu; - else if (val[i] == otk::Property::atoms.net_wm_window_type_utility) - _type = Type_Utility; - else if (val[i] == otk::Property::atoms.net_wm_window_type_splash) - _type = Type_Splash; - else if (val[i] == otk::Property::atoms.net_wm_window_type_dialog) - _type = Type_Dialog; - else if (val[i] == otk::Property::atoms.net_wm_window_type_normal) - _type = Type_Normal; - else if (val[i] == otk::Property::atoms.kde_net_wm_window_type_override){ - // prevent this window from getting any decor or functionality - _mwmhints.flags &= MwmFlag_Functions | MwmFlag_Decorations; - _mwmhints.decorations = 0; - _mwmhints.functions = 0; - } - if (_type != (WindowType) -1) - break; // grab the first known type - } - delete val; - } - - if (_type == (WindowType) -1) { - /* - * the window type hint was not set, which means we either classify ourself - * as a normal window or a dialog, depending on if we are a transient. - */ - if (_transient_for) - _type = Type_Dialog; - else - _type = Type_Normal; - } -} - - -void Client::setupDecorAndFunctions() -{ - // start with everything (cept fullscreen) - _decorations = Decor_Titlebar | Decor_Handle | Decor_Border | Decor_Icon | - Decor_AllDesktops | Decor_Iconify | Decor_Maximize; - _functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize | - Func_Shade; - if (_delete_window) { - _decorations |= Decor_Close; - _functions |= Func_Close; - } - - if (!(_min_size.width() < _max_size.width() || - _min_size.height() < _max_size.height())) { - _decorations &= ~(Decor_Maximize | Decor_Handle); - _functions &= ~(Func_Resize | Func_Maximize); - } - - switch (_type) { - case Type_Normal: - // normal windows retain all of the possible decorations and - // functionality, and are the only windows that you can fullscreen - _functions |= Func_Fullscreen; - break; - - case Type_Dialog: - // dialogs cannot be maximized - _decorations &= ~Decor_Maximize; - _functions &= ~Func_Maximize; - break; - - case Type_Menu: - case Type_Toolbar: - case Type_Utility: - // these windows get less functionality - _decorations &= ~(Decor_Iconify | Decor_Handle); - _functions &= ~(Func_Iconify | Func_Resize); - break; - - case Type_Desktop: - case Type_Dock: - case Type_Splash: - // none of these windows are manipulated by the window manager - _decorations = 0; - _functions = 0; - break; - } - - // Mwm Hints are applied subtractively to what has already been chosen for - // decor and functionality - if (_mwmhints.flags & MwmFlag_Decorations) { - if (! (_mwmhints.decorations & MwmDecor_All)) { - if (! (_mwmhints.decorations & MwmDecor_Border)) - _decorations &= ~Decor_Border; - if (! (_mwmhints.decorations & MwmDecor_Handle)) - _decorations &= ~Decor_Handle; - if (! (_mwmhints.decorations & MwmDecor_Title)) - _decorations &= ~Decor_Titlebar; - if (! (_mwmhints.decorations & MwmDecor_Iconify)) - _decorations &= ~Decor_Iconify; - if (! (_mwmhints.decorations & MwmDecor_Maximize)) - _decorations &= ~Decor_Maximize; - } - } - - if (_mwmhints.flags & MwmFlag_Functions) { - if (! (_mwmhints.functions & MwmFunc_All)) { - if (! (_mwmhints.functions & MwmFunc_Resize)) - _functions &= ~Func_Resize; - if (! (_mwmhints.functions & MwmFunc_Move)) - _functions &= ~Func_Move; - if (! (_mwmhints.functions & MwmFunc_Iconify)) - _functions &= ~Func_Iconify; - if (! (_mwmhints.functions & MwmFunc_Maximize)) - _functions &= ~Func_Maximize; - // dont let mwm hints kill the close button - //if (! (_mwmhints.functions & MwmFunc_Close)) - // _functions &= ~Func_Close; - } - } - - // can't maximize without moving/resizing - if (!((_functions & Func_Move) && (_functions & Func_Resize))) - _functions &= ~Func_Maximize; - - // finally, user specified disabled decorations are applied to subtract - // decorations - if (_disabled_decorations & Decor_Titlebar) - _decorations &= ~Decor_Titlebar; - if (_disabled_decorations & Decor_Handle) - _decorations &= ~Decor_Handle; - if (_disabled_decorations & Decor_Border) - _decorations &= ~Decor_Border; - if (_disabled_decorations & Decor_Iconify) - _decorations &= ~Decor_Iconify; - if (_disabled_decorations & Decor_Maximize) - _decorations &= ~Decor_Maximize; - if (_disabled_decorations & Decor_AllDesktops) - _decorations &= ~Decor_AllDesktops; - if (_disabled_decorations & Decor_Close) - _decorations &= ~Decor_Close; - - // if we don't have a titlebar, then we cannot shade! - if (!(_decorations & Decor_Titlebar)) - _functions &= ~Func_Shade; - - changeAllowedActions(); - - if (frame) { - frame->adjustSize(); // change the decors on the frame - frame->adjustPosition(); // with more/less decorations, we may need to be - // moved - remaximize(); // with new decor, the window's maximized size may change - } -} - - -void Client::getMwmHints() -{ - unsigned long num = MwmHints::elements; - unsigned long *hints; - - _mwmhints.flags = 0; // default to none - - if (!otk::Property::get(_window, otk::Property::atoms.motif_wm_hints, - otk::Property::atoms.motif_wm_hints, &num, - (unsigned long **)&hints)) - return; - - if (num >= MwmHints::elements) { - // retrieved the hints - _mwmhints.flags = hints[0]; - _mwmhints.functions = hints[1]; - _mwmhints.decorations = hints[2]; - } - - delete [] hints; -} - - -void Client::getArea() -{ - XWindowAttributes wattrib; - Status ret; - - ret = XGetWindowAttributes(**otk::display, _window, &wattrib); - assert(ret != BadWindow); - - _area = otk::Rect(wattrib.x, wattrib.y, wattrib.width, wattrib.height); - _border_width = wattrib.border_width; -} - - -void Client::getState() -{ - _modal = _shaded = _max_horz = _max_vert = _fullscreen = _above = _below = - _iconic = _skip_taskbar = _skip_pager = false; - - unsigned long *state; - unsigned long num; - - if (otk::Property::get(_window, otk::Property::atoms.net_wm_state, - otk::Property::atoms.atom, &num, &state)) { - for (unsigned long i = 0; i < num; ++i) { - if (state[i] == otk::Property::atoms.net_wm_state_modal) - _modal = true; - else if (state[i] == otk::Property::atoms.net_wm_state_shaded) - _shaded = true; - else if (state[i] == otk::Property::atoms.net_wm_state_hidden) - _iconic = true; - else if (state[i] == otk::Property::atoms.net_wm_state_skip_taskbar) - _skip_taskbar = true; - else if (state[i] == otk::Property::atoms.net_wm_state_skip_pager) - _skip_pager = true; - else if (state[i] == otk::Property::atoms.net_wm_state_fullscreen) - _fullscreen = true; - else if (state[i] == otk::Property::atoms.net_wm_state_maximized_vert) - _max_vert = true; - else if (state[i] == otk::Property::atoms.net_wm_state_maximized_horz) - _max_horz = true; - else if (state[i] == otk::Property::atoms.net_wm_state_above) - _above = true; - else if (state[i] == otk::Property::atoms.net_wm_state_below) - _below = true; - } - - delete [] state; - } -} - -void Client::getShaped() -{ - _shaped = false; -#ifdef SHAPE - if (otk::display->shape()) { - int foo; - unsigned int ufoo; - int s; - - XShapeSelectInput(**otk::display, _window, ShapeNotifyMask); - - XShapeQueryExtents(**otk::display, _window, &s, &foo, - &foo, &ufoo, &ufoo, &foo, &foo, &foo, &ufoo, &ufoo); - _shaped = (s != 0); - } -#endif // SHAPE -} - -Client *Client::searchFocusTree(Client *node, Client *skip) -{ - List::const_iterator it, end = node->_transients.end(); - Client *ret; - - for (it = node->_transients.begin(); it != end; ++it) { - if (*it == skip) continue; // circular? - if ((ret = searchModalTree(*it, skip))) return ret; // got one - if ((*it)->_focused) return *it; // got one - } - return 0; -} - -void Client::calcLayer() { - StackLayer l; - bool fs = false; - - // are we fullscreen, or do we have a fullscreen transient parent? - Client *c = this; - while (c) { - if (c->_fullscreen) { - fs =true; - break; - } - c = c->_transient_for; - } - if (!fs && _fullscreen) { - // is one of our transients focused? - c = searchFocusTree(this, this); - if (c) fs = true; - } - - if (_iconic) l = Layer_Icon; - else if (fs) l = Layer_Fullscreen; - else if (_type == Type_Desktop) l = Layer_Desktop; - else if (_type == Type_Dock) { - if (!_below) l = Layer_Top; - else l = Layer_Normal; - } - else if (_above) l = Layer_Above; - else if (_below) l = Layer_Below; - else l = Layer_Normal; - - if (l != _layer) { - _layer = l; - if (frame) { - /* - if we don't have a frame, then we aren't mapped yet (and this would - SIGSEGV :) - */ - openbox->screen(_screen)->raiseWindow(this); - } - } -} - -void Client::updateProtocols() -{ - Atom *proto; - int num_return = 0; - - _focus_notify = false; - _delete_window = false; - - if (XGetWMProtocols(**otk::display, _window, &proto, &num_return)) { - for (int i = 0; i < num_return; ++i) { - if (proto[i] == otk::Property::atoms.wm_delete_window) { - // this means we can request the window to close - _delete_window = true; - } else if (proto[i] == otk::Property::atoms.wm_take_focus) - // if this protocol is requested, then the window will be notified - // by the window manager whenever it receives focus - _focus_notify = true; - } - XFree(proto); - } -} - -void Client::updateNormalHints() -{ - XSizeHints size; - long ret; - int oldgravity = _gravity; - - // defaults - _min_ratio = 0.0; - _max_ratio = 0.0; - _size_inc = otk::Size(1, 1); - _base_size = otk::Size(0, 0); - _min_size = otk::Size(0, 0); - _max_size = otk::Size(INT_MAX, INT_MAX); - - // get the hints from the window - if (XGetWMNormalHints(**otk::display, _window, &size, &ret)) { - _positioned = (size.flags & (PPosition|USPosition)); - - if (size.flags & PWinGravity) { - _gravity = size.win_gravity; - - // if the client has a frame, i.e. has already been mapped and is - // changing its gravity - if (frame && _gravity != oldgravity) { - // move our idea of the client's position based on its new gravity - int x = frame->area().x(), y = frame->area().y(); - frame->frameGravity(x, y); - _area = otk::Rect(otk::Point(x, y), _area.size()); - } - } - - if (size.flags & PAspect) { - if (size.min_aspect.y) _min_ratio = size.min_aspect.x/size.min_aspect.y; - if (size.max_aspect.y) _max_ratio = size.max_aspect.x/size.max_aspect.y; - } - - if (size.flags & PMinSize) - _min_size = otk::Size(size.min_width, size.min_height); - - if (size.flags & PMaxSize) - _max_size = otk::Size(size.max_width, size.max_height); - - if (size.flags & PBaseSize) - _base_size = otk::Size(size.base_width, size.base_height); - - if (size.flags & PResizeInc) - _size_inc = otk::Size(size.width_inc, size.height_inc); - } -} - -void Client::updateWMHints(bool initstate) -{ - XWMHints *hints; - - // assume a window takes input if it doesnt specify - _can_focus = true; - bool ur = false; - - if ((hints = XGetWMHints(**otk::display, _window)) != NULL) { - if (hints->flags & InputHint) - _can_focus = hints->input; - - // only do this when initstate is true! - if (initstate && (hints->flags & StateHint)) - _iconic = hints->initial_state == IconicState; - - if (hints->flags & XUrgencyHint) - ur = true; - - if (hints->flags & WindowGroupHint) { - if (hints->window_group != _group) { - // XXX: remove from the old group if there was one - _group = hints->window_group; - // XXX: do stuff with the group - } - } else // no group! - _group = None; - - if (hints->flags & IconPixmapHint) { - updateKwmIcon(); // try get the kwm icon first, this is a fallback only - if (_pixmap_icon == None) { - _pixmap_icon = hints->icon_pixmap; - if (hints->flags & IconMaskHint) - _pixmap_icon_mask = hints->icon_mask; - else - _pixmap_icon_mask = None; - } - } - - XFree(hints); - } - - if (ur != _urgent) { - _urgent = ur; -#ifdef DEBUG - printf("Urgent Hint for 0x%lx: %s\n", - (long)_window, _urgent ? "ON" : "OFF"); -#endif - // fire the urgent callback if we're mapped, otherwise, wait until after - // we're mapped - if (frame) - fireUrgent(); - } -} - -void Client::updateTitle() -{ - _title = ""; - - // try netwm - if (!otk::Property::get(_window, otk::Property::atoms.net_wm_name, - otk::Property::utf8, &_title)) { - // try old x stuff - otk::Property::get(_window, otk::Property::atoms.wm_name, - otk::Property::ascii, &_title); - } - - if (_title.empty()) - _title = _("Unnamed Window"); - - if (frame) - frame->adjustTitle(); -} - -void Client::updateIconTitle() -{ - _icon_title = ""; - - // try netwm - if (!otk::Property::get(_window, otk::Property::atoms.net_wm_icon_name, - otk::Property::utf8, &_icon_title)) { - // try old x stuff - otk::Property::get(_window, otk::Property::atoms.wm_icon_name, - otk::Property::ascii, &_icon_title); - } - - if (_title.empty()) - _icon_title = _("Unnamed Window"); -} - -void Client::updateClass() -{ - // set the defaults - _app_name = _app_class = _role = ""; - - otk::Property::StringVect v; - unsigned long num = 2; - - if (otk::Property::get(_window, otk::Property::atoms.wm_class, - otk::Property::ascii, &num, &v)) { - if (num > 0) _app_name = v[0].c_str(); - if (num > 1) _app_class = v[1].c_str(); - } - - v.clear(); - num = 1; - if (otk::Property::get(_window, otk::Property::atoms.wm_window_role, - otk::Property::ascii, &num, &v)) { - if (num > 0) _role = v[0].c_str(); - } -} - -void Client::updateStrut() -{ - unsigned long num = 4; - unsigned long *data; - if (!otk::Property::get(_window, otk::Property::atoms.net_wm_strut, - otk::Property::atoms.cardinal, &num, &data)) - return; - - if (num == 4) { - _strut.left = data[0]; - _strut.right = data[1]; - _strut.top = data[2]; - _strut.bottom = data[3]; - - // updating here is pointless while we're being mapped cuz we're not in - // the screen's client list yet - if (frame) - openbox->screen(_screen)->updateStruts(); - } - - delete [] data; -} - -void Client::updateTransientFor() -{ - Window t = 0; - Client *c = 0; - - if (XGetTransientForHint(**otk::display, _window, &t) && - t != _window) { // cant be transient to itself! - c = openbox->findClient(t); - assert(c != this); // if this happens then we need to check for it - - if (!c /*XXX: && _group*/) { - // not transient to a client, see if it is transient for a group - if (//t == _group->leader() || - t == None || - t == otk::display->screenInfo(_screen)->rootWindow()) { - // window is a transient for its group! - // XXX: for now this is treated as non-transient. - // this needs to be fixed! - } - } - } - - // if anything has changed... - if (c != _transient_for) { - if (_transient_for) - _transient_for->_transients.remove(this); // remove from old parent - _transient_for = c; - if (_transient_for) - _transient_for->_transients.push_back(this); // add to new parent - } -} - -void Client::updateIcons() -{ - unsigned long num; - unsigned long *data; - unsigned long w, h, i = 0; - - for (int j = 0; j < _nicons; ++j) - delete [] _icons[j].data; - if (_nicons > 0) - delete [] _icons; - _nicons = 0; - - if (otk::Property::get(_window, otk::Property::atoms.net_wm_icon, - otk::Property::atoms.cardinal, &num, &data)) { - // figure out how man valid icons are in here - while (num - i > 2) { - w = data[i++]; - h = data[i++]; - i += w * h; - if (i > num) break; - ++_nicons; - } - - _icons = new Icon[_nicons]; - - // store the icons - i = 0; - for (int j = 0; j < _nicons; ++j) { - w = _icons[j].w = data[i++]; - h = _icons[j].h = data[i++]; - _icons[j].data = new unsigned long[w * h]; - ::memcpy(_icons[j].data, &data[i], w * h * sizeof(unsigned long)); - i += w * h; - assert(i <= num); - } - - delete [] data; - } - - if (_nicons <= 0) { - _nicons = 1; - _icons = new Icon[1]; - _icons[i].w = 0; - _icons[i].h = 0; - _icons[i].data = 0; - } - - assert(_nicons > 0); // there should always be a default.. - - if (frame) frame->adjustIcon(); -} - -void Client::updateKwmIcon() -{ - _pixmap_icon = _pixmap_icon_mask = None; - - unsigned long num = 2; - Pixmap *data; - if (otk::Property::get(_window, otk::Property::atoms.kwm_win_icon, - otk::Property::atoms.kwm_win_icon, &num, &data)) { - if (num == 2) { - _pixmap_icon = data[0]; - _pixmap_icon_mask = data[1]; - } - delete [] data; - } -} - -void Client::propertyHandler(const XPropertyEvent &e) -{ - otk::EventHandler::propertyHandler(e); - - // validate cuz we query stuff off the client here - if (!validate()) return; - - // compress changes to a single property into a single change - XEvent ce; - while (XCheckTypedEvent(**otk::display, e.type, &ce)) { - // XXX: it would be nice to compress ALL changes to a property, not just - // changes in a row without other props between. - if (ce.xproperty.atom != e.atom) { - XPutBackEvent(**otk::display, &ce); - break; - } - } - - if (e.atom == XA_WM_NORMAL_HINTS) { - updateNormalHints(); - setupDecorAndFunctions(); // normal hints can make a window non-resizable - } else if (e.atom == XA_WM_HINTS) - updateWMHints(); - else if (e.atom == XA_WM_TRANSIENT_FOR) { - updateTransientFor(); - getType(); - calcLayer(); // type may have changed, so update the layer - setupDecorAndFunctions(); - } - else if (e.atom == otk::Property::atoms.net_wm_name || - e.atom == otk::Property::atoms.wm_name) - updateTitle(); - else if (e.atom == otk::Property::atoms.net_wm_icon_name || - e.atom == otk::Property::atoms.wm_icon_name) - updateIconTitle(); - else if (e.atom == otk::Property::atoms.wm_class) - updateClass(); - else if (e.atom == otk::Property::atoms.wm_protocols) { - updateProtocols(); - setupDecorAndFunctions(); - } - else if (e.atom == otk::Property::atoms.net_wm_strut) - updateStrut(); - else if (e.atom == otk::Property::atoms.net_wm_icon) - updateIcons(); - else if (e.atom == otk::Property::atoms.kwm_win_icon) - updateKwmIcon(); -} - -void Client::setWMState(long state) -{ - if (state == _wmstate) return; // no change - - switch (state) { - case IconicState: - iconify(true); - break; - case NormalState: - iconify(false); - break; - } -} - -void Client::setDesktop(unsigned int target) -{ - if (target == _desktop) return; - - printf("Setting desktop %u\n", target); - - if (!(target < openbox->screen(_screen)->numDesktops() || - target == 0xffffffff)) - return; - - _desktop = target; - // set the desktop hint - otk::Property::set(_window, otk::Property::atoms.net_wm_desktop, - otk::Property::atoms.cardinal, _desktop); - frame->adjustState(); // the frame can display the current desktop state - // 'move' the window to the new desktop - showhide(); - openbox->screen(_screen)->updateStruts(); -} - -void Client::showhide() -{ - bool show; - Screen *s = openbox->screen(_screen); - - if (_iconic) show = false; - else if (!(_desktop == s->desktop() || - _desktop == 0xffffffff)) show = false; - else if (normal() && s->showingDesktop()) show = false; - else show = true; - - if (show) frame->show(); - else frame->hide(); -} - -void Client::setState(Atom action, long data1, long data2) -{ - bool shadestate = _shaded; - bool fsstate = _fullscreen; - bool maxh = _max_horz; - bool maxv = _max_vert; - - if (!(action == otk::Property::atoms.net_wm_state_add || - action == otk::Property::atoms.net_wm_state_remove || - action == otk::Property::atoms.net_wm_state_toggle)) - return; // an invalid action was passed to the client message, ignore it - - for (int i = 0; i < 2; ++i) { - Atom state = i == 0 ? data1 : data2; - - if (! state) continue; - - // if toggling, then pick whether we're adding or removing - if (action == otk::Property::atoms.net_wm_state_toggle) { - if (state == otk::Property::atoms.net_wm_state_modal) - action = _modal ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - else if (state == otk::Property::atoms.net_wm_state_maximized_vert) - action = _max_vert ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - else if (state == otk::Property::atoms.net_wm_state_maximized_horz) - action = _max_horz ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - else if (state == otk::Property::atoms.net_wm_state_shaded) - action = _shaded ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) - action = _skip_taskbar ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - else if (state == otk::Property::atoms.net_wm_state_skip_pager) - action = _skip_pager ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - else if (state == otk::Property::atoms.net_wm_state_fullscreen) - action = _fullscreen ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - else if (state == otk::Property::atoms.net_wm_state_above) - action = _above ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - else if (state == otk::Property::atoms.net_wm_state_below) - action = _below ? otk::Property::atoms.net_wm_state_remove : - otk::Property::atoms.net_wm_state_add; - } - - if (action == otk::Property::atoms.net_wm_state_add) { - if (state == otk::Property::atoms.net_wm_state_modal) { - if (_modal) continue; - _modal = true; - } else if (state == otk::Property::atoms.net_wm_state_maximized_vert) { - maxv = true; - } else if (state == otk::Property::atoms.net_wm_state_maximized_horz) { - if (_max_horz) continue; - maxh = true; - } else if (state == otk::Property::atoms.net_wm_state_shaded) { - shadestate = true; - } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) { - _skip_taskbar = true; - } else if (state == otk::Property::atoms.net_wm_state_skip_pager) { - _skip_pager = true; - } else if (state == otk::Property::atoms.net_wm_state_fullscreen) { - fsstate = true; - } else if (state == otk::Property::atoms.net_wm_state_above) { - if (_above) continue; - _above = true; - } else if (state == otk::Property::atoms.net_wm_state_below) { - if (_below) continue; - _below = true; - } - - } else { // action == otk::Property::atoms.net_wm_state_remove - if (state == otk::Property::atoms.net_wm_state_modal) { - if (!_modal) continue; - _modal = false; - } else if (state == otk::Property::atoms.net_wm_state_maximized_vert) { - maxv = false; - } else if (state == otk::Property::atoms.net_wm_state_maximized_horz) { - maxh = false; - } else if (state == otk::Property::atoms.net_wm_state_shaded) { - shadestate = false; - } else if (state == otk::Property::atoms.net_wm_state_skip_taskbar) { - _skip_taskbar = false; - } else if (state == otk::Property::atoms.net_wm_state_skip_pager) { - _skip_pager = false; - } else if (state == otk::Property::atoms.net_wm_state_fullscreen) { - fsstate = false; - } else if (state == otk::Property::atoms.net_wm_state_above) { - if (!_above) continue; - _above = false; - } else if (state == otk::Property::atoms.net_wm_state_below) { - if (!_below) continue; - _below = false; - } - } - } - if (maxh != _max_horz || maxv != _max_vert) { - if (maxh != _max_horz && maxv != _max_vert) { // toggling both - if (maxh == maxv) { // both going the same way - maximize(maxh, 0, true); - } else { - maximize(maxh, 1, true); - maximize(maxv, 2, true); - } - } else { // toggling one - if (maxh != _max_horz) - maximize(maxh, 1, true); - else - maximize(maxv, 2, true); - } - } - // change fullscreen state before shading, as it will affect if the window - // can shade or not - if (fsstate != _fullscreen) - fullscreen(fsstate, true); - if (shadestate != _shaded) - shade(shadestate); - calcLayer(); - changeState(); // change the hint to relect these changes -} - -void Client::toggleClientBorder(bool addborder) -{ - // adjust our idea of where the client is, based on its border. When the - // border is removed, the client should now be considered to be in a - // different position. - // when re-adding the border to the client, the same operation needs to be - // reversed. - int oldx = _area.x(), oldy = _area.y(); - int x = oldx, y = oldy; - switch(_gravity) { - default: - case NorthWestGravity: - case WestGravity: - case SouthWestGravity: - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - if (addborder) x -= _border_width * 2; - else x += _border_width * 2; - break; - case NorthGravity: - case SouthGravity: - case CenterGravity: - case ForgetGravity: - case StaticGravity: - if (addborder) x -= _border_width; - else x += _border_width; - break; - } - switch(_gravity) { - default: - case NorthWestGravity: - case NorthGravity: - case NorthEastGravity: - break; - case SouthWestGravity: - case SouthGravity: - case SouthEastGravity: - if (addborder) y -= _border_width * 2; - else y += _border_width * 2; - break; - case WestGravity: - case EastGravity: - case CenterGravity: - case ForgetGravity: - case StaticGravity: - if (addborder) y -= _border_width; - else y += _border_width; - break; - } - _area = otk::Rect(otk::Point(x, y), _area.size()); - - if (addborder) { - XSetWindowBorderWidth(**otk::display, _window, _border_width); - - // move the client so it is back it the right spot _with_ its border! - if (x != oldx || y != oldy) - XMoveWindow(**otk::display, _window, x, y); - } else - XSetWindowBorderWidth(**otk::display, _window, 0); -} - -void Client::clientMessageHandler(const XClientMessageEvent &e) -{ - otk::EventHandler::clientMessageHandler(e); - - // validate cuz we query stuff off the client here - if (!validate()) return; - - if (e.format != 32) return; - - if (e.message_type == otk::Property::atoms.wm_change_state) { - // compress changes into a single change - bool compress = false; - XEvent ce; - while (XCheckTypedEvent(**otk::display, e.type, &ce)) { - // XXX: it would be nice to compress ALL messages of a type, not just - // messages in a row without other message types between. - if (ce.xclient.message_type != e.message_type) { - XPutBackEvent(**otk::display, &ce); - break; - } - compress = true; - } - if (compress) - setWMState(ce.xclient.data.l[0]); // use the found event - else - setWMState(e.data.l[0]); // use the original event - } else if (e.message_type == otk::Property::atoms.net_wm_desktop) { - // compress changes into a single change - bool compress = false; - XEvent ce; - while (XCheckTypedEvent(**otk::display, e.type, &ce)) { - // XXX: it would be nice to compress ALL messages of a type, not just - // messages in a row without other message types between. - if (ce.xclient.message_type != e.message_type) { - XPutBackEvent(**otk::display, &ce); - break; - } - compress = true; - } - if (compress) - setDesktop(e.data.l[0]); // use the found event - else - setDesktop(e.data.l[0]); // use the original event - } else if (e.message_type == otk::Property::atoms.net_wm_state) { - // can't compress these -#ifdef DEBUG - printf("net_wm_state %s %ld %ld for 0x%lx\n", - (e.data.l[0] == 0 ? "Remove" : e.data.l[0] == 1 ? "Add" : - e.data.l[0] == 2 ? "Toggle" : "INVALID"), - e.data.l[1], e.data.l[2], _window); -#endif - setState(e.data.l[0], e.data.l[1], e.data.l[2]); - } else if (e.message_type == otk::Property::atoms.net_close_window) { -#ifdef DEBUG - printf("net_close_window for 0x%lx\n", _window); -#endif - close(); - } else if (e.message_type == otk::Property::atoms.net_active_window) { -#ifdef DEBUG - printf("net_active_window for 0x%lx\n", _window); -#endif - if (openbox->screen(_screen)->showingDesktop()) - openbox->screen(_screen)->showDesktop(false); - if (_iconic) - iconify(false); - else if (!frame->visible()) // if its not visible for other reasons, then - return; // don't mess with it - if (_shaded) - shade(false); - focus(); - openbox->screen(_screen)->raiseWindow(this); - } else if (e.message_type == otk::Property::atoms.openbox_active_window) { - if (openbox->screen(_screen)->showingDesktop()) - openbox->screen(_screen)->showDesktop(false); - if (_iconic) - iconify(false); - else if (!frame->visible()) // if its not visible for other reasons, then - return; // don't mess with it - if (e.data.l[0] && _shaded) - shade(false); - focus(); - if (e.data.l[1]) - openbox->screen(_screen)->raiseWindow(this); - } else if (e.message_type == otk::Property::atoms.openbox_restack_window) { -#ifdef DEBUG - printf("openbox_restack_window for 0x%lx\n", _window); -#endif - if (e.data.l[0] == 0) - openbox->screen(_screen)->raiseWindow(this); - else if (e.data.l[0] == 1) - openbox->screen(_screen)->lowerWindow(this); - } -} - -#if defined(SHAPE) -void Client::shapeHandler(const XShapeEvent &e) -{ - otk::EventHandler::shapeHandler(e); - - if (e.kind == ShapeBounding) { - _shaped = e.shaped; - frame->adjustShape(); - } -} -#endif - -void Client::resize(Corner anchor, int w, int h) -{ - if (!(_functions & Func_Resize)) return; - internal_resize(anchor, w, h); -} - -void Client::internal_resize(Corner anchor, int w, int h, - bool user, int x, int y) -{ - w -= _base_size.width(); - h -= _base_size.height(); - - if (user) { - // for interactive resizing. have to move half an increment in each - // direction. - int mw = w % _size_inc.width(); // how far we are towards the next size inc - int mh = h % _size_inc.height(); - int aw = _size_inc.width() / 2; // amount to add - int ah = _size_inc.height() / 2; - // don't let us move into a new size increment - if (mw + aw >= _size_inc.width()) aw = _size_inc.width() - mw - 1; - if (mh + ah >= _size_inc.height()) ah = _size_inc.height() - mh - 1; - w += aw; - h += ah; - - // if this is a user-requested resize, then check against min/max sizes - // and aspect ratios - - // smaller than min size or bigger than max size? - if (w > _max_size.width()) w = _max_size.width(); - if (w < _min_size.width()) w = _min_size.width(); - if (h > _max_size.height()) h = _max_size.height(); - if (h < _min_size.height()) h = _min_size.height(); - - // adjust the height ot match the width for the aspect ratios - if (_min_ratio) - if (h * _min_ratio > w) h = static_cast<int>(w / _min_ratio); - if (_max_ratio) - if (h * _max_ratio < w) h = static_cast<int>(w / _max_ratio); - } - - // keep to the increments - w /= _size_inc.width(); - h /= _size_inc.height(); - - // you cannot resize to nothing - if (w < 1) w = 1; - if (h < 1) h = 1; - - // store the logical size - _logical_size = otk::Size(w, h); - - w *= _size_inc.width(); - h *= _size_inc.height(); - - w += _base_size.width(); - h += _base_size.height(); - - if (x == INT_MIN || y == INT_MIN) { - x = _area.x(); - y = _area.y(); - switch (anchor) { - case TopLeft: - break; - case TopRight: - x -= w - _area.width(); - break; - case BottomLeft: - y -= h - _area.height(); - break; - case BottomRight: - x -= w - _area.width(); - y -= h - _area.height(); - break; - } - } - - _area = otk::Rect(_area.position(), otk::Size(w, h)); - - XResizeWindow(**otk::display, _window, w, h); - - // resize the frame to match the request - frame->adjustSize(); - internal_move(x, y); -} - -const Icon *Client::icon(const otk::Size &s) const -{ - unsigned long req = s.width() * s.height(); - // si is the smallest image >= req - // li is the largest image < req - unsigned long smallest = 0xffffffff, largest = 0, si = 0, li = 0; - - assert(_nicons > 0); // there should always be a default.. - for (int i = 0; i < _nicons; ++i) { - unsigned long size = _icons[i].w * _icons[i].h; - if (size < smallest && size >= req) { - smallest = size; - si = i; - } - if (size > largest && size <= req) { - largest = size; - li = i; - } - } - if (largest == 0) // didnt find one smaller than the requested size - return &_icons[si]; - return &_icons[li]; -} - -void Client::move(int x, int y, bool final) -{ - if (!(_functions & Func_Move)) return; - frame->frameGravity(x, y); // get the client's position based on x,y for the - // frame - internal_move(x, y, final); -} - -void Client::internal_move(int x, int y, bool final) -{ - _area = otk::Rect(otk::Point(x, y), _area.size()); - - // move the frame to be in the requested position - if (frame) { // this can be called while mapping, before frame exists - frame->adjustPosition(); - - // send synthetic configure notify (we don't need to if we aren't mapped - // yet) - if (final) { - XEvent event; - event.type = ConfigureNotify; - event.xconfigure.display = **otk::display; - event.xconfigure.event = _window; - event.xconfigure.window = _window; - - // root window coords with border in mind - event.xconfigure.x = x - _border_width + frame->size().left; - event.xconfigure.y = y - _border_width + frame->size().top; - - event.xconfigure.width = _area.width(); - event.xconfigure.height = _area.height(); - event.xconfigure.border_width = _border_width; - event.xconfigure.above = frame->plate(); - event.xconfigure.override_redirect = False; - XSendEvent(event.xconfigure.display, event.xconfigure.window, False, - StructureNotifyMask, &event); -#if 0//def DEBUG - printf("Sent synthetic ConfigureNotify %d,%d %d,%d to 0x%lx\n", - event.xconfigure.x, event.xconfigure.y, event.xconfigure.width, - event.xconfigure.height, event.xconfigure.window); -#endif - } - } -} - -void Client::close() -{ - XEvent ce; - - if (!(_functions & Func_Close)) return; - - // XXX: itd be cool to do timeouts and shit here for killing the client's - // process off - // like... if the window is around after 5 seconds, then the close button - // turns a nice red, and if this function is called again, the client is - // explicitly killed. - - ce.xclient.type = ClientMessage; - ce.xclient.message_type = otk::Property::atoms.wm_protocols; - ce.xclient.display = **otk::display; - ce.xclient.window = _window; - ce.xclient.format = 32; - ce.xclient.data.l[0] = otk::Property::atoms.wm_delete_window; - ce.xclient.data.l[1] = CurrentTime; - ce.xclient.data.l[2] = 0l; - ce.xclient.data.l[3] = 0l; - ce.xclient.data.l[4] = 0l; - XSendEvent(**otk::display, _window, false, NoEventMask, &ce); -} - -void Client::changeState() -{ - unsigned long state[2]; - state[0] = _wmstate; - state[1] = None; - otk::Property::set(_window, otk::Property::atoms.wm_state, - otk::Property::atoms.wm_state, state, 2); - - Atom netstate[10]; - int num = 0; - if (_modal) - netstate[num++] = otk::Property::atoms.net_wm_state_modal; - if (_shaded) - netstate[num++] = otk::Property::atoms.net_wm_state_shaded; - if (_iconic) - netstate[num++] = otk::Property::atoms.net_wm_state_hidden; - if (_skip_taskbar) - netstate[num++] = otk::Property::atoms.net_wm_state_skip_taskbar; - if (_skip_pager) - netstate[num++] = otk::Property::atoms.net_wm_state_skip_pager; - if (_fullscreen) - netstate[num++] = otk::Property::atoms.net_wm_state_fullscreen; - if (_max_vert) - netstate[num++] = otk::Property::atoms.net_wm_state_maximized_vert; - if (_max_horz) - netstate[num++] = otk::Property::atoms.net_wm_state_maximized_horz; - if (_above) - netstate[num++] = otk::Property::atoms.net_wm_state_above; - if (_below) - netstate[num++] = otk::Property::atoms.net_wm_state_below; - otk::Property::set(_window, otk::Property::atoms.net_wm_state, - otk::Property::atoms.atom, netstate, num); - - calcLayer(); - - if (frame) - frame->adjustState(); -} - -void Client::changeAllowedActions(void) -{ - Atom actions[9]; - int num = 0; - - actions[num++] = otk::Property::atoms.net_wm_action_change_desktop; - - if (_functions & Func_Shade) - actions[num++] = otk::Property::atoms.net_wm_action_shade; - if (_functions & Func_Close) - actions[num++] = otk::Property::atoms.net_wm_action_close; - if (_functions & Func_Move) - actions[num++] = otk::Property::atoms.net_wm_action_move; - if (_functions & Func_Iconify) - actions[num++] = otk::Property::atoms.net_wm_action_minimize; - if (_functions & Func_Resize) - actions[num++] = otk::Property::atoms.net_wm_action_resize; - if (_functions & Func_Fullscreen) - actions[num++] = otk::Property::atoms.net_wm_action_fullscreen; - if (_functions & Func_Maximize) { - actions[num++] = otk::Property::atoms.net_wm_action_maximize_horz; - actions[num++] = otk::Property::atoms.net_wm_action_maximize_vert; - } - - otk::Property::set(_window, otk::Property::atoms.net_wm_allowed_actions, - otk::Property::atoms.atom, actions, num); - - // make sure the window isn't breaking any rules now - - if (!(_functions & Func_Shade) && _shaded) - if (frame) shade(false); - else _shaded = false; - if (!(_functions & Func_Iconify) && _iconic) - if (frame) setDesktop(openbox->screen(_screen)->desktop()); - else _iconic = false; - if (!(_functions & Func_Fullscreen) && _fullscreen) - if (frame) fullscreen(false); - else _fullscreen = false; - if (!(_functions & Func_Maximize) && (_max_horz || _max_vert)) - if (frame) maximize(false, 0); - else _max_vert = _max_horz = false; -} - -void Client::remaximize() -{ - int dir; - if (_max_horz && _max_vert) - dir = 0; - else if (_max_horz) - dir = 1; - else if (_max_vert) - dir = 2; - else - return; // not maximized - _max_horz = _max_vert = false; - maximize(true, dir, false); -} - -void Client::applyStartupState() -{ - // these are in a carefully crafted order.. - - if (_iconic) { - _iconic = false; - iconify(true); - } - if (_fullscreen) { - _fullscreen = false; - fullscreen(true, false); - } - if (_shaded) { - _shaded = false; - shade(true); - } - if (_urgent) - fireUrgent(); - - if (_max_vert && _max_horz) { - _max_vert = _max_horz = false; - maximize(true, 0, false); - } else if (_max_vert) { - _max_vert = false; - maximize(true, 2, false); - } else if (_max_horz) { - _max_horz = false; - maximize(true, 1, false); - } - - if (_skip_taskbar); // nothing to do for this - if (_skip_pager); // nothing to do for this - if (_modal); // nothing to do for this - if (_above); // nothing to do for this - if (_below); // nothing to do for this -} - -void Client::fireUrgent() -{ - // call the python UrgentWindow callbacks - EventData data(_screen, this, EventAction::UrgentWindow, 0); - openbox->bindings()->fireEvent(&data); -} - -void Client::shade(bool shade) -{ - if (!(_functions & Func_Shade) || // can't - _shaded == shade) return; // already done - - // when we're iconic, don't change the wmstate - if (!_iconic) - _wmstate = shade ? IconicState : NormalState; - _shaded = shade; - changeState(); - frame->adjustSize(); -} - -void Client::maximize(bool max, int dir, bool savearea) -{ - assert(dir == 0 || dir == 1 || dir == 2); - if (!(_functions & Func_Maximize)) return; // can't - - // check if already done - if (max) { - if (dir == 0 && _max_horz && _max_vert) return; - if (dir == 1 && _max_horz) return; - if (dir == 2 && _max_vert) return; - } else { - if (dir == 0 && !_max_horz && !_max_vert) return; - if (dir == 1 && !_max_horz) return; - if (dir == 2 && !_max_vert) return; - } - - const otk::Rect &a = openbox->screen(_screen)->area(_desktop); - int x = frame->area().x(), y = frame->area().y(), - w = _area.width(), h = _area.height(); - - if (max) { - if (savearea) { - long dimensions[4]; - long *readdim; - unsigned long n = 4; - - dimensions[0] = x; - dimensions[1] = y; - dimensions[2] = w; - dimensions[3] = h; - - // get the property off the window and use it for the dimentions we are - // already maxed on - if (otk::Property::get(_window, otk::Property::atoms.openbox_premax, - otk::Property::atoms.cardinal, &n, - (long unsigned**) &readdim)) { - if (n == 4) { - if (_max_horz) { - dimensions[0] = readdim[0]; - dimensions[2] = readdim[2]; - } - if (_max_vert) { - dimensions[1] = readdim[1]; - dimensions[3] = readdim[3]; - } - } - delete readdim; - } - - otk::Property::set(_window, otk::Property::atoms.openbox_premax, - otk::Property::atoms.cardinal, - (long unsigned*)dimensions, 4); - } - if (dir == 0 || dir == 1) { // horz - x = a.x(); - w = a.width(); - } - if (dir == 0 || dir == 2) { // vert - y = a.y(); - h = a.height() - frame->size().top - frame->size().bottom; - } - } else { - long *dimensions; - long unsigned n = 4; - - if (otk::Property::get(_window, otk::Property::atoms.openbox_premax, - otk::Property::atoms.cardinal, &n, - (long unsigned**) &dimensions)) { - if (n == 4) { - if (dir == 0 || dir == 1) { // horz - x = (signed int)dimensions[0]; - w = (signed int)dimensions[2]; - } - if (dir == 0 || dir == 2) { // vert - y = (signed int)dimensions[1]; - h = (signed int)dimensions[3]; - } - } - delete dimensions; - } else { - // pick some fallbacks... - if (dir == 0 || dir == 1) { // horz - x = a.x() + a.width() / 4; - w = a.width() / 2; - } - if (dir == 0 || dir == 2) { // vert - y = a.y() + a.height() / 4; - h = a.height() / 2; - } - } - } - - if (dir == 0 || dir == 1) // horz - _max_horz = max; - if (dir == 0 || dir == 2) // vert - _max_vert = max; - - if (!_max_horz && !_max_vert) - otk::Property::erase(_window, otk::Property::atoms.openbox_premax); - - changeState(); // change the state hints on the client - - frame->frameGravity(x, y); // figure out where the client should be going - internal_resize(TopLeft, w, h, true, x, y); -} - -void Client::fullscreen(bool fs, bool savearea) -{ - static FunctionFlags saved_func; - static DecorationFlags saved_decor; - - if (!(_functions & Func_Fullscreen) || // can't - _fullscreen == fs) return; // already done - - _fullscreen = fs; - changeState(); // change the state hints on the client - - int x = _area.x(), y = _area.y(), w = _area.width(), h = _area.height(); - - if (fs) { - // save the functions and remove them - saved_func = _functions; - _functions = _functions & (Func_Close | Func_Fullscreen | Func_Iconify); - // save the decorations and remove them - saved_decor = _decorations; - _decorations = 0; - if (savearea) { - long dimensions[4]; - dimensions[0] = _area.x(); - dimensions[1] = _area.y(); - dimensions[2] = _area.width(); - dimensions[3] = _area.height(); - otk::Property::set(_window, otk::Property::atoms.openbox_premax, - otk::Property::atoms.cardinal, - (long unsigned*)dimensions, 4); - } - const otk::ScreenInfo *info = otk::display->screenInfo(_screen); - x = 0; - y = 0; - w = info->size().width(); - h = info->size().height(); - } else { - _functions = saved_func; - _decorations = saved_decor; - - long *dimensions; - long unsigned n = 4; - - if (otk::Property::get(_window, otk::Property::atoms.openbox_premax, - otk::Property::atoms.cardinal, &n, - (long unsigned**) &dimensions)) { - if (n == 4) { - x = dimensions[0]; - y = dimensions[1]; - w = dimensions[2]; - h = dimensions[3]; - } - delete dimensions; - } else { - // pick some fallbacks... - const otk::Rect &a = openbox->screen(_screen)->area(_desktop); - x = a.x() + a.width() / 4; - y = a.y() + a.height() / 4; - w = a.width() / 2; - h = a.height() / 2; - } - } - - changeAllowedActions(); // based on the new _functions - - // when fullscreening, don't obey things like increments, fill the screen - internal_resize(TopLeft, w, h, !fs, x, y); - - // raise (back) into our stacking layer - openbox->screen(_screen)->raiseWindow(this); - - // try focus us when we go into fullscreen mode - if (fs) focus(); -} - -void Client::iconify(bool iconic, bool curdesk) -{ - if (_iconic == iconic) return; // nothing to do - -#ifdef DEBUG - printf("%sconifying window: 0x%lx\n", (iconic ? "I" : "Uni"), _window); -#endif - - _iconic = iconic; - - if (_iconic) { - _wmstate = IconicState; - ignore_unmaps++; - // we unmap the client itself so that we can get MapRequest events, and - // because the ICCCM tells us to! - XUnmapWindow(**otk::display, _window); - } else { - if (curdesk) - setDesktop(openbox->screen(_screen)->desktop()); - _wmstate = NormalState; - XMapWindow(**otk::display, _window); - } - changeState(); - showhide(); - openbox->screen(_screen)->updateStruts(); -} - -void Client::disableDecorations(DecorationFlags flags) -{ - _disabled_decorations = flags; - setupDecorAndFunctions(); -} - -void Client::installColormap(bool install) const -{ - XWindowAttributes wa; - if (XGetWindowAttributes(**otk::display, _window, &wa)) { - if (install) - XInstallColormap(**otk::display, wa.colormap); - else - XUninstallColormap(**otk::display, wa.colormap); - } -} - -Client *Client::searchModalTree(Client *node, Client *skip) -{ - List::const_iterator it, end = node->_transients.end(); - Client *ret; - - for (it = node->_transients.begin(); it != end; ++it) { - if (*it == skip) continue; // circular? - if ((ret = searchModalTree(*it, skip))) return ret; // got one - if ((*it)->_modal) return *it; // got one - } - return 0; -} - -Client *Client::findModalChild() -{ - return searchModalTree(this, this); -} - - -bool Client::focus() -{ - // if we have a modal child, then focus it, not us - Client *c = findModalChild(); - if (c) return c->focus(); - - // won't try focus if the client doesn't want it, or if the window isn't - // visible on the screen - if (!(frame->visible() && (_can_focus || _focus_notify))) return false; - - // do a check to see if the window has already been unmapped or destroyed - // do this intelligently while watching out for unmaps we've generated - // (ignore_unmaps > 0) - XEvent ev; - if (XCheckTypedWindowEvent(**otk::display, _window, DestroyNotify, &ev)) { - XPutBackEvent(**otk::display, &ev); - return false; - } - while (XCheckTypedWindowEvent(**otk::display, _window, UnmapNotify, &ev)) { - if (ignore_unmaps) { - unmapHandler(ev.xunmap); - } else { - XPutBackEvent(**otk::display, &ev); - return false; - } - } - - if (_can_focus) - XSetInputFocus(**otk::display, _window, - RevertToNone, CurrentTime); - - if (_focus_notify) { - XEvent ce; - ce.xclient.type = ClientMessage; - ce.xclient.message_type = otk::Property::atoms.wm_protocols; - ce.xclient.display = **otk::display; - ce.xclient.window = _window; - ce.xclient.format = 32; - ce.xclient.data.l[0] = otk::Property::atoms.wm_take_focus; - ce.xclient.data.l[1] = openbox->lastTime(); - ce.xclient.data.l[2] = 0l; - ce.xclient.data.l[3] = 0l; - ce.xclient.data.l[4] = 0l; - XSendEvent(**otk::display, _window, False, NoEventMask, &ce); - } - - XSync(**otk::display, False); - return true; -} - - -void Client::unfocus() const -{ - assert(openbox->focusedClient() == this); - openbox->setFocusedClient(0); -} - - -void Client::focusHandler(const XFocusChangeEvent &e) -{ -#ifdef DEBUG -// printf("FocusIn for 0x%lx\n", e.window); -#endif // DEBUG - - otk::EventHandler::focusHandler(e); - - _focused = true; - frame->adjustFocus(); - - calcLayer(); // focus state can affect the stacking layer - - openbox->setFocusedClient(this); -} - - -void Client::unfocusHandler(const XFocusChangeEvent &e) -{ -#ifdef DEBUG -// printf("FocusOut for 0x%lx\n", e.window); -#endif // DEBUG - - otk::EventHandler::unfocusHandler(e); - - _focused = false; - frame->adjustFocus(); - - calcLayer(); // focus state can affect the stacking layer - - if (openbox->focusedClient() == this) - openbox->setFocusedClient(0); -} - - -void Client::configureRequestHandler(const XConfigureRequestEvent &ec) -{ -#ifdef DEBUG - printf("ConfigureRequest for 0x%lx\n", ec.window); -#endif // DEBUG - - otk::EventHandler::configureRequestHandler(ec); - - // compress these - XConfigureRequestEvent e = ec; - XEvent ev; - while (XCheckTypedWindowEvent(**otk::display, window(), ConfigureRequest, - &ev)) { - // XXX if this causes bad things.. we can compress config req's with the - // same mask. - e.value_mask |= ev.xconfigurerequest.value_mask; - if (ev.xconfigurerequest.value_mask & CWX) - e.x = ev.xconfigurerequest.x; - if (ev.xconfigurerequest.value_mask & CWY) - e.y = ev.xconfigurerequest.y; - if (ev.xconfigurerequest.value_mask & CWWidth) - e.width = ev.xconfigurerequest.width; - if (ev.xconfigurerequest.value_mask & CWHeight) - e.height = ev.xconfigurerequest.height; - if (ev.xconfigurerequest.value_mask & CWBorderWidth) - e.border_width = ev.xconfigurerequest.border_width; - if (ev.xconfigurerequest.value_mask & CWStackMode) - e.detail = ev.xconfigurerequest.detail; - } - - // if we are iconic (or shaded (fvwm does this)) ignore the event - if (_iconic || _shaded) return; - - if (e.value_mask & CWBorderWidth) - _border_width = e.border_width; - - // resize, then move, as specified in the EWMH section 7.7 - if (e.value_mask & (CWWidth | CWHeight)) { - int w = (e.value_mask & CWWidth) ? e.width : _area.width(); - int h = (e.value_mask & CWHeight) ? e.height : _area.height(); - - Corner corner; - switch (_gravity) { - case NorthEastGravity: - case EastGravity: - corner = TopRight; - break; - case SouthWestGravity: - case SouthGravity: - corner = BottomLeft; - break; - case SouthEastGravity: - corner = BottomRight; - break; - default: // NorthWest, Static, etc - corner = TopLeft; - } - - // if moving AND resizing ... - if (e.value_mask & (CWX | CWY)) { - int x = (e.value_mask & CWX) ? e.x : _area.x(); - int y = (e.value_mask & CWY) ? e.y : _area.y(); - internal_resize(corner, w, h, false, x, y); - } else // if JUST resizing... - internal_resize(corner, w, h, false); - } else if (e.value_mask & (CWX | CWY)) { // if JUST moving... - int x = (e.value_mask & CWX) ? e.x : _area.x(); - int y = (e.value_mask & CWY) ? e.y : _area.y(); - internal_move(x, y); - } - - if (e.value_mask & CWStackMode) { - switch (e.detail) { - case Below: - case BottomIf: - openbox->screen(_screen)->lowerWindow(this); - break; - - case Above: - case TopIf: - default: - openbox->screen(_screen)->raiseWindow(this); - break; - } - } -} - - -void Client::unmapHandler(const XUnmapEvent &e) -{ - if (ignore_unmaps) { -#ifdef DEBUG -// printf("Ignored UnmapNotify for 0x%lx (event 0x%lx)\n", e.window, e.event); -#endif // DEBUG - ignore_unmaps--; - return; - } - -#ifdef DEBUG - printf("UnmapNotify for 0x%lx\n", e.window); -#endif // DEBUG - - otk::EventHandler::unmapHandler(e); - - // this deletes us etc - openbox->screen(_screen)->unmanageWindow(this); -} - - -void Client::destroyHandler(const XDestroyWindowEvent &e) -{ -#ifdef DEBUG - printf("DestroyNotify for 0x%lx\n", e.window); -#endif // DEBUG - - otk::EventHandler::destroyHandler(e); - - // this deletes us etc - openbox->screen(_screen)->unmanageWindow(this); -} - - -void Client::reparentHandler(const XReparentEvent &e) -{ - // this is when the client is first taken captive in the frame - if (e.parent == frame->plate()) return; - -#ifdef DEBUG - printf("ReparentNotify for 0x%lx\n", e.window); -#endif // DEBUG - - otk::EventHandler::reparentHandler(e); - - /* - This event is quite rare and is usually handled in unmapHandler. - 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. - */ - - // we don't want the reparent event, put it back on the stack for the X - // server to deal with after we unmanage the window - XEvent ev; - ev.xreparent = e; - XPutBackEvent(**otk::display, &ev); - - // this deletes us etc - openbox->screen(_screen)->unmanageWindow(this); -} - -void Client::mapRequestHandler(const XMapRequestEvent &e) -{ -#ifdef DEBUG - printf("MapRequest for already managed 0x%lx\n", e.window); -#endif // DEBUG - - assert(_iconic); // we shouldn't be able to get this unless we're iconic - - // move to the current desktop (uniconify) - iconify(false); - // XXX: should we focus/raise the window? (basically a net_wm_active_window) -} - -}
D src/client.hh

@@ -1,759 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __client_hh -#define __client_hh - -/*! @file client.hh - @brief The Client class maintains the state of a client window by handling - property changes on the window and some client messages -*/ - -#include "screen.hh" -#include "otk/strut.hh" -#include "otk/rect.hh" -#include "otk/eventhandler.hh" -#include "otk/ustring.hh" - -extern "C" { -#include <X11/Xlib.h> - -#ifdef SHAPE -#include <X11/extensions/shape.h> -#endif // SHAPE -} - -#include <string> -#include <list> - -namespace ob { - -class Frame; -class Screen; - -struct Icon { - unsigned long w, h; - unsigned long *data; -}; - -//! The MWM Hints as retrieved from the window property -/*! - This structure only contains 3 elements, even though the Motif 2.0 - structure contains 5. We only use the first 3, so that is all gets defined. -*/ -struct MwmHints { - unsigned long flags; //!< A bitmask of Client::MwmFlags values - unsigned long functions; //!< A bitmask of Client::MwmFunctions values - unsigned long decorations;//!< A bitmask of Client::MwmDecorations values - //! The number of elements in the Client::MwmHints struct - static const unsigned int elements = 3; -}; - -//! Maintains the state of a client window. -/*! - Client maintains the state of a client window. The state consists of the - hints that the application sets on the window, such as the title, or window - gravity. - <p> - Client also manages client messages for the client window. When the - application (or any application) requests something to be changed for the - client, it will call the ActionHandler (for client messages) or update the - class' member variables and call whatever is nessary to complete the - change (such as causing a redraw of the titlebar after the title is changed). -*/ -class Client : public otk::EventHandler { -public: - - //! The frame window which decorates around the client window - /*! - NOTE: This should NEVER be used inside the client class's constructor! - */ - Frame *frame; - - //! Holds a list of Clients - typedef std::list<Client*> List; - - //! The possible stacking layers a client window can be a part of - enum StackLayer { - Layer_Icon, //!< 0 - iconified windows, in any order at all - Layer_Desktop, //!< 1 - desktop windows - Layer_Below, //!< 2 - normal windows w/ below - Layer_Normal, //!< 3 - normal windows - Layer_Above, //!< 4 - normal windows w/ above - Layer_Top, //!< 5 - always-on-top-windows (docks?) - Layer_Fullscreen, //!< 6 - fullscreeen windows - Layer_Internal, //!< 7 - openbox windows/menus - NUM_LAYERS - }; - - //! Corners of the client window, used for anchor positions - enum Corner { TopLeft, - TopRight, - BottomLeft, - BottomRight }; - - //! Possible window types - enum WindowType { Type_Desktop, //!< A desktop (bottom-most window) - Type_Dock, //!< A dock bar/panel window - Type_Toolbar, //!< A toolbar window, pulled off an app - Type_Menu, //!< An unpinned menu from an app - Type_Utility, //!< A small utility window such as a palette - Type_Splash, //!< A splash screen window - Type_Dialog, //!< A dialog window - Type_Normal //!< A normal application window - }; - - //! Possible flags for MWM Hints (defined by Motif 2.0) - enum MwmFlags { MwmFlag_Functions = 1 << 0, //!< The MMW Hints define funcs - MwmFlag_Decorations = 1 << 1 //!< The MWM Hints define decor - }; - - //! Possible functions for MWM Hints (defined by Motif 2.0) - enum MwmFunctions { MwmFunc_All = 1 << 0, //!< All functions - MwmFunc_Resize = 1 << 1, //!< Allow resizing - MwmFunc_Move = 1 << 2, //!< Allow moving - MwmFunc_Iconify = 1 << 3, //!< Allow to be iconfied - MwmFunc_Maximize = 1 << 4 //!< Allow to be maximized - //MwmFunc_Close = 1 << 5 //!< Allow to be closed - }; - - //! Possible decorations for MWM Hints (defined by Motif 2.0) - enum MemDecorations { MwmDecor_All = 1 << 0, //!< All decorations - MwmDecor_Border = 1 << 1, //!< Show a border - MwmDecor_Handle = 1 << 2, //!< Show a handle (bottom) - MwmDecor_Title = 1 << 3, //!< Show a titlebar - //MwmDecor_Menu = 1 << 4, //!< Show a menu - MwmDecor_Iconify = 1 << 5, //!< Show an iconify button - MwmDecor_Maximize = 1 << 6 //!< Show a maximize button - }; - - //! The things the user can do to the client window - enum Function { Func_Resize = 1 << 0, //!< Allow resizing - Func_Move = 1 << 1, //!< Allow moving - Func_Iconify = 1 << 2, //!< Allow to be iconified - Func_Maximize = 1 << 3, //!< Allow to be maximized - Func_Shade = 1 << 4, //!< Allow to be shaded - Func_Fullscreen = 1 << 5, //!< Allow to be made fullscreen - Func_Close = 1 << 6 //!< Allow to be closed - }; - //! Holds a bitmask of Client::Function values - typedef unsigned char FunctionFlags; - - //! The decorations the client window wants to be displayed on it - enum Decoration { Decor_Titlebar = 1 << 0, //!< Display a titlebar - Decor_Handle = 1 << 1, //!< Display a handle (bottom) - Decor_Border = 1 << 2, //!< Display a border - Decor_Icon = 1 << 3, //!< Display the window's icon - Decor_Iconify = 1 << 4, //!< Display an iconify button - Decor_Maximize = 1 << 5, //!< Display a maximize button - //! Display a button to toggle the window's placement on - //! all desktops - Decor_AllDesktops = 1 << 6, - Decor_Close = 1 << 7 //!< Display a close button - }; - //! Holds a bitmask of Client::Decoration values - typedef unsigned char DecorationFlags; - - //! The event mask to grab on client windows - static const long event_mask = PropertyChangeMask | FocusChangeMask | - StructureNotifyMask; - - //! The mask of events to not let propogate past the client - /*! - This makes things like xprop work on the client window, but means we have - to explicitly grab clicks that we want. - */ - static const long no_propagate_mask = ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask; - - //! The number of unmap events to ignore on the window - int ignore_unmaps; - -private: - //! The screen number on which the client resides - int _screen; - - //! The actual window that this class is wrapping up - Window _window; - - //! The id of the group the window belongs to - Window _group; - - //! The client which this client is a transient (child) for - Client *_transient_for; - - //! The clients which are transients (children) of this client - Client::List _transients; - - //! The desktop on which the window resides (0xffffffff for all desktops) - unsigned int _desktop; - - //! Normal window title - otk::ustring _title; - //! Window title when iconifiged - otk::ustring _icon_title; - - //! The application that created the window - std::string _app_name; - //! The class of the window, can used for grouping - std::string _app_class; - //! The specified role of the window, used for identification - std::string _role; - - //! The type of window (what its function is) - WindowType _type; - - //! Position and size of the window - /*! - This will not always be the actual position of the window on screen, it is - rather, the position requested by the client, to which the window's gravity - is applied. - */ - otk::Rect _area; - - //! The window's strut - /*! - The strut defines areas of the screen that are marked off-bounds for window - placement. In theory, where this window exists. - */ - otk::Strut _strut; - - //! The logical size of the window - /*! - The "logical" size of the window is refers to the user's perception of the - size of the window, and is the value that should be displayed to the user. - For example, with xterms, this value it the number of characters being - displayed in the terminal, instead of the number of pixels. - */ - otk::Size _logical_size; - - //! Width of the border on the window. - /*! - The window manager will set this to 0 while the window is being managed, - but needs to restore it afterwards, so it is saved here. - */ - int _border_width; - - //! The minimum aspect ratio the client window can be sized to. - /*! - A value of 0 means this is ignored. - */ - float _min_ratio; - //! The maximum aspect ratio the client window can be sized to. - /*! - A value of 0 means this is ignored. - */ - float _max_ratio; - - //! The minimum size of the client window - /*! - If the min is > the max, then the window is not resizable - */ - otk::Size _min_size; - //! The maximum size of the client window - /*! - If the min is > the max, then the window is not resizable - */ - otk::Size _max_size; - //! The size of increments to resize the client window by - otk::Size _size_inc; - //! The base size of the client window - /*! - This value should be subtracted from the window's actual size when - displaying its size to the user, or working with its min/max size - */ - otk::Size _base_size; - - //! Window decoration and functionality hints - MwmHints _mwmhints; - - //! Where to place the decorated window in relation to the undecorated window - int _gravity; - - //! The state of the window, one of WithdrawnState, IconicState, or - //! NormalState - long _wmstate; - - //! True if the client supports the delete_window protocol - bool _delete_window; - - //! Was the window's position requested by the application? if not, we should - //! place the window ourselves when it first appears - bool _positioned; - - //! Can the window receive input focus? - bool _can_focus; - //! Urgency flag - bool _urgent; - //! Notify the window when it receives focus? - bool _focus_notify; - //! Does the client window have the input focus? - bool _focused; - - //! The window uses shape extension to be non-rectangular? - bool _shaped; - - //! The window is modal, so it must be processed before any windows it is - //! related to can be focused - bool _modal; - //! Only the window's titlebar is displayed - bool _shaded; - //! The window is iconified - bool _iconic; - //! The window is maximized to fill the screen vertically - bool _max_vert; - //! The window is maximized to fill the screen horizontally - bool _max_horz; - //! The window should not be displayed by pagers - bool _skip_pager; - //! The window should not be displayed by taskbars - bool _skip_taskbar; - //! The window is a 'fullscreen' window, and should be on top of all others - bool _fullscreen; - //! The window should be on top of other windows of the same type - bool _above; - //! The window should be underneath other windows of the same type - bool _below; - - //! The layer in which the window will be stacked, windows in lower layers - //! are always below windows in higher layers. - StackLayer _layer; - - //! A bitmask of values in the Client::Decoration enum - /*! - The values in the variable are the decorations that the client wants to be - displayed around it. - */ - DecorationFlags _decorations; - - //! A bitmask of values in the Client::Decoration enum. - /*! - Specifies the decorations that should NOT be displayed on the client. - */ - DecorationFlags _disabled_decorations; - - //! A bitmask of values in the Client::Function enum - /*! - The values in the variable specify the ways in which the user is allowed to - modify this window. - */ - FunctionFlags _functions; - - //! Icons for the client as specified on the client window - Icon *_icons; - //! The number of icons in _icons - int _nicons; - - Pixmap _pixmap_icon; - Pixmap _pixmap_icon_mask; - - //! Retrieves the window's initial gravity - void getGravity(); - //! Retrieves the desktop hint's value and sets Client::_desktop - void getDesktop(); - //! Retrieves the window's type and sets Client::_type - void getType(); - //! Gets the MWM Hints and adjusts Client::_functions and - //! Client::_decorations - void getMwmHints(); - //! Gets the position and size of the window and sets Client::_area - void getArea(); - //! Gets the net_state hint and sets the boolean flags for any states set in - //! the hint - void getState(); - //! Determines if the window uses the Shape extension and sets - //! Client::_shaped - void getShaped(); - - //! Set up what decor should be shown on the window and what functions should - //! be allowed (Client::_decorations and Client::_functions). - /*! - This also updates the NET_WM_ALLOWED_ACTIONS hint. - */ - void setupDecorAndFunctions(); - - //! Sets the wm_state to the specified value - void setWMState(long state); - //! Adjusts the window's net_state - /*! - This should not be called as part of the window mapping process! It is for - use when updating the state post-mapping.<br> - Client::applyStartupState is used to do the same things during the mapping - process. - */ - void setState(Atom action, long data1, long data2); - - //! Sends the window to the specified desktop - void setDesktop(unsigned int desktop); - - //! Calculates the stacking layer for the client window - void calcLayer(); - - //! Update the protocols that the window supports and adjusts things if they - //! change - void updateProtocols(); - //! Updates the WMNormalHints and adjusts things if they change - void updateNormalHints(); - //! Updates the WMHints and adjusts things if they change - /*! - @param initstate Whether to read the initial_state property from the - WMHints. This should only be used during the mapping - process. - */ - void updateWMHints(bool initstate = false); - //! Updates the window's title - void updateTitle(); - //! Updates the window's icon title - void updateIconTitle(); - //! Updates the window's application name and class - void updateClass(); - //! Updates the strut for the client - void updateStrut(); - //! Updates the window's transient status, and any parents of it - void updateTransientFor(); - //! Updates the window's icons - void updateIcons(); - //! Updates the window's kwm icon - void updateKwmIcon(); - - //! Change the client's state hints to match the class' data - void changeState(); - //! Change the allowed actions set on the client - void changeAllowedActions(); - - //! Request the client to close its window. - void close(); - - //! Shades or unshades the client window - /*! - @param shade true if the window should be shaded; false if it should be - unshaded. - */ - void shade(bool shade); - - //! Recursively searches the client 'tree' for a modal client, always skips - //! the topmost node (the window you're starting with). - Client *Client::searchModalTree(Client *node, Client *skip); - - //! Recursively searches the client 'tree' for a focused client, always skips - //! the topmost node (the window you're starting with). - Client *Client::searchFocusTree(Client *node, Client *skip); - - //! Fires the urgent callbacks which lets the user do what they want with - //! urgent windows - void fireUrgent(); - - //! Fullscreen's or unfullscreen's the client window - /*! - @param fs true if the window should be made fullscreen; false if it should - be returned to normal state. - @param savearea true to have the client's current size and position saved; - otherwise, they are not. You should not save when mapping a - new window that is set to fullscreen. This has no effect - when restoring a window from fullscreen. - */ - void fullscreen(bool fs, bool savearea = true); - - //! Iconifies or uniconifies the client window - /*! - @param iconic true if the window should be iconified; false if it should be - restored. - @param curdesk If iconic is false, then this determines if the window will - be uniconified to the current viewable desktop (true) or to - its previous desktop (false) - */ - void iconify(bool iconic, bool curdesk = true); - - //! Maximize or unmaximize the client window - /*! - @param max true if the window should be maximized; false if it should be - returned to normal size. - @param dir 0 to set both horz and vert, 1 to set horz, 2 to set vert. - @param savearea true to have the client's current size and position saved; - otherwise, they are not. You should not save when mapping a - new window that is set to fullscreen. This has no effect - when unmaximizing a window. - */ - void maximize(bool max, int dir, bool savearea = true); - - //! Internal version of the Client::move function - /*! - @param x The X coordinate to move to. - @param y The Y coordinate to move to. - @param final true if this is the final move, false if there are more move - events coming. The client is not notified of the move when - final is false. - */ - void internal_move(int x, int y, bool final = true); - //! Internal version of the Client::resize function - /*! - This also maintains things like the client's minsize, and size increments. - @param anchor The corner to keep in the same position when resizing. - @param w The width component of the new size for the client. - @param h The height component of the new size for the client. - @param user Specifies whether this is a user-requested change or a - program requested change. - @param x An optional X coordinate to which the window will be moved - after resizing. - @param y An optional Y coordinate to which the window will be moved - after resizing. - The x and y coordinates must both be sepcified together, or they will have - no effect. When they are specified, the anchor is ignored. - */ - void internal_resize(Corner anchor, int w, int h, - bool user = true, int x = INT_MIN, int y = INT_MIN); - - //! Removes or reapplies the client's border to its window - /*! - Used when managing and unmanaging a window. - @param addborder true if adding the border to the client; false if removing - from the client - */ - void toggleClientBorder(bool addborder); - - //! Applies the states requested when the window mapped - /*! - This should be called only once, during the window mapping process. It - applies things like maximized, and fullscreen. - */ - void applyStartupState(); - -public: - //! Constructs a new Client object around a specified window id - /*! - @param window The window id that the Client class should handle - @param screen The screen on which the window resides - */ - Client(int screen, Window window); - //! Destroys the Client object - virtual ~Client(); - - //! Returns the screen on which the clien resides - inline int screen() const { return _screen; } - - //! Returns the window id that the Client object is handling - inline Window window() const { return _window; } - - //! Returns the type of the window, one of the Client::WindowType values - inline WindowType type() const { return _type; } - //! Returns if the window should be treated as a normal window. - /*! - Some windows (desktops, docks, splash screens) have special rules applied - to them in a number of places regarding focus or user interaction. - */ - inline bool normal() const { - return ! (_type == Type_Desktop || _type == Type_Dock || - _type == Type_Splash); - } - - //! Returns the desktop on which the window resides - /*! - This value is a 0-based index.<br> - A value of 0xffffffff indicates that the window exists on all desktops. - */ - inline unsigned int desktop() const { return _desktop; } - //! Returns the window's title - inline const otk::ustring &title() const { return _title; } - //! Returns the window's title when it is iconified - inline const otk::ustring &iconTitle() const { return _title; } - //! Returns the application's name to whom the window belongs - inline const std::string &appName() const { return _app_name; } - //! Returns the class of the window - inline const std::string &appClass() const { return _app_class; } - //! Returns the program-specified role of the window - inline const std::string &role() const { return _role; } - //! Returns if the window can be focused - /*! - @return true if the window can receive focus; otherwise, false - */ - inline bool canFocus() const { return _can_focus; } - //! Returns if the window has indicated that it needs urgent attention - inline bool urgent() const { return _urgent; } - //! Returns if the window wants to be notified when it receives focus - inline bool focusNotify() const { return _focus_notify; } - //! Returns if the window is the focused window - inline bool focused() const { return _focused; } - //! Returns if the window uses the Shape extension - inline bool shaped() const { return _shaped; } - //! Returns the window's gravity - /*! - This value determines where to place the decorated window in relation to - its position without decorations.<br> - One of: NorthWestGravity, SouthWestGravity, EastGravity, ..., - SouthGravity, StaticGravity, ForgetGravity - */ - inline int gravity() const { return _gravity; } - //! Returns if the application requested the initial position for the window - /*! - If the application did not request a position (this function returns false) - then the window should be placed intelligently by the window manager - initially - */ - inline bool positionRequested() const { return _positioned; } - //! Returns the decorations that the client window wishes to be displayed on - //! it - inline DecorationFlags decorations() const { return _decorations; } - //! Returns the decorations that the user has requested to be disabled on the - //! client - inline DecorationFlags disabledDecorations() const - { return _disabled_decorations; } - //! Returns the functions that the user can perform on the window - inline FunctionFlags functions() const { return _functions; } - - //! Return the client this window is transient for - inline Client *transientFor() const { return _transient_for; } - - //! Returns if the window is modal - /*! - If the window is modal, then no other windows that it is related to can get - focus while it exists/remains modal. - */ - inline bool modal() const { return _modal; } - //! The window should not be displayed by pagers - inline bool skipPager() const { return _skip_pager; } - //! The window should not be displayed by taskbars - inline bool skipTaskbar() const { return _skip_taskbar; } - //! Returns if the window is shaded - /*! - When the window is shaded, only its titlebar is visible. - */ - inline bool shaded() const { return _shaded; } - //! Returns if the window is in fullscreen mode - inline bool fullscreen() const { return _fullscreen; } - //! Returns if the window is iconified - /*! - When the window is iconified, it is not visible at all (except in iconbars/ - panels/etc that want to show lists of iconified windows - */ - inline bool iconic() const { return _iconic; } - //! Returns if the window is maximized vertically - inline bool maxVert() const { return _max_vert; } - //! Returns if the window is maximized horizontally - inline bool maxHorz() const { return _max_horz; } - //! Returns the window's stacking layer - inline StackLayer layer() const { return _layer; } - - //! Returns the logical size of the window - /*! - The "logical" size of the window is refers to the user's perception of the - size of the window, and is the value that should be displayed to the user. - For example, with xterms, this value it the number of characters being - displayed in the terminal, instead of the number of pixels. - */ - const otk::Size &logicalSize() const { return _logical_size; } - - //! Returns the position and size of the client relative to the root window - /*! - Note that this value is *not* the size and position of the window's - frame, though the position will often line up.<br> - If you want the frame's area, use Frame::area() instead. - */ - inline const otk::Rect &area() const { return _area; } - - //! Returns the client's strut definition - inline const otk::Strut &strut() const { return _strut; } - - //! Returns an icon for the window - /*! - The icon chosen will be the smallest icon available that is still bigger or - equal to the specified Size.<br> - If none that meet the requirements is found, the largest icon that is - smaller than the specified size will be returned. - */ - const Icon *icon(const otk::Size &s) const; - - //! Returns the pixmap for the pixmap icon specified on the window (or None) - /*! - The icon given by Client::icon should take precedence over this icon/mask. - */ - Pixmap pixmapIcon() const { return _pixmap_icon; } - //! Returns the mask for the pixmap icon specified on the window (or None) - /*! - The icon given by Client::icon should take precedence over this icon/mask. - */ - Pixmap pixmapIconMask() const { return _pixmap_icon_mask; } - - //! Move the window (actually, its frame) to a position. - /*! - This moves the window so that the top-left corner of its frame will be at - the position specified. - @param x The X coordinate to move to. - @param y The Y coordinate to move to. - @param final true if this is the final move, false if there are more move - events coming. The client is not notified of the move when - final is false. - */ - void move(int x, int y, bool final = true); - - //! Resizes the client window, anchoring it in a given corner - /*! - This also maintains things like the client's minsize, and size increments. - @param anchor The corner to keep in the same position when resizing. - @param w The width component of the new size for the client. - @param h The height component of the new size for the client. - */ - void resize(Corner anchor, int w, int h); - - //! Reapplies the maximized state to the window - /*! - Use this to make the window readjust its maximized size to new - surroundings (struts, etc). - */ - void remaximize(); - - //! Shows the window if it should be shown, or hides it - /*! - Used when changing desktops, the window's state, etc. - */ - void showhide(); - - //! Choose a mask of decorations to not display on the client - /*! - Pass a value of 0 to the function to turn all decorations back on. Note - that you cannot add decorations to a window with this, you can only remove - decorations that would otherwise have been displayed. - @param flags The mask of values from Client::Decoration to specify which - decorations should not be displayed. - */ - void disableDecorations(DecorationFlags flags); - - //! Return a modal child of the client window - /*! - @return A modal child of the client window, or 0 if none was found. - */ - Client *findModalChild(); - - //! Attempt to focus the client window - bool focus(); - - //! Remove focus from the client window - void unfocus() const; - - //! Validate client, by making sure no Destroy or Unmap events exist in - //! the event queue for the window. - /*! - @return true if the client is valid; false if the client has already - been unmapped/destroyed, and so is invalid. - */ - bool validate() const; - - void installColormap(bool install) const; - - virtual void focusHandler(const XFocusChangeEvent &e); - virtual void unfocusHandler(const XFocusChangeEvent &e); - virtual void propertyHandler(const XPropertyEvent &e); - virtual void clientMessageHandler(const XClientMessageEvent &e); - virtual void configureRequestHandler(const XConfigureRequestEvent &e); - virtual void unmapHandler(const XUnmapEvent &e); - virtual void destroyHandler(const XDestroyWindowEvent &e); - virtual void reparentHandler(const XReparentEvent &e); - virtual void mapRequestHandler(const XMapRequestEvent &e); -#if defined(SHAPE) - virtual void shapeHandler(const XShapeEvent &e); -#endif // SHAPE - - friend void Screen::manageWindow(Window); - friend void Screen::unmanageWindow(Client *); -}; - -} - -#endif // __client_hh
D src/config.cc

@@ -1,61 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -/* - python_get_stringlist("DESKTOP_NAMES", &desktop_names); - - python_get_string("THEME", &theme); - // initialize the screen's style - otk::RenderStyle::setStyle(_screen, theme); - // draw the root window - otk::bexec("obsetroot " + otk::RenderStyle::style(_screen)->rootArgs(), - info->displayString()); - - - if (!python_get_string("TITLEBAR_LAYOUT", &titlebar_layout)) { - fprintf(stderr, _("Unable to load config.%s\n"), "TITLEBAR_LAYOUT"); - ::exit(1); - } - - if (!python_get_long("DOUBLE_CLICK_DELAY", &double_click_delay)) { - fprintf(stderr, _("Unable to load config.%s\n"), "DOUBLE_CLICK_DELAY"); - ::exit(1); - } - if (!python_get_long("DRAG_THRESHOLD", &drag_threshold)) { - fprintf(stderr, _("Unable to load config.%s\n"), "DRAG_THRESHOLD"); - ::exit(1); - } - if (!python_get_long("NUMBER_OF_DESKTOPS", (long*)&num_desktops)) { - fprintf(stderr, _("Unable to load config.%s\n"), "NUMBER_OF_DESKTOPS"); - ::exit(1); - } - - // Set the net_desktop_names property - otk::Property::set(root, - otk::Property::atoms.net_desktop_names, - otk::Property::utf8, desktop_names); - // the above set() will cause screen::updateDesktopNames to fire right away - // so we have a list of desktop names - - XEvent ce; - ce.xclient.type = ClientMessage; - ce.xclient.message_type = otk::Property::atoms.net_number_of_desktops; - ce.xclient.display = **otk::display; - ce.xclient.window = root; - ce.xclient.format = 32; - ce.xclient.data.l[0] = num_desktops; - XSendEvent(**otk::display, root, False, - SubstructureNotifyMask | SubstructureRedirectMask, &ce); -} - -Config::Config(int screen) - : _screen(screen) -{ -} - -Config::~Config() -{ -} - -*/
D src/config.hh

@@ -1,14 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __config_hh -#define __config_hh - -/*! @file config.hh - @brief The Config class contains functions for accessing config variables - in the scripts. -*/ - -namespace ob { - -} - -#endif // __config_hh
D src/frame.cc

@@ -1,959 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -extern "C" { -#ifdef SHAPE -#include <X11/extensions/shape.h> -#endif // SHAPE -} - -#include "frame.hh" -#include "config.hh" -#include "openbox.hh" -#include "otk/display.hh" -#include "otk/surface.hh" - -#include <string> -#include <cassert> - -namespace ob { - -const long Frame::event_mask; - -Window createWindow(const otk::ScreenInfo *info, Window parent, - unsigned long mask, XSetWindowAttributes *attrib) -{ - return XCreateWindow(**otk::display, parent, 0, 0, 1, 1, 0, - info->depth(), InputOutput, info->visual(), - mask, attrib); - -} - -Frame::Frame(Client *client) - : _client(client), - _visible(false), - _plate(0), - _title(0), - _label(0), - _handle(0), - _lgrip(0), - _rgrip(0), - _max(0), - _desk(0), - _iconify(0), - _icon(0), - _close(0), - _frame_sur(0), - _title_sur(0), - _label_sur(0), - _handle_sur(0), - _grip_sur(0), - _max_sur(0), - _desk_sur(0), - _iconify_sur(0), - _icon_sur(0), - _close_sur(0), - _max_press(false), - _desk_press(false), - _iconify_press(false), - _icon_press(false), - _close_press(false), - _press_button(0) -{ - assert(client); - - XSetWindowAttributes attrib; - unsigned long mask; - const otk::ScreenInfo *info = otk::display->screenInfo(client->screen()); - - // create all of the decor windows (except title bar buttons) - mask = CWOverrideRedirect | CWEventMask; - attrib.event_mask = Frame::event_mask; - attrib.override_redirect = true; - _frame = createWindow(info, info->rootWindow(), mask, &attrib); - - mask = 0; - _plate = createWindow(info, _frame, mask, &attrib); - mask = CWEventMask; - attrib.event_mask = (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | - ExposureMask); - _title = createWindow(info, _frame, mask, &attrib); - _label = createWindow(info, _title, mask, &attrib); - _max = createWindow(info, _title, mask, &attrib); - _close = createWindow(info, _title, mask, &attrib); - _desk = createWindow(info, _title, mask, &attrib); - _icon = createWindow(info, _title, mask, &attrib); - _iconify = createWindow(info, _title, mask, &attrib); - _handle = createWindow(info, _frame, mask, &attrib); - mask |= CWCursor; - attrib.cursor = openbox->cursors().ll_angle; - _lgrip = createWindow(info, _handle, mask, &attrib); - attrib.cursor = openbox->cursors().lr_angle; - _rgrip = createWindow(info, _handle, mask, &attrib); - - // the other stuff is shown based on decor settings - XMapWindow(**otk::display, _plate); - XMapWindow(**otk::display, _lgrip); - XMapWindow(**otk::display, _rgrip); - XMapWindow(**otk::display, _label); - - applyStyle(*otk::RenderStyle::style(_client->screen())); - - _layout = "ITMC"; - python_get_string("titlebar_layout", &_layout); - - // register all of the windows with the event dispatcher - Window *w = allWindows(); - for (unsigned int i = 0; w[i]; ++i) - openbox->registerHandler(w[i], this); - delete [] w; -} - -Frame::~Frame() -{ - // unregister all of the windows with the event dispatcher - Window *w = allWindows(); - for (unsigned int i = 0; w[i]; ++i) - openbox->clearHandler(w[i]); - delete [] w; - - XDestroyWindow(**otk::display, _rgrip); - XDestroyWindow(**otk::display, _lgrip); - XDestroyWindow(**otk::display, _handle); - XDestroyWindow(**otk::display, _max); - XDestroyWindow(**otk::display, _icon); - XDestroyWindow(**otk::display, _iconify); - XDestroyWindow(**otk::display, _desk); - XDestroyWindow(**otk::display, _close); - XDestroyWindow(**otk::display, _label); - XDestroyWindow(**otk::display, _title); - XDestroyWindow(**otk::display, _frame); - - if (_frame_sur) delete _frame_sur; - if (_title_sur) delete _title_sur; - if (_label_sur) delete _label_sur; - if (_handle_sur) delete _handle_sur; - if (_grip_sur) delete _grip_sur; - if (_max_sur) delete _max_sur; - if (_desk_sur) delete _desk_sur; - if (_iconify_sur) delete _iconify_sur; - if (_icon_sur) delete _icon_sur; - if (_close_sur) delete _close_sur; -} - -void Frame::show() -{ - if (!_visible) { - _visible = true; - XMapWindow(**otk::display, _frame); - } -} - -void Frame::hide() -{ - if (_visible) { - _visible = false; - XUnmapWindow(**otk::display, _frame); - } -} - -void Frame::buttonPressHandler(const XButtonEvent &e) -{ - if (_press_button) return; - _press_button = e.button; - - if (e.window == _max) { - _max_press = true; - renderMax(); - } - if (e.window == _close) { - _close_press = true; - renderClose(); - } - if (e.window == _desk) { - _desk_press = true; - renderDesk(); - } - if (e.window == _iconify) { - _iconify_press = true; - renderIconify(); - } - if (e.window == _icon) { - _icon_press = true; - renderIcon(); - } -} - -void Frame::buttonReleaseHandler(const XButtonEvent &e) -{ - if (e.button != _press_button) return; - _press_button = 0; - - if (e.window == _max) { - _max_press = false; - renderMax(); - } - if (e.window == _close) { - _close_press = false; - renderClose(); - } - if (e.window == _desk) { - _desk_press = false; - renderDesk(); - } - if (e.window == _iconify) { - _iconify_press = false; - renderIconify(); - } - if (e.window == _icon) { - _icon_press = false; - renderIcon(); - } -} - -MouseContext::MC Frame::mouseContext(Window win) const -{ - if (win == _frame) return MouseContext::Frame; - if (win == _title || - win == _label) return MouseContext::Titlebar; - if (win == _handle) return MouseContext::Handle; - if (win == _plate) return MouseContext::Window; - if (win == _lgrip || - win == _rgrip) return MouseContext::Grip; - if (win == _max) return MouseContext::MaximizeButton; - if (win == _close) return MouseContext::CloseButton; - if (win == _desk) return MouseContext::AllDesktopsButton; - if (win == _iconify)return MouseContext::IconifyButton; - if (win == _icon) return MouseContext::IconButton; - return (MouseContext::MC) -1; -} - -Window *Frame::allWindows() const -{ - Window *w = new Window[12 + 1]; - unsigned int i = 0; - w[i++] = _frame; - w[i++] = _plate; - w[i++] = _title; - w[i++] = _label; - w[i++] = _handle; - w[i++] = _lgrip; - w[i++] = _rgrip; - w[i++] = _max; - w[i++] = _desk; - w[i++] = _close; - w[i++] = _icon; - w[i++] = _iconify; - w[i] = 0; - return w; -} - -void Frame::applyStyle(const otk::RenderStyle &style) -{ - // set static border colors - XSetWindowBorder(**otk::display, _frame, style.frameBorderColor()->pixel()); - XSetWindowBorder(**otk::display, _title, style.frameBorderColor()->pixel()); - XSetWindowBorder(**otk::display, _handle, style.frameBorderColor()->pixel()); - XSetWindowBorder(**otk::display, _lgrip, style.frameBorderColor()->pixel()); - XSetWindowBorder(**otk::display, _rgrip, style.frameBorderColor()->pixel()); - - // size all the fixed-size elements - geom.font_height = style.labelFont()->height(); - if (geom.font_height < 1) geom.font_height = 1; - geom.button_size = geom.font_height - 2; - if (geom.button_size < 1) geom.button_size = 1; - geom.handle_height = style.handleWidth(); - if (geom.handle_height < 1) geom.handle_height = 1; - geom.bevel = style.bevelWidth(); - - XResizeWindow(**otk::display, _lgrip, geom.grip_width(), geom.handle_height); - XResizeWindow(**otk::display, _rgrip, geom.grip_width(), geom.handle_height); - - XResizeWindow(**otk::display, _max, geom.button_size, geom.button_size); - XResizeWindow(**otk::display, _close, geom.button_size, geom.button_size); - XResizeWindow(**otk::display, _desk, geom.button_size, geom.button_size); - XResizeWindow(**otk::display, _iconify, geom.button_size, geom.button_size); - XResizeWindow(**otk::display, _icon, geom.button_size, geom.button_size); -} - -void Frame::styleChanged(const otk::RenderStyle &style) -{ - applyStyle(style); - - // size/position everything - adjustSize(); - adjustPosition(); -} - -void Frame::adjustFocus() -{ - // XXX optimizations later... - adjustSize(); -} - -void Frame::adjustTitle() -{ - // XXX optimizations later... - adjustSize(); -} - -static void render(int screen, const otk::Size &size, Window win, - otk::Surface **surface, - const otk::RenderTexture &texture, bool freedata=true) -{ - otk::Surface *s = new otk::Surface(screen, size); - if (texture.parentRelative()) - XSetWindowBackgroundPixmap(**otk::display, win, ParentRelative); - else { - otk::display->renderControl(screen)->drawBackground(*s, texture); - XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap()); - } - XClearWindow(**otk::display, win); - if (*surface) delete *surface; - if (freedata) s->freePixelData(); - *surface = s; -} - -void Frame::adjustSize() -{ - _decorations = _client->decorations(); - const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen()); - - if (_decorations & Client::Decor_Border) { - geom.bwidth = style->frameBorderWidth(); - geom.cbwidth = style->clientBorderWidth(); - } else { - geom.bwidth = geom.cbwidth = 0; - } - _innersize.left = _innersize.top = _innersize.bottom = _innersize.right = - geom.cbwidth; - geom.width = _client->area().width() + geom.cbwidth * 2; - assert(geom.width > 0); - - // set border widths - XSetWindowBorderWidth(**otk::display, _plate, geom.cbwidth); - XSetWindowBorderWidth(**otk::display, _frame, geom.bwidth); - XSetWindowBorderWidth(**otk::display, _title, geom.bwidth); - XSetWindowBorderWidth(**otk::display, _handle, geom.bwidth); - XSetWindowBorderWidth(**otk::display, _lgrip, geom.bwidth); - XSetWindowBorderWidth(**otk::display, _rgrip, geom.bwidth); - - // position/size and map/unmap all the windows - - if (_decorations & Client::Decor_Titlebar) { - XMoveResizeWindow(**otk::display, _title, -geom.bwidth, -geom.bwidth, - geom.width, geom.title_height()); - _innersize.top += geom.title_height() + geom.bwidth; - XMapWindow(**otk::display, _title); - - // layout the title bar elements - layoutTitle(); - } else { - XUnmapWindow(**otk::display, _title); - // make all the titlebar stuff not render - _decorations &= ~(Client::Decor_Icon | Client::Decor_Iconify | - Client::Decor_Maximize | Client::Decor_Close | - Client::Decor_AllDesktops); - } - - if (_decorations & Client::Decor_Handle) { - geom.handle_y = _innersize.top + _client->area().height() + geom.cbwidth; - XMoveResizeWindow(**otk::display, _handle, -geom.bwidth, geom.handle_y, - geom.width, geom.handle_height); - XMoveWindow(**otk::display, _lgrip, -geom.bwidth, -geom.bwidth); - XMoveWindow(**otk::display, _rgrip, - -geom.bwidth + geom.width - geom.grip_width(), - -geom.bwidth); - _innersize.bottom += geom.handle_height + geom.bwidth; - XMapWindow(**otk::display, _handle); - } else - XUnmapWindow(**otk::display, _handle); - - XResizeWindow(**otk::display, _frame, geom.width, - (_client->shaded() ? geom.title_height() : - _innersize.top + _innersize.bottom + - _client->area().height())); - - // do this in two steps because clients whose gravity is set to - // 'Static' don't end up getting moved at all with an XMoveResizeWindow - XMoveWindow(**otk::display, _plate, _innersize.left - geom.cbwidth, - _innersize.top - geom.cbwidth); - XResizeWindow(**otk::display, _plate, _client->area().width(), - _client->area().height()); - - _size.left = _innersize.left + geom.bwidth; - _size.right = _innersize.right + geom.bwidth; - _size.top = _innersize.top + geom.bwidth; - _size.bottom = _innersize.bottom + geom.bwidth; - - _area = otk::Rect(_area.position(), otk::Size(_client->area().width() + - _size.left + _size.right, - _client->area().height() + - _size.top + _size.bottom)); - - // render all the elements - int screen = _client->screen(); - bool focus = _client->focused(); - if (_decorations & Client::Decor_Titlebar) { - render(screen, otk::Size(geom.width, geom.title_height()), _title, - &_title_sur, *(focus ? style->titlebarFocusBackground() : - style->titlebarUnfocusBackground()), false); - - renderLabel(); - renderMax(); - renderDesk(); - renderIconify(); - renderIcon(); - renderClose(); - } - - if (_decorations & Client::Decor_Handle) { - render(screen, otk::Size(geom.width, geom.handle_height), _handle, - &_handle_sur, *(focus ? style->handleFocusBackground() : - style->handleUnfocusBackground())); - render(screen, otk::Size(geom.grip_width(), geom.handle_height), _lgrip, - &_grip_sur, *(focus ? style->gripFocusBackground() : - style->gripUnfocusBackground())); - if ((focus ? style->gripFocusBackground() : - style->gripUnfocusBackground())->parentRelative()) - XSetWindowBackgroundPixmap(**otk::display, _rgrip, ParentRelative); - else { - XSetWindowBackgroundPixmap(**otk::display, _rgrip, _grip_sur->pixmap()); - } - XClearWindow(**otk::display, _rgrip); - } - - XSetWindowBorder(**otk::display, _plate, - focus ? style->clientBorderFocusColor()->pixel() : - style->clientBorderUnfocusColor()->pixel()); - - adjustShape(); -} - -void Frame::renderLabel() -{ - const otk::RenderStyle *style = otk::RenderStyle::style(_client->screen()); - const otk::RenderControl *control = - otk::display->renderControl(_client->screen()); - const otk::Font *font = style->labelFont(); - - otk::Surface *s = new otk::Surface(_client->screen(), - otk::Size(geom.label_width, - geom.label_height())); - const otk::RenderTexture *tx = (_client->focused() ? - style->labelFocusBackground() : - style->labelUnfocusBackground()); - if (tx->parentRelative()) { - otk::pixel32 *dest = s->pixelData(), *src; - int w = _title_sur->size().width(); - - src = _title_sur->pixelData() + w * geom.bevel + geom.title_x; - - // get the background under the label - int xd = s->size().width(); - int yd = s->size().height(); - for (int y = 0; y < yd; ++y, src += w - xd) - for (int x = 0; x < xd; ++x, ++dest, ++src) - *dest = *src; - control->drawImage(*s, 0, 0, 0); // no image but draw the new background - } else - control->drawBackground(*s, *tx); - - otk::ustring t = _client->title(); // the actual text to draw - int x = geom.bevel; // x coord for the text - - if (x * 2 < geom.label_width) { - // find a string that will fit inside the area for text - otk::ustring::size_type text_len = t.size(); - int length; - int maxsize = geom.label_width - geom.bevel * 2; - - do { - t.resize(text_len); - length = font->measureString(t);// this returns an unsigned, so check < 0 - if (length < 0) length = maxsize;// if the string's that long just adjust - } while (length > maxsize && text_len-- > 0); - - // justify the text - switch (style->labelTextJustify()) { - case otk::RenderStyle::RightBottomJustify: - x += maxsize - length; - break; - case otk::RenderStyle::CenterJustify: - x += (maxsize - length) / 2; - break; - case otk::RenderStyle::LeftTopJustify: - break; - } - - if (text_len > 0) - control->drawString(*s, *font, x, 0, - *(_client->focused() ? style->textFocusColor() : - style->textUnfocusColor()), t); - } - - XSetWindowBackgroundPixmap(**otk::display, _label, s->pixmap()); - XClearWindow(**otk::display, _label); - if (_label_sur) delete _label_sur; - s->freePixelData(); - _label_sur = s; -} - -static void renderButton(int screen, bool focus, bool press, Window win, - otk::Surface **sur, int butsize, - const otk::PixmapMask *mask, int xoffset, int yoffset, - otk::Surface *bgsurface) -{ - const otk::RenderStyle *style = otk::RenderStyle::style(screen); - const otk::RenderControl *control = otk::display->renderControl(screen); - otk::Surface *s = new otk::Surface(screen, otk::Size(butsize, butsize)); - - const otk::RenderTexture *tx = (focus ? - (press ? - style->buttonPressFocusBackground() : - style->buttonUnpressFocusBackground()) : - (press ? - style->buttonPressUnfocusBackground() : - style->buttonUnpressUnfocusBackground())); - const otk::RenderColor *maskcolor = (focus ? - style->buttonFocusColor() : - style->buttonUnfocusColor()); - if (tx->parentRelative()) { - otk::pixel32 *dest = s->pixelData(), *src; - int w = bgsurface->size().width(); - - src = bgsurface->pixelData() + w * yoffset + xoffset; - - // get the background under the button - for (int y = 0; y < butsize; ++y, src += w - butsize) - for (int x = 0; x < butsize; ++x, ++dest, ++src) - *dest = *src; - control->drawImage(*s, 0, 0, 0); // no image but draw the new background - } else - control->drawBackground(*s, *tx); - control->drawMask(*s, *maskcolor, *mask); - - XSetWindowBackgroundPixmap(**otk::display, win, s->pixmap()); - XClearWindow(**otk::display, win); - if (*sur) delete *sur; - s->freePixelData(); - *sur = s; -} - -void Frame::renderMax() -{ - if (!(_decorations & Client::Decor_Maximize)) return; - bool press = _max_press || _client->maxVert() || _client->maxHorz(); - renderButton(_client->screen(), _client->focused(), press, _max, - &_max_sur, geom.button_size, - otk::RenderStyle::style(_client->screen())->maximizeMask(), - geom.max_x, (geom.bevel + 1), _title_sur); -} - -void Frame::renderDesk() -{ - if (!(_decorations & Client::Decor_AllDesktops)) return; - bool press = _desk_press || _client->desktop() == 0xffffffff; - renderButton(_client->screen(), _client->focused(), press, _desk, - &_desk_sur, geom.button_size, - otk::RenderStyle::style(_client->screen())->alldesktopsMask(), - geom.desktop_x, (geom.bevel + 1), _title_sur); -} - -void Frame::renderIconify() -{ - if (!(_decorations & Client::Decor_Iconify)) return; - renderButton(_client->screen(), _client->focused(), _iconify_press, _iconify, - &_iconify_sur, geom.button_size, - otk::RenderStyle::style(_client->screen())->iconifyMask(), - geom.iconify_x, (geom.bevel + 1), _title_sur); -} - -void Frame::renderClose() -{ - if (!(_decorations & Client::Decor_Close)) return; - renderButton(_client->screen(), _client->focused(), _close_press, _close, - &_close_sur, geom.button_size, - otk::RenderStyle::style(_client->screen())->closeMask(), - geom.close_x, (geom.bevel + 1), _title_sur); -} - -void Frame::renderIcon() -{ - if (!(_decorations & Client::Decor_Icon)) return; - const int screen = _client->screen(); - const otk::RenderControl *control = otk::display->renderControl(screen); - - otk::Surface *s = new otk::Surface(screen, otk::Size(geom.button_size, - geom.button_size)); - otk::pixel32 *dest = s->pixelData(), *src; - int w = _title_sur->size().width(); - - src = _title_sur->pixelData() + w * (geom.bevel + 1) + geom.icon_x; - - // get the background under the icon button - for (int y = 0; y < geom.button_size; ++y, src += w - geom.button_size) - for (int x = 0; x < geom.button_size; ++x, ++dest, ++src) - *dest = *src; - // draw the icon over it - const Icon *icon = _client->icon(otk::Size(geom.button_size, - geom.button_size)); - control->drawImage(*s, icon->w, icon->h, icon->data); - if (!icon->data) { - Pixmap p = _client->pixmapIcon(), m = _client->pixmapIconMask(); - if (p != None) - control->drawImage(*s, p, m); - } - - XSetWindowBackgroundPixmap(**otk::display, _icon, s->pixmap()); - XClearWindow(**otk::display, _icon); - if (_icon_sur) delete _icon_sur; - _icon_sur = s; -} - -void Frame::layoutTitle() -{ - // figure out whats being shown, and the width of the label - geom.label_width = geom.width - geom.bevel * 2; - bool n, d, i, t, m ,c; - n = d = i = t = m = c = false; - for (const char *l = _layout.c_str(); *l; ++l) { - switch (*l) { - case 'n': - case 'N': - if (!(_decorations & Client::Decor_Icon)) break; - n = true; - geom.label_width -= geom.button_size + geom.bevel; - break; - case 'd': - case 'D': - if (!(_decorations & Client::Decor_AllDesktops)) break; - d = true; - geom.label_width -= geom.button_size + geom.bevel; - break; - case 'i': - case 'I': - if (!(_decorations & Client::Decor_Iconify)) break; - i = true; - geom.label_width -= geom.button_size + geom.bevel; - break; - case 't': - case 'T': - t = true; - break; - case 'm': - case 'M': - if (!(_decorations & Client::Decor_Maximize)) break; - m = true; - geom.label_width -= geom.button_size + geom.bevel; - break; - case 'c': - case 'C': - if (!(_decorations & Client::Decor_Close)) break; - c = true; - geom.label_width -= geom.button_size + geom.bevel; - break; - } - } - if (geom.label_width < 1) geom.label_width = 1; - - XResizeWindow(**otk::display, _label, geom.label_width, geom.font_height); - - if (!n) { - _decorations &= ~Client::Decor_Icon; - XUnmapWindow(**otk::display, _icon); - } - if (!d) { - _decorations &= ~Client::Decor_AllDesktops; - XUnmapWindow(**otk::display, _desk); - } - if (!i) { - _decorations &= ~Client::Decor_Iconify; - XUnmapWindow(**otk::display, _iconify); - } - if (!t) - XUnmapWindow(**otk::display, _label); - if (!m) { - _decorations &= ~Client::Decor_Maximize; - XUnmapWindow(**otk::display, _max); - } - if (!c) { - _decorations &= ~Client::Decor_Close; - XUnmapWindow(**otk::display, _close); - } - - int x = geom.bevel; - for (const char *lc = _layout.c_str(); *lc; ++lc) { - switch (*lc) { - case 'n': - case 'N': - if (!n) break; - geom.icon_x = x; - XMapWindow(**otk::display, _icon); - XMoveWindow(**otk::display, _icon, x, geom.bevel + 1); - x += geom.button_size + geom.bevel; - break; - case 'd': - case 'D': - if (!d) break; - geom.desktop_x = x; - XMapWindow(**otk::display, _desk); - XMoveWindow(**otk::display, _desk, x, geom.bevel + 1); - x += geom.button_size + geom.bevel; - break; - case 'i': - case 'I': - if (!i) break; - geom.iconify_x = x; - XMapWindow(**otk::display, _iconify); - XMoveWindow(**otk::display, _iconify, x, geom.bevel + 1); - x += geom.button_size + geom.bevel; - break; - case 't': - case 'T': - if (!t) break; - geom.title_x = x; - XMapWindow(**otk::display, _label); - XMoveWindow(**otk::display, _label, x, geom.bevel); - x += geom.label_width + geom.bevel; - break; - case 'm': - case 'M': - if (!m) break; - geom.max_x = x; - XMapWindow(**otk::display, _max); - XMoveWindow(**otk::display, _max, x, geom.bevel + 1); - x += geom.button_size + geom.bevel; - break; - case 'c': - case 'C': - if (!c) break; - geom.close_x = x; - XMapWindow(**otk::display, _close); - XMoveWindow(**otk::display, _close, x, geom.bevel + 1); - x += geom.button_size + geom.bevel; - break; - } - } -} - -void Frame::adjustPosition() -{ - int x, y; - x = _client->area().x(); - y = _client->area().y(); - clientGravity(x, y); - XMoveWindow(**otk::display, _frame, x, y); - _area = otk::Rect(otk::Point(x, y), _area.size()); -} - - -void Frame::adjustShape() -{ -#ifdef SHAPE - if (!_client->shaped()) { - // clear the shape on the frame window - XShapeCombineMask(**otk::display, _frame, ShapeBounding, - _innersize.left, - _innersize.top, - None, ShapeSet); - } else { - // make the frame's shape match the clients - XShapeCombineShape(**otk::display, _frame, ShapeBounding, - _innersize.left, - _innersize.top, - _client->window(), ShapeBounding, ShapeSet); - - int num = 0; - XRectangle xrect[2]; - - if (_decorations & Client::Decor_Titlebar) { - xrect[0].x = -geom.bevel; - xrect[0].y = -geom.bevel; - xrect[0].width = geom.width + geom.bwidth * 2; - xrect[0].height = geom.title_height() + geom.bwidth * 2; - ++num; - } - - if (_decorations & Client::Decor_Handle) { - xrect[1].x = -geom.bevel; - xrect[1].y = geom.handle_y; - xrect[1].width = geom.width + geom.bwidth * 2; - xrect[1].height = geom.handle_height + geom.bwidth * 2; - ++num; - } - - XShapeCombineRectangles(**otk::display, _frame, - ShapeBounding, 0, 0, xrect, num, - ShapeUnion, Unsorted); - } -#endif // SHAPE -} - -void Frame::adjustState() -{ - renderDesk(); - renderMax(); -} - -void Frame::adjustIcon() -{ - renderIcon(); -} - -void Frame::grabClient() -{ - // reparent the client to the frame - XReparentWindow(**otk::display, _client->window(), _plate, 0, 0); - /* - When reparenting the client window, it is usually not mapped yet, since - this occurs from a MapRequest. However, in the case where Openbox is - starting up, the window is already mapped, so we'll see unmap events for - it. There are 2 unmap events generated that we see, one with the 'event' - member set the root window, and one set to the client, but both get handled - and need to be ignored. - */ - if (openbox->state() == Openbox::State_Starting) - _client->ignore_unmaps += 2; - - // select the event mask on the client's parent (to receive config/map req's) - // the ButtonPress is to catch clicks on the client border - XSelectInput(**otk::display, _plate, (SubstructureRedirectMask | - ButtonPressMask)); - - // map the client so it maps when the frame does - XMapWindow(**otk::display, _client->window()); - - adjustSize(); - adjustPosition(); -} - - -void Frame::releaseClient() -{ - XEvent ev; - - // check if the app has already reparented its window away - if (XCheckTypedWindowEvent(**otk::display, _client->window(), - ReparentNotify, &ev)) { - XPutBackEvent(**otk::display, &ev); - // re-map the window since the unmanaging process unmaps it - XMapWindow(**otk::display, _client->window()); - } else { - // according to the ICCCM - if the client doesn't reparent itself, then we - // will reparent the window to root for them - XReparentWindow(**otk::display, _client->window(), - otk::display->screenInfo(_client->screen())->rootWindow(), - _client->area().x(), _client->area().y()); - } -} - - -void Frame::clientGravity(int &x, int &y) -{ - // horizontal - switch (_client->gravity()) { - default: - case NorthWestGravity: - case SouthWestGravity: - case WestGravity: - break; - - case NorthGravity: - case SouthGravity: - case CenterGravity: - x -= (_size.left + _size.right) / 2; - break; - - case NorthEastGravity: - case SouthEastGravity: - case EastGravity: - x -= _size.left + _size.right; - break; - - case ForgetGravity: - case StaticGravity: - x -= _size.left; - break; - } - - // vertical - switch (_client->gravity()) { - default: - case NorthWestGravity: - case NorthEastGravity: - case NorthGravity: - break; - - case CenterGravity: - case EastGravity: - case WestGravity: - y -= (_size.top + _size.bottom) / 2; - break; - - case SouthWestGravity: - case SouthEastGravity: - case SouthGravity: - y -= _size.top + _size.bottom; - break; - - case ForgetGravity: - case StaticGravity: - y -= _size.top; - break; - } -} - - -void Frame::frameGravity(int &x, int &y) -{ - // horizontal - switch (_client->gravity()) { - default: - case NorthWestGravity: - case WestGravity: - case SouthWestGravity: - break; - case NorthGravity: - case CenterGravity: - case SouthGravity: - x += (_size.left + _size.right) / 2; - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - x += _size.left + _size.right; - break; - case StaticGravity: - case ForgetGravity: - x += _size.left; - break; - } - - // vertical - switch (_client->gravity()) { - default: - case NorthWestGravity: - case WestGravity: - case SouthWestGravity: - break; - case NorthGravity: - case CenterGravity: - case SouthGravity: - y += (_size.top + _size.bottom) / 2; - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - y += _size.top + _size.bottom; - break; - case StaticGravity: - case ForgetGravity: - y += _size.top; - break; - } -} - - -}
D src/frame.hh

@@ -1,203 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __frame_hh -#define __frame_hh - -/*! @file frame.hh -*/ - -extern "C" { -#include <X11/Xlib.h> -} - -#include "client.hh" -#include "python.hh" -#include "otk/strut.hh" -#include "otk/rect.hh" -#include "otk/renderstyle.hh" -#include "otk/ustring.hh" -#include "otk/surface.hh" -#include "otk/eventhandler.hh" - -#include <string> -#include <vector> - -namespace ob { - -//! Varius geometry settings in the frame decorations -struct FrameGeometry { - int width; // title and handle - int font_height; - int title_height() { return font_height + bevel*2; } - int label_width; - int label_height() { return font_height; } - int handle_height; // static, from the style - int icon_x; // x-position of the window icon button - int title_x; // x-position of the window title - int iconify_x; // x-position of the window iconify button - int desktop_x; // x-position of the window all-desktops button - int max_x; // x-position of the window maximize button - int close_x; // x-position of the window close button - int handle_y; - int button_size; // static, from the style - int grip_width() { return button_size * 2; } - int bevel; // static, from the style - int bwidth; // frame elements' border width - int cbwidth; // client border width -}; - -//! Holds and decorates a frame around an Client (client window) -/*! - The frame is responsible for calling XSelectInput on the client window's new - parent with the SubstructureRedirectMask so that structure events for the - client are sent to the window manager. -*/ -class Frame : public otk::StyleNotify, public otk::EventHandler { -public: - - //! The event mask to grab on frame windows - static const long event_mask = EnterWindowMask | LeaveWindowMask; - -private: - Client *_client; - - //! The size of the frame on each side of the client window - otk::Strut _size; - - //! The size of the frame on each side of the client window inside the border - otk::Strut _innersize; - - //! The position and size of the entire frame (including borders) - otk::Rect _area; - - bool _visible; - - //! The decorations that are being displayed in the frame. - Client::DecorationFlags _decorations; - - // decoration windows - Window _frame; // sits under everything - Window _plate; // sits entirely under the client window - Window _title; // the titlebar - Window _label; // the section of the titlebar which shows the window name - Window _handle; // bottom bar - Window _lgrip; // lefthand resize grab on the handle - Window _rgrip; // righthand resize grab on the handle - Window _max; // maximize button - Window _desk; // all-desktops button - Window _iconify; // iconify button - Window _icon; // window icon button - Window _close; // close button - - // surfaces for each - otk::Surface *_frame_sur; - otk::Surface *_title_sur; - otk::Surface *_label_sur; - otk::Surface *_handle_sur; - otk::Surface *_grip_sur; - otk::Surface *_max_sur; - otk::Surface *_desk_sur; - otk::Surface *_iconify_sur; - otk::Surface *_icon_sur; - otk::Surface *_close_sur; - - otk::ustring _layout; // layout of the titlebar - - bool _max_press; - bool _desk_press; - bool _iconify_press; - bool _icon_press; - bool _close_press; - unsigned int _press_button; // mouse button that started the press - - FrameGeometry geom; - - void applyStyle(const otk::RenderStyle &style); - void layoutTitle(); - void renderLabel(); - void renderMax(); - void renderDesk(); - void renderIconify(); - void renderClose(); - void renderIcon(); - -public: - //! Constructs an Frame object for a client - /*! - @param client The client which will be decorated by the new Frame - */ - Frame(Client *client); - //! Destroys the Frame object - virtual ~Frame(); - - //! Returns the size of the frame on each side of the client - const otk::Strut& size() const { return _size; } - - //! Set the style to decorate the frame with - virtual void styleChanged(const otk::RenderStyle &style); - - //! Reparents the client window from the root window onto the frame - void grabClient(); - //! Reparents the client window back to the root window - void releaseClient(); - - //! Update the frame's size to match the client - void adjustSize(); - //! Update the frame's position to match the client - void adjustPosition(); - //! Shape the frame window to the client window - void adjustShape(); - //! Update the frame to match the client's new state (for things like toggle - //! buttons, focus, and the title) XXX break this up - void adjustState(); - void adjustFocus(); - void adjustTitle(); - void adjustIcon(); - - //! Applies gravity to the client's position to find where the frame should - //! be positioned. - /*! - @return The proper coordinates for the frame, based on the client. - */ - void clientGravity(int &x, int &y); - - //! Reversly applies gravity to the frame's position to find where the client - //! should be positioned. - /*! - @return The proper coordinates for the client, based on the frame. - */ - void frameGravity(int &x, int &y); - - //! The position and size of the frame window - inline const otk::Rect& area() const { return _area; } - - //! Returns if the frame is visible - inline bool visible() const { return _visible; } - - //! Shows the frame - void show(); - //! Hides the frame - void hide(); - - void buttonPressHandler(const XButtonEvent &e); - void buttonReleaseHandler(const XButtonEvent &e); - - //! Returns the MouseContext for the given window id - /*! - Returns '-1' if no valid mouse context exists in the frame for the given - id. - */ - ob::MouseContext::MC mouseContext(Window win) const; - - //! Gets the window id of the frame's base top-level parent - inline Window window() const { return _frame; } - //! Gets the window id of the client's parent window - inline Window plate() const { return _plate; } - - //! Returns a null terminated array of the window ids that make up the - //! frame's decorations. - Window *allWindows() const; -}; - -} - -#endif // __frame_hh
D src/gettext.h

@@ -1,70 +0,0 @@

-/* Convenience header for conditional use of GNU <libintl.h>. - Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ - -#ifndef _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - - -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include <libintl.h> - -#else - -/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which - chokes if dcgettext is defined as a macro. So include it now, to make - later inclusions of <locale.h> a NOP. We don't include <libintl.h> - as well because people using "gettext.h" will not include <libintl.h>, - and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> - is OK. */ -#if defined(__sun) -# include <locale.h> -#endif - -/* Disabled NLS. - The casts to 'const char *' serve the purpose of producing warnings - for invalid uses of the value returned from these functions. - On pre-ANSI systems without 'const', the config.h file is supposed to - contain "#define const". */ -# define gettext(Msgid) ((const char *) (Msgid)) -# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) -# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) -# define textdomain(Domainname) ((const char *) (Domainname)) -# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) -# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) - -#endif - -/* A pseudo function call that serves as a marker for the automated - extraction of messages, but does not call gettext(). The run-time - translation is done at a different place in the code. - The argument, String, should be a literal string. Concatenated strings - and other string expressions won't work. - The macro's expansion is not parenthesized, so that it is suitable as - initializer for static 'char[]' or 'const char[]' variables. */ -#define gettext_noop(String) String - -#endif /* _LIBGETTEXT_H */
D src/main.cc

@@ -1,51 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -/*! @file main.cc - @brief Main entry point for the application -*/ - -#include "config.h" - -extern "C" { -#ifdef HAVE_UNISTD_H -# include <sys/types.h> -# include <unistd.h> -#endif // HAVE_UNISTD_H - -#include "gettext.h" -} - -#include "openbox.hh" -#include "otk/util.hh" - -#include <clocale> -#include <cstdio> - -int main(int argc, char **argv) { - // initialize the locale - if (!setlocale(LC_ALL, "")) - printf("Couldn't set locale from environment.\n"); - bindtextdomain(PACKAGE, LOCALEDIR); - bind_textdomain_codeset(PACKAGE, "UTF-8"); - textdomain(PACKAGE); - - ob::Openbox *openbox = new ob::Openbox(argc, argv); - openbox->eventLoop(); - - if (openbox->doRestart()) { - std::string prog = openbox->restartProgram(); - - delete openbox; // shutdown the current one! - - if (!prog.empty()) { - execl("/bin/sh", "/bin/sh", "-c", prog.c_str(), NULL); - perror(prog.c_str()); - } - - // fall back in case the above execlp doesn't work - execvp(argv[0], argv); - execvp(otk::basename(argv[0]).c_str(), argv); - } - - delete openbox; // shutdown -}
D src/openbox.cc

@@ -1,413 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "openbox.hh" -#include "client.hh" -#include "screen.hh" -#include "actions.hh" -#include "bindings.hh" -#include "python.hh" -#include "otk/property.hh" -#include "otk/assassin.hh" -#include "otk/property.hh" -#include "otk/util.hh" -#include "otk/rendercolor.hh" -#include "otk/renderstyle.hh" -#include "otk/messagedialog.hh" - -extern "C" { -#include <X11/cursorfont.h> - -#ifdef HAVE_SIGNAL_H -# include <signal.h> -#endif // HAVE_SIGNAL_H - -#ifdef HAVE_FCNTL_H -# include <fcntl.h> -#endif // HAVE_FCNTL_H - -#ifdef HAVE_SYS_WAIT_H -# include <sys/wait.h> -#endif // HAVE_SYS_WAIT_H - -#include "gettext.h" -#define _(str) gettext(str) -} - -#include <algorithm> -#include <cstdio> -#include <cstdlib> - -namespace otk { -extern void initialize(); -extern void destroy(); -} - -namespace ob { - -Openbox *openbox = (Openbox *) 0; - - -void Openbox::signalHandler(int signal) -{ - switch (signal) { - case SIGUSR1: - printf("Caught SIGUSR1 signal. Restarting.\n"); - openbox->restart(); - break; - - case SIGCHLD: - wait(NULL); - break; - - case SIGHUP: - case SIGINT: - case SIGTERM: - case SIGPIPE: - printf("Caught signal %d. Exiting.\n", signal); - openbox->shutdown(); - break; - - case SIGFPE: - case SIGSEGV: - printf("Caught signal %d. Aborting and dumping core.\n", signal); - abort(); - } -} - - -Openbox::Openbox(int argc, char **argv) - : otk::EventDispatcher(), - otk::EventHandler() -{ - struct sigaction action; - - _state = State_Starting; // initializing everything - - openbox = this; - - _argv = argv; - _shutdown = false; - _restart = false; - _rcfilepath = otk::expandTilde("~/.openbox/rc3"); - _scriptfilepath = otk::expandTilde("~/.openbox/user.py"); - _focused_client = 0; - _sync = false; - _single = false; - _remote = false; - - parseCommandLine(argc, argv); - - otk::initialize(); - - XSynchronize(**otk::display, _sync); - - // set up the signal handler - action.sa_handler = Openbox::signalHandler; - action.sa_mask = sigset_t(); - action.sa_flags = SA_NOCLDSTOP | SA_NODEFER; - sigaction(SIGUSR1, &action, (struct sigaction *) 0); - sigaction(SIGPIPE, &action, (struct sigaction *) 0); - sigaction(SIGSEGV, &action, (struct sigaction *) 0); - sigaction(SIGFPE, &action, (struct sigaction *) 0); - sigaction(SIGTERM, &action, (struct sigaction *) 0); - sigaction(SIGINT, &action, (struct sigaction *) 0); - sigaction(SIGHUP, &action, (struct sigaction *) 0); - sigaction(SIGCHLD, &action, (struct sigaction *) 0); - - // anything that died while we were restarting won't give us a SIGCHLD - while (waitpid(-1, NULL, WNOHANG) > 0); - - _actions = new Actions(); - _bindings = new Bindings(); - - setMasterHandler(_actions); // set as the master event handler - - // create the mouse cursors we'll use - _cursors.session = XCreateFontCursor(**otk::display, XC_left_ptr); - _cursors.move = XCreateFontCursor(**otk::display, XC_fleur); - _cursors.ll_angle = XCreateFontCursor(**otk::display, XC_ll_angle); - _cursors.lr_angle = XCreateFontCursor(**otk::display, XC_lr_angle); - _cursors.ul_angle = XCreateFontCursor(**otk::display, XC_ul_angle); - _cursors.ur_angle = XCreateFontCursor(**otk::display, XC_ur_angle); - - // initialize all the screens - _focused_screen = 0; - _managed_count = 0; - - for (int i = 0, max = ScreenCount(**otk::display); i < max; ++i) { - Screen *screen; - // in single mode skip the screens we don't want to manage - if (_single && i != DefaultScreen(**otk::display)) { - _screens.push_back(0); - continue; - } - // try manage the screen - screen = new Screen(i); - if (screen->managed()) { - _screens.push_back(screen); - if (!_focused_screen) // set this to the first screen managed - _focused_screen = screen; - _managed_count++; - } else { - delete screen; - _screens.push_back(0); - } - } - - if (!_managed_count) { - printf(_("No screens were found without a window manager. Exiting.\n")); - ::exit(1); - } - - assert(_focused_screen); - - // initialize scripting - python_init(argv[0]); - - // load the theme XXX TEMP SHIT - otk::RenderStyle::setStyle(0, ""); - - int ret = python_exec(_scriptfilepath.c_str()); - if (ret == 2) { - std::string msg; - msg += _("An error occured while executing the python scripts."); - msg += "\n\n"; - msg += _("See the exact error message in Openbox's output for details."); - otk::MessageDialog dia(this, _("Python Error"), msg); - otk::DialogButton ok(_("Okay"), true); - otk::DialogButton retry(_("Restart")); - dia.addButton(ok); - dia.addButton(retry); - dia.show(); - dia.focus(); - const otk::DialogButton &res = dia.run(); - if (res == retry) { - _restart = _shutdown = true; - return; - } - } - - if (ret) - python_exec(SCRIPTDIR"/defaults.py"); // system default bahaviors - - ScreenList::iterator it, end = _screens.end(); - for (it = _screens.begin(); it != end; ++it) - if (*it) (*it)->manageExisting(); - - // grab any keys set up before the screens existed - //_bindings->grabKeys(true); - - // set up input focus - setFocusedClient(0); - - _state = State_Normal; // done starting -} - - -Openbox::~Openbox() -{ - _state = State_Exiting; // time to kill everything - - std::for_each(_screens.begin(), _screens.end(), otk::PointerAssassin()); - - delete _bindings; - delete _actions; - - python_destroy(); - - XSetInputFocus(**otk::display, PointerRoot, RevertToNone, - CurrentTime); - XSync(**otk::display, false); - - otk::destroy(); -} - - -void Openbox::parseCommandLine(int argc, char **argv) -{ - bool err = false; - - for (int i = 1; i < argc; ++i) { - std::string arg(argv[i]); - - if (arg == "-rc") { - if (++i >= argc) - err = true; - else - _rcfilepath = argv[i]; - } else if (arg == "-menu") { - if (++i >= argc) - err = true; - else - _menufilepath = argv[i]; - } else if (arg == "-script") { - if (++i >= argc) - err = true; - else - _scriptfilepath = argv[i]; - } else if (arg == "-sync") { - _sync = true; - } else if (arg == "-single") { - _single = true; - } else if (arg == "-remote") { - _remote = true; - } else if (arg == "-version") { - showVersion(); - ::exit(0); - } else if (arg == "-help") { - showHelp(); - ::exit(0); - } else - err = true; - - if (err) { - showHelp(); - exit(1); - } - } -} - - -void Openbox::showVersion() -{ - printf(_("Openbox - version %s\n"), VERSION); - printf(" (c) 2002 - 2002 Ben Jansens\n\n"); -} - - -void Openbox::showHelp() -{ - showVersion(); // show the version string and copyright - - // print program usage and command line options - printf(_("Usage: %s [OPTIONS...]\n\ - Options:\n\ - -remote optimize for a remote (low bandwidth) connection to the\n\ - display/Xserver.\n\ - -single run on a single screen (default is to run every one).\n\ - -rc <string> use alternate resource file.\n\ - -menu <string> use alternate menu file.\n\ - -script <string> use alternate startup script file.\n\ - -sync run in synchronous mode (for debugging X errors).\n\ - -version display version and exit.\n\ - -help display this help text and exit.\n\n"), _argv[0]); - - printf(_("Compile time options:\n\ - Debugging: %s\n\ - Shape: %s\n\ - Xinerama: %s\n\ - Xkb: %s\n"), -#ifdef DEBUG - _("yes"), -#else // !DEBUG - _("no"), -#endif // DEBUG - -#ifdef SHAPE - _("yes"), -#else // !SHAPE - _("no"), -#endif // SHAPE - -#ifdef XINERAMA - _("yes"), -#else // !XINERAMA - _("no"), -#endif // XINERAMA - -#ifdef XKB - _("yes") -#else // !XKB - _("no") -#endif // XKB - ); -} - - -void Openbox::eventLoop() -{ - while (true) { - dispatchEvents(false); // from otk::EventDispatcher -// XFlush(**otk::display); // flush here before we go wait for timers - // .. the XPending() should have done this last - // already, it does a flush when it returns 0 - // don't wait if we're to shutdown - if (_shutdown) break; - otk::Timer::dispatchTimers(!_sync); // wait if not in sync mode - } -} - - -void Openbox::addClient(Window window, Client *client) -{ - _clients[window] = client; -} - - -void Openbox::removeClient(Window window) -{ - _clients.erase(window); -} - - -Client *Openbox::findClient(Window window) -{ - /* - NOTE: we dont use _clients[] to find the value because that will insert - a new null into the hash, which really sucks when we want to clean up the - hash at shutdown! - */ - ClientMap::iterator it = _clients.find(window); - if (it != _clients.end()) - return it->second; - else - return (Client*) 0; -} - - -void Openbox::setFocusedClient(Client *c) -{ - // sometimes this is called with the already-focused window, this is - // important for the python scripts to work (eg, c = 0 twice). don't just - // return if _focused_client == c - - assert(_focused_screen); - - // uninstall the old colormap - if (_focused_client) - _focused_client->installColormap(false); - else - _focused_screen->installColormap(false); - - _focused_client = c; - if (c) { - _focused_screen = _screens[c->screen()]; - - // install the client's colormap - c->installColormap(true); - } else { - XSetInputFocus(**otk::display, _focused_screen->focuswindow(), - RevertToNone, CurrentTime); - - // install the root window colormap - _focused_screen->installColormap(true); - } - // set the NET_ACTIVE_WINDOW hint for all screens - ScreenList::iterator it, end = _screens.end(); - for (it = _screens.begin(); it != end; ++it) { - int num = (*it)->number(); - Window root = otk::display->screenInfo(num)->rootWindow(); - otk::Property::set(root, otk::Property::atoms.net_active_window, - otk::Property::atoms.window, - (c && _focused_screen == *it) ? c->window() : None); - } - - // call the python Focus callbacks - EventData data(_focused_screen->number(), c, EventAction::Focus, 0); - _bindings->fireEvent(&data); -} - -} -
D src/openbox.hh

@@ -1,250 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __openbox_hh -#define __openbox_hh - -/*! @file openbox.hh - @brief The main class for the Openbox window manager -*/ - -extern "C" { -#include <X11/Xlib.h> -} - -#include <string> -#include <vector> -#include <map> - -#include "otk/display.hh" -#include "otk/screeninfo.hh" -#include "otk/eventdispatcher.hh" -#include "otk/eventhandler.hh" - -namespace ob { - -class Screen; -class Client; -class Actions; -class Bindings; - -//! Mouse cursors used throughout Openbox -struct Cursors { - Cursor session; //!< The default mouse cursor - Cursor move; //!< For moving a window - Cursor ll_angle; //!< For resizing the bottom left corner of a window - Cursor lr_angle; //!< For resizing the bottom right corner of a window - Cursor ul_angle; //!< For resizing the top left corner of a window - Cursor ur_angle; //!< For resizing the right corner of a window -}; - -class Openbox; - -//! The single instance of the Openbox class for the application -/*! - Since this variable is globally available in the application, the Openbox - class does not need to be passed around to any of the other classes. -*/ -extern Openbox *openbox; - -//! The main class for the Openbox window manager -/*! - Only a single instance of the Openbox class may be used in the application. A - pointer to this instance is held in the Openbox::instance static member - variable. - Instantiation of this class begins the window manager. After instantiation, - the Openbox::eventLoop function should be called. The eventLoop method does - not exit until the window manager is ready to be destroyed. Destruction of - the Openbox class instance will shutdown the window manager. -*/ -class Openbox : public otk::EventDispatcher, public otk::EventHandler -{ -public: - //! The posible running states of the window manager - enum RunState { - State_Starting, //!< The window manager is starting up (being created) - State_Normal, //!< The window manager is running in its normal state - State_Exiting //!< The window manager is exiting (being destroyed) - }; - - //! A map for looking up a specific client class from the window id - typedef std::map<Window, Client *> ClientMap; - - //! A list of Screen classes - typedef std::vector<Screen *> ScreenList; - -private: - // stuff that can be passed on the command line - //! Path to the config file to use/in use - /*! - Defaults to $(HOME)/.openbox/rc3 - */ - std::string _rcfilepath; - //! Path to the menu file to use/in use - /*! - Defaults to $(HOME)/.openbox/menu3 - */ - std::string _menufilepath; - //! Path to the script file to execute on startup - /*! - Defaults to $(HOME)/.openbox/user.py - */ - std::string _scriptfilepath; - //! The value of argv, i.e. how this application was executed - char **_argv; - //! Run the application in synchronous mode? (for debugging) - bool _sync; - //! Should Openbox run on a single screen or on all available screens? - bool _single; - //! Optimize for a remote/low-bandwidth connection to the display? - bool _remote; - - //! A list of all managed clients - ClientMap _clients; - - //! A list of all the managed screens - ScreenList _screens; - - //! The number of managed screens - int _managed_count; - - //! The action interface through which all user-available actions occur - Actions *_actions; - - //! The interface through which keys/buttons are grabbed and handled - Bindings *_bindings; - - //! The running state of the window manager - RunState _state; - - //! Mouse cursors used throughout Openbox - Cursors _cursors; - - //! When set to true, the Openbox::eventLoop function will stop and return - bool _shutdown; - - //! When set to true, and Openbox is about to exit, it will spawn a new - //! process - bool _restart; - - //! If this contains anything, a restart will try to execute the program in - //! this variable, and will fallback to reexec'ing itself if that fails - std::string _restart_prog; - - //! The client with input focus - /*! - Updated by the clients themselves. - */ - Client *_focused_client; - - //! The screen with input focus - /*! - Updated by the clients when they update the Openbox::focused_client - property. - */ - Screen *_focused_screen; - - //! Parses the command line used when executing this application - void parseCommandLine(int argv, char **argv); - //! Displays the version string to stdout - void showVersion(); - //! Displays usage information and help to stdout - void showHelp(); - - //! Handles signal events for the application - static void signalHandler(int signal); - -public: - //! Openbox constructor. - /*! - \param argc Number of command line arguments, as received in main() - \param argv The command line arguments, as received in main() - */ - Openbox(int argc, char **argv); - //! Openbox destructor. - virtual ~Openbox(); - - //! Returns the state of the window manager (starting, exiting, etc) - inline RunState state() const { return _state; } - - //! Returns the Actions instance for the window manager - inline Actions *actions() const { return _actions; } - - //! Returns the Bindings instance for the window manager - inline Bindings *bindings() const { return _bindings; } - - //! Returns a managed screen or a null pointer - /*! - ALWAYS check the return value for a non-null, as any unmanaged screens - will return one. This includes screen(0) if the first managed screen is 1. - */ - inline Screen *screen(int num) { - assert(num >= 0); assert(num < (signed)ScreenCount(**otk::display)); - if (num < 0 || num >= (signed)_screens.size()) return 0; - return _screens[num]; - } - - inline int managedScreenCount() const { return _managed_count; } - - inline Screen *managedScreen(int num) { - assert(num >= 0); assert(num < _managed_count); - if (num < 0 || num >= _managed_count) return 0; - ScreenList::iterator it, end = _screens.end(); - int i = -1; - for (it = _screens.begin(); it != end; ++it) - if (*it && ++i == num) - return *it; - } - - //! Returns the mouse cursors used throughout Openbox - inline const Cursors &cursors() const { return _cursors; } - - //! The main function of the Openbox class - /*! - This function should be called after instantiating the Openbox class. - It loops indefinately while handling all events for the application. - The Openbox::shutdown method will cause this function to exit. - */ - void eventLoop(); - - //! Adds an Client to the client list for lookups - void addClient(Window window, Client *client); - - //! Removes an Client from the client list for lookups - void removeClient(Window window); - - //! Finds an Client based on its window id - Client *findClient(Window window); - - //! The client with input focus - inline Client *focusedClient() { return _focused_client; } - - //! Change the client which has focus. - /*! - This is called by the clients themselves when their focus state changes. - */ - void setFocusedClient(Client *c); - - //! The screen with input focus - inline Screen *focusedScreen() { return _focused_screen; } - - //! Requests that the window manager exit - /*! - Causes the Openbox::eventLoop function to stop looping, so that the window - manager can be destroyed. - */ - inline void shutdown() { _shutdown = true; } - - inline void restart(const std::string &bin = "") { - _shutdown = true; _restart = true; _restart_prog = bin; - } - - //! True if Openbox should be restarted instead of exiting - inline bool doRestart() const { return _restart; } - - //! The command line requested to be executed in place of restarting - //! Openbox the way it was run previously. - inline const std::string &restartProgram() const { return _restart_prog; } -}; - -} - -#endif // __openbox_hh
D src/python.cc

@@ -1,141 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "python.hh" -#include "openbox.hh" -#include "actions.hh" -#include "python.hh" -#include "bindings.hh" -#include "otk/display.hh" -#include "otk/util.hh" - -extern "C" { -#include <Python.h> - -#include "gettext.h" -#define _(str) gettext(str) -} - -namespace ob { - -static PyObject *get = NULL; - -void python_init(char *argv0) -{ - // start the python engine - Py_SetProgramName(argv0); - Py_Initialize(); - // prepend the openbox directories for python scripts to the sys path - PyRun_SimpleString("import sys"); - PyRun_SimpleString("sys.path.insert(0, '" SCRIPTDIR "')"); - PyRun_SimpleString(const_cast<char*>(("sys.path.insert(0, '" + - otk::expandTilde("~/.openbox/python") + - "')").c_str())); - - return; - PyObject *obmodule = PyImport_ImportModule("config"); - if (obmodule == NULL) { - PyErr_Print(); - return; - } - PyObject *configdict = PyModule_GetDict(obmodule); - Py_DECREF(obmodule); - - get = PyDict_GetItemString(configdict, "get"); - if (get == NULL) { - PyErr_Print(); - return; - } -} - -void python_destroy() -{ - Py_Finalize(); -} - -int python_exec(const std::string &path) -{ - FILE *rcpyfd = fopen(path.c_str(), "r"); - if (!rcpyfd) { - fprintf(stderr, _("Unabled to open python file %s\n"), path.c_str()); - return 1; - } - - //PyRun_SimpleFile(rcpyfd, const_cast<char*>(path.c_str())); - - PyObject *module = PyImport_AddModule("__main__"); - assert(module); - PyObject *dict = PyModule_GetDict(module); - assert(dict); - PyObject *result = PyRun_File(rcpyfd, const_cast<char*>(path.c_str()), - Py_file_input, dict, dict); - int ret = result == NULL ? 2 : 0; - if (result == NULL) - PyErr_Print(); - - Py_XDECREF(result); - - Py_DECREF(dict); - - fclose(rcpyfd); - return ret; -} - -bool python_get_long(const char *name, long *value) -{ - return false; - if (get == NULL) return false; - bool ret = false; - - PyObject *val = PyObject_CallFunction(get, "ss", "openbox", name); - if (val == NULL) - PyErr_Print(); - else if (PyInt_Check(val)) { - *value = PyInt_AsLong(val); - ret = true; - } else if (PyLong_Check(val)) { - *value = PyLong_AsLong(val); - ret = true; - } - Py_XDECREF(val); - return ret; -} - -bool python_get_string(const char *name, otk::ustring *value) -{ - return false; - if (get == NULL) return false; - bool ret = false; - - PyObject *val = PyObject_CallFunction(get, "ss", "openbox", name); - if (val == NULL) - PyErr_Print(); - else if (PyString_Check(val)) { - *value = std::string(PyString_AsString(val), PyString_Size(val)); - ret = true; - } - Py_XDECREF(val); - return ret; -} - -bool python_get_stringlist(const char *name, std::vector<otk::ustring> *value) -{ - return false; - if (get == NULL) return false; - bool ret = false; - - PyObject *val = PyObject_CallFunction(get, "ss", "openbox", name); - if (val == NULL) - PyErr_Print(); - else if (PyList_Check(val)) { - for (int i = 0, end = PyList_Size(val); i < end; ++i) { - PyObject *str = PyList_GET_ITEM(val, i); - if (PyString_Check(str)) - value->push_back(std::string(PyString_AsString(str), - PyString_Size(str))); - } - } - Py_XDECREF(val); - return ret; -} - -}
D src/python.hh

@@ -1,243 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __python_hh -#define __python_hh - -/*! @file python.hh - @brief wee -*/ - -#include "otk/point.hh" -#include "otk/rect.hh" -#include "otk/property.hh" -#include "otk/display.hh" -#include "otk/ustring.hh" - -extern "C" { -#include <X11/Xlib.h> -} - -#include <string> -#include <vector> - - -namespace ob { - -class Client; - -struct MouseContext { - enum MC { - Frame, - Titlebar, - Handle, - Window, - IconButton, - MaximizeButton, - CloseButton, - IconifyButton, - AllDesktopsButton, - Grip, - Root, - MenuItem -#ifndef DOXYGEN_IGNORE - , NUM_MOUSE_CONTEXT -#endif - }; -}; - -struct MouseAction { - enum MA { - Press, - Release, - Click, - DoubleClick, - Motion -#ifndef DOXYGEN_IGNORE - , NUM_MOUSE_ACTION -#endif - }; -}; - -struct KeyContext { - enum KC { - Menu, - All -#ifndef DOXYGEN_IGNORE - , NUM_KEY_CONTEXT -#endif - }; -}; - -struct KeyAction { - enum KA { - Press, - Release -#ifndef DOXYGEN_IGNORE - , NUM_KEY_ACTION -#endif - }; -}; - -struct EventAction { - enum EA { - EnterWindow, //!< Occurs when the mouse enters a window - LeaveWindow, //!< Occurs when the mouse leaves a window - //! Occurs while a window is being managed. The handler should call - //! Client::move on the window - PlaceWindow, - //! Occurs while a window is being managed, just before the window is - //! displayed - /*! - Note that the window's state may not be completely stabilized by this - point. The NewWindow event should be used when possible. - */ - DisplayingWindow, - //! Occurs when a window is finished being managed - NewWindow, - //! Occurs when a window has been closed and is going to be unmanaged - CloseWindow, - //! Occurs when the window manager manages a screen - /*! - This event occurs on each managed screen during startup. - */ - Startup, - //! Occurs when the window manager unmanages a screen - /*! - This event occurs on each managed screen during shutdown. - */ - Shutdown, - //! Occurs when the input focus target changes - /*! - The data.client will be None of no client is focused. - */ - Focus, - //! Occurs when the system is fired through X. - /*! - The data.client will hold the client associated with the bell if - one has been specified, or None. - */ - Bell, - //! Occurs when a client toggles its urgent status. - /*! - The Client::urgent method can be used to get the status. - */ - UrgentWindow -#ifndef DOXYGEN_IGNORE - , NUM_EVENT_ACTION -#endif - }; -}; - -class MouseData { -public: - int screen; - Client *client; - Time time; - unsigned int state; - unsigned int button; - MouseContext::MC context; - MouseAction::MA action; - int xroot; - int yroot; - int pressx; - int pressy; - int press_clientx; - int press_clienty; - int press_clientwidth; - int press_clientheight; - - MouseData(int screen, Client *client, Time time, unsigned int state, - unsigned int button, MouseContext::MC context, - MouseAction::MA action, int xroot, int yroot, - const otk::Point &initpos, const otk::Rect &initarea) { - this->screen = screen; - this->client = client; - this->time = time; - this->state = state; - this->button = button; - this->context= context; - this->action = action; - this->xroot = xroot; - this->yroot = yroot; - this->pressx = initpos.x(); - this->pressy = initpos.y(); - this->press_clientx = initarea.x(); - this->press_clienty = initarea.y(); - this->press_clientwidth = initarea.width(); - this->press_clientheight = initarea.height(); - } - MouseData(int screen, Client *client, Time time, unsigned int state, - unsigned int button, MouseContext::MC context, - MouseAction::MA action) { - this->screen = screen; - this->client = client; - this->time = time; - this->state = state; - this->button = button; - this->context= context; - this->action = action; - this->xroot = xroot; - this->yroot = yroot; - this->pressx = 0; - this->pressy = 0; - this->press_clientx = 0; - this->press_clienty = 0; - this->press_clientwidth = 0; - this->press_clientheight = 0; - } -}; - -class EventData { -public: - int screen; - Client *client; - unsigned int state; - EventAction::EA action; - - EventData(int screen, Client *client, EventAction::EA action, - unsigned int state) { - this->screen = screen; - this->client = client; - this->action = action; - this->state = state; - } -}; - -class KeyData { -public: - int screen; - Client *client; - Time time; - unsigned int state; - char *key; - KeyAction::KA action; - - KeyData(int screen, Client *client, Time time, unsigned int state, - unsigned int key, KeyAction::KA action) { - this->screen = screen; - this->client = client; - this->time = time; - this->state = state; - this->key = XKeysymToString(XKeycodeToKeysym(**otk::display, - key, 0)); - this->action = action; - } -}; - -// The void*'s will be used to hold the native language's function pointer -typedef void (*MouseCallback)(MouseData*, void*); -typedef void (*KeyCallback)(KeyData*, void*); -typedef void (*EventCallback)(EventData*, void*); - -void python_init(char *argv0); -void python_destroy(); -//! Returns 0 for success, 1 for failing to open the file, 2 for an exception -int python_exec(const std::string &path); - -bool python_get_long(const char *name, long *value); -bool python_get_string(const char *name, otk::ustring *value); -bool python_get_stringlist(const char *name, std::vector<otk::ustring> *value); - -} - - -#endif // __python_hh
D src/screen.cc

@@ -1,945 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- - -#include "config.h" - -#include "screen.hh" -#include "client.hh" -#include "openbox.hh" -#include "frame.hh" -#include "bindings.hh" -#include "python.hh" -#include "otk/display.hh" -#include "otk/property.hh" -#include "otk/util.hh" - -extern "C" { -#ifdef HAVE_UNISTD_H -# include <sys/types.h> -# include <unistd.h> -#endif // HAVE_UNISTD_H - -#include "gettext.h" -#define _(str) gettext(str) -} - -#include <vector> -#include <algorithm> -#include <cstdio> -#include <cstring> - -static bool running; -static int anotherWMRunning(Display *display, XErrorEvent *) { - printf(_("Another window manager already running on display %s.\n"), - DisplayString(display)); - running = true; - return -1; -} - - -namespace ob { - - -Screen::Screen(int screen) - : _number(screen) -{ - assert(screen >= 0); assert(screen < ScreenCount(**otk::display)); - _info = otk::display->screenInfo(screen); - - ::running = false; - XErrorHandler old = XSetErrorHandler(::anotherWMRunning); - XSelectInput(**otk::display, _info->rootWindow(), - Screen::event_mask); - XSync(**otk::display, false); - XSetErrorHandler(old); - - _managed = !::running; - if (! _managed) return; // was unable to manage the screen - -#ifdef DEBUG - printf(_("Managing screen %d: visual 0x%lx, depth %d\n"), - _number, XVisualIDFromVisual(_info->visual()), _info->depth()); -#endif - - otk::Property::set(_info->rootWindow(), otk::Property::atoms.openbox_pid, - otk::Property::atoms.cardinal, (unsigned long) getpid()); - - // set the mouse cursor for the root window (the default cursor) - XDefineCursor(**otk::display, _info->rootWindow(), - openbox->cursors().session); - - // set up notification of netwm support - changeSupportedAtoms(); - - // Set the netwm properties for geometry - unsigned long geometry[] = { _info->size().width(), - _info->size().height() }; - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_desktop_geometry, - otk::Property::atoms.cardinal, geometry, 2); - - _desktop = 0; - - changeNumDesktops(4); // set the hint - changeDesktop(0); // set the hint - - // don't start in showing-desktop mode - _showing_desktop = false; - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_showing_desktop, - otk::Property::atoms.cardinal, 0); - - // create the window which gets focus when no clients get it - XSetWindowAttributes attr; - attr.override_redirect = true; - _focuswindow = XCreateWindow(**otk::display, _info->rootWindow(), - -100, -100, 1, 1, 0, 0, InputOnly, - _info->visual(), CWOverrideRedirect, &attr); - XMapRaised(**otk::display, _focuswindow); - - // these may be further updated if any pre-existing windows are found in - // the manageExising() function - changeClientList(); // initialize the client lists, which will be empty - - updateDesktopLayout(); - - // register this class as the event handler for the root window - openbox->registerHandler(_info->rootWindow(), this); - - // call the python Startup callbacks - EventData data(_number, 0, EventAction::Startup, 0); - openbox->bindings()->fireEvent(&data); -} - - -Screen::~Screen() -{ - if (! _managed) return; - - XSelectInput(**otk::display, _info->rootWindow(), NoEventMask); - - // unmanage all windows - while (!clients.empty()) - unmanageWindow(clients.front()); - - // call the python Shutdown callbacks - EventData data(_number, 0, EventAction::Shutdown, 0); - openbox->bindings()->fireEvent(&data); - - XDestroyWindow(**otk::display, _focuswindow); - XDestroyWindow(**otk::display, _supportwindow); -} - - -void Screen::manageExisting() -{ - unsigned int i, j, nchild; - Window r, p, *children; - XQueryTree(**otk::display, _info->rootWindow(), &r, &p, - &children, &nchild); - - // preen the window list of all icon windows... for better dockapp support - for (i = 0; i < nchild; i++) { - if (children[i] == None) continue; - - XWMHints *wmhints = XGetWMHints(**otk::display, - children[i]); - - if (wmhints) { - if ((wmhints->flags & IconWindowHint) && - (wmhints->icon_window != children[i])) { - for (j = 0; j < nchild; j++) { - if (children[j] == wmhints->icon_window) { - children[j] = None; - break; - } - } - } - - XFree(wmhints); - } - } - - // manage shown windows - for (i = 0; i < nchild; ++i) { - if (children[i] == None) - continue; - - XWindowAttributes attrib; - if (XGetWindowAttributes(**otk::display, children[i], &attrib)) { - if (attrib.override_redirect) continue; - - if (attrib.map_state != IsUnmapped) { - manageWindow(children[i]); - } - } - } - - XFree(children); -} - -void Screen::updateDesktopLayout() -{ - //const unsigned long _NET_WM_ORIENTATION_HORZ = 0; - const unsigned long _NET_WM_ORIENTATION_VERT = 1; - //const unsigned long _NET_WM_TOPLEFT = 0; - const unsigned long _NET_WM_TOPRIGHT = 1; - const unsigned long _NET_WM_BOTTOMRIGHT = 2; - const unsigned long _NET_WM_BOTTOMLEFT = 3; - - // defaults - _layout.orientation = DesktopLayout::Horizontal; - _layout.start_corner = DesktopLayout::TopLeft; - _layout.rows = 1; - _layout.columns = _num_desktops; - - unsigned long *data, num = 4; - if (otk::Property::get(_info->rootWindow(), - otk::Property::atoms.net_desktop_layout, - otk::Property::atoms.cardinal, - &num, &data)) { - if (num == 4) { - if (data[0] == _NET_WM_ORIENTATION_VERT) - _layout.orientation = DesktopLayout::Vertical; - if (data[3] == _NET_WM_TOPRIGHT) - _layout.start_corner = DesktopLayout::TopRight; - else if (data[3] == _NET_WM_BOTTOMRIGHT) - _layout.start_corner = DesktopLayout::BottomRight; - else if (data[3] == _NET_WM_BOTTOMLEFT) - _layout.start_corner = DesktopLayout::BottomLeft; - - // fill in a zero rows/columns - if (!(data[1] == 0 && data[2] == 0)) { // both 0's is bad data.. - if (data[1] == 0) { - data[1] = (_num_desktops + _num_desktops % data[2]) / data[2]; - } else if (data[2] == 0) { - data[2] = (_num_desktops + _num_desktops % data[1]) / data[1]; - } - _layout.columns = data[1]; - _layout.rows = data[2]; - } - - // bounds checking - if (_layout.orientation == DesktopLayout::Horizontal) { - if (_layout.rows > _num_desktops) _layout.rows = _num_desktops; - if (_layout.columns > (_num_desktops + _num_desktops % _layout.rows) / - _layout.rows) - _layout.columns = (_num_desktops + _num_desktops % _layout.rows) / - _layout.rows; - } else { - if (_layout.columns > _num_desktops) _layout.columns = _num_desktops; - if (_layout.rows > (_num_desktops + _num_desktops % _layout.columns) / - _layout.columns) - _layout.rows = (_num_desktops + _num_desktops % _layout.columns) / - _layout.columns; - } - } - delete [] data; - } -} - -void Screen::updateStruts() -{ - struct ApplyStrut { - void operator()(otk::Strut &self, const otk::Strut &other) { - self.left = std::max(self.left, other.left); - self.right = std::max(self.right, other.right); - self.top = std::max(self.top, other.top); - self.bottom = std::max(self.bottom, other.bottom); - } - } apply; - - StrutList::iterator sit, send = _struts.end(); - // reset them all - for (sit = _struts.begin(); sit != send; ++sit) - sit->left = sit->right = sit->top = sit->bottom = 0; - - std::list<Client*>::const_iterator it, end = clients.end(); - for (it = clients.begin(); it != end; ++it) { - if ((*it)->iconic()) continue; // these dont count in the strut - - unsigned int desk = (*it)->desktop(); - const otk::Strut &s = (*it)->strut(); - - if (desk == 0xffffffff) - for (unsigned int i = 0, e = _struts.size(); i < e; ++i) - apply(_struts[i], s); - else if (desk < _struts.size()) - apply(_struts[desk], s); - else - assert(false); // invalid desktop otherwise.. - // apply to the 'all desktops' strut - apply(_struts.back(), s); - } - changeWorkArea(); -} - - -void Screen::changeWorkArea() -{ - unsigned long *dims = new unsigned long[4 * _num_desktops]; - for (unsigned int i = 0; i < _num_desktops + 1; ++i) { - otk::Rect old_area = _area[i]; -/* -#ifdef XINERAMA - // reset to the full areas - if (isXineramaActive()) - xineramaUsableArea = getXineramaAreas(); -#endif // XINERAMA -*/ - - _area[i] = otk::Rect(_struts[i].left, _struts[i].top, - _info->size().width() - (_struts[i].left + - _struts[i].right), - _info->size().height() - (_struts[i].top + - _struts[i].bottom)); - -/* -#ifdef XINERAMA - if (isXineramaActive()) { - // keep each of the ximerama-defined areas inside the strut - RectList::iterator xit, xend = xineramaUsableArea.end(); - for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) { - if (xit->x() < usableArea.x()) { - xit->setX(usableArea.x()); - xit->setWidth(xit->width() - usableArea.x()); - } - if (xit->y() < usableArea.y()) { - xit->setY(usableArea.y()); - xit->setHeight(xit->height() - usableArea.y()); - } - if (xit->x() + xit->width() > usableArea.width()) - xit->setWidth(usableArea.width() - xit->x()); - if (xit->y() + xit->height() > usableArea.height()) - xit->setHeight(usableArea.height() - xit->y()); - } - } -#endif // XINERAMA -*/ - if (old_area != _area[i]) { - // the area has changed, adjust all the maximized windows - std::list<Client*>::iterator it, end = clients.end(); - for (it = clients.begin(); it != end; ++it) - if (i < _num_desktops) { - if ((*it)->desktop() == i) - (*it)->remaximize(); - } else { - // the 'all desktops' size - if ((*it)->desktop() == 0xffffffff) - (*it)->remaximize(); - } - } - - // don't set these for the 'all desktops' area - if (i < _num_desktops) { - dims[(i * 4) + 0] = _area[i].x(); - dims[(i * 4) + 1] = _area[i].y(); - dims[(i * 4) + 2] = _area[i].width(); - dims[(i * 4) + 3] = _area[i].height(); - } - } - otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_workarea, - otk::Property::atoms.cardinal, dims, 4 * _num_desktops); - delete [] dims; -} - - -void Screen::changeSupportedAtoms() -{ - // create the netwm support window - _supportwindow = XCreateSimpleWindow(**otk::display, - _info->rootWindow(), - 0, 0, 1, 1, 0, 0, 0); - - // set supporting window - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_supporting_wm_check, - otk::Property::atoms.window, _supportwindow); - - //set properties on the supporting window - otk::Property::set(_supportwindow, otk::Property::atoms.net_wm_name, - otk::Property::utf8, "Openbox"); - otk::Property::set(_supportwindow, - otk::Property::atoms.net_supporting_wm_check, - otk::Property::atoms.window, _supportwindow); - - - Atom supported[] = { - otk::Property::atoms.net_current_desktop, - otk::Property::atoms.net_number_of_desktops, - otk::Property::atoms.net_desktop_geometry, - otk::Property::atoms.net_desktop_viewport, - otk::Property::atoms.net_active_window, - otk::Property::atoms.net_workarea, - otk::Property::atoms.net_client_list, - otk::Property::atoms.net_client_list_stacking, - otk::Property::atoms.net_desktop_names, - otk::Property::atoms.net_close_window, - otk::Property::atoms.net_desktop_layout, - otk::Property::atoms.net_showing_desktop, - otk::Property::atoms.net_wm_name, - otk::Property::atoms.net_wm_visible_name, - otk::Property::atoms.net_wm_icon_name, - otk::Property::atoms.net_wm_visible_icon_name, - otk::Property::atoms.net_wm_desktop, - otk::Property::atoms.net_wm_strut, - otk::Property::atoms.net_wm_window_type, - otk::Property::atoms.net_wm_window_type_desktop, - otk::Property::atoms.net_wm_window_type_dock, - otk::Property::atoms.net_wm_window_type_toolbar, - otk::Property::atoms.net_wm_window_type_menu, - otk::Property::atoms.net_wm_window_type_utility, - otk::Property::atoms.net_wm_window_type_splash, - otk::Property::atoms.net_wm_window_type_dialog, - otk::Property::atoms.net_wm_window_type_normal, -/* - otk::Property::atoms.net_wm_moveresize, - otk::Property::atoms.net_wm_moveresize_size_topleft, - otk::Property::atoms.net_wm_moveresize_size_topright, - otk::Property::atoms.net_wm_moveresize_size_bottomleft, - otk::Property::atoms.net_wm_moveresize_size_bottomright, - otk::Property::atoms.net_wm_moveresize_move, -*/ - otk::Property::atoms.net_wm_allowed_actions, - otk::Property::atoms.net_wm_action_move, - otk::Property::atoms.net_wm_action_resize, - otk::Property::atoms.net_wm_action_minimize, - otk::Property::atoms.net_wm_action_shade, -/* otk::Property::atoms.net_wm_action_stick,*/ - otk::Property::atoms.net_wm_action_maximize_horz, - otk::Property::atoms.net_wm_action_maximize_vert, - otk::Property::atoms.net_wm_action_fullscreen, - otk::Property::atoms.net_wm_action_change_desktop, - otk::Property::atoms.net_wm_action_close, - - otk::Property::atoms.net_wm_state, - otk::Property::atoms.net_wm_state_modal, - otk::Property::atoms.net_wm_state_maximized_vert, - otk::Property::atoms.net_wm_state_maximized_horz, - otk::Property::atoms.net_wm_state_shaded, - otk::Property::atoms.net_wm_state_skip_taskbar, - otk::Property::atoms.net_wm_state_skip_pager, - otk::Property::atoms.net_wm_state_hidden, - otk::Property::atoms.net_wm_state_fullscreen, - otk::Property::atoms.net_wm_state_above, - otk::Property::atoms.net_wm_state_below, - }; - const int num_supported = sizeof(supported)/sizeof(Atom); - - otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_supported, - otk::Property::atoms.atom, supported, num_supported); -} - - -void Screen::changeClientList() -{ - Window *windows; - unsigned int size = clients.size(); - - // create an array of the window ids - if (size > 0) { - Window *win_it; - - windows = new Window[size]; - win_it = windows; - std::list<Client*>::const_iterator it = clients.begin(); - const std::list<Client*>::const_iterator end = clients.end(); - for (; it != end; ++it, ++win_it) - *win_it = (*it)->window(); - } else - windows = (Window*) 0; - - otk::Property::set(_info->rootWindow(), otk::Property::atoms.net_client_list, - otk::Property::atoms.window, windows, size); - - if (size) - delete [] windows; - - changeStackingList(); -} - - -void Screen::changeStackingList() -{ - Window *windows; - unsigned int size = _stacking.size(); - - assert(size == clients.size()); // just making sure.. :) - - - // create an array of the window ids (from bottom to top, reverse order!) - if (size > 0) { - Window *win_it; - - windows = new Window[size]; - win_it = windows; - std::list<Client*>::const_reverse_iterator it = _stacking.rbegin(); - const std::list<Client*>::const_reverse_iterator end = _stacking.rend(); - for (; it != end; ++it, ++win_it) - *win_it = (*it)->window(); - } else - windows = (Window*) 0; - - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_client_list_stacking, - otk::Property::atoms.window, windows, size); - - if (size) - delete [] windows; -} - - -void Screen::manageWindow(Window window) -{ - Client *client = 0; - XWMHints *wmhint; - XSetWindowAttributes attrib_set; - XEvent e; - XWindowAttributes attrib; - - otk::display->grab(); - - // check if it has already been unmapped by the time we started mapping - // the grab does a sync so we don't have to here - if (XCheckTypedWindowEvent(**otk::display, window, DestroyNotify, &e) || - XCheckTypedWindowEvent(**otk::display, window, UnmapNotify, &e)) { - XPutBackEvent(**otk::display, &e); - - otk::display->ungrab(); - return; // don't manage it - } - - if (!XGetWindowAttributes(**otk::display, window, &attrib) || - attrib.override_redirect) { - otk::display->ungrab(); - return; // don't manage it - } - - // is the window a docking app - if ((wmhint = XGetWMHints(**otk::display, window))) { - if ((wmhint->flags & StateHint) && - wmhint->initial_state == WithdrawnState) { - //slit->addClient(w); // XXX: make dock apps work! - - otk::display->ungrab(); - XFree(wmhint); - return; - } - XFree(wmhint); - } - - // choose the events we want to receive on the CLIENT window - attrib_set.event_mask = Client::event_mask; - attrib_set.do_not_propagate_mask = Client::no_propagate_mask; - XChangeWindowAttributes(**otk::display, window, - CWEventMask|CWDontPropagate, &attrib_set); - - // create the Client class, which gets all of the hints on the window - client = new Client(_number, window); - // register for events - openbox->registerHandler(window, client); - // add to the wm's map - openbox->addClient(window, client); - - // we dont want a border on the client - client->toggleClientBorder(false); - - // specify that if we exit, the window should not be destroyed and should be - // reparented back to root automatically - XChangeSaveSet(**otk::display, window, SetModeInsert); - - // create the decoration frame for the client window - client->frame = new Frame(client); - // register the plate for events (map req's) - // this involves removing itself from the handler list first, since it is - // auto added to the list, being a widget. we won't get any events on the - // plate except for events for the client (SubstructureRedirectMask) - openbox->clearHandler(client->frame->plate()); - openbox->registerHandler(client->frame->plate(), client); - - // add to the wm's map - Window *w = client->frame->allWindows(); - for (unsigned int i = 0; w[i]; ++i) - openbox->addClient(w[i], client); - delete [] w; - - // reparent the client to the frame - client->frame->grabClient(); - - if (openbox->state() != Openbox::State_Starting) { - // position the window intelligenty .. hopefully :) - // call the python PLACEWINDOW binding - EventData data(_number, client, EventAction::PlaceWindow, 0); - openbox->bindings()->fireEvent(&data); - } - - EventData ddata(_number, client, EventAction::DisplayingWindow, 0); - openbox->bindings()->fireEvent(&ddata); - - client->showhide(); - - client->applyStartupState(); - - otk::display->ungrab(); - - // add to the screen's list - clients.push_back(client); - // once the client is in the list, update our strut to include the new - // client's (it is good that this happens after window placement!) - updateStruts(); - // this puts into the stacking order, then raises it - _stacking.push_back(client); - raiseWindow(client); - // update the root properties - changeClientList(); - - openbox->bindings()->grabButtons(true, client); - - EventData ndata(_number, client, EventAction::NewWindow, 0); - openbox->bindings()->fireEvent(&ndata); - -#ifdef DEBUG - printf("Managed window 0x%lx frame 0x%lx\n", - window, client->frame->window()); -#endif -} - - -void Screen::unmanageWindow(Client *client) -{ - Frame *frame = client->frame; - - // call the python CLOSEWINDOW binding - EventData data(_number, client, EventAction::CloseWindow, 0); - openbox->bindings()->fireEvent(&data); - - openbox->bindings()->grabButtons(false, client); - - // remove from the wm's map - openbox->removeClient(client->window()); - Window *w = frame->allWindows(); - for (unsigned int i = 0; w[i]; ++i) - openbox->addClient(w[i], client); - delete [] w; - // unregister for handling events - openbox->clearHandler(client->window()); - - // remove the window from our save set - XChangeSaveSet(**otk::display, client->window(), SetModeDelete); - - // we dont want events no more - XSelectInput(**otk::display, client->window(), NoEventMask); - - frame->hide(); - - // give the client its border back - client->toggleClientBorder(true); - - // reparent the window out of the frame - frame->releaseClient(); - -#ifdef DEBUG - Window framewin = client->frame->window(); -#endif - delete client->frame; - client->frame = 0; - - // remove from the stacking order - _stacking.remove(client); - - // remove from the screen's list - clients.remove(client); - - // once the client is out of the list, update our strut to remove it's - // influence - updateStruts(); - - // unset modal before dropping our focus - client->_modal = false; - - // unfocus the client (calls the focus callbacks) - if (client->focused()) client->unfocus(); - -#ifdef DEBUG - printf("Unmanaged window 0x%lx frame 0x%lx\n", client->window(), framewin); -#endif - - delete client; - - // update the root properties - changeClientList(); -} - -void Screen::lowerWindow(Client *client) -{ - Window wins[2]; // only ever restack 2 windows. - - assert(!_stacking.empty()); // this would be bad - - std::list<Client*>::iterator it = --_stacking.end(); - const std::list<Client*>::iterator end = _stacking.begin(); - - if (client->modal() && client->transientFor()) { - // don't let a modal window lower below its transient_for - it = std::find(_stacking.begin(), _stacking.end(), client->transientFor()); - assert(it != _stacking.end()); - - wins[0] = (it == _stacking.begin() ? _focuswindow : - ((*(--std::list<Client*>::const_iterator(it)))-> - frame->window())); - wins[1] = client->frame->window(); - if (wins[0] == wins[1]) return; // already right above the window - - _stacking.remove(client); - _stacking.insert(it, client); - } else { - for (; it != end && (*it)->layer() < client->layer(); --it); - if (*it == client) return; // already the bottom, return - - wins[0] = (*it)->frame->window(); - wins[1] = client->frame->window(); - - _stacking.remove(client); - _stacking.insert(++it, client); - } - - XRestackWindows(**otk::display, wins, 2); - changeStackingList(); -} - -void Screen::raiseWindow(Client *client) -{ - Window wins[2]; // only ever restack 2 windows. - - assert(!_stacking.empty()); // this would be bad - - Client *m = client->findModalChild(); - // if we have a modal child, raise it instead, we'll go along tho later - if (m) raiseWindow(m); - - // remove the client before looking so we can't run into ourselves - _stacking.remove(client); - - std::list<Client*>::iterator it = _stacking.begin(); - const std::list<Client*>::iterator end = _stacking.end(); - - // the stacking list is from highest to lowest - for (; it != end && ((*it)->layer() > client->layer() || m == *it); ++it); - - /* - if our new position is the top, we want to stack under the _focuswindow - otherwise, we want to stack under the previous window in the stack. - */ - wins[0] = (it == _stacking.begin() ? _focuswindow : - ((*(--std::list<Client*>::const_iterator(it)))->frame->window())); - wins[1] = client->frame->window(); - - _stacking.insert(it, client); - - XRestackWindows(**otk::display, wins, 2); - - changeStackingList(); -} - -void Screen::changeDesktop(unsigned int desktop) -{ - if (desktop >= _num_desktops) return; - - printf("Moving to desktop %u\n", desktop); - - unsigned int old = _desktop; - - _desktop = desktop; - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_current_desktop, - otk::Property::atoms.cardinal, _desktop); - - if (old == _desktop) return; - - std::list<Client*>::iterator it, end = clients.end(); - for (it = clients.begin(); it != end; ++it) - (*it)->showhide(); - - // force the callbacks to fire - if (!openbox->focusedClient()) - openbox->setFocusedClient(0); -} - -void Screen::changeNumDesktops(unsigned int num) -{ - assert(num > 0); - - if (!(num > 0)) return; - - // move windows on desktops that will no longer exist! - std::list<Client*>::iterator it, end = clients.end(); - for (it = clients.begin(); it != end; ++it) { - unsigned int d = (*it)->desktop(); - if (d >= num && d != 0xffffffff) { - XEvent ce; - ce.xclient.type = ClientMessage; - ce.xclient.message_type = otk::Property::atoms.net_wm_desktop; - ce.xclient.display = **otk::display; - ce.xclient.window = (*it)->window(); - ce.xclient.format = 32; - ce.xclient.data.l[0] = num - 1; - XSendEvent(**otk::display, _info->rootWindow(), false, - SubstructureNotifyMask | SubstructureRedirectMask, &ce); - } - } - - _num_desktops = num; - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_number_of_desktops, - otk::Property::atoms.cardinal, _num_desktops); - - // set the viewport hint - unsigned long *viewport = new unsigned long[_num_desktops * 2]; - memset(viewport, 0, sizeof(unsigned long) * _num_desktops * 2); - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_desktop_viewport, - otk::Property::atoms.cardinal, - viewport, _num_desktops * 2); - delete [] viewport; - - // change our struts/area to match - _area.resize(_num_desktops + 1); - _struts.resize(_num_desktops + 1); - updateStruts(); - - // the number of rows/columns will differ - updateDesktopLayout(); - - // may be some unnamed desktops that we need to fill in with names - updateDesktopNames(); - - // change our desktop if we're on one that no longer exists! - if (_desktop >= _num_desktops) - changeDesktop(_num_desktops - 1); -} - - -void Screen::updateDesktopNames() -{ - unsigned long num; - - if (!otk::Property::get(_info->rootWindow(), - otk::Property::atoms.net_desktop_names, - otk::Property::utf8, &num, &_desktop_names)) - _desktop_names.clear(); - while (_desktop_names.size() < _num_desktops) - _desktop_names.push_back("Unnamed"); -} - - -const otk::Rect& Screen::area(unsigned int desktop) const { - assert(desktop < _num_desktops || desktop == 0xffffffff); - if (desktop < _num_desktops) - return _area[desktop]; - else - return _area[_num_desktops]; -} - -void Screen::installColormap(bool install) const -{ - if (install) - XInstallColormap(**otk::display, _info->colormap()); - else - XUninstallColormap(**otk::display, _info->colormap()); -} - -void Screen::showDesktop(bool show) -{ - if (show == _showing_desktop) return; // no change - - // save the window focus, and restore it when leaving the show-desktop mode - static Window saved_focus = 0; - if (show) { - Client *c = openbox->focusedClient(); - if (c) saved_focus = c->window(); - } - - _showing_desktop = show; - - std::list<Client*>::iterator it, end = clients.end(); - for (it = clients.begin(); it != end; ++it) { - if ((*it)->type() == Client::Type_Desktop) { - if (show) - (*it)->focus(); - } else - (*it)->showhide(); - } - - if (!show) { - Client *f = openbox->focusedClient(); - if (!f || f->type() == Client::Type_Desktop) { - Client *c = openbox->findClient(saved_focus); - if (c) c->focus(); - } - } - - otk::Property::set(_info->rootWindow(), - otk::Property::atoms.net_showing_desktop, - otk::Property::atoms.cardinal, - show ? 1 : 0); -} - -void Screen::propertyHandler(const XPropertyEvent &e) -{ - otk::EventHandler::propertyHandler(e); - - // compress changes to a single property into a single change - XEvent ce; - while (XCheckTypedWindowEvent(**otk::display, _info->rootWindow(), - e.type, &ce)) { - // XXX: it would be nice to compress ALL changes to a property, not just - // changes in a row without other props between. - if (ce.xproperty.atom != e.atom) { - XPutBackEvent(**otk::display, &ce); - break; - } - } - - if (e.atom == otk::Property::atoms.net_desktop_names) - updateDesktopNames(); - else if (e.atom == otk::Property::atoms.net_desktop_layout) - updateDesktopLayout(); -} - - -void Screen::clientMessageHandler(const XClientMessageEvent &e) -{ - otk::EventHandler::clientMessageHandler(e); - - if (e.format != 32) return; - - if (e.message_type == otk::Property::atoms.net_current_desktop) { - changeDesktop(e.data.l[0]); - } else if (e.message_type == otk::Property::atoms.net_number_of_desktops) { - changeNumDesktops(e.data.l[0]); - } else if (e.message_type == otk::Property::atoms.net_showing_desktop) { - showDesktop(e.data.l[0] != 0); - } -} - - -void Screen::mapRequestHandler(const XMapRequestEvent &e) -{ - otk::EventHandler::mapRequestHandler(e); - -#ifdef DEBUG - printf("MapRequest for 0x%lx\n", e.window); -#endif // DEBUG - - Client *c = openbox->findClient(e.window); - if (c) { -#ifdef DEBUG - printf("DEBUG: MAP REQUEST CAUGHT IN SCREEN. IGNORED.\n"); -#endif - } else { - if (_showing_desktop) - showDesktop(false); // leave showing-the-desktop mode - manageWindow(e.window); - } -} - -}
D src/screen.hh

@@ -1,230 +0,0 @@

-// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifndef __screen_hh -#define __screen_hh - -/*! @file screen.hh - @brief Screen manages a single screen -*/ - -extern "C" { -#include <X11/Xlib.h> -} - -#include "otk/strut.hh" -#include "otk/rect.hh" -#include "otk/screeninfo.hh" -#include "otk/eventhandler.hh" -#include "otk/property.hh" -#include "otk/ustring.hh" - -#include <string> -#include <list> - -namespace ob { - -class Client; - -struct DesktopLayout { - enum Corner { TopLeft, TopRight, BottomRight, BottomLeft }; - enum Direction { Horizontal, Vertical }; - - Direction orientation; - Corner start_corner; - unsigned int rows; - unsigned int columns; -}; - -//! Manages a single screen -/*! -*/ -class Screen : public otk::EventHandler { -public: - //! Holds a list of otk::Strut objects - typedef std::vector<otk::Strut> StrutList; - //! Holds a list of otk::Rect objects - typedef std::vector<otk::Rect> RectList; - - static const unsigned long event_mask = ColormapChangeMask | - EnterWindowMask | - LeaveWindowMask | - PropertyChangeMask | - SubstructureNotifyMask | - SubstructureRedirectMask | - ButtonPressMask | - ButtonReleaseMask; - - //! All managed clients on the screen (in order of being mapped) - std::list<Client*> clients; - -private: - //! Was %Openbox able to manage the screen? - bool _managed; - - //! The number of the screen on the X server - int _number; - - //! Information about this screen - const otk::ScreenInfo *_info; - - //! Area usable for placement etc (total - struts), one per desktop, - //! plus one extra for windows on all desktops - RectList _area; - - //! Combined strut from all of the clients' struts, one per desktop, - //! plus one extra for windows on all desktops - StrutList _struts; - - //! An offscreen window which gets focus when nothing else has it - Window _focuswindow; - - //! An offscreen window which shows that a NETWM compliant window manager is - //! running - Window _supportwindow; - - //! A list of all managed clients on the screen, in their stacking order - std::list<Client*> _stacking; - - //! The desktop currently being displayed - unsigned int _desktop; - - //! The number of desktops - unsigned int _num_desktops; - - //! The names of all desktops - otk::Property::StringVect _desktop_names; - - //! The layout of the desktops as specified by an EWMH compliant pager - DesktopLayout _layout; - - //! True when the window manager is in 'showing desktop' mode - bool _showing_desktop; - - //! Calculate the Screen::_area member - void calcArea(); - //! Set the list of supported NETWM atoms on the root window - void changeSupportedAtoms(); - //! Set the client list on the root window - /*! - Sets the _NET_CLIENT_LIST root window property.<br> - Also calls Screen::updateStackingList. - */ - void changeClientList(); - //! Set the client stacking list on the root window - /*! - Set the _NET_CLIENT_LIST_STACKING root window property. - */ - void changeStackingList(); - //! Set the work area hint on the root window - /*! - Set the _NET_WORKAREA root window property. - */ - void changeWorkArea(); - - //! Get desktop names from the root window property - void updateDesktopNames(); - - //! Gets the layout of the desktops from the root window property - void updateDesktopLayout(); - - //! Changes to the specified desktop, displaying windows on it and hiding - //! windows on the others. - /*! - @param desktop The number of the desktop to switch to (starts from 0). - If the desktop is out of valid range, it is ignored. - */ - void changeDesktop(unsigned int desktop); - - //! Changes the number of desktops. - /*! - @param num The number of desktops that should exist. This value must be - greater than 0 or it will be ignored. - */ - void changeNumDesktops(unsigned int num); - -public: - //! Constructs a new Screen object - Screen(int screen); - //! Destroys the Screen object - virtual ~Screen(); - - inline int number() const { return _number; } - - //! Returns if the screen was successfully managed - /*! - If this is false, then the screen should be deleted and should NOT be - used. - */ - inline bool managed() const { return _managed; } - - //! An offscreen window which gets focus when nothing else has it - inline Window focuswindow() const { return _focuswindow; } - //! Returns the desktop being displayed - inline unsigned int desktop() const { return _desktop; } - //! Returns the number of desktops - inline unsigned int numDesktops() const { return _num_desktops; } - //! When true, the desktop is being shown and all clients are hidden - inline bool showingDesktop() const { return _showing_desktop; } - - //! Returns the area of the screen not reserved by applications' Struts - /*! - @param desktop The desktop number of the area to retrieve for. A value of - 0xffffffff will return an area that combines all struts - on all desktops. - */ - const otk::Rect& area(unsigned int desktop) const; - - //! Gives the layout of how the desktops are being displayed, the number of - //! rows and columns etc. - const DesktopLayout& desktopLayout() const { return _layout; } - - //! Shows and focuses the desktop and hides all the client windows, or - //! returns to the normal state, showing client windows. - void showDesktop(bool show); - - //! Update's the screen's combined strut of all the clients. - /*! - Clients should call this whenever they change their strut. - */ - void updateStruts(); - - //! Manage any pre-existing windows on the screen - void manageExisting(); - //! Manage a client window - /*! - This gives the window a frame, reparents it, selects events on it, etc. - */ - void manageWindow(Window window); - //! Unmanage a client - /*! - This removes the window's frame, reparents it to root, unselects events on - it, etc. - @param client The client to unmanage - */ - void unmanageWindow(Client *client); - - //! Raises a client window above all others in its stacking layer - /*! - raiseWindow has a couple of constraints that lowerWindow does not.<br> - 1) raiseWindow can be called after changing a Client's stack layer, and - the list will be reorganized properly.<br> - 2) raiseWindow guarantees that XRestackWindows() will <i>always</i> be - called for the specified client. - */ - void raiseWindow(Client *client); - - //! Lowers a client window below all others in its stacking layer - void lowerWindow(Client *client); - - const otk::Property::StringVect& desktopNames() const - { return _desktop_names; } - - void installColormap(bool install) const; - - virtual void propertyHandler(const XPropertyEvent &e); - virtual void clientMessageHandler(const XClientMessageEvent &e); - virtual void mapRequestHandler(const XMapRequestEvent &e); -}; - -} - -#endif// __screen_hh