kill the c dir

This commit is contained in:
Dana Jansens 2003-03-21 07:54:23 +00:00
parent 474f689132
commit a648c05a7a
40 changed files with 0 additions and 8241 deletions

View file

@ -1,5 +0,0 @@
ob3
Makefile.in
.libs
.deps
Makefile

View file

@ -1,34 +0,0 @@
localedir=$(datadir)/locale
scriptdir = $(libdir)/openbox/python
CPPFLAGS=$(PYTHON_CFLAGS) $(GLIB_CFLAGS) @CPPFLAGS@ \
-DLOCALEDIR=\"$(localedir)\" \
-DSCRIPTDIR=\"$(scriptdir)\" \
-DG_LOG_DOMAIN=\"Openbox\"
LIBS=$(PYTHON_LIBS) $(GLIB_LIBS) @LIBS@
bin_PROGRAMS= ob3
ob3_LDADD=@LIBINTL@
ob3_LDFLAGS=-export-dynamic
ob3_SOURCES=client.c event.c extensions.c focus.c frame.c openbox.c prop.c \
python.c screen.c stacking.c xerror.c hooks.c eventdata.c obexport.c \
clientwrap.c screenwrap.c kbind.c mbind.c
noinst_HEADERS=client.h event.h extensions.h focus.h frame.h geom.h gettext.h \
openbox.h prop.h python.h screen.h stacking.h xerror.h hooks.h \
eventdata.h clientwrap.h obexport.h screenwrap.h kbind.h mbind.h
MAINTAINERCLEANFILES= Makefile.in
#if CVS
#ob3.i: $(wildcard *.h)
# @touch $@
#ob3_wrap.c: ob3.i
# $(SWIG) $(SWIG_PYTHON_OPT) $(filter -I%,$(CPPFLAGS)) -o $@ $<
#endif
distclean-local:
$(RM) *\~ *.orig *.rej .\#*

1869
c/client.c

File diff suppressed because it is too large Load diff

View file

@ -1,401 +0,0 @@
#ifndef __client_h
#define __client_h
#include "geom.h"
#include "obexport.h"
#include <glib.h>
#include <X11/Xlib.h>
struct ClientWrap;
struct Frame;
/*! Holds an icon in ARGB format */
typedef struct Icon {
unsigned long w, h;
unsigned long *data;
} Icon;
/*! 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.
*/
typedef struct MwmHints {
/*! A bitmask of Client::MwmFlags values */
unsigned long flags;
/*! A bitmask of Client::MwmFunctions values */
unsigned long functions;
/*! A bitmask of Client::MwmDecorations values */
unsigned long decorations;
} MwmHints;
/*! The number of elements in the Client::MwmHints struct */
#define MWM_ELEMENTS 3
/*! Possible flags for MWM Hints (defined by Motif 2.0) */
typedef enum {
MwmFlag_Functions = 1 << 0, /*!< The MMW Hints define funcs */
MwmFlag_Decorations = 1 << 1 /*!< The MWM Hints define decor */
} MwmFlags;
/*! Possible functions for MWM Hints (defined by Motif 2.0) */
typedef enum {
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 */
} MwmFunctions;
/*! Possible decorations for MWM Hints (defined by Motif 2.0) */
typedef enum {
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 */
} MemDecorations;
typedef struct Client {
Window window;
struct Frame *frame;
/*! The number of unmap events to ignore on the window */
int ignore_unmaps;
/*! The id of the group the window belongs to */
Window group;
/*! Whether or not the client is a transient window. This is guaranteed to
be TRUE if transient_for != NULL, but not guaranteed to be FALSE if
transient_for == NULL. */
gboolean transient;
/*! The client which this client is a transient (child) for */
struct Client *transient_for;
/*! The clients which are transients (children) of this client */
GSList *transients;
/*! The desktop on which the window resides (0xffffffff for all
desktops) */
unsigned int desktop;
/*! Normal window title */
gchar *title;
/*! Window title when iconified */
gchar *icon_title;
/*! The application that created the window */
gchar *res_name;
/*! The class of the window, can used for grouping */
gchar *res_class;
/*! The specified role of the window, used for identification */
gchar *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.
*/
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.
*/
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.
*/
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.
*/
guint 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
*/
Size min_size;
/*! The maximum size of the client window
If the min is > the max, then the window is not resizable
*/
Size max_size;
/*! The size of increments to resize the client window by */
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
*/
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 */
gboolean delete_window;
/*! Was the window's position requested by the application? if not, we
should place the window ourselves when it first appears */
gboolean positioned;
/*! Can the window receive input focus? */
gboolean can_focus;
/*! Urgency flag */
gboolean urgent;
/*! Notify the window when it receives focus? */
gboolean focus_notify;
/*! Does the client window have the input focus? */
gboolean focused;
/*! The window uses shape extension to be non-rectangular? */
gboolean shaped;
/*! The window is modal, so it must be processed before any windows it is
related to can be focused */
gboolean modal;
/*! Only the window's titlebar is displayed */
gboolean shaded;
/*! The window is iconified */
gboolean iconic;
/*! The window is maximized to fill the screen vertically */
gboolean max_vert;
/*! The window is maximized to fill the screen horizontally */
gboolean max_horz;
/*! The window should not be displayed by pagers */
gboolean skip_pager;
/*! The window should not be displayed by taskbars */
gboolean skip_taskbar;
/*! The window is a 'fullscreen' window, and should be on top of all
others */
gboolean fullscreen;
/*! The window should be on top of other windows of the same type */
gboolean above;
/*! The window should be underneath other windows of the same type */
gboolean 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 Decoration enum
The values in the variable are the decorations that the client wants to
be displayed around it.
*/
int decorations;
/*! A bitmask of values in the Decoration enum.
Specifies the decorations that should NOT be displayed on the client.
*/
int disabled_decorations;
/*! A bitmask of values in the Function enum
The values in the variable specify the ways in which the user is allowed
to modify this window.
*/
int functions;
/*! Icons for the client as specified on the client window */
Icon *icons;
/*! The number of icons in icons */
int nicons;
/*! The icon for the client specified in the WMHints or the KWM hints */
Pixmap pixmap_icon;
/*! The mask for the pixmap_icon, or None if its not masked */
Pixmap pixmap_icon_mask;
/* The instance of the wrapper class if one exists */
struct ClientWrap *wrap;
} Client;
extern GSList *client_list;
extern GHashTable *client_map;
void client_startup();
void client_shutdown();
/*! Manages all existing windows */
void client_manage_all();
/*! Manages a given window */
void client_manage(Window win);
/*! Unmanages all managed windows */
void client_unmanage_all();
/*! Unmanages a given client */
void client_unmanage(Client *client);
/*! Sets the client list on the root window from the client_list */
void client_set_list();
/*! Reapplies the maximized state to the window
Use this to make the window readjust its maximized size to new
surroundings (struts, etc). */
void client_remaximize(Client *self);
/*! Shows the window if it should be shown, or hides it
Used when changing desktops, the window's state, etc. */
void client_showhide(Client *self);
/*! 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. */
gboolean client_normal(Client *self);
/*! 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 x The x coordiante of the new position for the client.
@param y The y coordiante of the new position for the client.
@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. For program requested changes, the
constraints are not checked.
@param final If user is true, then this should specify if this is a final
configuration. e.g. Final should be FALSE if doing an
interactive move/resize, and then be TRUE for the last call
only.
*/
void client_configure(Client *self, Corner anchor, int x, int y, int w, int h,
gboolean user, gboolean final);
/*! 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 client_fullscreen(Client *self, gboolean fs, gboolean savearea);
/*! 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 client_iconify(Client *self, gboolean iconic, gboolean curdesk);
/*! 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 client_maximize(Client *self, gboolean max, int dir,
gboolean savearea);
/*! Shades or unshades the client window
@param shade true if the window should be shaded; false if it should be
unshaded.
*/
void client_shade(Client *self, gboolean shade);
/*! Request the client to close its window. */
void client_close(Client *self);
/*! Sends the window to the specified desktop */
void client_set_desktop(Client *self, unsigned int target);
/*! Return a modal child of the client window
@return A modal child of the client window, or 0 if none was found.
*/
Client *client_find_modal_child(Client *self);
/*! 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.
*/
gboolean client_validate(Client *self);
/*! Sets the wm_state to the specified value */
void client_set_wm_state(Client *self, 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_apply_startup_state is used to do the same things during the mapping
process.
*/
void client_set_state(Client *self, Atom action, long data1, long data2);
/*! Attempt to focus the client window */
gboolean client_focus(Client *self);
/*! Remove focus from the client window */
void client_unfocus(Client *self);
/*! Calculates the stacking layer for the client window */
void client_calc_layer(Client *self);
/*! Updates the window's transient status, and any parents of it */
void client_update_transient_for(Client *self);
/*! Update the protocols that the window supports and adjusts things if they
change */
void client_update_protocols(Client *self);
/*! Updates the WMNormalHints and adjusts things if they change */
void client_update_normal_hints(Client *self);
/*! 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 client_update_wmhints(Client *self);
/*! Updates the window's title */
void client_update_title(Client *self);
/*! Updates the window's icon title */
void client_update_icon_title(Client *self);
/*! Updates the window's application name and class */
void client_update_class(Client *self);
/*! Updates the strut for the client */
void client_update_strut(Client *self);
/*! Updates the window's icons */
void client_update_icons(Client *self);
/*! Updates the window's kwm icon */
void client_update_kwm_icon(Client *self);
/*! 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 client_setup_decor_and_functions(Client *self);
/*! Retrieves the window's type and sets Client->type */
void client_get_type(Client *self);
#endif

View file

@ -1,792 +0,0 @@
#include "clientwrap.h"
#include "client.h"
#include "frame.h"
#include "stacking.h"
#include "focus.h"
#include <glib.h>
/***************************************************************************
Define the type 'ClientWrap'
***************************************************************************/
#define IS_CWRAP(v) ((v)->ob_type == &ClientWrapType)
#define IS_VALID_CWRAP(v) ((v)->client != NULL)
#define CHECK_CWRAP(self, funcname) { \
if (!IS_CWRAP(self)) { \
PyErr_SetString(PyExc_TypeError, \
"descriptor '" funcname "' requires a 'Client' " \
"object"); \
return NULL; \
} \
if (!IS_VALID_CWRAP(self)) { \
PyErr_SetString(PyExc_ValueError, \
"This 'Client' is wrapping a client which no longer "\
"exists."); \
return NULL; \
} \
}
staticforward PyTypeObject ClientWrapType;
/***************************************************************************
Attribute methods
***************************************************************************/
static PyObject *cwrap_window(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "window");
if (!PyArg_ParseTuple(args, ":window"))
return NULL;
return PyInt_FromLong(self->client->window);
}
static PyObject *cwrap_group(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "group");
if (!PyArg_ParseTuple(args, ":group"))
return NULL;
return PyInt_FromLong(self->client->group);
}
static PyObject *cwrap_parent(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "parent");
if (!PyArg_ParseTuple(args, ":parent"))
return NULL;
if (self->client->transient_for != NULL)
return clientwrap_new(self->client->transient_for);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *cwrap_children(ClientWrap *self, PyObject *args)
{
PyObject *list;
GSList *it;
guint i, s;
CHECK_CWRAP(self, "children");
if (!PyArg_ParseTuple(args, ":children"))
return NULL;
s = g_slist_length(self->client->transients);
list = PyList_New(s);
for (i = 0, it = self->client->transients; i < s; ++i, it = it->next)
PyList_SET_ITEM(list, i, clientwrap_new(it->data));
return list;
}
static PyObject *cwrap_desktop(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "desktop");
if (!PyArg_ParseTuple(args, ":desktop"))
return NULL;
return PyInt_FromLong(self->client->desktop);
}
static PyObject *cwrap_title(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "title");
if (!PyArg_ParseTuple(args, ":title"))
return NULL;
return PyString_FromString(self->client->title);
}
static PyObject *cwrap_iconTitle(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "iconTitle");
if (!PyArg_ParseTuple(args, ":iconTitle"))
return NULL;
return PyString_FromString(self->client->icon_title);
}
static PyObject *cwrap_resName(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "resName");
if (!PyArg_ParseTuple(args, ":resName"))
return NULL;
return PyString_FromString(self->client->res_name);
}
static PyObject *cwrap_resClass(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "resClass");
if (!PyArg_ParseTuple(args, ":resClass"))
return NULL;
return PyString_FromString(self->client->res_class);
}
static PyObject *cwrap_role(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "role");
if (!PyArg_ParseTuple(args, ":role"))
return NULL;
return PyString_FromString(self->client->role);
}
static PyObject *cwrap_type(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "type");
if (!PyArg_ParseTuple(args, ":type"))
return NULL;
return PyInt_FromLong(self->client->type);
}
static PyObject *cwrap_area(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "area");
if (!PyArg_ParseTuple(args, ":area"))
return NULL;
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->area.x));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->area.y));
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(self->client->area.width));
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(self->client->area.height));
return tuple;
}
static PyObject *cwrap_screenArea(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "screenArea");
if (!PyArg_ParseTuple(args, ":screenArea"))
return NULL;
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->frame->area.x));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->frame->area.y));
PyTuple_SET_ITEM(tuple, 2,
PyInt_FromLong(self->client->frame->area.width));
PyTuple_SET_ITEM(tuple, 3,
PyInt_FromLong(self->client->frame->area.height));
return tuple;
}
static PyObject *cwrap_strut(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "strut");
if (!PyArg_ParseTuple(args, ":strut"))
return NULL;
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->strut.left));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->strut.top));
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(self->client->strut.right));
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(self->client->strut.bottom));
return tuple;
}
static PyObject *cwrap_logicalSize(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "logicalSize");
if (!PyArg_ParseTuple(args, ":logicalSize"))
return NULL;
tuple = PyTuple_New(2);
PyTuple_SET_ITEM(tuple, 0,
PyInt_FromLong(self->client->logical_size.width));
PyTuple_SET_ITEM(tuple, 1,
PyInt_FromLong(self->client->logical_size.height));
return tuple;
}
static PyObject *cwrap_minRatio(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "minRatio");
if (!PyArg_ParseTuple(args, ":minRatio"))
return NULL;
return PyFloat_FromDouble(self->client->min_ratio);
}
static PyObject *cwrap_maxRatio(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "maxRatio");
if (!PyArg_ParseTuple(args, ":maxRatio"))
return NULL;
return PyFloat_FromDouble(self->client->max_ratio);
}
static PyObject *cwrap_minSize(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "minSize");
if (!PyArg_ParseTuple(args, ":minSize"))
return NULL;
tuple = PyTuple_New(2);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->min_size.width));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->min_size.height));
return tuple;
}
static PyObject *cwrap_maxSize(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "maxSize");
if (!PyArg_ParseTuple(args, ":maxSize"))
return NULL;
tuple = PyTuple_New(2);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->max_size.width));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->max_size.height));
return tuple;
}
static PyObject *cwrap_sizeIncrement(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "sizeIncrement");
if (!PyArg_ParseTuple(args, ":sizeIncrement"))
return NULL;
tuple = PyTuple_New(2);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->size_inc.width));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->size_inc.height));
return tuple;
}
static PyObject *cwrap_baseSize(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "baseSize");
if (!PyArg_ParseTuple(args, ":baseSize"))
return NULL;
tuple = PyTuple_New(2);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->base_size.width));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->base_size.height));
return tuple;
}
static PyObject *cwrap_gravity(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "gravity");
if (!PyArg_ParseTuple(args, ":gravity"))
return NULL;
return PyInt_FromLong(self->client->gravity);
}
static PyObject *cwrap_canClose(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "canClose");
if (!PyArg_ParseTuple(args, ":canClose"))
return NULL;
return PyInt_FromLong(self->client->delete_window ? 1 : 0);
}
static PyObject *cwrap_positionRequested(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "positionRequested");
if (!PyArg_ParseTuple(args, ":positionRequested"))
return NULL;
return PyInt_FromLong(self->client->positioned ? 1 : 0);
}
static PyObject *cwrap_canFocus(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "canFocus");
if (!PyArg_ParseTuple(args, ":canFocus"))
return NULL;
return PyInt_FromLong(self->client->can_focus ||
self->client->focus_notify);
}
static PyObject *cwrap_urgent(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "urgent");
if (!PyArg_ParseTuple(args, ":urgent"))
return NULL;
return PyInt_FromLong(self->client->urgent ? 1 : 0);
}
static PyObject *cwrap_focused(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "focused");
if (!PyArg_ParseTuple(args, ":focused"))
return NULL;
return PyInt_FromLong(self->client->focused ? 1 : 0);
}
static PyObject *cwrap_modal(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "modal");
if (!PyArg_ParseTuple(args, ":modal"))
return NULL;
return PyInt_FromLong(self->client->modal ? 1 : 0);
}
static PyObject *cwrap_shaded(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "shaded");
if (!PyArg_ParseTuple(args, ":shaded"))
return NULL;
return PyInt_FromLong(self->client->shaded ? 1 : 0);
}
static PyObject *cwrap_iconic(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "iconic");
if (!PyArg_ParseTuple(args, ":iconc"))
return NULL;
return PyInt_FromLong(self->client->iconic ? 1 : 0);
}
static PyObject *cwrap_maximizedVertical(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "maximizedVertical");
if (!PyArg_ParseTuple(args, ":maximizedVertical"))
return NULL;
return PyInt_FromLong(self->client->max_vert ? 1 : 0);
}
static PyObject *cwrap_maximizedHorizontal(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "maximizedHorizontal");
if (!PyArg_ParseTuple(args, ":maximizedHorizontal"))
return NULL;
return PyInt_FromLong(self->client->max_horz ? 1 : 0);
}
static PyObject *cwrap_skipPager(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "skipPager");
if (!PyArg_ParseTuple(args, ":skipPager"))
return NULL;
return PyInt_FromLong(self->client->skip_pager ? 1 : 0);
}
static PyObject *cwrap_skipTaskbar(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "skipTaskbar");
if (!PyArg_ParseTuple(args, ":skipTaskbar"))
return NULL;
return PyInt_FromLong(self->client->skip_taskbar ? 1 : 0);
}
static PyObject *cwrap_fullscreen(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "fullscreen");
if (!PyArg_ParseTuple(args, ":fullscreen"))
return NULL;
return PyInt_FromLong(self->client->fullscreen ? 1 : 0);
}
static PyObject *cwrap_above(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "above");
if (!PyArg_ParseTuple(args, ":above"))
return NULL;
return PyInt_FromLong(self->client->above ? 1 : 0);
}
static PyObject *cwrap_below(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "below");
if (!PyArg_ParseTuple(args, ":below"))
return NULL;
return PyInt_FromLong(self->client->below ? 1 : 0);
}
static PyObject *cwrap_layer(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "layer");
if (!PyArg_ParseTuple(args, ":layer"))
return NULL;
return PyInt_FromLong(self->client->layer);
}
static PyObject *cwrap_decorations(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "decorations");
if (!PyArg_ParseTuple(args, ":decorations"))
return NULL;
return PyInt_FromLong(self->client->decorations);
}
static PyObject *cwrap_disabledDecorations(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "disabledDecorations");
if (!PyArg_ParseTuple(args, ":disabledDecorations"))
return NULL;
return PyInt_FromLong(self->client->disabled_decorations);
}
static PyObject *cwrap_functions(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "functions");
if (!PyArg_ParseTuple(args, ":functions"))
return NULL;
return PyInt_FromLong(self->client->functions);
}
static PyObject *cwrap_visible(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "visible");
if (!PyArg_ParseTuple(args, ":visible"))
return NULL;
return PyInt_FromLong(self->client->frame->visible ? 1 : 0);
}
static PyObject *cwrap_decorationSize(ClientWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_CWRAP(self, "decorationSize");
if (!PyArg_ParseTuple(args, ":decorationSize"))
return NULL;
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->client->frame->size.left));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->client->frame->size.top));
PyTuple_SET_ITEM(tuple, 2,
PyInt_FromLong(self->client->frame->size.right));
PyTuple_SET_ITEM(tuple, 3,
PyInt_FromLong(self->client->frame->size.bottom));
return tuple;
}
static PyObject *cwrap_normal(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "normal");
if (!PyArg_ParseTuple(args, ":normal"))
return NULL;
return PyInt_FromLong(client_normal(self->client) ? 1 : 0);
}
static PyObject *cwrap_setVisible(ClientWrap *self, PyObject *args)
{
int i;
CHECK_CWRAP(self, "setVisible");
if (!PyArg_ParseTuple(args, "i:setVisible", &i))
return NULL;
if (i)
frame_show(self->client->frame);
else
frame_hide(self->client->frame);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *cwrap_raiseWindow(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "raiseWindow");
if (!PyArg_ParseTuple(args, ":raiseWindow"))
return NULL;
stacking_raise(self->client);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *cwrap_lowerWindow(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "lowerWindow");
if (!PyArg_ParseTuple(args, ":lowerWindow"))
return NULL;
stacking_lower(self->client);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *cwrap_focus(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "focus");
if (!PyArg_ParseTuple(args, ":focus"))
return NULL;
return PyInt_FromLong(client_focus(self->client) ? 1 : 0);
}
static PyObject *cwrap_unfocus(ClientWrap *self, PyObject *args)
{
CHECK_CWRAP(self, "unfocus");
if (!PyArg_ParseTuple(args, ":unfocus"))
return NULL;
client_unfocus(self->client);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *cwrap_move(ClientWrap *self, PyObject *args)
{
int x, y;
int final = TRUE;
CHECK_CWRAP(self, "move");
if (!PyArg_ParseTuple(args, "ii|i:unfocus", &x, &y, &final))
return NULL;
/* get the client's position based on x,y for the frame */
frame_frame_gravity(self->client->frame, &x, &y);
client_configure(self->client, Corner_TopLeft, x, y,
self->client->area.width, self->client->area.height,
TRUE, final);
Py_INCREF(Py_None);
return Py_None;
}
#define ATTRMETH(n, d) {#n, (PyCFunction)cwrap_##n, METH_VARARGS, #d}
static PyMethodDef ClientWrapMethods[] = {
ATTRMETH(window,
"c.window() -- Returns the window id for the Client."),
ATTRMETH(group,
"c.group() -- Returns the group id for the Client."),
ATTRMETH(parent,
"c.parent() -- Returns the parent Client for the Client, or the "
"Client for which this Client is a transient. Returns None if it "
"is not a transient."),
ATTRMETH(children,
"c.parent() -- Returns a list of child Clients for the Client, "
"or the Clients transients."),
ATTRMETH(desktop,
"c.desktop() -- Returns the desktop on which the Client resides, "
"or 0xffffffff for 'all desktops'."),
ATTRMETH(title,
"c.title() -- Returns the Client's title string. This is in "
"UTF-8 encoding."),
ATTRMETH(iconTitle,
"c.iconTitle() -- Returns the Client's icon title string. This "
"is in UTF-8 encoding."),
ATTRMETH(resName,
"c.resName() -- Returns the application's specified resource "
"name."),
ATTRMETH(resClass,
"c.resClass() -- Returns the application's specified resource "
"class."),
ATTRMETH(role,
"c.role() -- Returns the window's role, which should be unique "
"for every window of an application, if it is not empty."),
ATTRMETH(type,
"c.type() -- Returns the window's type, one of the ob.Type_ "
"constants. This is the logical type of the window."),
ATTRMETH(area,
"c.area() -- Returns the area rectangle for the Client in a "
"tuple. The tuple's format is (x, y, width, height). This is "
"not the area on-screen that the Client and frame occupies, but "
"rather, the position and size that the Client has requested, "
"before its gravity() and decorations have been applied. You "
"should use the c.screenArea() to get the actual on-screen area "
"for the Client."),
ATTRMETH(screenArea,
"c.screenArea() -- Returns the on-screen area rectangle for the "
"Client in a tuple. The tuple's format is (x, y, width, height). "
"This is the actual position and size of the Client plus its "
"decorations."),
ATTRMETH(strut,
"c.strut() -- Returns the strut requested by the Client in a "
"tuple. The format of the tuple is (left, top, right, bottom)."),
ATTRMETH(logicalSize,
"c.logicalSize() -- Returns the logical size of the Client. This "
"is the 'user friendly' size for the Client, such as for an "
"xterm, it will be the number of characters in the xterm "
"instead of the number of pixels it takes up."),
ATTRMETH(minRatio,
"c.minRatio() -- Returns the minimum width:height ratio for "
"the Client. A value of 0 implies no ratio enforcement."),
ATTRMETH(maxRatio,
"c.maxRatio() -- Returns the maximum width:height ratio for "
"the Client. A value of 0 implies no ratio enforcement."),
ATTRMETH(minSize,
"c.minSize() -- Returns the minimum size of the Client."),
ATTRMETH(maxSize,
"c.maxSize() -- Returns the maximum size of the Client."),
ATTRMETH(sizeIncrement,
"c.sizeIncrement() -- Returns the size increments in which the "
"Client must be resized."),
ATTRMETH(baseSize,
"c.baseSize() -- Returns the base size of the Client, which is "
"subtracted from the Client's size before comparing to its "
"various sizing constraints."),
ATTRMETH(gravity,
"c.gravity() -- Returns the gravity for the Client. One of the "
"ob.Gravity_ constants."),
ATTRMETH(canClose,
"c.canClose() -- Returns whether or not the Client provides a "
"means for Openbox to request that it close."),
ATTRMETH(positionRequested,
"c.positionRequested() -- Returns whether or not the Client has "
"requested a specified position on screen. When it has it should "
"probably not be placed using an algorithm when it is managed."),
ATTRMETH(canFocus,
"c.canFocus() -- Returns whether or not the Client can be "
"given input focus."),
ATTRMETH(urgent,
"c.urgent() -- Returns the urgent state of the window (on/off)."),
ATTRMETH(focused,
"c.focused() -- Returns whether or not the Client has the input "
"focus."),
ATTRMETH(modal,
"c.modal() -- Returns whether or not the Client is modal. A "
"modal Client implies that it needs to be closed before its "
"parent() can be used (focsed) again."),
ATTRMETH(shaded,
"c.shaded() -- Returns whether or not the Client is shaded. "
"Shaded clients are hidden except for their titlebar."),
ATTRMETH(iconic,
"c.iconic() -- Returns whether or not the Client is iconic. "
"Iconic windows are represented only by icons, or possibly "
"hidden entirely."),
ATTRMETH(maximizedVertical,
"c.maximizedVertical() -- Returns whether or not the Client is "
"maxized vertically. When a Client is maximized it will expand "
"to fill as much of the screen as it can in that direction."),
ATTRMETH(maximizedHorizontal,
"c.maximizedHorizontal() -- Returns whether or not the Client is "
"maxized horizontally. When a Client is maximized it will expand "
"to fill as much of the screen as it can in that direction."),
ATTRMETH(skipPager,
"c.skipPager() -- Returns whether the Client as requested to be "
"skipped by pagers."),
ATTRMETH(skipTaskbar,
"c.skipTaskbar() -- Returns whether the Client as requested to "
"be skipped by taskbars."),
ATTRMETH(fullscreen,
"c.fullscreen() -- Returns whether the Client is in fullscreen "
"mode."),
ATTRMETH(above,
"c.above() -- Returns whether the Client should be stacked above "
"other windows of the same type."),
ATTRMETH(below,
"c.below() -- Returns whether the Client should be stacked below "
"other windows of the same type."),
ATTRMETH(layer,
"c.layer() -- Returns the layer in which the window should be "
"stacked. This is one of the ob.Layer_ constants. Windows in "
"layers with higher values should be kept above windows in lower "
"valued layers."),
ATTRMETH(decorations,
"c.decorations() -- Returns a mask of decorations which the "
"Client will be given. It is made up of the ob.Decor_ constants. "
"These can be turned off with the "
" disabledDecorations()."),
ATTRMETH(disabledDecorations,
"c.disabledDecorations() -- returns a mask of decorations which "
"are disabled on the Client. This is made up of the ob.Decor_ "
"constants."),
ATTRMETH(functions,
"ob.functions() -- Returns the list of functionality for the "
"Client, in a mask made up of the ob.Func_ constants."),
ATTRMETH(visible,
"ob.visible() -- Returns if the client is currently visible "
"or hidden."),
ATTRMETH(decorationSize,
"c.decorationSize() -- Returns the size of the Client's "
"decorations around the Client window, in a tuple. The format of "
"the tuple is (left, top, right, bottom)."),
ATTRMETH(normal,
"c.normal() -- Returns if the window should be treated as a "
"normal window. Some windows (desktops, docks, splash screens) "
"should have special rules applied to them in a number of "
"places regarding focus or user interaction."),
ATTRMETH(setVisible,
"c.setVisible(show) -- Shows or hides the Client."),
ATTRMETH(raiseWindow,
"c.raiseWindow() -- Raises the Client to the top of its layer."),
ATTRMETH(lowerWindow,
"c.lowerWindow() -- Lowers the Client to the bottom of its "
"layer."),
ATTRMETH(focus,
"c.focus() -- Focuses the Client. Returns 1 if the Client will "
"be focused, or 0 if it will not."),
ATTRMETH(unfocus,
"c.unfocus() -- Unfocuses the Client, leaving nothing focused."),
ATTRMETH(move,
"c.move(x, y) -- Moves the Client to the specified position. The "
"top left corner of the Client's decorations is positioned at "
"the given x, y."),
{ NULL, NULL, 0, NULL }
};
/***************************************************************************
Type methods/struct
***************************************************************************/
/*static PyObject *cwrap_getattr(ClientWrap *self, char *name)
{
CHECK_CWRAP(self, "getattr");
return Py_FindMethod(ClientWrapAttributeMethods, (PyObject*)self, name);
}*/
static void cwrap_dealloc(ClientWrap *self)
{
if (self->client != NULL)
self->client->wrap = NULL;
PyObject_Del((PyObject*) self);
}
static PyObject *cwrap_repr(ClientWrap *self)
{
CHECK_CWRAP(self, "repr");
return PyString_FromFormat("0x%x", (guint)self->client->window);
}
static int cwrap_compare(ClientWrap *self, ClientWrap *other)
{
Window w1, w2;
if (!IS_VALID_CWRAP(self)) {
PyErr_SetString(PyExc_ValueError,
"This 'Client' is wrapping a client which no longer "
"exists.");
}
w1 = self->client->window;
w2 = self->client->window;
return w1 > w2 ? 1 : w1 < w2 ? -1 : 0;
}
static PyTypeObject ClientWrapType = {
PyObject_HEAD_INIT(NULL)
0,
"Client",
sizeof(ClientWrap),
0,
(destructor) cwrap_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
(cmpfunc) cwrap_compare, /*tp_compare*/
(reprfunc) cwrap_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
/***************************************************************************
External methods
***************************************************************************/
void clientwrap_startup()
{
ClientWrapType.ob_type = &PyType_Type;
ClientWrapType.tp_methods = ClientWrapMethods;
PyType_Ready(&ClientWrapType);
}
void clientwrap_shutdown()
{
}
PyObject *clientwrap_new(Client *client)
{
g_assert(client != NULL);
if (client->wrap != NULL) {
/* already has a wrapper! */
Py_INCREF((PyObject*) client->wrap);
} else {
client->wrap = PyObject_New(ClientWrap, &ClientWrapType);
client->wrap->client = client;
}
return (PyObject*) client->wrap;
}

View file

@ -1,19 +0,0 @@
#ifndef __clientwrap_h
#define __clientwrap_h
#include <Python.h>
struct Client;
/* ClientWrap is a PyObject */
typedef struct ClientWrap {
PyObject_HEAD
struct Client *client;
} ClientWrap;
void clientwrap_startup();
void clientwrap_shutdown();
PyObject *clientwrap_new(struct Client *client);
#endif

593
c/event.c
View file

@ -1,593 +0,0 @@
#include "openbox.h"
#include "client.h"
#include "xerror.h"
#include "prop.h"
#include "screen.h"
#include "frame.h"
#include "focus.h"
#include "hooks.h"
#include "stacking.h"
#include "kbind.h"
#include "mbind.h"
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
static void event_process(XEvent *e);
static void event_handle_root(XEvent *e);
static void event_handle_client(Client *c, XEvent *e);
Time event_lasttime = 0;
/*! A list of all possible combinations of keyboard lock masks */
static unsigned int mask_list[8];
/*! The value of the mask for the NumLock modifier */
static unsigned int NumLockMask;
/*! The value of the mask for the ScrollLock modifier */
static unsigned int ScrollLockMask;
/*! The key codes for the modifier keys */
static XModifierKeymap *modmap;
/*! Table of the constant modifier masks */
static const int mask_table[] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
static int mask_table_size;
void event_startup()
{
mask_table_size = sizeof(mask_table) / sizeof(mask_table[0]);
/* get lock masks that are defined by the display (not constant) */
modmap = XGetModifierMapping(ob_display);
g_assert(modmap);
if (modmap && modmap->max_keypermod > 0) {
size_t cnt;
const size_t size = mask_table_size * 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(ob_display, XK_Num_Lock);
const KeyCode scroll_lock = XKeysymToKeycode(ob_display,
XK_Scroll_Lock);
for (cnt = 0; cnt < size; ++cnt) {
if (! modmap->modifiermap[cnt]) continue;
if (num_lock == modmap->modifiermap[cnt])
NumLockMask = mask_table[cnt / modmap->max_keypermod];
if (scroll_lock == modmap->modifiermap[cnt])
ScrollLockMask = mask_table[cnt / modmap->max_keypermod];
}
}
mask_list[0] = 0;
mask_list[1] = LockMask;
mask_list[2] = NumLockMask;
mask_list[3] = LockMask | NumLockMask;
mask_list[4] = ScrollLockMask;
mask_list[5] = ScrollLockMask | LockMask;
mask_list[6] = ScrollLockMask | NumLockMask;
mask_list[7] = ScrollLockMask | LockMask | NumLockMask;
}
void event_shutdown()
{
XFreeModifiermap(modmap);
}
void event_loop()
{
fd_set selset;
XEvent e;
int x_fd;
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 (ob_remote) {
if (!XPending(ob_display))
break;
} 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(ob_display, FALSE);
if (!XEventsQueued(ob_display, QueuedAlready))
break;
}
XNextEvent(ob_display, &e);
event_process(&e);
}
x_fd = ConnectionNumber(ob_display);
FD_ZERO(&selset);
FD_SET(x_fd, &selset);
select(x_fd + 1, &selset, NULL, NULL, NULL);
}
void event_process(XEvent *e)
{
XEvent ce;
KeyCode *kp;
Window window;
int i, k;
Client *client;
GQuark context;
static guint motion_button = 0;
/* pick a window */
switch (e->type) {
case UnmapNotify:
window = e->xunmap.window;
break;
case DestroyNotify:
window = e->xdestroywindow.window;
break;
case ConfigureRequest:
window = e->xconfigurerequest.window;
break;
default:
window = e->xany.window;
}
/* grab the lasttime and hack up the state */
switch (e->type) {
case ButtonPress:
case ButtonRelease:
event_lasttime = e->xbutton.time;
e->xbutton.state &= ~(LockMask | NumLockMask | ScrollLockMask);
/* kill off the Button1Mask etc, only want the modifiers */
e->xbutton.state &= (ControlMask | ShiftMask | Mod1Mask |
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
break;
case KeyPress:
event_lasttime = e->xkey.time;
e->xkey.state &= ~(LockMask | NumLockMask | ScrollLockMask);
/* kill off the Button1Mask etc, only want the modifiers */
e->xkey.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..) */
/* I'm commenting this out cuz i don't want "C-Control_L" being returned. */
/* kp = modmap->modifiermap;*/
/* for (i = 0; i < mask_table_size; ++i) {*/
/* for (k = 0; k < modmap->max_keypermod; ++k) {*/
/* if (*kp == e->xkey.keycode) {*/ /* found the keycode */
/* add the mask for it */
/* e->xkey.state |= mask_table[i];*/
/* cause the first loop to break; */
/* i = mask_table_size;*/
/* break;*/ /* get outta here! */
/* }*/
/* ++kp;*/
/* }*/
/* }*/
break;
case KeyRelease:
event_lasttime = e->xkey.time;
e->xkey.state &= ~(LockMask | NumLockMask | ScrollLockMask);
/* kill off the Button1Mask etc, only want the modifiers */
e->xkey.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..) */
kp = modmap->modifiermap;
for (i = 0; i < mask_table_size; ++i) {
for (k = 0; k < modmap->max_keypermod; ++k) {
if (*kp == e->xkey.keycode) { /* found the keycode */
/* remove the mask for it */
e->xkey.state &= ~mask_table[i];
/* cause the first loop to break; */
i = mask_table_size;
break; /* get outta here! */
}
++kp;
}
}
break;
case MotionNotify:
event_lasttime = e->xmotion.time;
e->xmotion.state &= ~(LockMask | NumLockMask | ScrollLockMask);
/* kill off the Button1Mask etc, only want the modifiers */
e->xmotion.state &= (ControlMask | ShiftMask | Mod1Mask |
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
/* compress events */
while (XCheckTypedWindowEvent(ob_display, window, e->type, &ce)) {
e->xmotion.x_root = ce.xmotion.x_root;
e->xmotion.y_root = ce.xmotion.y_root;
}
break;
case PropertyNotify:
event_lasttime = e->xproperty.time;
break;
case FocusIn:
case FocusOut:
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; /* skip me! */
if (e->type == FocusOut) {
/* FocusOut events just make us look for FocusIn events. They
are mostly ignored otherwise. */
XEvent fi;
if (XCheckTypedEvent(ob_display, FocusIn, &fi)) {
event_process(&fi);
/* dont unfocus the window we just focused! */
if (fi.xfocus.window == e->xfocus.window)
return;
}
}
break;
case EnterNotify:
case LeaveNotify:
event_lasttime = e->xcrossing.time;
if (e->xcrossing.mode != NotifyNormal)
return; /* skip me! */
break;
}
client = g_hash_table_lookup(client_map, (gpointer)window);
if (client) {
event_handle_client(client, e);
} else if (window == ob_root)
event_handle_root(e);
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;
g_message("Proxying configure event for 0x%lx\n", window);
/* we are not to be held responsible if someone sends us an
invalid request! */
xerror_set_ignore(TRUE);
XConfigureWindow(ob_display, window,
e->xconfigurerequest.value_mask, &xwc);
xerror_set_ignore(FALSE);
}
/* dispatch Crossing, Pointer and Key events to the hooks */
switch(e->type) {
case EnterNotify:
context = frame_get_context(client, window);
LOGICALHOOK(EnterWindow, context, client);
break;
case LeaveNotify:
context = frame_get_context(client, window);
LOGICALHOOK(LeaveWindow, context, client);
break;
case ButtonPress:
if (!motion_button) motion_button = e->xbutton.button;
context = frame_get_context(client, window);
mbind_fire(e->xbutton.state, e->xbutton.button, context,
Pointer_Press, client, e->xbutton.x_root,
e->xbutton.y_root);
break;
case ButtonRelease:
if (motion_button == e->xbutton.button) motion_button = 0;
context = frame_get_context(client, window);
mbind_fire(e->xbutton.state, e->xbutton.button, context,
Pointer_Release, client, e->xbutton.x_root,
e->xbutton.y_root);
break;
case MotionNotify:
context = frame_get_context(client, window);
mbind_fire(e->xkey.state, motion_button, context, Pointer_Motion,
client, e->xmotion.x_root, e->xmotion.y_root);
break;
case KeyPress:
kbind_fire(e->xkey.state, e->xkey.keycode, TRUE);
break;
case KeyRelease:
kbind_fire(e->xkey.state, e->xkey.keycode, FALSE);
break;
}
}
static void event_handle_root(XEvent *e)
{
Atom msgtype;
switch(e->type) {
case MapRequest:
g_message("MapRequest on root");
client_manage(e->xmap.window);
break;
case ClientMessage:
if (e->xclient.format != 32) break;
msgtype = e->xclient.message_type;
if (msgtype == prop_atoms.net_current_desktop) {
unsigned int d = e->xclient.data.l[0];
if (d <= screen_num_desktops)
screen_set_desktop(d);
} else if (msgtype == prop_atoms.net_number_of_desktops) {
unsigned int d = e->xclient.data.l[0];
if (d > 0)
screen_set_num_desktops(d);
} else if (msgtype == prop_atoms.net_showing_desktop) {
screen_show_desktop(e->xclient.data.l[0] != 0);
}
break;
case PropertyNotify:
if (e->xproperty.atom == prop_atoms.net_desktop_names)
screen_update_desktop_names();
else if (e->xproperty.atom == prop_atoms.net_desktop_layout)
screen_update_layout();
break;
}
}
static void event_handle_client(Client *client, XEvent *e)
{
XEvent ce;
Atom msgtype;
switch (e->type) {
case FocusIn:
client->focused = TRUE;
frame_adjust_focus(client->frame);
/* focus state can affect the stacking layer */
client_calc_layer(client);
focus_set_client(client);
break;
case FocusOut:
client->focused = FALSE;
frame_adjust_focus(client->frame);
/* focus state can affect the stacking layer */
client_calc_layer(client);
if (focus_client == client)
focus_set_client(NULL);
break;
case ConfigureRequest:
g_message("ConfigureRequest for window %lx", client->window);
/* compress these */
while (XCheckTypedWindowEvent(ob_display, client->window,
ConfigureRequest, &ce)) {
/* XXX if this causes bad things.. we can compress config req's
with the same mask. */
e->xconfigurerequest.value_mask |=
ce.xconfigurerequest.value_mask;
if (ce.xconfigurerequest.value_mask & CWX)
e->xconfigurerequest.x = ce.xconfigurerequest.x;
if (ce.xconfigurerequest.value_mask & CWY)
e->xconfigurerequest.y = ce.xconfigurerequest.y;
if (ce.xconfigurerequest.value_mask & CWWidth)
e->xconfigurerequest.width = ce.xconfigurerequest.width;
if (ce.xconfigurerequest.value_mask & CWHeight)
e->xconfigurerequest.height = ce.xconfigurerequest.height;
if (ce.xconfigurerequest.value_mask & CWBorderWidth)
e->xconfigurerequest.border_width =
ce.xconfigurerequest.border_width;
if (ce.xconfigurerequest.value_mask & CWStackMode)
e->xconfigurerequest.detail = ce.xconfigurerequest.detail;
}
/* if we are iconic (or shaded (fvwm does this)) ignore the event */
if (client->iconic || client->shaded) return;
if (e->xconfigurerequest.value_mask & CWBorderWidth)
client->border_width = e->xconfigurerequest.border_width;
/* resize, then move, as specified in the EWMH section 7.7 */
if (e->xconfigurerequest.value_mask & (CWWidth | CWHeight |
CWX | CWY)) {
int x, y, w, h;
Corner corner;
x = (e->xconfigurerequest.value_mask & CWX) ?
e->xconfigurerequest.x : client->area.x;
y = (e->xconfigurerequest.value_mask & CWY) ?
e->xconfigurerequest.y : client->area.y;
w = (e->xconfigurerequest.value_mask & CWWidth) ?
e->xconfigurerequest.width : client->area.width;
h = (e->xconfigurerequest.value_mask & CWHeight) ?
e->xconfigurerequest.height : client->area.height;
switch (client->gravity) {
case NorthEastGravity:
case EastGravity:
corner = Corner_TopRight;
break;
case SouthWestGravity:
case SouthGravity:
corner = Corner_BottomLeft;
break;
case SouthEastGravity:
corner = Corner_BottomRight;
break;
default: /* NorthWest, Static, etc */
corner = Corner_TopLeft;
}
client_configure(client, corner, x, y, w, h, FALSE, FALSE);
}
if (e->xconfigurerequest.value_mask & CWStackMode) {
switch (e->xconfigurerequest.detail) {
case Below:
case BottomIf:
stacking_lower(client);
break;
case Above:
case TopIf:
default:
stacking_raise(client);
break;
}
}
break;
case UnmapNotify:
if (client->ignore_unmaps) {
client->ignore_unmaps--;
break;
}
g_message("UnmapNotify for %lx", client->window);
client_unmanage(client);
break;
case DestroyNotify:
g_message("DestroyNotify for %lx", client->window);
client_unmanage(client);
break;
case ReparentNotify:
/* this is when the client is first taken captive in the frame */
if (e->xreparent.parent == client->frame->plate) break;
/*
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 */
XPutBackEvent(ob_display, e);
client_unmanage(client);
break;
case MapRequest:
/* we shouldn't be able to get this unless we're iconic */
g_assert(client->iconic);
LOGICALHOOK(RequestActivate, g_quark_try_string("client"), client);
break;
case ClientMessage:
/* validate cuz we query stuff off the client here */
if (!client_validate(client)) break;
if (e->xclient.format != 32) return;
msgtype = e->xclient.message_type;
if (msgtype == prop_atoms.wm_change_state) {
/* compress changes into a single change */
while (XCheckTypedWindowEvent(ob_display, e->type,
client->window, &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 != msgtype) {
XPutBackEvent(ob_display, &ce);
break;
}
e->xclient = ce.xclient;
}
client_set_wm_state(client, e->xclient.data.l[0]);
} else if (msgtype == prop_atoms.net_wm_desktop) {
/* compress changes into a single change */
while (XCheckTypedWindowEvent(ob_display, e->type,
client->window, &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 != msgtype) {
XPutBackEvent(ob_display, &ce);
break;
}
e->xclient = ce.xclient;
}
client_set_desktop(client, e->xclient.data.l[0]);
} else if (msgtype == prop_atoms.net_wm_state) {
/* can't compress these */
g_message("net_wm_state %s %ld %ld for 0x%lx\n",
(e->xclient.data.l[0] == 0 ? "Remove" :
e->xclient.data.l[0] == 1 ? "Add" :
e->xclient.data.l[0] == 2 ? "Toggle" : "INVALID"),
e->xclient.data.l[1], e->xclient.data.l[2],
client->window);
client_set_state(client, e->xclient.data.l[0],
e->xclient.data.l[1], e->xclient.data.l[2]);
} else if (msgtype == prop_atoms.net_close_window) {
g_message("net_close_window for 0x%lx\n", client->window);
client_close(client);
} else if (msgtype == prop_atoms.net_active_window) {
g_message("net_active_window for 0x%lx\n", client->window);
if (screen_showing_desktop)
screen_show_desktop(FALSE);
if (client->iconic)
client_iconify(client, FALSE, TRUE);
else if (!client->frame->visible)
/* if its not visible for other reasons, then don't mess
with it */
return;
LOGICALHOOK(RequestActivate, g_quark_try_string("client"), client);
}
break;
case PropertyNotify:
/* validate cuz we query stuff off the client here */
if (!client_validate(client)) break;
/* compress changes to a single property into a single change */
while (XCheckTypedWindowEvent(ob_display, e->type,
client->window, &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->xproperty.atom) {
XPutBackEvent(ob_display, &ce);
break;
}
}
msgtype = e->xproperty.atom;
if (msgtype == XA_WM_NORMAL_HINTS) {
client_update_normal_hints(client);
/* normal hints can make a window non-resizable */
client_setup_decor_and_functions(client);
} else if (msgtype == XA_WM_HINTS)
client_update_wmhints(client);
else if (msgtype == XA_WM_TRANSIENT_FOR) {
client_update_transient_for(client);
client_get_type(client);
/* type may have changed, so update the layer */
client_calc_layer(client);
client_setup_decor_and_functions(client);
}
else if (msgtype == prop_atoms.net_wm_name ||
msgtype == prop_atoms.wm_name)
client_update_title(client);
else if (msgtype == prop_atoms.net_wm_icon_name ||
msgtype == prop_atoms.wm_icon_name)
client_update_icon_title(client);
else if (msgtype == prop_atoms.wm_class)
client_update_class(client);
else if (msgtype == prop_atoms.wm_protocols) {
client_update_protocols(client);
client_setup_decor_and_functions(client);
}
else if (msgtype == prop_atoms.net_wm_strut)
client_update_strut(client);
else if (msgtype == prop_atoms.net_wm_icon)
client_update_icons(client);
else if (msgtype == prop_atoms.kwm_win_icon)
client_update_kwm_icon(client);
}
}

View file

@ -1,12 +0,0 @@
#ifndef __events_h
#define __events_h
/*! Time at which the last event with a timestamp occured. */
extern Time event_lasttime;
void event_startup();
void event_shutdown();
void event_loop();
#endif

View file

@ -1,433 +0,0 @@
#include "eventdata.h"
#include "openbox.h"
#include "event.h"
#include "clientwrap.h"
#include <X11/Xlib.h>
/*
*
* Define the type 'EventData'
*
*/
#define IS_EVENTDATA(v) ((v)->ob_type == &EventDataType)
#define CHECK_EVENTDATA(self, funcname) { \
if (!IS_EVENTDATA(self)) { \
PyErr_SetString(PyExc_TypeError, \
"descriptor '" funcname "' requires an 'EventData' " \
"object"); \
return NULL; \
} \
}
staticforward PyTypeObject EventDataType;
static PyObject *eventdata_type(EventData *self, PyObject *args)
{
CHECK_EVENTDATA(self, "type");
if (!PyArg_ParseTuple(args, ":type"))
return NULL;
return PyInt_FromLong(self->type);
}
static PyObject *eventdata_time(EventData *self, PyObject *args)
{
CHECK_EVENTDATA(self, "time");
if (!PyArg_ParseTuple(args, ":time"))
return NULL;
return PyInt_FromLong(event_lasttime);
}
static PyObject *eventdata_context(EventData *self, PyObject *args)
{
CHECK_EVENTDATA(self, "context");
if (!PyArg_ParseTuple(args, ":context"))
return NULL;
return PyString_FromString(self->context);
}
static PyObject *eventdata_client(EventData *self, PyObject *args)
{
CHECK_EVENTDATA(self, "client");
if (!PyArg_ParseTuple(args, ":client"))
return NULL;
if (self->client == NULL) {
Py_INCREF(Py_None);
return Py_None;
} else {
return clientwrap_new(self->client);
}
}
static PyObject *eventdata_keycode(EventData *self, PyObject *args)
{
CHECK_EVENTDATA(self, "keycode");
if (!PyArg_ParseTuple(args, ":keycode"))
return NULL;
switch (self->type) {
case Key_Press:
case Key_Release:
break;
default:
PyErr_SetString(PyExc_TypeError,
"The EventData object is not a Key event");
return NULL;
}
return PyInt_FromLong(self->details.key->keycode);
}
static PyObject *eventdata_modifiers(EventData *self, PyObject *args)
{
CHECK_EVENTDATA(self, "key");
if (!PyArg_ParseTuple(args, ":key"))
return NULL;
switch (self->type) {
case Key_Press:
case Key_Release:
case Pointer_Press:
case Pointer_Release:
case Pointer_Motion:
break;
default:
PyErr_SetString(PyExc_TypeError,
"The EventData object is not a Key or Pointer event");
return NULL;
}
return PyInt_FromLong(self->details.key->modifiers);
}
static PyObject *eventdata_keyName(EventData *self, PyObject *args)
{
GList *it;
PyObject *tuple;
int i;
CHECK_EVENTDATA(self, "keyName");
if (!PyArg_ParseTuple(args, ":keyName"))
return NULL;
switch (self->type) {
case Key_Press:
case Key_Release:
break;
default:
PyErr_SetString(PyExc_TypeError,
"The EventData object is not a Key event");
return NULL;
}
if (self->details.key->keylist != NULL) {
tuple = PyTuple_New(g_list_length(self->details.key->keylist));
for (i = 0, it = self->details.key->keylist; it != NULL;
it = it->next, ++i)
PyTuple_SET_ITEM(tuple, i, PyString_FromString(it->data));
return tuple;
} else {
GString *str = g_string_sized_new(0);
KeySym sym;
if (self->details.key->modifiers & ControlMask)
g_string_append(str, "C-");
if (self->details.key->modifiers & ShiftMask)
g_string_append(str, "S-");
if (self->details.key->modifiers & Mod1Mask)
g_string_append(str, "Mod1-");
if (self->details.key->modifiers & Mod2Mask)
g_string_append(str, "Mod2-");
if (self->details.key->modifiers & Mod3Mask)
g_string_append(str, "Mod3-");
if (self->details.key->modifiers & Mod4Mask)
g_string_append(str, "Mod4-");
if (self->details.key->modifiers & Mod5Mask)
g_string_append(str, "Mod5-");
sym = XKeycodeToKeysym(ob_display, self->details.key->keycode, 0);
if (sym == NoSymbol)
g_string_append(str, "NoSymbol");
else {
char *name = XKeysymToString(sym);
if (name == NULL)
name = "Undefined";
g_string_append(str, name);
}
tuple = PyTuple_New(1);
PyTuple_SET_ITEM(tuple, 0, PyString_FromString(str->str));
g_string_free(str, TRUE);
return tuple;
}
}
static PyObject *eventdata_button(EventData *self, PyObject *args)
{
CHECK_EVENTDATA(self, "button");
if (!PyArg_ParseTuple(args, ":button"))
return NULL;
switch (self->type) {
case Pointer_Press:
case Pointer_Release:
case Pointer_Motion:
break;
default:
PyErr_SetString(PyExc_TypeError,
"The EventData object is not a Pointer event");
return NULL;
}
return PyInt_FromLong(self->details.pointer->button);
}
static PyObject *eventdata_buttonName(EventData *self, PyObject *args)
{
CHECK_EVENTDATA(self, "buttonName");
if (!PyArg_ParseTuple(args, ":buttonName"))
return NULL;
switch (self->type) {
case Pointer_Press:
case Pointer_Release:
case Pointer_Motion:
break;
default:
PyErr_SetString(PyExc_TypeError,
"The EventData object is not a Pointer event");
return NULL;
}
if (self->details.pointer->name != NULL) {
return PyString_FromString(self->details.pointer->name);
} else {
PyObject *pystr;
GString *str = g_string_sized_new(0);
if (self->details.pointer->modifiers & ControlMask)
g_string_append(str, "C-");
if (self->details.pointer->modifiers & ShiftMask)
g_string_append(str, "S-");
if (self->details.pointer->modifiers & Mod1Mask)
g_string_append(str, "Mod1-");
if (self->details.pointer->modifiers & Mod2Mask)
g_string_append(str, "Mod2-");
if (self->details.pointer->modifiers & Mod3Mask)
g_string_append(str, "Mod3-");
if (self->details.pointer->modifiers & Mod4Mask)
g_string_append(str, "Mod4-");
if (self->details.pointer->modifiers & Mod5Mask)
g_string_append(str, "Mod5-");
g_string_append_printf(str, "%d", self->details.pointer->button);
pystr = PyString_FromString(str->str);
g_string_free(str, TRUE);
return pystr;
}
}
static PyObject *eventdata_position(EventData *self, PyObject *args)
{
PyObject *tuple;
CHECK_EVENTDATA(self, "position");
if (!PyArg_ParseTuple(args, ":position"))
return NULL;
switch (self->type) {
case Pointer_Press:
case Pointer_Release:
case Pointer_Motion:
break;
default:
PyErr_SetString(PyExc_TypeError,
"The EventData object is not a Pointer event");
return NULL;
}
tuple = PyTuple_New(2);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->details.pointer->xroot));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->details.pointer->yroot));
return tuple;
}
static PyMethodDef EventDataAttributeMethods[] = {
{"type", (PyCFunction)eventdata_type, METH_VARARGS,
"data.type() -- Return the event type"},
{"context", (PyCFunction)eventdata_context, METH_VARARGS,
"data.context() -- Return the context for the event. If it is "
"\"client\", then data.client() can be used to find out the "
"client."},
{"client", (PyCFunction)eventdata_client, METH_VARARGS,
"data.client() -- Return the client for the event. This may be None if "
"there is no client, even if data.context() gives Context_Client."},
{"time", (PyCFunction)eventdata_time, METH_VARARGS,
"data.time() -- Return the time at which the last X event occured with "
"a timestamp. Should be the time at which this event, or the event that "
"caused this event to occur happened."},
{"modifiers", (PyCFunction)eventdata_modifiers, METH_VARARGS,
"data.modifiers() -- Return the modifier keymask that was pressed "
"when the event occured. A bitmask of ShiftMask, LockMask, ControlMask, "
"Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask. Cannot be used "
"when the data.type() is not a Key_* or Pointer_* event type."},
{"keycode", (PyCFunction)eventdata_keycode, METH_VARARGS,
"data.keycode() -- Return the keycode for the key which generated the "
"event. Cannot be used when the data.type() is not a Key_* event type."},
{"keyName", (PyCFunction)eventdata_keyName, METH_VARARGS,
"data.keyName() -- Return a tuple of the string names of the key which "
"generated the event. Cannot be used when the data.type() is not a Key_* "
"event "
"type."},
{"button", (PyCFunction)eventdata_button, METH_VARARGS,
"data.button() -- Return the pointer button which generated the event. "
"Cannot be used when the data.type() is not a Pointer_* event type."},
{"buttonName", (PyCFunction)eventdata_keyName, METH_VARARGS,
"data.buttonName() -- Return the name of the button which generated the "
"event. Cannot be used when the data.type() is not a Pointer_* event "
"type."},
{"position", (PyCFunction)eventdata_position, METH_VARARGS,
"data.position() -- Returns the current position of the pointer on the "
"root window when the event was generated. Gives the position in a tuple "
"with a format of (x, y). Cannot be used when the data.type() is not a "
"Pointer_* event type."},
{ NULL, NULL, 0, NULL }
};
static void data_dealloc(EventData *self)
{
GList *it;
switch(self->type) {
case Logical_EnterWindow:
case Logical_LeaveWindow:
case Logical_NewWindow:
case Logical_CloseWindow:
case Logical_Startup:
case Logical_Shutdown:
case Logical_RequestActivate:
case Logical_WindowShow:
case Logical_WindowHide:
case Logical_Focus:
case Logical_Bell:
case Logical_UrgentWindow:
g_free(self->details.logical);
break;
case Pointer_Press:
case Pointer_Release:
case Pointer_Motion:
if (self->details.pointer->name != NULL)
g_free(self->details.pointer->name);
g_free(self->details.pointer);
break;
case Key_Press:
case Key_Release:
for (it = self->details.key->keylist; it != NULL; it = it->next)
g_free(it->data);
g_list_free(self->details.key->keylist);
g_free(self->details.key);
break;
default:
g_assert_not_reached();
}
PyObject_Del((PyObject*) self);
}
static PyObject *eventdata_getattr(EventData *self, char *name)
{
return Py_FindMethod(EventDataAttributeMethods, (PyObject*)self, name);
}
static PyTypeObject EventDataType = {
PyObject_HEAD_INIT(NULL)
0,
"EventData",
sizeof(EventData),
0,
(destructor) data_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc) eventdata_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
void eventdata_startup()
{
EventDataType.ob_type = &PyType_Type;
PyType_Ready(&EventDataType);
}
void eventdata_shutdown()
{
}
void eventdata_free(EventData *data)
{
Py_DECREF(data);
}
EventData *eventdata_new_logical(EventType type, GQuark context,
struct Client *client)
{
EventData *data;
g_assert(type < Pointer_Press);
data = PyObject_New(EventData, &EventDataType);
data->type = type;
data->context = g_quark_to_string(context);
data->client = client;
data->details.logical = g_new(LogicalEvent, 1);
return data;
}
EventData *eventdata_new_pointer(EventType type, GQuark context,
struct Client *client, guint modifiers,
guint button, char *name,
int xroot, int yroot)
{
EventData *data;
g_assert(type >= Pointer_Press && type < Key_Press);
data = PyObject_New(EventData, &EventDataType);
data->type = type;
data->context = g_quark_to_string(context);
data->client = client;
data->details.pointer = g_new(PointerEvent, 1);
data->details.pointer->modifiers = modifiers;
data->details.pointer->button = button;
data->details.pointer->name = name == NULL ? name : g_strdup(name);
data->details.pointer->xroot = xroot;
data->details.pointer->yroot = yroot;
return data;
}
EventData *eventdata_new_key(EventType type, GQuark context,
struct Client *client, guint modifiers,
guint keycode, GList *keylist)
{
EventData *data;
GList *mykeylist, *it;
g_assert(type >= Key_Press);
data = PyObject_New(EventData, &EventDataType);
data->type = type;
data->context = g_quark_to_string(context);
data->client = client;
data->details.key = g_new(KeyEvent, 1);
/* make a copy of the keylist.
If the user were to clear the key bindings, then the keylist given here
would no longer point at valid memory.*/
mykeylist = g_list_copy(keylist); /* shallow copy */
for (it = mykeylist; it != NULL; it = it->next) /* deep copy */
it->data = g_strdup(it->data);
data->details.key->keylist = mykeylist;
data->details.key->keycode = keycode;
data->details.key->modifiers = modifiers;
return data;
}

View file

@ -1,74 +0,0 @@
#ifndef __eventdata_h
#define __eventdata_h
#include "obexport.h"
#include <Python.h>
#include <glib.h>
struct Client;
typedef struct {
int temp:1; /* just a placeholder to kill warnings for now.. */
} LogicalEvent;
typedef struct {
/*! The button which generated the event */
guint button;
/*! The pointer's x position on the root window when the event occured */
int xroot;
/*! The pointer's y position on the root window when the event occured */
int yroot;
/*! The modifiers that were pressed when the event occured. A bitmask of:
ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask,
Mod4Mask, Mod5Mask */
guint modifiers;
/*! The name of the button/modifier combination being pressed,
eg "Mod1-1" */
char *name;
} PointerEvent;
typedef struct {
/*! The keycode of the key which generated the event */
guint keycode;
/*! The modifiers that were pressed when the event occured. A bitmask of:
ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask,
Mod4Mask, Mod5Mask */
guint modifiers;
/* The list of strings which make up the chain that fired,
eg ("Mod1-a", "a") */
GList *keylist;
} KeyEvent;
/* EventData is a PyObject */
typedef struct EventData {
PyObject_HEAD
/* The type of event which occured */
EventType type;
/*! The context in which the event occured, the type of window it occured
for. */
const char *context;
/* The Client on which the event occured, or NULL */
struct Client *client;
union EventDetails {
LogicalEvent *logical;
PointerEvent *pointer;
KeyEvent *key;
} details;
} EventData;
void eventdata_startup();
void eventdata_shutdown();
EventData *eventdata_new_logical(EventType type, GQuark context,
struct Client *client);
EventData *eventdata_new_pointer(EventType type, GQuark context,
struct Client *client, guint modifiers,
guint button, char *name,
int xroot, int yroot);
EventData *eventdata_new_key(EventType type, GQuark context,
struct Client *client, guint modifiers,
guint keycode, GList *keylist);
void eventdata_free(EventData *data);
#endif

View file

@ -1,34 +0,0 @@
#include "openbox.h"
#include "extensions.h"
gboolean extensions_xkb = FALSE;
int extensions_xkb_event_basep;
gboolean extensions_shape = FALSE;
int extensions_shape_event_basep;
gboolean extensions_xinerama = FALSE;
int extensions_xinerama_event_basep;
void extensions_query_all()
{
int junk;
(void)junk;
#ifdef XKB
extensions_xkb =
XkbQueryExtension(ob_display, &junk, &extensions_xkb_event_basep,
&junk, NULL, NULL);
#endif
#ifdef SHAPE
extensions_shape =
XShapeQueryExtension(ob_display, &extensions_shape_event_basep,
&junk);
#endif
#ifdef XINERAMA
extensions_xinerama =
XineramaQueryExtension(ob_display, &extensions_xinerama_event_basep,
&junk);
#endif
}

View file

@ -1,33 +0,0 @@
#ifndef __extensions_h
#define __extensions_h
#include <X11/Xlib.h>
#ifdef XKB
#include <X11/XKBlib.h>
#endif
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#include <glib.h>
/*! Does the display have the XKB extension? */
extern gboolean extensions_xkb;
/*! Base for events for the XKB extension */
extern int extensions_xkb_event_basep;
/*! Does the display have the Shape extension? */
extern gboolean extensions_shape;
/*! Base for events for the Shape extension */
extern int extensions_shape_event_basep;
/*! Does the display have the Xinerama extension? */
extern gboolean extensions_xinerama;
/*! Base for events for the Xinerama extension */
extern int extensions_xinerama_event_basep;
void extensions_query_all();
#endif

View file

@ -1,56 +0,0 @@
#include "openbox.h"
#include "client.h"
#include "screen.h"
#include "prop.h"
#include "hooks.h"
#include <X11/Xlib.h>
Client *focus_client = NULL;
Window focus_backup = None;
void focus_set_client(Client *client);
void focus_startup()
{
/* create the window which gets focus when no clients get it. Have to
make it override-redirect so we don't try manage it, since it is
mapped. */
XSetWindowAttributes attrib;
attrib.override_redirect = TRUE;
focus_backup = XCreateWindow(ob_display, ob_root,
-100, -100, 1, 1, 0, 0, InputOnly,
CopyFromParent, CWOverrideRedirect, &attrib);
XMapRaised(ob_display, focus_backup);
/* start with nothing focused */
focus_set_client(NULL);
}
void focus_set_client(Client *client)
{
Window active;
/* 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 */
/* uninstall the old colormap, and install the new one */
screen_install_colormap(focus_client, FALSE);
screen_install_colormap(client, TRUE);
if (client == NULL) {
/* when nothing will be focused, send focus to the backup target */
XSetInputFocus(ob_display, focus_backup, RevertToNone, CurrentTime);
}
focus_client = client;
/* set the NET_ACTIVE_WINDOW hint */
active = client ? client->window : None;
PROP_SET32(ob_root, net_active_window, window, active);
LOGICALHOOK(Focus, g_quark_try_string("client"), client);
}

View file

@ -1,20 +0,0 @@
#ifndef __focus_h
#define __focus_h
#include <X11/Xlib.h>
struct Client;
/*! The window which gets focus when nothing else will be focused */
extern Window focus_backup;
/*! The client which is currently focused */
extern struct Client *focus_client;
void focus_startup();
/*! Specify which client is currently focused, this doesn't actually
send focus anywhere, its called by the Focus event handlers */
void focus_set_client(struct Client *client);
#endif

533
c/frame.c
View file

@ -1,533 +0,0 @@
#include "openbox.h"
#include "frame.h"
#include "extensions.h"
#include "hooks.h"
#define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
#define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask)
static Window createWindow(Window parent, unsigned long mask,
XSetWindowAttributes *attrib)
{
/* XXX DONT USE THE DEFAULT SHIT */
return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
DefaultDepth(ob_display, ob_screen), InputOutput,
DefaultVisual(ob_display, ob_screen),
mask, attrib);
}
Frame *frame_new(Client *client)
{
XSetWindowAttributes attrib;
unsigned long mask;
Frame *self;
self = g_new(Frame, 1);
self->client = client;
self->visible = FALSE;
/* create all of the decor windows */
mask = CWOverrideRedirect | CWEventMask;
attrib.event_mask = FRAME_EVENTMASK;
attrib.override_redirect = TRUE;
self->window = createWindow(ob_root, mask, &attrib);
mask = 0;
self->plate = createWindow(self->window, mask, &attrib);
mask = CWEventMask;
attrib.event_mask = (ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask);
self->title = createWindow(self->window, mask, &attrib);
self->label = createWindow(self->title, mask, &attrib);
self->max = createWindow(self->title, mask, &attrib);
self->close = createWindow(self->title, mask, &attrib);
self->desk = createWindow(self->title, mask, &attrib);
self->icon = createWindow(self->title, mask, &attrib);
self->iconify = createWindow(self->title, mask, &attrib);
self->handle = createWindow(self->window, mask, &attrib);
mask |= CWCursor;
attrib.cursor = ob_cursors.ll_angle;
self->lgrip = createWindow(self->handle, mask, &attrib);
attrib.cursor = ob_cursors.lr_angle;
self->rgrip = createWindow(self->handle, mask, &attrib);
/* the other stuff is shown based on decor settings */
XMapWindow(ob_display, self->plate);
XMapWindow(ob_display, self->lgrip);
XMapWindow(ob_display, self->rgrip);
XMapWindow(ob_display, self->label);
/* XXX TEMPORARY OF COURSE!@&*(@! */
XSetWindowBackground(ob_display, self->title, 0x3333aa);
XSetWindowBackground(ob_display, self->handle, 0x3333aa);
XSetWindowBackground(ob_display, self->lgrip, 0x2233aa);
XSetWindowBackground(ob_display, self->rgrip, 0x2233aa);
XSetWindowBorder(ob_display, self->window, 0);
XSetWindowBorder(ob_display, self->label, 0);
XSetWindowBorder(ob_display, self->rgrip, 0);
XSetWindowBorder(ob_display, self->lgrip, 0);
XSetWindowBorder(ob_display, self->plate, 0x771122);
/* XXX /TEMPORARY OF COURSE!@&*(@! */
/* set all the windows for the frame in the client_map */
g_hash_table_insert(client_map, (gpointer)self->window, self->client);
g_hash_table_insert(client_map, (gpointer)self->plate, self->client);
g_hash_table_insert(client_map, (gpointer)self->title, self->client);
g_hash_table_insert(client_map, (gpointer)self->label, self->client);
g_hash_table_insert(client_map, (gpointer)self->max, self->client);
g_hash_table_insert(client_map, (gpointer)self->close, self->client);
g_hash_table_insert(client_map, (gpointer)self->desk, self->client);
g_hash_table_insert(client_map, (gpointer)self->icon, self->client);
g_hash_table_insert(client_map, (gpointer)self->iconify, self->client);
g_hash_table_insert(client_map, (gpointer)self->handle, self->client);
g_hash_table_insert(client_map, (gpointer)self->lgrip, self->client);
g_hash_table_insert(client_map, (gpointer)self->rgrip, self->client);
return self;
}
void frame_free(Frame *self)
{
/* remove all the windows for the frame from the client_map */
g_hash_table_remove(client_map, (gpointer)self->window);
g_hash_table_remove(client_map, (gpointer)self->plate);
g_hash_table_remove(client_map, (gpointer)self->title);
g_hash_table_remove(client_map, (gpointer)self->label);
g_hash_table_remove(client_map, (gpointer)self->max);
g_hash_table_remove(client_map, (gpointer)self->close);
g_hash_table_remove(client_map, (gpointer)self->desk);
g_hash_table_remove(client_map, (gpointer)self->icon);
g_hash_table_remove(client_map, (gpointer)self->iconify);
g_hash_table_remove(client_map, (gpointer)self->handle);
g_hash_table_remove(client_map, (gpointer)self->lgrip);
g_hash_table_remove(client_map, (gpointer)self->rgrip);
XDestroyWindow(ob_display, self->window);
g_free(self);
}
void frame_grab_client(Frame *self)
{
/* reparent the client to the frame */
XReparentWindow(ob_display, self->client->window, self->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 (ob_state == State_Starting)
self->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(ob_display, self->plate, PLATE_EVENTMASK);
/* map the client so it maps when the frame does */
XMapWindow(ob_display, self->client->window);
frame_adjust_size(self);
frame_adjust_position(self);
}
void frame_release_client(Frame *self)
{
XEvent ev;
/* check if the app has already reparented its window away */
if (XCheckTypedWindowEvent(ob_display, self->client->window,
ReparentNotify, &ev)) {
XPutBackEvent(ob_display, &ev);
/* re-map the window since the unmanaging process unmaps it */
XMapWindow(ob_display, self->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(ob_display, self->client->window, ob_root,
self->client->area.x, self->client->area.y);
}
}
void frame_show(Frame *self)
{
if (!self->visible) {
self->visible = TRUE;
XMapWindow(ob_display, self->window);
LOGICALHOOK(WindowShow, g_quark_try_string("client"), self->client);
}
}
void frame_hide(Frame *self)
{
if (self->visible) {
self->visible = FALSE;
self->client->ignore_unmaps++;
XUnmapWindow(ob_display, self->window);
LOGICALHOOK(WindowHide, g_quark_try_string("client"), self->client);
}
}
void frame_adjust_size(Frame *self)
{
self->decorations = self->client->decorations;
/* XXX set shit from the style */
self->geom.font_height = 10;
self->geom.bevel = 1;
self->geom.button_size = self->geom.font_height - 2;
self->geom.handle_height = 2;
self->geom.grip_width = self->geom.button_size * 2;
XResizeWindow(ob_display, self->lgrip, self->geom.grip_width,
self->geom.handle_height);
XResizeWindow(ob_display, self->rgrip, self->geom.grip_width,
self->geom.handle_height);
if (self->decorations & Decor_Border) {
self->geom.bwidth = 1;/*XXX style->frameBorderWidth(); */
self->geom.cbwidth = 1; /*XXX style->clientBorderWidth(); */
} else {
self->geom.bwidth = self->geom.cbwidth = 0;
}
STRUT_SET(self->innersize, self->geom.cbwidth, self->geom.cbwidth,
self->geom.cbwidth, self->geom.cbwidth);
self->geom.width = self->client->area.width + self->geom.cbwidth * 2;
g_assert(self->geom.width > 0);
/* set border widths */
XSetWindowBorderWidth(ob_display, self->plate, self->geom.cbwidth);
XSetWindowBorderWidth(ob_display, self->window, self->geom.bwidth);
XSetWindowBorderWidth(ob_display, self->title, self->geom.bwidth);
XSetWindowBorderWidth(ob_display, self->handle, self->geom.bwidth);
XSetWindowBorderWidth(ob_display, self->lgrip, self->geom.bwidth);
XSetWindowBorderWidth(ob_display, self->rgrip, self->geom.bwidth);
/* position/size and map/unmap all the windows */
if (self->decorations & Decor_Titlebar) {
self->geom.title_height = self->geom.font_height +
self->geom.bevel * 2;
XMoveResizeWindow(ob_display, self->title,
-self->geom.bwidth, -self->geom.bwidth,
self->geom.width, self->geom.title_height);
self->innersize.top += self->geom.title_height + self->geom.bwidth;
XMapWindow(ob_display, self->title);
/* layout the title bar elements */
/*XXX layoutTitle(); */
} else {
XUnmapWindow(ob_display, self->title);
/* make all the titlebar stuff not render */
self->decorations &= ~(Decor_Icon | Decor_Iconify |
Decor_Maximize | Decor_Close |
Decor_AllDesktops);
}
if (self->decorations & Decor_Handle) {
self->geom.handle_y = self->innersize.top +
self->client->area.height + self->geom.cbwidth;
XMoveResizeWindow(ob_display, self->handle,
-self->geom.bwidth, self->geom.handle_y,
self->geom.width, self->geom.handle_height);
XMoveWindow(ob_display, self->lgrip,
-self->geom.bwidth, -self->geom.bwidth);
XMoveWindow(ob_display, self->rgrip,
-self->geom.bwidth + self->geom.width -
self->geom.grip_width, -self->geom.bwidth);
self->innersize.bottom += self->geom.handle_height +
self->geom.bwidth;
XMapWindow(ob_display, self->handle);
} else
XUnmapWindow(ob_display, self->handle);
XResizeWindow(ob_display, self->window, self->geom.width,
(self->client->shaded ? self->geom.title_height :
self->innersize.top + self->innersize.bottom +
self->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(ob_display, self->plate,
self->innersize.left - self->geom.cbwidth,
self->innersize.top - self->geom.cbwidth);
XResizeWindow(ob_display, self->plate, self->client->area.width,
self->client->area.height);
STRUT_SET(self->size,
self->innersize.left + self->geom.bwidth,
self->innersize.right + self->geom.bwidth,
self->innersize.top + self->geom.bwidth,
self->innersize.bottom + self->geom.bwidth);
RECT_SET_SIZE(self->area,
self->client->area.width +
self->size.left + self->size.right,
self->client->area.height +
self->size.top + self->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());
*/
frame_adjust_shape(self);
}
void frame_adjust_position(Frame *self)
{
self->area.x = self->client->area.x;
self->area.y = self->client->area.y;
frame_client_gravity(self, &self->area.x, &self->area.y);
XMoveWindow(ob_display, self->window, self->area.x, self->area.y);
}
void frame_adjust_shape(Frame *self)
{
#ifdef SHAPE
int num;
XRectangle xrect[2];
if (!self->client->shaped) {
/* clear the shape on the frame window */
XShapeCombineMask(ob_display, self->window, ShapeBounding,
self->innersize.left,
self->innersize.top,
None, ShapeSet);
} else {
/* make the frame's shape match the clients */
XShapeCombineShape(ob_display, self->window, ShapeBounding,
self->innersize.left,
self->innersize.top,
self->client->window, ShapeBounding, ShapeSet);
num = 0;
if (self->decorations & Decor_Titlebar) {
xrect[0].x = -self->geom.bevel;
xrect[0].y = -self->geom.bevel;
xrect[0].width = self->geom.width + self->geom.bwidth * 2;
xrect[0].height = self->geom.title_height +
self->geom.bwidth * 2;
++num;
}
if (self->decorations & Decor_Handle) {
xrect[1].x = -self->geom.bevel;
xrect[1].y = self->geom.handle_y;
xrect[1].width = self->geom.width + self->geom.bwidth * 2;
xrect[1].height = self->geom.handle_height +
self->geom.bwidth * 2;
++num;
}
XShapeCombineRectangles(ob_display, self->window,
ShapeBounding, 0, 0, xrect, num,
ShapeUnion, Unsorted);
}
#endif
}
void frame_client_gravity(Frame *self, int *x, int *y)
{
/* horizontal */
switch (self->client->gravity) {
default:
case NorthWestGravity:
case SouthWestGravity:
case WestGravity:
break;
case NorthGravity:
case SouthGravity:
case CenterGravity:
*x -= (self->size.left + self->size.right) / 2;
break;
case NorthEastGravity:
case SouthEastGravity:
case EastGravity:
*x -= self->size.left + self->size.right;
break;
case ForgetGravity:
case StaticGravity:
*x -= self->size.left;
break;
}
/* vertical */
switch (self->client->gravity) {
default:
case NorthWestGravity:
case NorthEastGravity:
case NorthGravity:
break;
case CenterGravity:
case EastGravity:
case WestGravity:
*y -= (self->size.top + self->size.bottom) / 2;
break;
case SouthWestGravity:
case SouthEastGravity:
case SouthGravity:
*y -= self->size.top + self->size.bottom;
break;
case ForgetGravity:
case StaticGravity:
*y -= self->size.top;
break;
}
}
void frame_frame_gravity(Frame *self, int *x, int *y)
{
/* horizontal */
switch (self->client->gravity) {
default:
case NorthWestGravity:
case WestGravity:
case SouthWestGravity:
break;
case NorthGravity:
case CenterGravity:
case SouthGravity:
*x += (self->size.left + self->size.right) / 2;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
*x += self->size.left + self->size.right;
break;
case StaticGravity:
case ForgetGravity:
x += self->size.left;
break;
}
/* vertical */
switch (self->client->gravity) {
default:
case NorthWestGravity:
case WestGravity:
case SouthWestGravity:
break;
case NorthGravity:
case CenterGravity:
case SouthGravity:
*y += (self->size.top + self->size.bottom) / 2;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
*y += self->size.top + self->size.bottom;
break;
case StaticGravity:
case ForgetGravity:
*y += self->size.top;
break;
}
}
void frame_adjust_state(Frame *self)
{
/* XXX do shit.. buttons? */
}
void frame_adjust_focus(Frame *self)
{
/* XXX optimizations later... */
frame_adjust_size(self);
}
void frame_adjust_title(Frame *self)
{
/* XXX optimizations later... */
frame_adjust_size(self);
}
void frame_adjust_icon(Frame *self)
{
/* XXX render icon */
}
GQuark frame_get_context(Client *client, Window win)
{
Frame *self;
if (win == ob_root) return g_quark_try_string("root");
if (client == NULL) return g_quark_try_string("none");
if (win == client->window) return g_quark_try_string("client");
self = client->frame;
if (win == self->window) return g_quark_try_string("frame");
if (win == self->plate) return g_quark_try_string("frame");
if (win == self->title) return g_quark_try_string("titlebar");
if (win == self->label) return g_quark_try_string("titlebar");
if (win == self->handle) return g_quark_try_string("handle");
if (win == self->lgrip) return g_quark_try_string("blcorner");
if (win == self->rgrip) return g_quark_try_string("brcorner");
return g_quark_try_string("none");
}
void frame_startup(void)
{
g_quark_from_string("none");
g_quark_from_string("root");
g_quark_from_string("client");
g_quark_from_string("titlebar");
g_quark_from_string("handle");
g_quark_from_string("frame");
g_quark_from_string("blcorner");
g_quark_from_string("brcorner");
g_quark_from_string("tlcorner");
g_quark_from_string("trcorner");
g_quark_from_string("foo");
}

101
c/frame.h
View file

@ -1,101 +0,0 @@
#ifndef __frame_h
#define __frame_h
#include <X11/Xlib.h>
#include "geom.h"
#include "client.h"
/*! Varius geometry settings in the frame decorations */
typedef struct {
int width; /* title and handle */
int font_height;
/* int title_height() { return font_height + bevel*2; } */
int title_height;
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 grip_width;
int bevel; /* static, from the style */
int bwidth; /* frame elements' border width */
int cbwidth; /* client border width */
} FrameGeometry;
typedef struct Frame {
Window window;
Window plate;
Window title;
Window label;
Window max;
Window close;
Window desk;
Window icon;
Window iconify;
Window handle;
Window lgrip;
Window rgrip;
Strut size;
Strut innersize;
Rect area;
FrameGeometry geom;
Client *client;
int decorations;
gboolean visible;
} Frame;
Frame *frame_new(struct Client *client);
void frame_free(Frame *self);
void frame_grab_client(Frame *self);
void frame_release_client(Frame *self);
/*! Update the frame's size to match the client */
void frame_adjust_size(Frame *self);
/*! Update the frame's position to match the client */
void frame_adjust_position(Frame *self);
/*! Shape the frame window to the client window */
void frame_adjust_shape(Frame *self);
/*! Update the frame to match the client's new state (for things like toggle
buttons, focus, and the title) XXX break this up */
void frame_adjust_state(Frame *self);
/*! Update the frame to match the client's focused state */
void frame_adjust_focus(Frame *self);
/*! Update the frame to display the client's current title */
void frame_adjust_title(Frame *self);
/*! Update the frame to display the client's current icon */
void frame_adjust_icon(Frame *self);
/*! 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 frame_client_gravity(Frame *self, 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 frame_frame_gravity(Frame *self, int *x, int *y);
/*! Shows the frame */
void frame_show(Frame *self);
/*! Hides the frame */
void frame_hide(Frame *self);
/*! inits quarks - this will go in engines later */
void frame_startup(void);
GQuark frame_get_context(Client *client, Window win);
#endif

View file

@ -1,53 +0,0 @@
#ifndef __geom_h
#define __geom_h
#ifdef HAVE_ASSERT_H
# include <assert.h>
#endif
typedef struct Point {
int x;
int y;
} Point;
#define POINT_SET(pt, nx, ny) {pt.x = nx; pt.y = ny;}
typedef struct Size {
int width;
int height;
} Size;
#define SIZE_SET(sz, w, h) {sz.width = w; sz.height = h;}
typedef struct Rect {
int x;
int y;
int width;
int height;
} Rect;
#define RECT_SET_POINT(r, nx, ny) \
{r.x = ny; r.y = ny;}
#define RECT_SET_SIZE(r, w, h) \
{r.width = w; r.height = h;}
#define RECT_SET(r, nx, ny, w, h) \
{r.x = nx; r.y = ny; r.width = w; r.height = h;}
#define RECT_EQUAL(r1, r2) (r1.x == r2.x && r1.y == r2.y && \
r1.width == r2.width && r1.height == r2.height)
typedef struct Strut {
int left;
int top;
int right;
int bottom;
} Strut;
#define STRUT_SET(s, l, t, r, b) \
{s.left = l; s.top = t; s.right = r; s.bottom = b; }
#define STRUT_ADD(s1, s2) \
{s1.left = MAX(s1.left, s2.left); s1.right = MAX(s1.right, s2.right); \
s1.top = MAX(s1.top, s2.top); s1.bottom = MAX(s1.bottom, s2.bottom); }
#endif

View file

@ -1,73 +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
/* Custom macro to make life easier */
#define _(str) gettext(str)
#endif /* _LIBGETTEXT_H */

285
c/hooks.c
View file

@ -1,285 +0,0 @@
#include "hooks.h"
#include <Python.h>
#include <glib.h>
/* the 'hooks' module and its dictionary */
static PyObject *hooks = NULL, *hooksdict = NULL;
/*
*
* Define the type 'Hook'
*
*/
#define IS_HOOK(v) ((v)->ob_type == &HookType)
staticforward PyTypeObject HookType;
typedef struct {
PyObject_HEAD
GSList *funcs;
} HookObject;
static PyObject *create_Hook(PyObject *self, PyObject *args)
{
HookObject *hook;
char *name;
int ret;
(void) self;
if (!PyArg_ParseTuple(args, "s:Hook", &name))
return NULL;
hook = PyObject_New(HookObject, &HookType);
hook->funcs = NULL;
/* add it to the hooks module */
ret = PyDict_SetItemString(hooksdict, name, (PyObject*) hook);
Py_DECREF(hook);
if (ret == -1) {
char *s = g_strdup_printf(
"Failed to add the hook '%s' to the 'hooks' module", name);
PyErr_SetString(PyExc_RuntimeError, s);
g_free(s);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static void hook_dealloc(HookObject *self)
{
GSList *it;
for (it = self->funcs; it != NULL; it = it->next)
Py_DECREF((PyObject*) it->data);
PyObject_Del((PyObject*) self);
}
static PyObject *hook_fire(HookObject *self, PyObject *args)
{
GSList *it;
if (!IS_HOOK(self)) {
PyErr_SetString(PyExc_TypeError,
"descriptor 'fire' requires a 'Hook' object");
return NULL;
}
for (it = self->funcs; it != NULL; it = it->next) {
PyObject *ret = PyObject_CallObject(it->data, args);
if (ret == NULL)
return NULL;
Py_DECREF(ret);
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *hook_add(HookObject *self, PyObject *args)
{
PyObject *func;
if (!IS_HOOK(self)) {
PyErr_SetString(PyExc_TypeError,
"descriptor 'add' requires a 'Hook' object");
return NULL;
}
if (!PyArg_ParseTuple(args, "O:add", &func))
return NULL;
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError,
"descriptor 'add' requires a callable argument");
return NULL;
}
self->funcs = g_slist_append(self->funcs, func);
Py_INCREF(func);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *hook_remove(HookObject *self, PyObject *args)
{
PyObject *func;
GSList *it;
if (!IS_HOOK(self)) {
PyErr_SetString(PyExc_TypeError,
"descriptor 'remove' requires a 'Hook' object");
return NULL;
}
if (!PyArg_ParseTuple(args, "O:remove", &func))
return NULL;
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError,
"descriptor 'remove' requires a callable argument");
return NULL;
}
it = g_slist_find(self->funcs, func);
if (it != NULL) {
self->funcs = g_slist_delete_link(self->funcs, it);
Py_DECREF(func);
Py_INCREF(Py_None);
return Py_None;
}
PyErr_SetString(PyExc_TypeError,
"given callable object was not found in Hook");
return NULL;
}
static PyObject *hook_count(HookObject *self, PyObject *args)
{
if (!IS_HOOK(self)) {
PyErr_SetString(PyExc_TypeError,
"descriptor 'fire' requires a 'Hook' object");
return NULL;
}
if (!PyArg_ParseTuple(args, ":count"))
return NULL;
return PyInt_FromLong(g_slist_length(self->funcs));
}
static PyTypeObject HookType = {
PyObject_HEAD_INIT(NULL)
0,
"Hook",
sizeof(HookObject),
0,
(destructor) hook_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
static PyMethodDef HookMethods[] = {
{"fire", (PyCFunction)hook_fire, METH_VARARGS,
"hook.fire() -- Fire the added hook functions for the Hook."},
{"add", (PyCFunction)hook_add, METH_VARARGS,
"hook.add(func) -- Add a function to the hook." },
{"remove", (PyCFunction)hook_remove, METH_VARARGS,
"hook.remove(func) -- Remove a function from the hook." },
{"count", (PyCFunction)hook_count, METH_VARARGS,
"hook.count() -- Return the number of functions in the hook." },
{ NULL, NULL, 0, NULL }
};
/*
*
* Module initialization/finalization
*
*/
/* the "events" hook */
static HookObject *events_hook = NULL, *keyboard_hook = NULL,
*pointer_hook = NULL;
static PyMethodDef HooksMethods[] = {
{"create", create_Hook, METH_VARARGS,
"hooks.create('name') -- Add a hook called 'name' to the hooks module."},
{ NULL, NULL, 0, NULL }
};
void hooks_startup()
{
int ret;
HookType.ob_type = &PyType_Type;
HookType.tp_methods = HookMethods;
PyType_Ready(&HookType);
Py_InitModule("hooks", HooksMethods);
/* get the hooks module/dict */
hooks = PyImport_ImportModule("hooks"); /* new */
g_assert(hooks != NULL);
hooksdict = PyModule_GetDict(hooks); /* borrowed */
g_assert(hooksdict != NULL);
/* create the "events" hook */
events_hook = PyObject_New(HookObject, &HookType);
events_hook->funcs = NULL;
/* add it to the hooks module */
ret = PyDict_SetItemString(hooksdict, "events", (PyObject*) events_hook);
g_assert(ret == 0);
/* create the "keyboard" hook */
keyboard_hook = PyObject_New(HookObject, &HookType);
keyboard_hook->funcs = NULL;
/* add it to the hooks module */
ret = PyDict_SetItemString(hooksdict, "keyboard",
(PyObject*) keyboard_hook);
g_assert(ret == 0);
/* create the "pointer" hook */
pointer_hook = PyObject_New(HookObject, &HookType);
pointer_hook->funcs = NULL;
/* add it to the hooks module */
ret = PyDict_SetItemString(hooksdict, "pointer", (PyObject*) pointer_hook);
g_assert(ret == 0);
}
void hooks_shutdown()
{
Py_DECREF(pointer_hook);
Py_DECREF(keyboard_hook);
Py_DECREF(events_hook);
Py_DECREF(hooks);
}
void hooks_fire(EventData *data)
{
PyObject *ret, *args;
g_assert(events_hook != NULL);
args = Py_BuildValue("(O)", data);
ret = hook_fire(events_hook, args);
Py_DECREF(args);
if (ret == NULL)
PyErr_Print();
}
void hooks_fire_keyboard(EventData *data)
{
PyObject *ret, *args;
g_assert(events_hook != NULL);
args = Py_BuildValue("(O)", data);
ret = hook_fire(keyboard_hook, args);
Py_DECREF(args);
if (ret == NULL)
PyErr_Print();
}
void hooks_fire_pointer(EventData *data)
{
PyObject *ret, *args;
g_assert(events_hook != NULL);
args = Py_BuildValue("(O)", data);
ret = hook_fire(pointer_hook, args);
Py_DECREF(args);
if (ret == NULL)
PyErr_Print();
}

View file

@ -1,23 +0,0 @@
#ifndef __hooks_h
#define __hooks_h
#include "eventdata.h"
void hooks_startup();
void hooks_shutdown();
void hooks_fire(EventData *data);
void hooks_fire_keyboard(EventData *data);
void hooks_fire_pointer(EventData *data);
#define LOGICALHOOK(type, context, client) \
{ EventData *data = eventdata_new_logical(Logical_##type, \
context, client); \
g_assert(data != NULL); \
hooks_fire(data); \
eventdata_free(data); \
}
#endif

354
c/kbind.c
View file

@ -1,354 +0,0 @@
#include "focus.h"
#include "openbox.h"
#include "hooks.h"
#include "kbind.h"
#include <glib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
typedef struct KeyBindingTree {
guint state;
guint key;
GList *keylist;
/* the next binding in the tree at the same level */
struct KeyBindingTree *next_sibling;
/* the first child of this binding (next binding in a chained sequence).*/
struct KeyBindingTree *first_child;
} KeyBindingTree;
static KeyBindingTree *firstnode, *curpos;
static guint reset_key, reset_state;
static gboolean grabbed, user_grabbed;
guint kbind_translate_modifier(char *str)
{
if (!strcmp("Mod1", str)) return Mod1Mask;
else if (!strcmp("Mod2", str)) return Mod2Mask;
else if (!strcmp("Mod3", str)) return Mod3Mask;
else if (!strcmp("Mod4", str)) return Mod4Mask;
else if (!strcmp("Mod5", str)) return Mod5Mask;
else if (!strcmp("C", str)) return ControlMask;
else if (!strcmp("S", str)) return ShiftMask;
g_warning("Invalid modifier '%s' in binding.", str);
return 0;
}
static gboolean translate(char *str, guint *state, guint *keycode)
{
char **parsed;
char *l;
int i;
gboolean ret = FALSE;
KeySym sym;
parsed = g_strsplit(str, "-", -1);
/* first, find the key (last token) */
l = NULL;
for (i = 0; parsed[i] != NULL; ++i)
l = parsed[i];
if (l == NULL)
goto translation_fail;
/* figure out the mod mask */
*state = 0;
for (i = 0; parsed[i] != l; ++i) {
guint m = kbind_translate_modifier(parsed[i]);
if (!m) goto translation_fail;
*state |= m;
}
/* figure out the keycode */
sym = XStringToKeysym(l);
if (sym == NoSymbol) {
g_warning("Invalid key name '%s' in key binding.", l);
goto translation_fail;
}
*keycode = XKeysymToKeycode(ob_display, sym);
if (!keycode) {
g_warning("Key '%s' does not exist on the display.", l);
goto translation_fail;
}
ret = TRUE;
translation_fail:
g_strfreev(parsed);
return ret;
}
static void destroytree(KeyBindingTree *tree)
{
KeyBindingTree *c;
while (tree) {
destroytree(tree->next_sibling);
c = tree->first_child;
if (c == NULL) {
GList *it;
for (it = tree->keylist; it != NULL; it = it->next)
g_free(it->data);
g_list_free(tree->keylist);
}
g_free(tree);
tree = c;
}
}
static KeyBindingTree *buildtree(GList *keylist)
{
GList *it;
KeyBindingTree *ret = NULL, *p;
if (g_list_length(keylist) <= 0)
return NULL; /* nothing in the list.. */
for (it = g_list_last(keylist); it != NULL; it = it->prev) {
p = ret;
ret = g_new(KeyBindingTree, 1);
ret->next_sibling = NULL;
if (p == NULL) {
GList *it;
/* this is the first built node, the bottom node of the tree */
ret->keylist = g_list_copy(keylist); /* shallow copy */
for (it = ret->keylist; it != NULL; it = it->next) /* deep copy */
it->data = g_strdup(it->data);
}
ret->first_child = p;
if (!translate(it->data, &ret->state, &ret->key)) {
destroytree(ret);
return NULL;
}
}
return ret;
}
static void assimilate(KeyBindingTree *node)
{
KeyBindingTree *a, *b, *tmp, *last;
if (firstnode == NULL) {
/* there are no nodes at this level yet */
firstnode = node;
} else {
a = firstnode;
last = a;
b = node;
while (a) {
last = a;
if (!(a->state == b->state && a->key == b->key)) {
a = a->next_sibling;
} else {
tmp = b;
b = b->first_child;
g_free(tmp);
a = a->first_child;
}
}
if (!(last->state == b->state && last->key == a->key))
last->next_sibling = b;
else {
last->first_child = b->first_child;
g_free(b);
}
}
}
KeyBindingTree *find(KeyBindingTree *search, gboolean *conflict)
{
KeyBindingTree *a, *b;
*conflict = FALSE;
a = firstnode;
b = search;
while (a && b) {
if (!(a->state == b->state && a->key == b->key)) {
a = a->next_sibling;
} else {
if ((a->first_child == NULL) == (b->first_child == NULL)) {
if (a->first_child == NULL) {
/* found it! (return the actual node, not the search's) */
return a;
}
} else {
*conflict = TRUE;
return NULL; /* the chain status' don't match (conflict!) */
}
b = b->first_child;
a = a->first_child;
}
}
return NULL; // it just isn't in here
}
static void grab_keys(gboolean grab)
{
if (!grab) {
XUngrabKey(ob_display, AnyKey, AnyModifier, ob_root);
} else {
KeyBindingTree *p = firstnode;
while (p) {
XGrabKey(ob_display, p->key, p->state, ob_root, FALSE,
GrabModeAsync, GrabModeSync);
p = p->next_sibling;
}
}
}
void reset_chains()
{
/* XXX kill timer */
curpos = NULL;
if (grabbed) {
grabbed = FALSE;
g_message("reset chains. user: %d", user_grabbed);
if (!user_grabbed)
XUngrabKeyboard(ob_display, CurrentTime);
}
}
void kbind_fire(guint state, guint key, gboolean press)
{
EventData *data;
struct Client *c = focus_client;
GQuark context = c != NULL ? g_quark_try_string("client")
: g_quark_try_string("root");
if (user_grabbed) {
data = eventdata_new_key(press ? Key_Press : Key_Release,
context, c, state, key, NULL);
g_assert(data != NULL);
hooks_fire_keyboard(data);
eventdata_free(data);
}
if (key == reset_key && state == reset_state) {
reset_chains();
XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
} else {
KeyBindingTree *p;
if (curpos == NULL)
p = firstnode;
else
p = curpos->first_child;
while (p) {
if (p->key == key && p->state == state) {
if (p->first_child != NULL) { /* part of a chain */
/* XXX TIMER */
if (!grabbed && !user_grabbed) {
/*grab should never fail because we should have a sync
grab at this point */
XGrabKeyboard(ob_display, ob_root, 0, GrabModeAsync,
GrabModeSync, CurrentTime);
}
grabbed = TRUE;
curpos = p;
XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
} else {
data = eventdata_new_key(press ? Key_Press : Key_Release,
context, c, state, key,
p->keylist);
g_assert(data != NULL);
hooks_fire(data);
eventdata_free(data);
XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
reset_chains();
}
break;
}
p = p->next_sibling;
}
}
}
gboolean kbind_add(GList *keylist)
{
KeyBindingTree *tree, *t;
gboolean conflict;
if (!(tree = buildtree(keylist)))
return FALSE; /* invalid binding requested */
t = find(tree, &conflict);
if (conflict) {
/* conflicts with another binding */
destroytree(tree);
return FALSE;
}
if (t != NULL) {
/* already bound to something */
destroytree(tree);
} else {
/* grab the server here to make sure no key pressed go missed */
XGrabServer(ob_display);
XSync(ob_display, FALSE);
grab_keys(FALSE);
/* assimilate this built tree into the main tree */
assimilate(tree); // assimilation destroys/uses the tree
grab_keys(TRUE);
XUngrabServer(ob_display);
XFlush(ob_display);
}
return TRUE;
}
void kbind_clearall()
{
grab_keys(FALSE);
destroytree(firstnode);
firstnode = NULL;
grab_keys(TRUE);
}
void kbind_startup()
{
gboolean b;
curpos = firstnode = NULL;
grabbed = user_grabbed = FALSE;
b = translate("C-G", &reset_state, &reset_key);
g_assert(b);
}
void kbind_shutdown()
{
if (grabbed || user_grabbed) {
grabbed = FALSE;
kbind_grab_keyboard(FALSE);
}
grab_keys(FALSE);
destroytree(firstnode);
firstnode = NULL;
}
gboolean kbind_grab_keyboard(gboolean grab)
{
gboolean ret = TRUE;
if (!grab)
g_message("grab_keyboard(false). grabbed: %d", grabbed);
user_grabbed = grab;
if (!grabbed) {
if (grab)
ret = XGrabKeyboard(ob_display, ob_root, 0, GrabModeAsync,
GrabModeAsync, CurrentTime) == GrabSuccess;
else
XUngrabKeyboard(ob_display, CurrentTime);
}
return ret;
}

View file

@ -1,23 +0,0 @@
#ifndef __kbind_h
#define __kbind_h
#include <glib.h>
void kbind_startup();
void kbind_shutdown();
/*! 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.
*/
gboolean kbind_add(GList *keylist);
void kbind_clearall();
guint kbind_translate_modifier(char *str);
void kbind_fire(guint state, guint key, gboolean press);
gboolean kbind_grab_keyboard(gboolean grab);
#endif

220
c/mbind.c
View file

@ -1,220 +0,0 @@
#include "mbind.h"
#include "kbind.h"
#include "frame.h"
#include "openbox.h"
#include "eventdata.h"
#include "hooks.h"
#include <glib.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
/* GData of GSList*'s of PointerBinding*'s. */
static GData *bound_contexts;
static gboolean grabbed;
struct mbind_foreach_grab_temp {
Client *client;
gboolean grab;
};
typedef struct {
guint state;
guint button;
char *name;
} PointerBinding;
static gboolean translate(char *str, guint *state, guint *button)
{
char **parsed;
char *l;
int i;
gboolean ret = FALSE;
parsed = g_strsplit(str, "-", -1);
/* first, find the button (last token) */
l = NULL;
for (i = 0; parsed[i] != NULL; ++i)
l = parsed[i];
if (l == NULL)
goto translation_fail;
/* figure out the mod mask */
*state = 0;
for (i = 0; parsed[i] != l; ++i) {
guint m = kbind_translate_modifier(parsed[i]);
if (!m) goto translation_fail;
*state |= m;
}
/* figure out the button */
*button = atoi(l);
if (!*button) {
g_warning("Invalid button '%s' in pointer binding.", l);
goto translation_fail;
}
ret = TRUE;
translation_fail:
g_strfreev(parsed);
return ret;
}
void grab_button(Client *client, guint state, guint button, GQuark context,
gboolean grab)
{
Window win;
int mode = GrabModeAsync;
unsigned int mask;
if (context == g_quark_try_string("frame")) {
win = client->frame->window;
mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
} else if (context == g_quark_try_string("client")) {
win = client->frame->plate;
mode = GrabModeSync; /* this is handled in mbind_fire */
mask = ButtonPressMask; /* can't catch more than this with Sync mode
the release event is manufactured in
mbind_fire */
} else return;
if (grab)
XGrabButton(ob_display, button, state, win, FALSE, mask, mode,
GrabModeAsync, None, None);
else
XUngrabButton(ob_display, button, state, win);
}
static void mbind_foreach_grab(GQuark key, gpointer data, gpointer user_data)
{
struct mbind_foreach_grab_temp *d = user_data;
PointerBinding *b = ((GSList *)data)->data;
if (b != NULL)
grab_button(d->client, b->state, b->button, key, d->grab);
}
void mbind_grab_all(Client *client, gboolean grab)
{
struct mbind_foreach_grab_temp bt;
bt.client = client;
bt.grab = grab;
g_datalist_foreach(&bound_contexts, mbind_foreach_grab, &bt);
}
void grab_all_clients(gboolean grab)
{
GSList *it;
for (it = client_list; it != NULL; it = it->next)
mbind_grab_all(it->data, grab);
}
void mbind_startup()
{
grabbed = FALSE;
g_datalist_init(&bound_contexts);
}
void mbind_shutdown()
{
if (grabbed)
mbind_grab_pointer(FALSE);
mbind_clearall();
g_datalist_clear(&bound_contexts);
}
gboolean mbind_add(char *name, GQuark context)
{
guint state, button;
PointerBinding *b;
GSList *it;
if (!translate(name, &state, &button))
return FALSE;
for (it = g_datalist_id_get_data(&bound_contexts, context);
it != NULL; it = it->next){
b = it->data;
if (b->state == state && b->button == button)
return TRUE; /* already bound */
}
grab_all_clients(FALSE);
/* add the binding */
b = g_new(PointerBinding, 1);
b->state = state;
b->button = button;
b->name = g_strdup(name);
g_datalist_id_set_data(&bound_contexts, context,
g_slist_append(g_datalist_id_get_data(&bound_contexts, context), b));
grab_all_clients(TRUE);
return TRUE;
}
static void mbind_foreach_clear(GQuark key, gpointer data, gpointer user_data)
{
GSList *it;
user_data = user_data;
for (it = data; it != NULL; it = it->next) {
PointerBinding *b = it->data;
g_free(b->name);
g_free(b);
}
g_slist_free(data);
}
void mbind_clearall()
{
grab_all_clients(FALSE);
g_datalist_foreach(&bound_contexts, mbind_foreach_clear, NULL);
}
void mbind_fire(guint state, guint button, GQuark context, EventType type,
Client *client, int xroot, int yroot)
{
GSList *it;
if (grabbed) {
EventData *data;
data = eventdata_new_pointer(type, context, client, state, button,
NULL, xroot, yroot);
g_assert(data != NULL);
hooks_fire_pointer(data);
eventdata_free(data);
return;
}
for (it = g_datalist_id_get_data(&bound_contexts, context);
it != NULL; it = it->next){
PointerBinding *b = it->data;
if (b->state == state && b->button == button) {
EventData *data;
data = eventdata_new_pointer(type, context, client, state, button,
b->name, xroot, yroot);
g_assert(data != NULL);
hooks_fire(data);
eventdata_free(data);
break;
}
}
}
gboolean mbind_grab_pointer(gboolean grab)
{
gboolean ret = TRUE;
if (grab)
ret = XGrabPointer(ob_display, ob_root, FALSE, (ButtonPressMask |
ButtonReleaseMask |
ButtonMotionMask |
PointerMotionMask),
GrabModeAsync, GrabModeAsync, None, None,
CurrentTime) == GrabSuccess;
else
XUngrabPointer(ob_display, CurrentTime);
return ret;
}

View file

@ -1,21 +0,0 @@
#ifndef __mbind_h
#define __mbind_h
#include "obexport.h"
#include "client.h"
#include <glib.h>
void mbind_startup();
void mbind_shutdown();
/*! Adds a new pointer binding */
gboolean mbind_add(char *name, GQuark context);
void mbind_clearall();
void mbind_fire(guint state, guint button, GQuark context, EventType type,
Client *client, int xroot, int yroot);
void mbind_grab_all(Client *client, gboolean grab);
gboolean mbind_grab_pointer(gboolean grab);
#endif

View file

@ -1,116 +0,0 @@
#include "obexport.h"
#include <Python.h>
#include <glib.h>
static PyMethodDef obMethods[] = {
{ NULL, NULL, 0, NULL }
};
#define ADD_INT_CONST(n) (PyModule_AddIntConstant(ob, #n, n))
void obexport_startup()
{
PyObject *ob, *obdict;
Py_InitModule("ob", obMethods);
/* get the ob module/dict */
ob = PyImport_ImportModule("ob"); /* new */
g_assert(ob != NULL);
obdict = PyModule_GetDict(ob); /* borrowed */
g_assert(obdict != NULL);
/* define all the constants! */
/* State */
ADD_INT_CONST(State_Starting);
ADD_INT_CONST(State_Exiting);
ADD_INT_CONST(State_Running);
/* Corner */
ADD_INT_CONST(Corner_TopLeft);
ADD_INT_CONST(Corner_TopRight);
ADD_INT_CONST(Corner_BottomLeft);
ADD_INT_CONST(Corner_BottomRight);
/* Orientation */
ADD_INT_CONST(Orientation_Horz);
ADD_INT_CONST(Orientation_Vert);
/* Gravity */
ADD_INT_CONST(Gravity_Forget);
ADD_INT_CONST(Gravity_NE);
ADD_INT_CONST(Gravity_N);
ADD_INT_CONST(Gravity_NW);
ADD_INT_CONST(Gravity_W);
ADD_INT_CONST(Gravity_SW);
ADD_INT_CONST(Gravity_S);
ADD_INT_CONST(Gravity_SE);
ADD_INT_CONST(Gravity_E);
ADD_INT_CONST(Gravity_Center);
ADD_INT_CONST(Gravity_Static);
/* WindowType */
ADD_INT_CONST(Type_Desktop);
ADD_INT_CONST(Type_Dock);
ADD_INT_CONST(Type_Toolbar);
ADD_INT_CONST(Type_Menu);
ADD_INT_CONST(Type_Utility);
ADD_INT_CONST(Type_Splash);
ADD_INT_CONST(Type_Dialog);
ADD_INT_CONST(Type_Normal);
/* Function */
ADD_INT_CONST(Func_Resize);
ADD_INT_CONST(Func_Move);
ADD_INT_CONST(Func_Iconify);
ADD_INT_CONST(Func_Maximize);
ADD_INT_CONST(Func_Shade);
ADD_INT_CONST(Func_Fullscreen);
ADD_INT_CONST(Func_Close);
/* Decoration */
ADD_INT_CONST(Decor_Titlebar);
ADD_INT_CONST(Decor_Handle);
ADD_INT_CONST(Decor_Border);
ADD_INT_CONST(Decor_Icon);
ADD_INT_CONST(Decor_Iconify);
ADD_INT_CONST(Decor_Maximize);
ADD_INT_CONST(Decor_AllDesktops);
ADD_INT_CONST(Decor_Close);
/* StackLayer */
ADD_INT_CONST(Layer_Icon);
ADD_INT_CONST(Layer_Desktop);
ADD_INT_CONST(Layer_Below);
ADD_INT_CONST(Layer_Normal);
ADD_INT_CONST(Layer_Above);
ADD_INT_CONST(Layer_Top);
ADD_INT_CONST(Layer_Fullscreen);
ADD_INT_CONST(Layer_Internal);
/* EventType */
ADD_INT_CONST(Logical_EnterWindow);
ADD_INT_CONST(Logical_LeaveWindow);
ADD_INT_CONST(Logical_NewWindow);
ADD_INT_CONST(Logical_CloseWindow);
ADD_INT_CONST(Logical_Startup);
ADD_INT_CONST(Logical_Shutdown);
ADD_INT_CONST(Logical_RequestActivate);
ADD_INT_CONST(Logical_Focus);
ADD_INT_CONST(Logical_Bell);
ADD_INT_CONST(Logical_UrgentWindow);
ADD_INT_CONST(Logical_WindowShow);
ADD_INT_CONST(Logical_WindowHide);
ADD_INT_CONST(Pointer_Press);
ADD_INT_CONST(Pointer_Release);
ADD_INT_CONST(Pointer_Motion);
ADD_INT_CONST(Key_Press);
ADD_INT_CONST(Key_Release);
Py_DECREF(ob);
}
void obexport_shutdown()
{
}

View file

@ -1,74 +0,0 @@
#ifndef __obexport_h
#define __obexport_h
#include <X11/Xlib.h>
/* Define values which will be exported in the 'ob' module. */
typedef enum {
/*! Occurs when the mouse enters a window */
Logical_EnterWindow,
/*! Occurs when the mouse enters a window */
Logical_LeaveWindow,
/*! Occurs when a window is finished being managed, just before it is
(possibly) displayed.
The python scripts are reponsible for showing the window when this is
called if they want it to be shown.
*/
Logical_NewWindow,
/*! Occurs when a window is being unmanaged */
Logical_CloseWindow,
/*! Occurs when the window manager starts up */
Logical_Startup,
/*! Occurs when the window manager is shutting down */
Logical_Shutdown,
/*! Occurs when a client is requesting/requested to be activated (i.e.
focused, raised, unshaded) */
Logical_RequestActivate,
/*! Occurs when the input focus target changes
The data.client will be NULL of no client is focused. */
Logical_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 NULL. */
Logical_Bell,
/*! Occurs when a client toggles its urgent status.
The client.urgent member can be used to get the status. */
Logical_UrgentWindow,
/*! Occurs when a client becomes visible */
Logical_WindowShow,
/*! Occurs when a client becomes non-visible */
Logical_WindowHide,
/*! Occurs when a pointer button is pressed on a client or its
decorations.
Note: to get the event for the client's window or for the entire
window+decorations, you need to do an mgrab for the window. */
Pointer_Press,
/*! Occurs when a pointer button is released on a client or its
decorations.
Note: to get the event for the client's window or for the entire
window+decorations, you need to do an mgrab for the window. */
Pointer_Release,
/*! Occurs when a pointer button is held and the pointer is dragged on a
client or its decorations.
Note: to get the event for the client's window or for the entire
window+decorations, you need to do an mgrab for the window, or an
mgrab_pointer (in which case it may not be a drag). */
Pointer_Motion,
/*! Occurs when a key is pressed.
Note: in order to recieve a key event, a kgrab must be done for the
key combination, or a kgrab_keyboard.
*/
Key_Press,
/*! Occurs when a key is released.
Note: in order to recieve a key event, a kgrab must be done for the
key combination, or a kgrab_keyboard.
*/
Key_Release
} EventType;
/* create the 'ob' module */
void obexport_startup();
void obexport_shutdown();
#endif

View file

@ -1,203 +0,0 @@
#include "openbox.h"
#include "event.h"
#include "client.h"
#include "xerror.h"
#include "prop.h"
#include "screen.h"
#include "focus.h"
#include "extensions.h"
#include "python.h"
#include "hooks.h"
#include "eventdata.h"
#include "gettext.h"
#include "clientwrap.h"
#include "screenwrap.h"
#include "kbind.h"
#include "mbind.h"
#include "frame.h"
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/types.h>
# include <sys/wait.h>
#endif
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
#include <X11/cursorfont.h>
Display *ob_display = NULL;
int ob_screen;
Window ob_root;
State ob_state;
gboolean ob_shutdown = FALSE;
gboolean ob_restart = FALSE;
gboolean ob_remote = FALSE;
gboolean ob_sync = TRUE;
Cursors ob_cursors;
void signal_handler(int signal);
int main(int argc, char **argv)
{
struct sigaction action;
sigset_t sigset;
ob_state = State_Starting;
/* initialize the locale */
if (!setlocale(LC_ALL, ""))
g_warning("Couldn't set locale from environment.\n");
bindtextdomain(PACKAGE, LOCALEDIR);
bind_textdomain_codeset(PACKAGE, "UTF-8");
textdomain(PACKAGE);
/* set up signal handler */
sigemptyset(&sigset);
action.sa_handler = signal_handler;
action.sa_mask = sigset;
action.sa_flags = SA_NOCLDSTOP | SA_NODEFER;
sigaction(SIGUSR1, &action, (struct sigaction *) NULL);
sigaction(SIGPIPE, &action, (struct sigaction *) NULL);
sigaction(SIGSEGV, &action, (struct sigaction *) NULL);
sigaction(SIGFPE, &action, (struct sigaction *) NULL);
sigaction(SIGTERM, &action, (struct sigaction *) NULL);
sigaction(SIGINT, &action, (struct sigaction *) NULL);
sigaction(SIGHUP, &action, (struct sigaction *) NULL);
sigaction(SIGCHLD, &action, (struct sigaction *) NULL);
/* anything that died while we were restarting won't give us a SIGCHLD */
while (waitpid(-1, NULL, WNOHANG) > 0);
/* XXX parse out command line args */
(void)argc;(void)argv;
/* critical warnings will exit the program */
g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
ob_display = XOpenDisplay(NULL);
if (ob_display == NULL)
/* print a message and exit */
g_critical("Failed to open the display.");
if (fcntl(ConnectionNumber(ob_display), F_SETFD, 1) == -1)
/* print a message and exit */
g_critical("Failed to set display as close-on-exec.");
ob_screen = DefaultScreen(ob_display);
ob_root = RootWindow(ob_display, ob_screen);
/* XXX fork self onto other screens */
XSynchronize(ob_display, ob_sync);
/* check for locale support */
if (!XSupportsLocale())
g_warning("X server does not support locale.");
if (!XSetLocaleModifiers(""))
g_warning("Cannot set locale modifiers for the X server.");
/* set our error handler */
XSetErrorHandler(xerror_handler);
/* set the DISPLAY environment variable for any lauched children, to the
display we're using, so they open in the right place. */
putenv(g_strdup_printf("DISPLAY=%s", DisplayString(ob_display)));
ob_cursors.left_ptr = XCreateFontCursor(ob_display, XC_left_ptr);
ob_cursors.ll_angle = XCreateFontCursor(ob_display, XC_ll_angle);
ob_cursors.lr_angle = XCreateFontCursor(ob_display, XC_lr_angle);
prop_init(); /* get atoms values for the display */
extensions_query_all(); /* find which extensions are present */
if (screen_annex()) { /* it will be ours! */
frame_startup();
python_startup();
obexport_startup();
hooks_startup();
screenwrap_startup();
clientwrap_startup();
eventdata_startup();
event_startup();
screen_startup();
focus_startup();
client_startup();
kbind_startup();
mbind_startup();
/* load the user's settings */
if (!python_import("rc"))
g_warning("ERROR LOADING RC FILE");
LOGICALHOOK(Startup, g_quark_try_string("none"), NULL);
/* get all the existing windows */
client_manage_all();
ob_state = State_Running;
while (!ob_shutdown) {
event_loop();
}
ob_state = State_Exiting;
client_unmanage_all();
LOGICALHOOK(Shutdown, g_quark_try_string("none"), NULL);
mbind_shutdown();
kbind_shutdown();
client_shutdown();
screen_shutdown();
event_shutdown();
eventdata_shutdown();
clientwrap_shutdown();
screenwrap_shutdown();
hooks_shutdown();
obexport_shutdown();
python_shutdown();
}
XCloseDisplay(ob_display);
/* XXX if (ob_restart) */
return 0;
}
void signal_handler(int signal)
{
switch (signal) {
case SIGUSR1:
g_message("Caught SIGUSR1 signal. Restarting.");
ob_shutdown = ob_restart = TRUE;
break;
case SIGCHLD:
wait(NULL);
break;
case SIGHUP:
case SIGINT:
case SIGTERM:
case SIGPIPE:
g_message("Caught signal %d. Exiting.", signal);
ob_shutdown = TRUE;
break;
case SIGFPE:
case SIGSEGV:
g_error("Caught signal %d. Aborting and dumping core.", signal);
}
}

View file

@ -1,35 +0,0 @@
#ifndef __openbox_h
#define __openbox_h
#include "obexport.h"
#include <glib.h>
#include <X11/Xlib.h>
/*! The X display */
extern Display *ob_display;
/*! The number of the screen on which we're running */
extern int ob_screen;
/*! The root window */
extern Window ob_root;
/* The state of execution of the window manager */
State ob_state;
/*! When set to true, Openbox will exit */
extern gboolean ob_shutdown;
/*! When set to true, Openbox will restart instead of shutting down */
extern gboolean ob_restart;
/*! Runtime option to specify running on a remote display */
extern gboolean ob_remote;
/*! Runtime option to run in synchronous mode */
extern gboolean ob_sync;
typedef struct Cursors {
Cursor left_ptr;
Cursor ll_angle;
Cursor lr_angle;
} Cursors;
Cursors ob_cursors;
#endif

271
c/prop.c
View file

@ -1,271 +0,0 @@
#include "prop.h"
#include "openbox.h"
#include <X11/Xatom.h>
Atoms prop_atoms;
#define CREATE(var, name) (prop_atoms.var = \
XInternAtom(ob_display, name, FALSE))
void prop_init()
{
g_assert(ob_display != NULL);
CREATE(cardinal, "CARDINAL");
CREATE(window, "WINDOW");
CREATE(pixmap, "PIXMAP");
CREATE(atom, "ATOM");
CREATE(string, "STRING");
CREATE(utf8, "UTF8_STRING");
CREATE(wm_colormap_windows, "WM_COLORMAP_WINDOWS");
CREATE(wm_protocols, "WM_PROTOCOLS");
CREATE(wm_state, "WM_STATE");
CREATE(wm_change_state, "WM_CHANGE_STATE");
CREATE(wm_delete_window, "WM_DELETE_WINDOW");
CREATE(wm_take_focus, "WM_TAKE_FOCUS");
CREATE(wm_name, "WM_NAME");
CREATE(wm_icon_name, "WM_ICON_NAME");
CREATE(wm_class, "WM_CLASS");
CREATE(wm_window_role, "WM_WINDOW_ROLE");
CREATE(motif_wm_hints, "_MOTIF_WM_HINTS");
CREATE(net_supported, "_NET_SUPPORTED");
CREATE(net_client_list, "_NET_CLIENT_LIST");
CREATE(net_client_list_stacking, "_NET_CLIENT_LIST_STACKING");
CREATE(net_number_of_desktops, "_NET_NUMBER_OF_DESKTOPS");
CREATE(net_desktop_geometry, "_NET_DESKTOP_GEOMETRY");
CREATE(net_desktop_viewport, "_NET_DESKTOP_VIEWPORT");
CREATE(net_current_desktop, "_NET_CURRENT_DESKTOP");
CREATE(net_desktop_names, "_NET_DESKTOP_NAMES");
CREATE(net_active_window, "_NET_ACTIVE_WINDOW");
CREATE(net_workarea, "_NET_WORKAREA");
CREATE(net_supporting_wm_check, "_NET_SUPPORTING_WM_CHECK");
/* CREATE(net_virtual_roots, "_NET_VIRTUAL_ROOTS"); */
CREATE(net_desktop_layout, "_NET_DESKTOP_LAYOUT");
CREATE(net_showing_desktop, "_NET_SHOWING_DESKTOP");
CREATE(net_close_window, "_NET_CLOSE_WINDOW");
CREATE(net_wm_moveresize, "_NET_WM_MOVERESIZE");
/* CREATE(net_properties, "_NET_PROPERTIES"); */
CREATE(net_wm_name, "_NET_WM_NAME");
CREATE(net_wm_visible_name, "_NET_WM_VISIBLE_NAME");
CREATE(net_wm_icon_name, "_NET_WM_ICON_NAME");
CREATE(net_wm_visible_icon_name, "_NET_WM_VISIBLE_ICON_NAME");
CREATE(net_wm_desktop, "_NET_WM_DESKTOP");
CREATE(net_wm_window_type, "_NET_WM_WINDOW_TYPE");
CREATE(net_wm_state, "_NET_WM_STATE");
CREATE(net_wm_strut, "_NET_WM_STRUT");
/* CREATE(net_wm_icon_geometry, "_NET_WM_ICON_GEOMETRY"); */
CREATE(net_wm_icon, "_NET_WM_ICON");
/* CREATE(net_wm_pid, "_NET_WM_PID"); */
/* CREATE(net_wm_handled_icons, "_NET_WM_HANDLED_ICONS"); */
CREATE(net_wm_allowed_actions, "_NET_WM_ALLOWED_ACTIONS");
/* CREATE(net_wm_ping, "_NET_WM_PING"); */
CREATE(net_wm_window_type_desktop, "_NET_WM_WINDOW_TYPE_DESKTOP");
CREATE(net_wm_window_type_dock, "_NET_WM_WINDOW_TYPE_DOCK");
CREATE(net_wm_window_type_toolbar, "_NET_WM_WINDOW_TYPE_TOOLBAR");
CREATE(net_wm_window_type_menu, "_NET_WM_WINDOW_TYPE_MENU");
CREATE(net_wm_window_type_utility, "_NET_WM_WINDOW_TYPE_UTILITY");
CREATE(net_wm_window_type_splash, "_NET_WM_WINDOW_TYPE_SPLASH");
CREATE(net_wm_window_type_dialog, "_NET_WM_WINDOW_TYPE_DIALOG");
CREATE(net_wm_window_type_normal, "_NET_WM_WINDOW_TYPE_NORMAL");
CREATE(net_wm_moveresize_size_topleft, "_NET_WM_MOVERESIZE_SIZE_TOPLEFT");
CREATE(net_wm_moveresize_size_topright,
"_NET_WM_MOVERESIZE_SIZE_TOPRIGHT");
CREATE(net_wm_moveresize_size_bottomleft,
"_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT");
CREATE(net_wm_moveresize_size_bottomright,
"_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT");
CREATE(net_wm_moveresize_move, "_NET_WM_MOVERESIZE_MOVE");
CREATE(net_wm_action_move, "_NET_WM_ACTION_MOVE");
CREATE(net_wm_action_resize, "_NET_WM_ACTION_RESIZE");
CREATE(net_wm_action_minimize, "_NET_WM_ACTION_MINIMIZE");
CREATE(net_wm_action_shade, "_NET_WM_ACTION_SHADE");
CREATE(net_wm_action_stick, "_NET_WM_ACTION_STICK");
CREATE(net_wm_action_maximize_horz, "_NET_WM_ACTION_MAXIMIZE_HORZ");
CREATE(net_wm_action_maximize_vert, "_NET_WM_ACTION_MAXIMIZE_VERT");
CREATE(net_wm_action_fullscreen, "_NET_WM_ACTION_FULLSCREEN");
CREATE(net_wm_action_change_desktop, "_NET_WM_ACTION_CHANGE_DESKTOP");
CREATE(net_wm_action_close, "_NET_WM_ACTION_CLOSE");
CREATE(net_wm_state_modal, "_NET_WM_STATE_MODAL");
CREATE(net_wm_state_sticky, "_NET_WM_STATE_STICKY");
CREATE(net_wm_state_maximized_vert, "_NET_WM_STATE_MAXIMIZED_VERT");
CREATE(net_wm_state_maximized_horz, "_NET_WM_STATE_MAXIMIZED_HORZ");
CREATE(net_wm_state_shaded, "_NET_WM_STATE_SHADED");
CREATE(net_wm_state_skip_taskbar, "_NET_WM_STATE_SKIP_TASKBAR");
CREATE(net_wm_state_skip_pager, "_NET_WM_STATE_SKIP_PAGER");
CREATE(net_wm_state_hidden, "_NET_WM_STATE_HIDDEN");
CREATE(net_wm_state_fullscreen, "_NET_WM_STATE_FULLSCREEN");
CREATE(net_wm_state_above, "_NET_WM_STATE_ABOVE");
CREATE(net_wm_state_below, "_NET_WM_STATE_BELOW");
prop_atoms.net_wm_state_add = 1;
prop_atoms.net_wm_state_remove = 0;
prop_atoms.net_wm_state_toggle = 2;
prop_atoms.net_wm_orientation_horz = 0;
prop_atoms.net_wm_orientation_vert = 1;
prop_atoms.net_wm_topleft = 0;
prop_atoms.net_wm_topright = 1;
prop_atoms.net_wm_bottomright = 2;
prop_atoms.net_wm_bottomleft = 3;
CREATE(kde_net_system_tray_windows, "_KDE_NET_SYSTEM_TRAY_WINDOWS");
CREATE(kde_net_wm_system_tray_window_for,
"_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR");
CREATE(kde_net_wm_window_type_override,
"_KDE_NET_WM_WINDOW_TYPE_OVERRIDE");
CREATE(kwm_win_icon, "KWM_WIN_ICON");
CREATE(rootpmapid, "_XROOTPMAP_ID");
CREATE(esetrootid, "ESETROOT_PMAP_ID");
CREATE(openbox_pid, "_OPENBOX_PID");
CREATE(openbox_premax, "_OPENBOX_PREMAX");
}
gboolean prop_get(Window win, Atom prop, Atom type, int size,
guchar **data, gulong num)
{
gboolean ret = FALSE;
int res;
guchar *xdata = NULL;
Atom ret_type;
int ret_size;
gulong ret_items, bytes_left;
long num32 = 32 / size * num; /* num in 32-bit elements */
res = XGetWindowProperty(ob_display, win, prop, 0l, num32,
FALSE, type, &ret_type, &ret_size,
&ret_items, &bytes_left, &xdata);
if (res == Success && ret_items && xdata) {
if (ret_size == size && ret_items >= num) {
*data = g_memdup(xdata, num * (size / 8));
ret = TRUE;
}
XFree(xdata);
}
return ret;
}
gboolean prop_get_prealloc(Window win, Atom prop, Atom type, int size,
guchar *data, gulong num)
{
gboolean ret = FALSE;
int res;
guchar *xdata = NULL;
Atom ret_type;
int ret_size;
gulong ret_items, bytes_left;
long num32 = 32 / size * num; /* num in 32-bit elements */
res = XGetWindowProperty(ob_display, win, prop, 0l, num32,
FALSE, type, &ret_type, &ret_size,
&ret_items, &bytes_left, &xdata);
if (res == Success && ret_items && xdata) {
if (ret_size == size && ret_items >= num) {
gulong i;
for (i = 0; i < num; ++i)
switch (size) {
case 8:
data[i] = xdata[i];
break;
case 16:
((guint16*)data)[i] = ((guint16*)xdata)[i];
break;
case 32:
((guint32*)data)[i] = ((guint32*)xdata)[i];
break;
default:
g_assert_not_reached(); /* unhandled size */
}
ret = TRUE;
}
XFree(xdata);
}
return ret;
}
gboolean prop_get_all(Window win, Atom prop, Atom type, int size,
guchar **data, gulong *num)
{
gboolean ret = FALSE;
int res;
guchar *xdata = NULL;
Atom ret_type;
int ret_size;
gulong ret_items, bytes_left;
res = XGetWindowProperty(ob_display, win, prop, 0l, G_MAXLONG,
FALSE, type, &ret_type, &ret_size,
&ret_items, &bytes_left, &xdata);
if (res == Success) {
if (ret_size == size && ret_items > 0) {
*data = g_memdup(xdata, ret_items * (size / 8));
*num = ret_items;
ret = TRUE;
}
XFree(xdata);
}
return ret;
}
gboolean prop_get_string(Window win, Atom prop, Atom type, guchar **data)
{
guchar *raw;
gulong num;
GString *str;
if (prop_get_all(win, prop, type, 8, &raw, &num)) {
str = g_string_new_len((char*)raw, num);
g_assert(str->str[num] == '\0');
g_free(raw);
*data = (guchar*)g_string_free(str, FALSE);
return TRUE;
}
return FALSE;
}
gboolean prop_get_strings(Window win, Atom prop, Atom type,
GPtrArray *data)
{
guchar *raw;
gulong num;
GString *str, *str2;
guint i, start;
if (prop_get_all(win, prop, type, 8, &raw, &num)) {
str = g_string_new_len((gchar*)raw, num);
g_assert(str->str[num] == '\0'); /* assuming this is always true.. */
g_free(raw);
/* split it into the list */
for (start = 0, i = 0; i < str->len; ++i) {
if (str->str[i] == '\0') {
str2 = g_string_new_len(&str->str[start], i - start);
g_ptr_array_add(data, g_string_free(str2, FALSE));
start = i + 1;
}
}
g_string_free(str, TRUE);
if (data->len > 0)
return TRUE;
}
return FALSE;
}
void prop_erase(Window win, Atom prop)
{
XDeleteProperty(ob_display, win, prop);
}

202
c/prop.h
View file

@ -1,202 +0,0 @@
#ifndef __atoms_h
#define __atoms_h
#include <X11/Xlib.h>
#include <glib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#include "openbox.h"
/*! The atoms on the X server which this class will cache */
typedef 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 */
/* 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;
/* 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 net_wm_orientation_horz;
Atom net_wm_orientation_vert;
Atom net_wm_topleft;
Atom net_wm_topright;
Atom net_wm_bottomright;
Atom net_wm_bottomleft;
/* Extra atoms */
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;
/* Openbox specific atoms */
Atom openbox_pid;
Atom openbox_premax;
} Atoms;
Atoms prop_atoms;
void prop_init();
gboolean prop_get(Window win, Atom prop, Atom type, int size,
guchar **data, gulong num);
gboolean prop_get_prealloc(Window win, Atom prop, Atom type, int size,
guchar *data, gulong num);
gboolean prop_get_all(Window win, Atom prop, Atom type, int size,
guchar **data, gulong *num);
gboolean prop_get_string(Window win, Atom prop, Atom type, guchar **data);
gboolean prop_get_strings(Window win, Atom prop, Atom type,
GPtrArray *data);
void prop_erase(Window win, Atom prop);
/* Set an 8-bit property from a string */
#define PROP_SETS(win, prop, type, value) \
(XChangeProperty(ob_display, win, prop_atoms.prop, prop_atoms.type, 8, \
PropModeReplace, (guchar*)value, strlen(value)))
/* Set a 32-bit property from a single value */
#define PROP_SET32(win, prop, type, value) \
(XChangeProperty(ob_display, win, prop_atoms.prop, prop_atoms.type, 32, \
PropModeReplace, (guchar*)&value, 1))
/* Set a 32-bit property from an array */
#define PROP_SET32A(win, prop, type, value, num) \
(XChangeProperty(ob_display, win, prop_atoms.prop, prop_atoms.type, 32, \
PropModeReplace, (guchar*)value, num))
/* Get an 8-bit property into a string */
#define PROP_GETS(win, prop, type, value) \
(prop_get_string(win, prop_atoms.prop, prop_atoms.type, \
(guchar**)&value))
/* Get an 8-bit property into a GPtrArray of strings
(The strings must be freed, the GPtrArray must already be created.) */
#define PROP_GETSA(win, prop, type, value) \
(prop_get_strings(win, prop_atoms.prop, prop_atoms.type, \
value))
/* Get an entire 8-bit property into an array (which must be freed) */
#define PROP_GET8U(win, prop, type, value, num) \
(prop_get_all(win, prop_atoms.prop, prop_atoms.type, 8, \
(guchar**)&value, &num))
/* Get 1 element of a 32-bit property into a given variable */
#define PROP_GET32(win, prop, type, value) \
(prop_get_prealloc(win, prop_atoms.prop, prop_atoms.type, 32, \
(guchar*)&value, 1))
/* Get an amount of a 32-bit property into an array (which must be freed) */
#define PROP_GET32A(win, prop, type, value, num) \
(prop_get(win, prop_atoms.prop, prop_atoms.type, 32, \
(guchar**)&value, num))
/* Get an entire 32-bit property into an array (which must be freed) */
#define PROP_GET32U(win, prop, type, value, num) \
(prop_get_all(win, prop_atoms.prop, prop_atoms.type, 32, \
(guchar**)&value, &num))
#define PROP_ERASE(win, prop) (prop_erase(win, prop_atoms.prop))
#endif

View file

@ -1,55 +0,0 @@
#include <Python.h>
#include <glib.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
void python_startup()
{
PyObject *sys, *sysdict, *syspath, *path1, *path2;
char *home, *homescriptdir;
Py_Initialize();
/* fix up the system path */
sys = PyImport_ImportModule((char*)"sys"); /* new */
sysdict = PyModule_GetDict(sys); /* borrowed */
syspath = PyDict_GetItemString(sysdict, (char*)"path"); /* borrowed */
path1 = PyString_FromString(SCRIPTDIR); /* new */
PyList_Insert(syspath, 0, path1);
Py_DECREF(path1);
home = getenv("HOME");
if (home != NULL) {
homescriptdir = g_strdup_printf("%s/.openbox", home);
path2 = PyString_FromString(homescriptdir); /* new */
g_free(homescriptdir);
PyList_Insert(syspath, 0, path2);
Py_DECREF(path2);
} else
g_warning("Failed to read the $HOME environment variable");
Py_DECREF(sys);
}
void python_shutdown()
{
Py_Finalize();
}
gboolean python_import(char *module)
{
PyObject *mod;
mod = PyImport_ImportModule(module); /* new */
if (mod == NULL) {
PyErr_Print();
return FALSE;
}
Py_DECREF(mod);
return TRUE;
}

View file

@ -1,10 +0,0 @@
#ifndef __python_h
#define __python_h
void python_startup();
void python_shutdown();
/*! Import a python module */
gboolean python_import(char *module);
#endif

View file

@ -1,516 +0,0 @@
#include "openbox.h"
#include "prop.h"
#include "screen.h"
#include "client.h"
#include "focus.h"
#include <X11/Xlib.h>
#ifdef HAVE_UNISTD_H
# include <sys/types.h>
# include <unistd.h>
#endif
/*! The event mask to grab on the root window */
#define ROOT_EVENTMASK (/*ColormapChangeMask |*/ PropertyChangeMask | \
EnterWindowMask | LeaveWindowMask | \
SubstructureNotifyMask | SubstructureRedirectMask | \
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
guint screen_num_desktops = 1;
guint screen_desktop = 0;
Size screen_physical_size;
gboolean screen_showing_desktop;
DesktopLayout screen_desktop_layout;
GPtrArray *screen_desktop_names;
static Rect *area = NULL;
static Strut *strut = NULL;
static void screen_update_area();
static gboolean running;
static int another_running(Display *d, XErrorEvent *e)
{
(void)d;(void)e;
g_message("A window manager is already running on screen %d",
ob_screen);
running = TRUE;
return -1;
}
gboolean screen_annex()
{
XErrorHandler old;
Window support;
pid_t pid;
int i, num_support;
Atom *supported;
running = FALSE;
old = XSetErrorHandler(another_running);
XSelectInput(ob_display, ob_root, ROOT_EVENTMASK);
XSync(ob_display, FALSE);
XSetErrorHandler(old);
if (running)
return FALSE;
g_message("Managing screen %d", ob_screen);
/* set the mouse cursor for the root window (the default cursor) */
XDefineCursor(ob_display, ob_root, ob_cursors.left_ptr);
/* set the OPENBOX_PID hint */
pid = getpid();
PROP_SET32(ob_root, openbox_pid, cardinal, pid);
/* create the netwm support window */
support = XCreateSimpleWindow(ob_display, ob_root, 0, 0, 1, 1, 0, 0, 0);
/* set supporting window */
PROP_SET32(ob_root, net_supporting_wm_check, window, support);
/* set properties on the supporting window */
PROP_SETS(support, net_wm_name, utf8, "Openbox");
PROP_SET32(support, net_supporting_wm_check, window, support);
/* set the _NET_SUPPORTED_ATOMS hint */
num_support = 48;
i = 0;
supported = g_new(Atom, num_support);
supported[i++] = prop_atoms.net_current_desktop;
supported[i++] = prop_atoms.net_number_of_desktops;
supported[i++] = prop_atoms.net_desktop_geometry;
supported[i++] = prop_atoms.net_desktop_viewport;
supported[i++] = prop_atoms.net_active_window;
supported[i++] = prop_atoms.net_workarea;
supported[i++] = prop_atoms.net_client_list;
supported[i++] = prop_atoms.net_client_list_stacking;
supported[i++] = prop_atoms.net_desktop_names;
supported[i++] = prop_atoms.net_close_window;
supported[i++] = prop_atoms.net_desktop_layout;
supported[i++] = prop_atoms.net_showing_desktop;
supported[i++] = prop_atoms.net_wm_name;
supported[i++] = prop_atoms.net_wm_visible_name;
supported[i++] = prop_atoms.net_wm_icon_name;
supported[i++] = prop_atoms.net_wm_visible_icon_name;
supported[i++] = prop_atoms.net_wm_desktop;
supported[i++] = prop_atoms.net_wm_strut;
supported[i++] = prop_atoms.net_wm_window_type;
supported[i++] = prop_atoms.net_wm_window_type_desktop;
supported[i++] = prop_atoms.net_wm_window_type_dock;
supported[i++] = prop_atoms.net_wm_window_type_toolbar;
supported[i++] = prop_atoms.net_wm_window_type_menu;
supported[i++] = prop_atoms.net_wm_window_type_utility;
supported[i++] = prop_atoms.net_wm_window_type_splash;
supported[i++] = prop_atoms.net_wm_window_type_dialog;
supported[i++] = prop_atoms.net_wm_window_type_normal;
supported[i++] = prop_atoms.net_wm_allowed_actions;
supported[i++] = prop_atoms.net_wm_action_move;
supported[i++] = prop_atoms.net_wm_action_resize;
supported[i++] = prop_atoms.net_wm_action_minimize;
supported[i++] = prop_atoms.net_wm_action_shade;
supported[i++] = prop_atoms.net_wm_action_maximize_horz;
supported[i++] = prop_atoms.net_wm_action_maximize_vert;
supported[i++] = prop_atoms.net_wm_action_fullscreen;
supported[i++] = prop_atoms.net_wm_action_change_desktop;
supported[i++] = prop_atoms.net_wm_action_close;
supported[i++] = prop_atoms.net_wm_state;
supported[i++] = prop_atoms.net_wm_state_modal;
supported[i++] = prop_atoms.net_wm_state_maximized_vert;
supported[i++] = prop_atoms.net_wm_state_maximized_horz;
supported[i++] = prop_atoms.net_wm_state_shaded;
supported[i++] = prop_atoms.net_wm_state_skip_taskbar;
supported[i++] = prop_atoms.net_wm_state_skip_pager;
supported[i++] = prop_atoms.net_wm_state_hidden;
supported[i++] = prop_atoms.net_wm_state_fullscreen;
supported[i++] = prop_atoms.net_wm_state_above;
supported[i++] = prop_atoms.net_wm_state_below;
g_assert(i == num_support);
/*
supported[] = prop_atoms.net_wm_moveresize;
supported[] = prop_atoms.net_wm_moveresize_size_topleft;
supported[] = prop_atoms.net_wm_moveresize_size_topright;
supported[] = prop_atoms.net_wm_moveresize_size_bottomleft;
supported[] = prop_atoms.net_wm_moveresize_size_bottomright;
supported[] = prop_atoms.net_wm_moveresize_move;
supported[] = prop_atoms.net_wm_action_stick;
*/
PROP_SET32A(ob_root, net_supported, atom, supported, num_support);
g_free(supported);
return TRUE;
}
void screen_startup()
{
screen_desktop_names = g_ptr_array_new();
/* get the initial size */
screen_resize();
screen_set_num_desktops(4);
screen_set_desktop(0);
/* don't start in showing-desktop mode */
screen_showing_desktop = FALSE;
PROP_SET32(ob_root, net_showing_desktop, cardinal, screen_showing_desktop);
screen_update_layout();
}
void screen_shutdown()
{
guint i;
for (i = 0; i < screen_desktop_names->len; ++i)
g_free(g_ptr_array_index(screen_desktop_names, i));
g_ptr_array_free(screen_desktop_names, TRUE);
g_free(strut);
g_free(area);
}
void screen_resize()
{
/* Set the _NET_DESKTOP_GEOMETRY hint */
/* XXX RandR support here? */
int geometry[2];
geometry[0] = WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen));
geometry[1] = HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen));
PROP_SET32A(ob_root, net_desktop_geometry, cardinal, geometry, 2);
screen_physical_size.width = geometry[0];
screen_physical_size.height = geometry[1];
if (ob_state == State_Starting)
return;
screen_update_struts();
/* XXX adjust more stuff ? */
}
void screen_set_num_desktops(guint num)
{
unsigned long *viewport;
g_assert(num > 0);
/* move windows on desktops that will no longer exist! */
/* XXX
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);
}
}
*/
screen_num_desktops = num;
PROP_SET32(ob_root, net_number_of_desktops, cardinal, num);
/* set the viewport hint */
viewport = g_new0(unsigned long, num * 2);
PROP_SET32A(ob_root, net_desktop_viewport, cardinal, viewport, num * 2);
g_free(viewport);
/* change our struts/area to match */
screen_update_struts();
/* the number of rows/columns will differ */
screen_update_layout();
/* may be some unnamed desktops that we need to fill in with names */
screen_update_desktop_names();
/* change our desktop if we're on one that no longer exists! */
if (screen_desktop >= screen_num_desktops)
screen_set_desktop(num - 1);
}
void screen_set_desktop(guint num)
{
guint old = screen_desktop;
g_assert(num < screen_num_desktops);
g_message("Moving to desktop %u", num);
screen_desktop = num;
PROP_SET32(ob_root, net_current_desktop, cardinal, num);
if (old == num) return;
/* XXX show/hide all the clients
std::list<Client*>::iterator it, end = clients.end();
for (it = clients.begin(); it != end; ++it)
(*it)->showhide(); */
/* XXX force the callbacks to fire
if (!openbox->focusedClient())
openbox->setFocusedClient(0); */
}
void screen_update_layout()
{
unsigned long *data = NULL;
/* defaults */
screen_desktop_layout.orientation = prop_atoms.net_wm_orientation_horz;
screen_desktop_layout.start_corner = prop_atoms.net_wm_topleft;
screen_desktop_layout.rows = 1;
screen_desktop_layout.columns = screen_num_desktops;
if (PROP_GET32A(ob_root, net_desktop_layout, cardinal, data, 4)) {
if (data[0] == prop_atoms.net_wm_orientation_vert)
screen_desktop_layout.orientation = data[0];
if (data[3] == prop_atoms.net_wm_topright)
screen_desktop_layout.start_corner = data[3];
else if (data[3] == prop_atoms.net_wm_bottomright)
screen_desktop_layout.start_corner = data[3];
else if (data[3] == prop_atoms.net_wm_bottomleft)
screen_desktop_layout.start_corner = data[3];
/* 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] = (screen_num_desktops +
screen_num_desktops % data[2]) / data[2];
} else if (data[2] == 0) {
data[2] = (screen_num_desktops +
screen_num_desktops % data[1]) / data[1];
}
screen_desktop_layout.columns = data[1];
screen_desktop_layout.rows = data[2];
}
/* bounds checking */
if (screen_desktop_layout.orientation ==
prop_atoms.net_wm_orientation_horz) {
if (screen_desktop_layout.rows > screen_num_desktops)
screen_desktop_layout.rows = screen_num_desktops;
if (screen_desktop_layout.columns > ((screen_num_desktops +
screen_num_desktops %
screen_desktop_layout.rows) /
screen_desktop_layout.rows))
screen_desktop_layout.columns =
(screen_num_desktops + screen_num_desktops %
screen_desktop_layout.rows) /
screen_desktop_layout.rows;
} else {
if (screen_desktop_layout.columns > screen_num_desktops)
screen_desktop_layout.columns = screen_num_desktops;
if (screen_desktop_layout.rows > ((screen_num_desktops +
screen_num_desktops %
screen_desktop_layout.columns) /
screen_desktop_layout.columns))
screen_desktop_layout.rows =
(screen_num_desktops + screen_num_desktops %
screen_desktop_layout.columns) /
screen_desktop_layout.columns;
}
g_free(data);
}
}
void screen_update_desktop_names()
{
guint i;
/* empty the array */
for (i = 0; i < screen_desktop_names->len; ++i)
g_free(g_ptr_array_index(screen_desktop_names, i));
g_ptr_array_set_size(screen_desktop_names, 0);
PROP_GETSA(ob_root, net_desktop_names, utf8, screen_desktop_names);
while (screen_desktop_names->len < screen_num_desktops)
g_ptr_array_add(screen_desktop_names, g_strdup("Unnamed Desktop"));
}
void screen_show_desktop(gboolean show)
{
GSList *it;
static Window saved_focus = 0;
if (show == screen_showing_desktop) return; /* no change */
/* save the window focus, and restore it when leaving the show-desktop
mode */
if (show && focus_client)
saved_focus = focus_client->window;
screen_showing_desktop = show;
for (it = client_list; it; it = g_slist_next(it)) {
Client *client = it->data;
if (client->type == Type_Desktop) {
if (show) client_focus(client);
} else
client_showhide(client);
}
if (!show) {
Client *f = focus_client;
if (!f || f->type == Type_Desktop) {
Client *c = g_hash_table_lookup(client_map,
(gpointer)saved_focus);
if (c) client_focus(c);
}
}
show = show ? 1 : 0; /* make it boolean */
PROP_SET32(ob_root, net_showing_desktop, cardinal, show);
}
void screen_install_colormap(Client *client, gboolean install)
{
if (client == NULL) {
/* XXX DONT USE THE DEFAULT SHIT HERE */
if (install)
XInstallColormap(ob_display,
DefaultColormap(ob_display, ob_screen));
else
XUninstallColormap(ob_display,
DefaultColormap(ob_display, ob_screen));
} else {
XWindowAttributes wa;
if (XGetWindowAttributes(ob_display, client->window, &wa)) {
if (install)
XInstallColormap(ob_display, wa.colormap);
else
XUninstallColormap(ob_display, wa.colormap);
}
}
}
void screen_update_struts()
{
GSList *it;
guint i;
if (strut != NULL)
g_free(strut);
strut = g_new0(Strut, screen_num_desktops + 1);
for (it = client_list; it; it = it->next) {
Client *c = it->data;
if (c->iconic) continue; /* these dont count in the strut */
if (c->desktop == 0xffffffff) {
for (i = 0; i < screen_num_desktops; ++i)
STRUT_ADD(strut[i], c->strut);
} else {
g_assert(c->desktop < screen_num_desktops);
STRUT_ADD(strut[c->desktop], c->strut);
}
/* apply to the 'all desktops' strut */
STRUT_ADD(strut[screen_num_desktops], c->strut);
}
screen_update_area();
}
static void screen_update_area()
{
guint i;
gulong *dims;
if (area != NULL)
g_free(area);
area = g_new0(Rect, screen_num_desktops + 1);
dims = g_new(unsigned long, 4 * screen_num_desktops);
for (i = 0; i < screen_num_desktops + 1; ++i) {
Rect old_area = area[i];
/*
#ifdef XINERAMA
// reset to the full areas
if (isXineramaActive())
xineramaUsableArea = getXineramaAreas();
#endif // XINERAMA
*/
RECT_SET(area[i], strut[i].left, strut[i].top,
screen_physical_size.width - (strut[i].left +
strut[i].right),
screen_physical_size.height - (strut[i].top +
strut[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 (!RECT_EQUAL(old_area, area[i])) {
/* the area has changed, adjust all the maximized windows */
GSList *it;
for (it = client_list; it; it = it->next) {
Client *c = it->data;
if (i < screen_num_desktops) {
if (c->desktop == i)
client_remaximize(c);
} else {
/* the 'all desktops' size */
if (c->desktop == DESKTOP_ALL)
client_remaximize(c);
}
}
}
/* don't set these for the 'all desktops' area */
if (i < screen_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;
}
}
PROP_SET32A(ob_root, net_workarea, cardinal,
dims, 4 * screen_num_desktops);
g_free(dims);
}
Rect *screen_area(guint desktop)
{
if (desktop >= screen_num_desktops) {
if (desktop == DESKTOP_ALL)
return &area[screen_num_desktops];
return NULL;
}
return &area[desktop];
}
Strut *screen_strut(guint desktop)
{
if (desktop >= screen_num_desktops) {
if (desktop == DESKTOP_ALL)
return &strut[screen_num_desktops];
return NULL;
}
return &strut[desktop];
}

View file

@ -1,66 +0,0 @@
#ifndef __screen_h
#define __screen_h
#include "geom.h"
struct Client;
#define DESKTOP_ALL (0xffffffff)
/*! The number of available desktops */
extern guint screen_num_desktops;
/*! The current desktop */
extern guint screen_desktop;
/*! The size of the screen */
extern Size screen_physical_size;
/*! Are we in showing-desktop mode? */
extern gboolean screen_showing_desktop;
typedef struct DesktopLayout {
guint orientation;
guint start_corner;
guint rows;
guint columns;
} DesktopLayout;
extern DesktopLayout screen_desktop_layout;
/*! An array of gchar*'s which are desktop names in UTF-8 format */
extern GPtrArray *screen_desktop_names;
/*! Take over the screen, set the basic hints on it claming it as ours */
gboolean screen_annex();
/*! Once the screen is ours, set up its initial state */
void screen_startup();
/*! Free resources */
void screen_shutdown();
/*! Figure out the new size of the screen and adjust stuff for it */
void screen_resize();
/*! Change the number of available desktops */
void screen_set_num_desktops(guint num);
/*! Change the current desktop */
void screen_set_desktop(guint num);
/*! Shows and focuses the desktop and hides all the client windows, or
returns to the normal state, showing client windows. */
void screen_show_desktop(gboolean show);
/*! Updates the desktop layout from the root property if available */
void screen_update_layout();
/*! Get desktop names from the root window property */
void screen_update_desktop_names();
/*! Installs or uninstalls a colormap for a client. If client is NULL, then
it handles the root colormap. */
void screen_install_colormap(struct Client *client, gboolean install);
void screen_update_struts();
Rect *screen_area(guint desktop);
Strut *screen_strut(guint desktop);
#endif

View file

@ -1,433 +0,0 @@
#include "screenwrap.h"
#include "openbox.h"
#include "screen.h"
#include "kbind.h"
#include "mbind.h"
ScreenWrap *screenwrap_instance;
/***************************************************************************
Define the type 'ScreenWrap'
***************************************************************************/
#define IS_SWRAP(v) ((v)->ob_type == &ScreenWrapType)
#define CHECK_SWRAP(self, funcname) { \
if (!IS_SWRAP(self)) { \
PyErr_SetString(PyExc_TypeError, \
"descriptor '" funcname "' a 'Screen' object"); \
return NULL; \
} \
}
staticforward PyTypeObject ScreenWrapType;
/***************************************************************************
Attribute methods
***************************************************************************/
static PyObject *swrap_number(ScreenWrap *self, PyObject *args)
{
CHECK_SWRAP(self, "number");
if (!PyArg_ParseTuple(args, ":number"))
return NULL;
return PyInt_FromLong(ob_screen);
}
static PyObject *swrap_rootWindow(ScreenWrap *self, PyObject *args)
{
CHECK_SWRAP(self, "rootWindow");
if (!PyArg_ParseTuple(args, ":rootWindow"))
return NULL;
return PyInt_FromLong(ob_root);
}
static PyObject *swrap_state(ScreenWrap *self, PyObject *args)
{
CHECK_SWRAP(self, "state");
if (!PyArg_ParseTuple(args, ":state"))
return NULL;
return PyInt_FromLong(ob_state);
}
static PyObject *swrap_numDesktops(ScreenWrap *self, PyObject *args)
{
CHECK_SWRAP(self, "numDesktops");
if (!PyArg_ParseTuple(args, ":numDesktops"))
return NULL;
return PyInt_FromLong(screen_num_desktops);
}
static PyObject *swrap_desktop(ScreenWrap *self, PyObject *args)
{
CHECK_SWRAP(self, "desktop");
if (!PyArg_ParseTuple(args, ":desktop"))
return NULL;
return PyInt_FromLong(screen_desktop);
}
static PyObject *swrap_physicalSize(ScreenWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_SWRAP(self, "physicalSize");
if (!PyArg_ParseTuple(args, ":physicalSize"))
return NULL;
tuple = PyTuple_New(2);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(screen_physical_size.width));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(screen_physical_size.height));
return tuple;
}
static PyObject *swrap_showingDesktop(ScreenWrap *self, PyObject *args)
{
CHECK_SWRAP(self, "showingDesktop");
if (!PyArg_ParseTuple(args, ":showingDesktop"))
return NULL;
return PyInt_FromLong(screen_showing_desktop ? 1 : 0);
}
static PyObject *swrap_desktopLayout(ScreenWrap *self, PyObject *args)
{
PyObject *tuple;
CHECK_SWRAP(self, "desktopLayout");
if (!PyArg_ParseTuple(args, ":desktopLayout"))
return NULL;
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0,
PyInt_FromLong(screen_desktop_layout.orientation));
PyTuple_SET_ITEM(tuple, 1,
PyInt_FromLong(screen_desktop_layout.start_corner));
PyTuple_SET_ITEM(tuple, 2,
PyInt_FromLong(screen_desktop_layout.rows));
PyTuple_SET_ITEM(tuple, 3,
PyInt_FromLong(screen_desktop_layout.columns));
return tuple;
}
static PyObject *swrap_desktopNames(ScreenWrap *self, PyObject *args)
{
PyObject *list;
guint s, i;
CHECK_SWRAP(self, "desktopNames");
if (!PyArg_ParseTuple(args, ":desktopNames"))
return NULL;
s = screen_desktop_names->len;
list = PyList_New(s);
for (i = 0; i < s; ++i)
PyList_SET_ITEM(list, i, PyString_FromString
(g_ptr_array_index(screen_desktop_names, i)));
return list;
}
static PyObject *swrap_area(ScreenWrap *self, PyObject *args)
{
PyObject * tuple;
Rect *r;
guint i;
CHECK_SWRAP(self, "area");
if (!PyArg_ParseTuple(args, "i:area", &i))
return NULL;
r = screen_area(i);
if (r == NULL) {
PyErr_SetString(PyExc_IndexError,
"the requested desktop was not valid");
return NULL;
}
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(r->x));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(r->y));
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(r->width));
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(r->height));
return tuple;
}
static PyObject *swrap_strut(ScreenWrap *self, PyObject *args)
{
PyObject *tuple;
Strut *s;
guint i;
CHECK_SWRAP(self, "strut");
if (!PyArg_ParseTuple(args, "i:strut", &i))
return NULL;
s = screen_strut(i);
if (s == NULL) {
PyErr_SetString(PyExc_IndexError,
"the requested desktop was not valid");
return NULL;
}
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(s->left));
PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(s->top));
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(s->right));
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(s->bottom));
return tuple;
}
static PyObject *swrap_grabKey(ScreenWrap *self, PyObject *args)
{
PyObject *item, *tuple;
GList *keylist = NULL, *it;
int i, s;
gboolean grab = FALSE;
CHECK_SWRAP(self, "grabKey");
if (!PyArg_ParseTuple(args, "O:grabKey", &tuple))
return NULL;
if (PyTuple_Check(tuple)) {
s = PyTuple_GET_SIZE(tuple);
if (s > 0) {
for (i = 0; i < s; ++i) {
item = PyTuple_GET_ITEM(tuple, i);
if (!PyString_Check(item))
break;
keylist = g_list_append(keylist,
g_strdup(PyString_AsString(item)));
}
if (i == s)
grab = kbind_add(keylist);
for (it = keylist; it != NULL; it = it->next)
g_free(it->data);
g_list_free(it);
if (grab) {
Py_INCREF(Py_None);
return Py_None;
} else {
PyErr_SetString(PyExc_ValueError,
"the key could not be grabbed");
return NULL;
}
}
}
PyErr_SetString(PyExc_TypeError, "expected a tuple of strings");
return NULL;
}
static PyObject *swrap_clearKeyGrabs(ScreenWrap *self, PyObject *args)
{
CHECK_SWRAP(self, "clearKeyGrabs");
if (!PyArg_ParseTuple(args, ":clearKeyGrabs"))
return NULL;
kbind_clearall();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *swrap_grabKeyboard(ScreenWrap *self, PyObject *args)
{
int grab;
CHECK_SWRAP(self, "grabKeyboard");
if (!PyArg_ParseTuple(args, "i:grabKeyboard", &grab))
return NULL;
if (!kbind_grab_keyboard(grab)) {
PyErr_SetString(PyExc_RuntimeError, "failed to grab keyboard");
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *swrap_grabButton(ScreenWrap *self, PyObject *args)
{
char *name;
char *context_str;
GQuark context;
CHECK_SWRAP(self, "grabButton");
if (!PyArg_ParseTuple(args, "ss:grabKey", &name, &context_str))
return NULL;
context = g_quark_try_string(context_str);
if (!context) {
PyErr_SetString(PyExc_ValueError, "invalid context");
return NULL;
}
if (mbind_add(name, context)) {
Py_INCREF(Py_None);
return Py_None;
} else {
PyErr_SetString(PyExc_ValueError,
"the button could not be grabbed");
return NULL;
}
}
static PyObject *swrap_clearButtonGrabs(ScreenWrap *self, PyObject *args)
{
CHECK_SWRAP(self, "clearButtonGrabs");
if (!PyArg_ParseTuple(args, ":clearButtonGrabs"))
return NULL;
mbind_clearall();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *swrap_grabPointer(ScreenWrap *self, PyObject *args)
{
int grab;
CHECK_SWRAP(self, "grabPointer");
if (!PyArg_ParseTuple(args, "i:grabPointer", &grab))
return NULL;
if (!mbind_grab_pointer(grab)) {
PyErr_SetString(PyExc_RuntimeError, "failed to grab pointer");
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef ScreenWrapAttributeMethods[] = {
{"number", (PyCFunction)swrap_number, METH_VARARGS,
"Screen.number() -- Returns the number of the screen on the X server on "
"which this Openbox instance is running."},
{"rootWindow", (PyCFunction)swrap_rootWindow, METH_VARARGS,
"Screen.rootWindow() -- Returns the window id of the root window."},
{"state", (PyCFunction)swrap_state, METH_VARARGS,
"Screen.state() -- Returns the running state of Openbox. One of the "
"ob.State_ constants."},
{"numDesktops", (PyCFunction)swrap_numDesktops, METH_VARARGS,
"Screen.numDesktops() -- Returns the number of desktops available."},
{"desktop", (PyCFunction)swrap_desktop, METH_VARARGS,
"Screen.desktop() -- Returns the currently visible desktop."},
{"physicalSize", (PyCFunction)swrap_physicalSize, METH_VARARGS,
"Screen.physicalSize() -- Returns the physical size (in pixels) of the "
"display in a tuple. The tuple is formatted as (width, height)."},
{"showingDesktop", (PyCFunction)swrap_showingDesktop, METH_VARARGS,
"Screen.showingDesktop() -- Returns if in showing-the-desktop mode or "
"not."},
{"desktopNames", (PyCFunction)swrap_desktopNames, METH_VARARGS,
"Screen.desktopNames() -- Returns a list of the names of all the "
"desktops, and possibly for desktops beyond those. The names are encoded "
"as UTF-8."},
{"desktopLayout", (PyCFunction)swrap_desktopLayout, METH_VARARGS,
"Screen.desktopLayout() -- Returns the layout of the desktops, as "
"specified by a compliant pager, in a tuple. The format of the tuple is "
"(orientation, corner, rows, columns). Where, orientation is one of the "
"ob.Orientation_ constants, corner is one of the ob.Corner_ constants, "
"and rows and columns specify the size of the layout. The rows and "
"columns will always include all the desktops."},
{"area", (PyCFunction)swrap_area, METH_VARARGS,
"Screen.area(d) -- Returns the usuable area on the Screen for a desktop, "
"in the form of a tuple. The tuples format is (x, y, width, height). The "
"desktop must be in the range of desktops on the screen, or 0xffffffff "
"to get a combined area for 'all desktops'."},
{"strut", (PyCFunction)swrap_area, METH_VARARGS,
"Screen.strut(d) -- Returns the combined strut of all clients on a "
"desktop, in the form of a tuple. The tuples format is "
"(left, top, right, bottom). The desktop must be in the range of "
"desktops on the screen, or 0xffffffff to get a combined strut for "
"'all desktops'."},
{"grabKey", (PyCFunction)swrap_grabKey, METH_VARARGS,
"Screen.grabKey(('Mod1-C-a', 'd')) -- Grabs a key chain so that key "
"events for it will occur. The argument must be a tuple of one or "
"more elements. Each key element is made up of "
"Modifier-Modifier-...-Key, where Modifier is one of Mod1, Mod2, "
"Mod3, Mod4, Mod5, S (for Shift), or C (for Control)."},
{"clearKeyGrabs", (PyCFunction)swrap_clearKeyGrabs, METH_VARARGS,
"Screen.clearKeyGrabs() -- Removes all key grabs that have been done "
"with grabKey()."},
{"grabKeyboard", (PyCFunction)swrap_grabKeyboard, METH_VARARGS,
"Screen.grabKeyboard(grab) -- Grabs or ungrabs the entire keyboard. When "
"the keyboard is grabbed, all key presses will be sent to the "
"hooks.keyboard hook. (grabbed keys will go to the hooks.events hook "
"too. "},
{"grabButton", (PyCFunction)swrap_grabButton, METH_VARARGS,
"Screen.grabButton('C-1', \"frame\") -- Grabs a pointer button "
"for the given context. The context must be one of the ob.Context_* "
"constants. The button definition is made up of "
"Modifier-Modifier-...-Button, where Modifier is one of Mod1, Mod2, "
"Mod3, Mod4, Mod5, S (for Shift), or C (for Control)."},
{"clearButtonGrabs", (PyCFunction)swrap_clearButtonGrabs, METH_VARARGS,
"Screen.clearButtonGrabs() -- Removes all button grabs that have been "
"done with grabButton()."},
{"grabPointer", (PyCFunction)swrap_grabPointer, METH_VARARGS,
"grabPointer(grab) -- Grabs or ungrabs the pointer device. When the "
"pointer is grabbed, all pointer events will be sent to the "
"hooks.pointer hook. (grabbed buttons will NOT go to the hooks.events "
"hook while the pointer is grabbed)."},
{NULL, NULL, 0, NULL}
};
/***************************************************************************
Type methods/struct
***************************************************************************/
static PyObject *swrap_getattr(ScreenWrap *self, char *name)
{
CHECK_SWRAP(self, "getattr");
return Py_FindMethod(ScreenWrapAttributeMethods, (PyObject*)self, name);
}
static void swrap_dealloc(ScreenWrap *self)
{
PyObject_Del((PyObject*) self);
}
static PyTypeObject ScreenWrapType = {
PyObject_HEAD_INIT(NULL)
0,
"Screen",
sizeof(ScreenWrap),
0,
(destructor) swrap_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc) swrap_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
/***************************************************************************
External methods
***************************************************************************/
void screenwrap_startup()
{
PyObject *ob, *obdict;
ScreenWrap *swrap;
ScreenWrapType.ob_type = &PyType_Type;
ScreenWrapType.tp_doc = "Wraps information and functionality global to an "
"instance of Openbox.";
PyType_Ready(&ScreenWrapType);
swrap = PyObject_New(ScreenWrap, &ScreenWrapType);
/* get the ob module/dict */
ob = PyImport_ImportModule("ob"); /* new */
g_assert(ob != NULL);
obdict = PyModule_GetDict(ob); /* borrowed */
g_assert(obdict != NULL);
PyDict_SetItemString(obdict, "Screen", (PyObject*)swrap);
Py_DECREF(swrap);
Py_DECREF(ob);
}
void screenwrap_shutdown()
{
}

View file

@ -1,14 +0,0 @@
#ifndef __screenwrap_h
#define __screenwrap_h
#include <Python.h>
/* ScreenWrap is a PyObject */
typedef struct ScreenWrap {
PyObject_HEAD
} ScreenWrap;
void screenwrap_startup();
void screenwrap_shutdown();
#endif

View file

@ -1,116 +0,0 @@
#include "openbox.h"
#include "prop.h"
#include "focus.h"
#include "client.h"
#include "frame.h"
#include <glib.h>
GList *stacking_list = NULL;
void stacking_set_list()
{
Window *windows, *win_it;
GList *it;
guint size = g_list_length(stacking_list);
/* create an array of the window ids (from bottom to top,
reverse order!) */
if (size > 0) {
windows = g_new(Window, size);
win_it = windows;
for (it = g_list_last(stacking_list); it; it = it->prev, ++win_it)
*win_it = ((Client*)it->data)->window;
} else
windows = NULL;
PROP_SET32A(ob_root, net_client_list_stacking, window, windows, size);
if (windows)
g_free(windows);
}
void stacking_raise(Client *client)
{
Window wins[2]; /* only ever restack 2 windows. */
GList *it;
Client *m;
g_assert(stacking_list != NULL); /* this would be bad */
m = client_find_modal_child(client);
/* if we have a modal child, raise it instead, we'll go along tho later */
if (m) stacking_raise(m);
/* remove the client before looking so we can't run into ourselves */
stacking_list = g_list_remove(stacking_list, client);
/* the stacking list is from highest to lowest */
it = stacking_list;
while (it) {
Client *c = it->data;
if (client->layer >= c->layer && m != c)
break;
it = it->next;
}
/*
if our new position is the top, we want to stack under the focus_backup.
otherwise, we want to stack under the previous window in the stack.
*/
if (it == stacking_list)
wins[0] = focus_backup;
else if (it != NULL)
wins[0] = ((Client*)it->prev->data)->frame->window;
else
wins[0] = ((Client*)g_list_last(stacking_list)->data)->frame->window;
wins[1] = client->frame->window;
stacking_list = g_list_insert_before(stacking_list, it, client);
XRestackWindows(ob_display, wins, 2);
stacking_set_list();
}
void stacking_lower(Client *client)
{
Window wins[2]; /* only ever restack 2 windows. */
GList *it;
g_assert(stacking_list != NULL); /* this would be bad */
it = g_list_last(stacking_list);
if (client->modal && client->transient_for) {
/* don't let a modal window lower below its transient_for */
it = g_list_find(stacking_list, client->transient_for);
g_assert(it != NULL);
wins[0] = (it == stacking_list ? focus_backup :
((Client*)it->prev->data)->frame->window);
wins[1] = client->frame->window;
if (wins[0] == wins[1]) return; /* already right above the window */
stacking_list = g_list_remove(stacking_list, client);
stacking_list = g_list_insert_before(stacking_list, it, client);
} else {
while (it != stacking_list) {
Client *c = it->data;
if (client->layer >= c->layer)
break;
it = it->prev;
}
if (it->data == client) return; /* already the bottom, return */
wins[0] = ((Client*)it->data)->frame->window;
wins[1] = client->frame->window;
stacking_list = g_list_remove(stacking_list, client);
stacking_list = g_list_insert_before(stacking_list,
it->next, client);
}
XRestackWindows(ob_display, wins, 2);
stacking_set_list();
}

View file

@ -1,26 +0,0 @@
#ifndef __stacking_h
#define __stacking_h
#include <glib.h>
struct Client;
extern GList *stacking_list;
/*! Sets the client stacking list on the root window from the
stacking_clientlist */
void stacking_set_list();
/*! 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 stacking_raise(struct Client *client);
/*! Lowers a client window below all others in its stacking layer */
void stacking_lower(struct Client *client);
#endif

View file

@ -1,32 +0,0 @@
#include "openbox.h"
#include <glib.h>
#include <X11/Xlib.h>
static gboolean xerror_ignore = FALSE;
int xerror_handler(Display *d, XErrorEvent *e)
{
#ifdef DEBUG
if (!xerror_ignore) {
char errtxt[128];
/*if (e->error_code != BadWindow) */
{
XGetErrorText(d, e->error_code, errtxt, 127);
if (e->error_code == BadWindow)
g_warning("X Error: %s", errtxt);
else
g_error("X Error: %s", errtxt);
}
}
#else
(void)d; (void)e;
#endif
return 0;
}
void xerror_set_ignore(gboolean ignore)
{
XSync(ob_display, FALSE);
xerror_ignore = ignore;
}

View file

@ -1,11 +0,0 @@
#ifndef __xerror_h
#define __xerror_h
#include <X11/Xlib.h>
#include <glib.h>
int xerror_handler(Display *, XErrorEvent *);
void xerror_set_ignore(gboolean ignore);
#endif