rename "Slit" to "Dock".

add config options to the rc3 for the dock.
create a window_map, add DockApps to the ObWindow types, use the window_map for translating windows into objects for event handling (only one lookup now) and remove the old maps (client_map, menu_map).
This commit is contained in:
Dana Jansens 2003-05-16 18:10:10 +00:00
parent 6e42b65bda
commit b77e40e1c7
18 changed files with 744 additions and 608 deletions

View file

@ -53,6 +53,39 @@ names = ("one" "two" "three" "four")
# the theme to display # the theme to display
#theme = "operation" #theme = "operation"
[dock]
# The position on the screen to place the dock. Options are:
# Floating - uses the floatingX and floatingY options to position itself
# TopLeft, Top, TopRight, Right, BottomRight, Bottom, BottomLeft, Left
# - the appropriate corner/edge of the screen
#position = "TopLeft"
# When position is "Floating", this specifies the x-coordinate to place the
# the dock at.
#floatingx = 0
# When position is "Floating", this specifies the y-coordinate to place the
# the dock at.
#floatingy = 0
# The stacking layer that the dock will be in. Options are:
# Top - above all normal windows, same layer as panels
# Normal - can be above and below normal windows
# Bottom - below all normal windows
#stacking = "Top"
# When true, the dock will grow horizontally when dock apps are added to it,
# otherwise it will grow vertically.
#horizontal = no
# When true, the dock will hide itself while the pointer is not over it, and
# will show itself when the pointer is.
#autoHide = no
# The number of milliseconds to wait before hiding the dock when the pointer
# leaves it, if the autoHide option is on.
#hideTimeout = 3000
[keyboard] [keyboard]
#kbind (Key [Key...]) Action [Parameter] #kbind (Key [Key...]) Action [Parameter]

View file

@ -26,13 +26,13 @@ openbox3_SOURCES=parse.tab.c parse.lex.c action.c client.c config.c \
extensions.c focus.c frame.c grab.c menu.c menu_render.c \ extensions.c focus.c frame.c grab.c menu.c menu_render.c \
openbox.c framerender.c parse.c plugin.c prop.c screen.c \ openbox.c framerender.c parse.c plugin.c prop.c screen.c \
stacking.c dispatch.c event.c group.c timer.c xerror.c \ stacking.c dispatch.c event.c group.c timer.c xerror.c \
moveresize.c startup.c popup.c slit.c window.c moveresize.c startup.c popup.c dock.c window.c
noinst_HEADERS=action.h client.h config.h dispatch.h event.h extensions.h \ noinst_HEADERS=action.h client.h config.h dispatch.h event.h extensions.h \
focus.h frame.h framerender.h geom.h gettext.h grab.h group.h \ focus.h frame.h framerender.h geom.h gettext.h grab.h group.h \
menu.h openbox.h parse.h parse.tab.h plugin.h prop.h screen.h \ menu.h openbox.h parse.h parse.tab.h plugin.h prop.h screen.h \
stacking.h timer.h xerror.h moveresize.h startup.h popup.h \ stacking.h timer.h xerror.h moveresize.h startup.h popup.h \
slit.h window.h dock.h window.h
# kill the implicit .c.y rule # kill the implicit .c.y rule
%.c: %.y %.c: %.y

View file

@ -1,5 +1,5 @@
#include "client.h" #include "client.h"
#include "slit.h" #include "dock.h"
#include "startup.h" #include "startup.h"
#include "screen.h" #include "screen.h"
#include "moveresize.h" #include "moveresize.h"
@ -26,7 +26,6 @@
ButtonMotionMask) ButtonMotionMask)
GList *client_list = NULL; GList *client_list = NULL;
GHashTable *client_map = NULL;
static void client_get_all(Client *self); static void client_get_all(Client *self);
static void client_toggle_border(Client *self, gboolean show); static void client_toggle_border(Client *self, gboolean show);
@ -41,20 +40,13 @@ static void client_change_allowed_actions(Client *self);
static void client_change_state(Client *self); static void client_change_state(Client *self);
static void client_apply_startup_state(Client *self); static void client_apply_startup_state(Client *self);
static guint map_hash(Window *w) { return *w; }
static gboolean map_key_comp(Window *w1, Window *w2) { return *w1 == *w2; }
void client_startup() void client_startup()
{ {
client_map = g_hash_table_new((GHashFunc)map_hash,
(GEqualFunc)map_key_comp);
client_set_list(); client_set_list();
} }
void client_shutdown() void client_shutdown()
{ {
g_hash_table_destroy(client_map);
} }
void client_set_list() void client_set_list()
@ -117,7 +109,6 @@ void client_manage_all()
Window w, *children; Window w, *children;
XWMHints *wmhints; XWMHints *wmhints;
XWindowAttributes attrib; XWindowAttributes attrib;
Client *active;
XQueryTree(ob_display, ob_root, &w, &w, &children, &nchild); XQueryTree(ob_display, ob_root, &w, &w, &children, &nchild);
@ -154,19 +145,28 @@ void client_manage_all()
stacking list are on the top where you can see them instead of buried stacking list are on the top where you can see them instead of buried
at the bottom! */ at the bottom! */
for (i = startup_stack_size; i > 0; --i) { for (i = startup_stack_size; i > 0; --i) {
Client *c; ObWindow *obw;
w = startup_stack_order[i-1]; w = startup_stack_order[i-1];
c = g_hash_table_lookup(client_map, &w); obw = g_hash_table_lookup(window_map, &w);
if (c) stacking_lower(CLIENT_AS_WINDOW(c)); if (obw) {
g_assert(WINDOW_IS_CLIENT(obw));
stacking_lower(CLIENT_AS_WINDOW(obw));
}
} }
g_free(startup_stack_order); g_free(startup_stack_order);
startup_stack_order = NULL; startup_stack_order = NULL;
startup_stack_size = 0; startup_stack_size = 0;
if (config_focus_new) { if (config_focus_new) {
active = g_hash_table_lookup(client_map, &startup_active); ObWindow *active;
if (!(active && client_focus(active)))
active = g_hash_table_lookup(window_map, &startup_active);
if (active) {
g_assert(WINDOW_IS_CLIENT(active));
if (!client_focus(WINDOW_AS_CLIENT(active)))
focus_fallback(Fallback_NoFocus);
} else
focus_fallback(Fallback_NoFocus); focus_fallback(Fallback_NoFocus);
} }
} }
@ -203,7 +203,7 @@ void client_manage(Window window)
if ((wmhint = XGetWMHints(ob_display, window))) { if ((wmhint = XGetWMHints(ob_display, window))) {
if ((wmhint->flags & StateHint) && if ((wmhint->flags & StateHint) &&
wmhint->initial_state == WithdrawnState) { wmhint->initial_state == WithdrawnState) {
slit_add(window, wmhint); dock_add(window, wmhint);
grab_server(FALSE); grab_server(FALSE);
XFree(wmhint); XFree(wmhint);
return; return;
@ -245,7 +245,7 @@ void client_manage(Window window)
/* add to client list/map */ /* add to client list/map */
client_list = g_list_append(client_list, self); client_list = g_list_append(client_list, self);
g_hash_table_insert(client_map, &self->window, self); g_hash_table_insert(window_map, &self->window, self);
/* update the focus lists */ /* update the focus lists */
focus_order_add_new(self); focus_order_add_new(self);
@ -330,7 +330,7 @@ void client_unmanage(Client *self)
client_list = g_list_remove(client_list, self); client_list = g_list_remove(client_list, self);
stacking_remove(self); stacking_remove(self);
g_hash_table_remove(client_map, &self->window); g_hash_table_remove(window_map, &self->window);
/* update the focus lists */ /* update the focus lists */
focus_order_remove(self); focus_order_remove(self);
@ -673,9 +673,10 @@ void client_update_transient_for(Client *self)
if (XGetTransientForHint(ob_display, self->window, &t)) { if (XGetTransientForHint(ob_display, self->window, &t)) {
self->transient = TRUE; self->transient = TRUE;
if (t != self->window) { /* cant be transient to itself! */ if (t != self->window) { /* cant be transient to itself! */
c = g_hash_table_lookup(client_map, &t); c = g_hash_table_lookup(window_map, &t);
/* if this happens then we need to check for it*/ /* if this happens then we need to check for it*/
g_assert(c != self); g_assert(c != self);
g_assert(!c || WINDOW_IS_CLIENT(c));
if (!c && self->group) { if (!c && self->group) {
/* not transient to a client, see if it is transient for a /* not transient to a client, see if it is transient for a

View file

@ -294,7 +294,6 @@ typedef struct Client {
} Client; } Client;
extern GList *client_list; extern GList *client_list;
extern GHashTable *client_map;
void client_startup(); void client_startup();
void client_shutdown(); void client_shutdown();

View file

@ -15,6 +15,14 @@ GSList *config_desktops_names;
gboolean config_opaque_move; gboolean config_opaque_move;
gboolean config_opaque_resize; gboolean config_opaque_resize;
StackLayer config_dock_layer;
DockPosition config_dock_pos;
int config_dock_x;
int config_dock_y;
gboolean config_dock_horz;
gboolean config_dock_hide;
guint config_dock_hide_timeout;
static void parse_focus(char *name, ParseToken *value) static void parse_focus(char *name, ParseToken *value)
{ {
if (!g_ascii_strcasecmp(name, "focusnew")) { if (!g_ascii_strcasecmp(name, "focusnew")) {
@ -118,6 +126,81 @@ static void parse_moveresize(char *name, ParseToken *value)
parse_free_token(value); parse_free_token(value);
} }
static void parse_dock(char *name, ParseToken *value)
{
if (!g_ascii_strcasecmp(name, "stacking")) {
if (value->type != TOKEN_STRING)
yyerror("invalid value");
else {
if (!g_ascii_strcasecmp(value->data.string, "bottom"))
config_dock_layer = Layer_Below;
else if (!g_ascii_strcasecmp(value->data.string, "normal"))
config_dock_layer = Layer_Normal;
else if (!g_ascii_strcasecmp(value->data.string, "top"))
config_dock_layer = Layer_Top;
else
yyerror("invalid layer");
}
} else if (!g_ascii_strcasecmp(name, "position")) {
if (value->type != TOKEN_STRING)
yyerror("invalid value");
else {
if (!g_ascii_strcasecmp(value->data.string, "topleft"))
config_dock_pos = DockPos_TopLeft;
else if (!g_ascii_strcasecmp(value->data.string, "top"))
config_dock_pos = DockPos_Top;
else if (!g_ascii_strcasecmp(value->data.string, "topright"))
config_dock_pos = DockPos_TopRight;
else if (!g_ascii_strcasecmp(value->data.string, "right"))
config_dock_pos = DockPos_Right;
else if (!g_ascii_strcasecmp(value->data.string, "bottomright"))
config_dock_pos = DockPos_BottomRight;
else if (!g_ascii_strcasecmp(value->data.string, "bottom"))
config_dock_pos = DockPos_Bottom;
else if (!g_ascii_strcasecmp(value->data.string, "bottomleft"))
config_dock_pos = DockPos_BottomLeft;
else if (!g_ascii_strcasecmp(value->data.string, "left"))
config_dock_pos = DockPos_Left;
else if (!g_ascii_strcasecmp(value->data.string, "floating"))
config_dock_pos = DockPos_Floating;
else
yyerror("invalid position");
}
} else if (!g_ascii_strcasecmp(name, "floatingx")) {
if (value->type != TOKEN_INTEGER)
yyerror("invalid value");
else {
config_dock_x = value->data.integer;
}
} else if (!g_ascii_strcasecmp(name, "floatingy")) {
if (value->type != TOKEN_INTEGER)
yyerror("invalid value");
else {
config_dock_y = value->data.integer;
}
} else if (!g_ascii_strcasecmp(name, "horizontal")) {
if (value->type != TOKEN_BOOL)
yyerror("invalid value");
else {
config_dock_horz = value->data.bool;
}
} else if (!g_ascii_strcasecmp(name, "autohide")) {
if (value->type != TOKEN_BOOL)
yyerror("invalid value");
else {
config_dock_hide = value->data.bool;
}
} else if (!g_ascii_strcasecmp(name, "hidetimeout")) {
if (value->type != TOKEN_INTEGER)
yyerror("invalid value");
else {
config_dock_hide_timeout = value->data.integer;
}
} else
yyerror("invalid option");
parse_free_token(value);
}
void config_startup() void config_startup()
{ {
config_focus_new = TRUE; config_focus_new = TRUE;
@ -141,6 +224,16 @@ void config_startup()
config_opaque_resize = TRUE; config_opaque_resize = TRUE;
parse_reg_section("moveresize", NULL, parse_moveresize); parse_reg_section("moveresize", NULL, parse_moveresize);
config_dock_layer = Layer_Top;
config_dock_pos = DockPos_TopRight;
config_dock_x = 0;
config_dock_y = 0;
config_dock_horz = FALSE;
config_dock_hide = FALSE;
config_dock_hide_timeout = 3000;
parse_reg_section("dock", NULL, parse_dock);
} }
void config_shutdown() void config_shutdown()

View file

@ -1,6 +1,9 @@
#ifndef __config_h #ifndef __config_h
#define __config_h #define __config_h
#include "dock.h"
#include "stacking.h"
#include <glib.h> #include <glib.h>
/*! Should new windows be focused */ /*! Should new windows be focused */
@ -22,6 +25,23 @@ extern gboolean config_opaque_move;
while they are resize */ while they are resize */
extern gboolean config_opaque_resize; extern gboolean config_opaque_resize;
/*! The stacking layer the dock will reside in */
extern StackLayer config_dock_layer;
/*! The position at which to place the dock */
extern DockPosition config_dock_pos;
/*! If config_dock_pos is DockPos_Floating, this is the top-left corner's
position */
extern int config_dock_x;
/*! If config_dock_pos is DockPos_Floating, this is the top-left corner's
position */
extern int config_dock_y;
/*! Whether the dock places the dockapps in it horizontally or vertically */
extern gboolean config_dock_horz;
/*! Whether to auto-hide the dock when the pointer is not over it */
extern gboolean config_dock_hide;
/*! The number of milliseconds to wait before hiding the dock */
extern guint config_dock_hide_timeout;
/* The name of the theme */ /* The name of the theme */
char *config_theme; char *config_theme;

382
openbox/dock.c Normal file
View file

@ -0,0 +1,382 @@
#include "dock.h"
#include "screen.h"
#include "config.h"
#include "grab.h"
#include "openbox.h"
#include "render/theme.h"
#define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
EnterWindowMask | LeaveWindowMask)
#define DOCKAPP_EVENT_MASK (StructureNotifyMask)
static Dock *dock;
void dock_startup()
{
XSetWindowAttributes attrib;
int i;
dock = g_new0(struct Dock, 1);
dock->obwin.type = Window_Dock;
dock->hidden = TRUE;
attrib.event_mask = DOCK_EVENT_MASK;
attrib.override_redirect = True;
dock->frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
render_depth, InputOutput, render_visual,
CWOverrideRedirect | CWEventMask,
&attrib);
dock->a_frame = appearance_copy(theme_a_unfocused_title);
XSetWindowBorder(ob_display, dock->frame, theme_b_color->pixel);
XSetWindowBorderWidth(ob_display, dock->frame, theme_bwidth);
g_hash_table_insert(window_map, &dock->frame, dock);
stacking_add(DOCK_AS_WINDOW(&dock[i]));
stacking_raise(DOCK_AS_WINDOW(&dock[i]));
}
void dock_shutdown()
{
XDestroyWindow(ob_display, dock->frame);
appearance_free(dock->a_frame);
g_hash_table_remove(window_map, &dock->frame);
stacking_remove(dock);
}
void dock_add(Window win, XWMHints *wmhints)
{
DockApp *app;
XWindowAttributes attrib;
app = g_new0(DockApp, 1);
app->win = win;
app->icon_win = (wmhints->flags & IconWindowHint) ?
wmhints->icon_window : win;
if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
app->w = attrib.width;
app->h = attrib.height;
} else {
app->w = app->h = 64;
}
dock->dock_apps = g_list_append(dock->dock_apps, app);
dock_configure();
XReparentWindow(ob_display, app->icon_win, dock->frame, app->x, app->y);
/*
This is the same case as in frame.c for client windows. When Openbox is
starting, the window is already mapped so we see unmap events occur 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)
app->ignore_unmaps += 2;
if (app->win != app->icon_win) {
/* have to map it so that it can be re-managed on a restart */
XMoveWindow(ob_display, app->win, -1000, -1000);
XMapWindow(ob_display, app->win);
}
XMapWindow(ob_display, app->icon_win);
XSync(ob_display, False);
/* specify that if we exit, the window should not be destroyed and should
be reparented back to root automatically */
XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
XSelectInput(ob_display, app->icon_win, DOCKAPP_EVENT_MASK);
grab_button_full(2, 0, app->icon_win,
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
GrabModeAsync, ob_cursors.move);
g_hash_table_insert(window_map, &app->icon_win, app);
g_message("Managed Dock App: 0x%lx", app->icon_win);
}
void dock_remove_all()
{
while (dock->dock_apps)
dock_remove(dock->dock_apps->data, TRUE);
}
void dock_remove(DockApp *app, gboolean reparent)
{
ungrab_button(2, 0, app->icon_win);
XSelectInput(ob_display, app->icon_win, NoEventMask);
/* remove the window from our save set */
XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
XSync(ob_display, False);
g_hash_table_remove(window_map, &app->icon_win);
if (reparent)
XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
dock->dock_apps = g_list_remove(dock->dock_apps, app);
dock_configure();
g_message("Unmanaged Dock App: 0x%lx", app->icon_win);
g_free(app);
}
void dock_configure()
{
GList *it;
int spot;
int gravity;
dock->w = dock->h = spot = 0;
for (it = dock->dock_apps; it; it = it->next) {
struct DockApp *app = it->data;
if (config_dock_horz) {
app->x = spot;
app->y = 0;
dock->w += app->w;
dock->h = MAX(dock->h, app->h);
spot += app->w;
} else {
app->x = 0;
app->y = spot;
dock->w = MAX(dock->w, app->w);
dock->h += app->h;
spot += app->h;
}
XMoveWindow(ob_display, app->icon_win, app->x, app->y);
}
/* used for calculating offsets */
dock->w += theme_bwidth * 2;
dock->h += theme_bwidth * 2;
/* calculate position */
switch (config_dock_pos) {
case DockPos_Floating:
dock->x = config_dock_x;
dock->y = config_dock_y;
gravity = NorthWestGravity;
break;
case DockPos_TopLeft:
dock->x = 0;
dock->y = 0;
gravity = NorthWestGravity;
break;
case DockPos_Top:
dock->x = screen_physical_size.width / 2;
dock->y = 0;
gravity = NorthGravity;
break;
case DockPos_TopRight:
dock->x = screen_physical_size.width;
dock->y = 0;
gravity = NorthEastGravity;
break;
case DockPos_Left:
dock->x = 0;
dock->y = screen_physical_size.height / 2;
gravity = WestGravity;
break;
case DockPos_Right:
dock->x = screen_physical_size.width;
dock->y = screen_physical_size.height / 2;
gravity = EastGravity;
break;
case DockPos_BottomLeft:
dock->x = 0;
dock->y = screen_physical_size.height;
gravity = SouthWestGravity;
break;
case DockPos_Bottom:
dock->x = screen_physical_size.width / 2;
dock->y = screen_physical_size.height;
gravity = SouthGravity;
break;
case DockPos_BottomRight:
dock->x = screen_physical_size.width;
dock->y = screen_physical_size.height;
gravity = SouthEastGravity;
break;
}
switch(gravity) {
case NorthGravity:
case CenterGravity:
case SouthGravity:
dock->x -= dock->w / 2;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
dock->x -= dock->w;
break;
}
switch(gravity) {
case WestGravity:
case CenterGravity:
case EastGravity:
dock->y -= dock->h / 2;
break;
case SouthWestGravity:
case SouthGravity:
case SouthEastGravity:
dock->y -= dock->h;
break;
}
if (config_dock_hide && dock->hidden) {
switch (config_dock_pos) {
case DockPos_Floating:
break;
case DockPos_TopLeft:
if (config_dock_horz)
dock->y -= dock->h - theme_bwidth;
else
dock->x -= dock->w - theme_bwidth;
break;
case DockPos_Top:
dock->y -= dock->h - theme_bwidth;
break;
case DockPos_TopRight:
if (config_dock_horz)
dock->y -= dock->h - theme_bwidth;
else
dock->x += dock->w - theme_bwidth;
break;
case DockPos_Left:
dock->x -= dock->w - theme_bwidth;
break;
case DockPos_Right:
dock->x += dock->w - theme_bwidth;
break;
case DockPos_BottomLeft:
if (config_dock_horz)
dock->y += dock->h - theme_bwidth;
else
dock->x -= dock->w - theme_bwidth;
break;
case DockPos_Bottom:
dock->y += dock->h - theme_bwidth;
break;
case DockPos_BottomRight:
if (config_dock_horz)
dock->y += dock->h - theme_bwidth;
else
dock->x += dock->w - theme_bwidth;
break;
}
}
/* not used for actually sizing shit */
dock->w -= theme_bwidth * 2;
dock->h -= theme_bwidth * 2;
if (dock->w > 0 && dock->h > 0) {
RECT_SET(dock->a_frame->area, 0, 0, dock->w, dock->h);
XMoveResizeWindow(ob_display, dock->frame,
dock->x, dock->y, dock->w, dock->h);
paint(dock->frame, dock->a_frame);
XMapWindow(ob_display, dock->frame);
} else
XUnmapWindow(ob_display, dock->frame);
/* but they are useful outside of this function! */
dock->w += theme_bwidth * 2;
dock->h += theme_bwidth * 2;
}
void dock_app_configure(DockApp *app, int w, int h)
{
app->w = w;
app->h = h;
dock_configure();
}
void dock_app_drag(DockApp *app, XMotionEvent *e)
{
DockApp *over = NULL;
GList *it;
int x, y;
gboolean after;
x = e->x_root;
y = e->y_root;
/* are we on top of the dock? */
if (!(x >= dock->x &&
y >= dock->y &&
x < dock->x + dock->w &&
y < dock->y + dock->h))
return;
x -= dock->x;
y -= dock->y;
/* which dock app are we on top of? */
for (it = dock->dock_apps; it; it = it->next) {
over = it->data;
if (config_dock_horz) {
if (x >= over->x && x < over->x + over->w)
break;
} else {
if (y >= over->y && y < over->y + over->h)
break;
}
}
if (!it || app == over) return;
x -= over->x;
y -= over->y;
if (config_dock_horz)
after = (x > over->w / 2);
else
after = (y > over->h / 2);
/* remove before doing the it->next! */
dock->dock_apps = g_list_remove(dock->dock_apps, app);
if (after) it = it->next;
dock->dock_apps = g_list_insert_before(dock->dock_apps, it, app);
dock_configure();
}
static void hide_timeout(void *n)
{
/* dont repeat */
timer_stop(dock->hide_timer);
dock->hide_timer = NULL;
/* hide */
dock->hidden = TRUE;
dock_configure();
}
void dock_hide(gboolean hide)
{
if (dock->hidden == hide || !config_dock_hide)
return;
if (!hide) {
/* show */
dock->hidden = FALSE;
dock_configure();
/* if was hiding, stop it */
if (dock->hide_timer) {
timer_stop(dock->hide_timer);
dock->hide_timer = NULL;
}
} else {
g_assert(!dock->hide_timer);
dock->hide_timer = timer_start(config_dock_hide_timeout * 1000,
(TimeoutHandler)hide_timeout,
NULL);
}
}

66
openbox/dock.h Normal file
View file

@ -0,0 +1,66 @@
#ifndef __dock_h
#define __dock_h
#include "timer.h"
#include "render/render.h"
#include "window.h"
#include "stacking.h"
#include <glib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
typedef enum {
DockPos_Floating,
DockPos_TopLeft,
DockPos_Top,
DockPos_TopRight,
DockPos_Right,
DockPos_BottomRight,
DockPos_Bottom,
DockPos_BottomLeft,
DockPos_Left
} DockPosition;
typedef struct Dock {
ObWindow obwin;
Window frame;
Appearance *a_frame;
/* actual position (when not auto-hidden) */
int x, y;
int w, h;
gboolean hidden;
Timer *hide_timer;
GList *dock_apps;
} Dock;
typedef struct DockApp {
int ignore_unmaps;
Window icon_win;
Window win;
int x;
int y;
int w;
int h;
} DockApp;
void dock_startup();
void dock_shutdown();
void dock_configure();
void dock_hide(gboolean hide);
void dock_add(Window win, XWMHints *wmhints);
void dock_remove_all();
void dock_remove(DockApp *app, gboolean reparent);
void dock_app_drag(DockApp *app, XMotionEvent *e);
void dock_app_configure(DockApp *app, int w, int h);
#endif

View file

@ -1,5 +1,5 @@
#include "openbox.h" #include "openbox.h"
#include "slit.h" #include "dock.h"
#include "client.h" #include "client.h"
#include "xerror.h" #include "xerror.h"
#include "prop.h" #include "prop.h"
@ -27,8 +27,8 @@
static void event_process(XEvent *e); static void event_process(XEvent *e);
static void event_handle_root(XEvent *e); static void event_handle_root(XEvent *e);
static void event_handle_slit(Slit *s, XEvent *e); static void event_handle_dock(Dock *s, XEvent *e);
static void event_handle_slitapp(SlitApp *app, XEvent *e); static void event_handle_dockapp(DockApp *app, XEvent *e);
static void event_handle_client(Client *c, XEvent *e); static void event_handle_client(Client *c, XEvent *e);
static void event_handle_menu(Menu *menu, XEvent *e); static void event_handle_menu(Menu *menu, XEvent *e);
@ -394,15 +394,32 @@ static void event_process(XEvent *e)
{ {
Window window; Window window;
Client *client = NULL; Client *client = NULL;
Slit *slit = NULL; Dock *dock = NULL;
SlitApp *slitapp = NULL; DockApp *dockapp = NULL;
Menu *menu = NULL; Menu *menu = NULL;
ObWindow *obwin = NULL;
window = event_get_window(e); window = event_get_window(e);
if (!(client = g_hash_table_lookup(client_map, &window))) if ((obwin = g_hash_table_lookup(window_map, &window))) {
if (!(slitapp = g_hash_table_lookup(slit_app_map, &window))) switch (obwin->type) {
if (!(slit = g_hash_table_lookup(slit_map, &window))) case Window_Dock:
menu = g_hash_table_lookup(menu_map, &window); dock = WINDOW_AS_DOCK(obwin);
break;
case Window_DockApp:
dockapp = WINDOW_AS_DOCKAPP(obwin);
break;
case Window_Menu:
menu = WINDOW_AS_MENU(obwin);
break;
case Window_Client:
client = WINDOW_AS_CLIENT(obwin);
break;
case Window_Internal:
/* not to be used for events */
g_assert_not_reached();
break;
}
}
event_set_lasttime(e); event_set_lasttime(e);
event_hack_mods(e); event_hack_mods(e);
@ -415,10 +432,10 @@ static void event_process(XEvent *e)
return; return;
} else if (client) } else if (client)
event_handle_client(client, e); event_handle_client(client, e);
else if (slitapp) else if (dockapp)
event_handle_slitapp(slitapp, e); event_handle_dockapp(dockapp, e);
else if (slit) else if (dock)
event_handle_slit(slit, e); event_handle_dock(dock, e);
else if (window == ob_root) else if (window == ob_root)
event_handle_root(e); event_handle_root(e);
else if (e->type == MapRequest) else if (e->type == MapRequest)
@ -969,41 +986,41 @@ void fd_event_handle()
g_datalist_foreach(&fd_handler_list, fd_event_handle_foreach, NULL); g_datalist_foreach(&fd_handler_list, fd_event_handle_foreach, NULL);
} }
static void event_handle_slit(Slit *s, XEvent *e) static void event_handle_dock(Dock *s, XEvent *e)
{ {
switch (e->type) { switch (e->type) {
case ButtonPress: case ButtonPress:
stacking_raise(SLIT_AS_WINDOW(s)); stacking_raise(DOCK_AS_WINDOW(s));
case EnterNotify: case EnterNotify:
slit_hide(s, FALSE); dock_hide(FALSE);
break; break;
case LeaveNotify: case LeaveNotify:
slit_hide(s, TRUE); dock_hide(TRUE);
break; break;
} }
} }
static void event_handle_slitapp(SlitApp *app, XEvent *e) static void event_handle_dockapp(DockApp *app, XEvent *e)
{ {
switch (e->type) { switch (e->type) {
case MotionNotify: case MotionNotify:
slit_app_drag(app, &e->xmotion); dock_app_drag(app, &e->xmotion);
break; break;
case UnmapNotify: case UnmapNotify:
if (app->ignore_unmaps) { if (app->ignore_unmaps) {
app->ignore_unmaps--; app->ignore_unmaps--;
break; break;
} }
slit_remove(app, TRUE); dock_remove(app, TRUE);
break; break;
case DestroyNotify: case DestroyNotify:
slit_remove(app, FALSE); dock_remove(app, FALSE);
break; break;
case ReparentNotify: case ReparentNotify:
slit_remove(app, FALSE); dock_remove(app, FALSE);
break; break;
case ConfigureNotify: case ConfigureNotify:
slit_app_configure(app, e->xconfigure.width, e->xconfigure.height); dock_app_configure(app, e->xconfigure.width, e->xconfigure.height);
break; break;
} }
} }

View file

@ -430,20 +430,20 @@ void frame_grab_client(Frame *self, Client *client)
frame_adjust_area(self, TRUE, TRUE); frame_adjust_area(self, TRUE, TRUE);
/* set all the windows for the frame in the client_map */ /* set all the windows for the frame in the window_map */
g_hash_table_insert(client_map, &self->window, client); g_hash_table_insert(window_map, &self->window, client);
g_hash_table_insert(client_map, &self->plate, client); g_hash_table_insert(window_map, &self->plate, client);
g_hash_table_insert(client_map, &self->title, client); g_hash_table_insert(window_map, &self->title, client);
g_hash_table_insert(client_map, &self->label, client); g_hash_table_insert(window_map, &self->label, client);
g_hash_table_insert(client_map, &self->max, client); g_hash_table_insert(window_map, &self->max, client);
g_hash_table_insert(client_map, &self->close, client); g_hash_table_insert(window_map, &self->close, client);
g_hash_table_insert(client_map, &self->desk, client); g_hash_table_insert(window_map, &self->desk, client);
g_hash_table_insert(client_map, &self->shade, client); g_hash_table_insert(window_map, &self->shade, client);
g_hash_table_insert(client_map, &self->icon, client); g_hash_table_insert(window_map, &self->icon, client);
g_hash_table_insert(client_map, &self->iconify, client); g_hash_table_insert(window_map, &self->iconify, client);
g_hash_table_insert(client_map, &self->handle, client); g_hash_table_insert(window_map, &self->handle, client);
g_hash_table_insert(client_map, &self->lgrip, client); g_hash_table_insert(window_map, &self->lgrip, client);
g_hash_table_insert(client_map, &self->rgrip, client); g_hash_table_insert(window_map, &self->rgrip, client);
} }
void frame_release_client(Frame *self, Client *client) void frame_release_client(Frame *self, Client *client)
@ -470,20 +470,20 @@ void frame_release_client(Frame *self, Client *client)
client->area.y); client->area.y);
} }
/* remove all the windows for the frame from the client_map */ /* remove all the windows for the frame from the window_map */
g_hash_table_remove(client_map, &self->window); g_hash_table_remove(window_map, &self->window);
g_hash_table_remove(client_map, &self->plate); g_hash_table_remove(window_map, &self->plate);
g_hash_table_remove(client_map, &self->title); g_hash_table_remove(window_map, &self->title);
g_hash_table_remove(client_map, &self->label); g_hash_table_remove(window_map, &self->label);
g_hash_table_remove(client_map, &self->max); g_hash_table_remove(window_map, &self->max);
g_hash_table_remove(client_map, &self->close); g_hash_table_remove(window_map, &self->close);
g_hash_table_remove(client_map, &self->desk); g_hash_table_remove(window_map, &self->desk);
g_hash_table_remove(client_map, &self->shade); g_hash_table_remove(window_map, &self->shade);
g_hash_table_remove(client_map, &self->icon); g_hash_table_remove(window_map, &self->icon);
g_hash_table_remove(client_map, &self->iconify); g_hash_table_remove(window_map, &self->iconify);
g_hash_table_remove(client_map, &self->handle); g_hash_table_remove(window_map, &self->handle);
g_hash_table_remove(client_map, &self->lgrip); g_hash_table_remove(window_map, &self->lgrip);
g_hash_table_remove(client_map, &self->rgrip); g_hash_table_remove(window_map, &self->rgrip);
frame_free(self); frame_free(self);
} }

View file

@ -8,7 +8,6 @@
#include "plugin.h" #include "plugin.h"
static GHashTable *menu_hash = NULL; static GHashTable *menu_hash = NULL;
GHashTable *menu_map = NULL;
#define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \ #define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \
LeaveWindowMask) LeaveWindowMask)
@ -34,9 +33,9 @@ void menu_destroy_hash_value(Menu *self)
g_free(self->label); g_free(self->label);
g_free(self->name); g_free(self->name);
g_hash_table_remove(menu_map, &self->title); g_hash_table_remove(window_map, &self->title);
g_hash_table_remove(menu_map, &self->frame); g_hash_table_remove(window_map, &self->frame);
g_hash_table_remove(menu_map, &self->items); g_hash_table_remove(window_map, &self->items);
stacking_remove(self); stacking_remove(self);
@ -53,7 +52,7 @@ void menu_entry_free(MenuEntry *self)
g_free(self->label); g_free(self->label);
action_free(self->action); action_free(self->action);
g_hash_table_remove(menu_map, &self->item); g_hash_table_remove(window_map, &self->item);
appearance_free(self->a_item); appearance_free(self->a_item);
appearance_free(self->a_disabled); appearance_free(self->a_disabled);
@ -73,7 +72,6 @@ void menu_startup()
menu_hash = g_hash_table_new_full(g_str_hash, g_str_equal, menu_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
menu_destroy_hash_key, menu_destroy_hash_key,
(GDestroyNotify)menu_destroy_hash_value); (GDestroyNotify)menu_destroy_hash_value);
menu_map = g_hash_table_new(g_int_hash, g_int_equal);
m = menu_new(NULL, "root", NULL); m = menu_new(NULL, "root", NULL);
@ -137,7 +135,6 @@ void menu_startup()
void menu_shutdown() void menu_shutdown()
{ {
g_hash_table_destroy(menu_hash); g_hash_table_destroy(menu_hash);
g_hash_table_destroy(menu_map);
} }
static Window createWindow(Window parent, unsigned long mask, static Window createWindow(Window parent, unsigned long mask,
@ -195,9 +192,9 @@ Menu *menu_new_full(char *label, char *name, Menu *parent,
self->a_title = appearance_copy(theme_a_menu_title); self->a_title = appearance_copy(theme_a_menu_title);
self->a_items = appearance_copy(theme_a_menu); self->a_items = appearance_copy(theme_a_menu);
g_hash_table_insert(menu_map, &self->frame, self); g_hash_table_insert(window_map, &self->frame, self);
g_hash_table_insert(menu_map, &self->title, self); g_hash_table_insert(window_map, &self->title, self);
g_hash_table_insert(menu_map, &self->items, self); g_hash_table_insert(window_map, &self->items, self);
g_hash_table_insert(menu_hash, g_strdup(name), self); g_hash_table_insert(menu_hash, g_strdup(name), self);
stacking_add(MENU_AS_WINDOW(self)); stacking_add(MENU_AS_WINDOW(self));
@ -259,7 +256,7 @@ void menu_add_entry(Menu *menu, MenuEntry *entry)
menu->invalid = TRUE; menu->invalid = TRUE;
g_hash_table_insert(menu_map, &entry->item, menu); g_hash_table_insert(window_map, &entry->item, menu);
} }
void menu_show(char *name, int x, int y, Client *client) void menu_show(char *name, int x, int y, Client *client)

View file

@ -7,8 +7,6 @@
#include <glib.h> #include <glib.h>
extern GHashTable *menu_map;
struct Menu; struct Menu;
struct MenuEntry; struct MenuEntry;

View file

@ -1,5 +1,5 @@
#include "openbox.h" #include "openbox.h"
#include "slit.h" #include "dock.h"
#include "event.h" #include "event.h"
#include "menu.h" #include "menu.h"
#include "client.h" #include "client.h"
@ -184,6 +184,7 @@ int main(int argc, char **argv)
g_free(theme); g_free(theme);
if (!theme) return 1; if (!theme) return 1;
window_startup();
menu_startup(); menu_startup();
frame_startup(); frame_startup();
moveresize_startup(); moveresize_startup();
@ -191,7 +192,7 @@ int main(int argc, char **argv)
screen_startup(); screen_startup();
group_startup(); group_startup();
client_startup(); client_startup();
slit_startup(); dock_startup();
/* call startup for all the plugins */ /* call startup for all the plugins */
plugin_startall(); plugin_startall();
@ -204,11 +205,11 @@ int main(int argc, char **argv)
event_loop(); event_loop();
ob_state = State_Exiting; ob_state = State_Exiting;
slit_remove_all(); dock_remove_all();
client_unmanage_all(); client_unmanage_all();
plugin_shutdown(); /* calls all the plugins' shutdown functions */ plugin_shutdown(); /* calls all the plugins' shutdown functions */
slit_shutdown(); dock_shutdown();
client_shutdown(); client_shutdown();
group_shutdown(); group_shutdown();
screen_shutdown(); screen_shutdown();
@ -216,6 +217,7 @@ int main(int argc, char **argv)
moveresize_shutdown(); moveresize_shutdown();
frame_shutdown(); frame_shutdown();
menu_shutdown(); menu_shutdown();
window_shutdown();
grab_shutdown(); grab_shutdown();
event_shutdown(); event_shutdown();
theme_shutdown(); theme_shutdown();

View file

@ -1,5 +1,5 @@
#include "openbox.h" #include "openbox.h"
#include "slit.h" #include "dock.h"
#include "prop.h" #include "prop.h"
#include "startup.h" #include "startup.h"
#include "config.h" #include "config.h"
@ -219,7 +219,7 @@ void screen_resize(int w, int h)
if (ob_state == State_Starting) if (ob_state == State_Starting)
return; return;
slit_configure_all(); dock_configure();
screen_update_struts(); screen_update_struts();
for (it = client_list; it; it = it->next) for (it = client_list; it; it = it->next)

View file

@ -1,424 +0,0 @@
#include "slit.h"
#include "screen.h"
#include "grab.h"
#include "openbox.h"
#include "render/theme.h"
#define SLIT_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
EnterWindowMask | LeaveWindowMask)
#define SLITAPP_EVENT_MASK (StructureNotifyMask)
GHashTable *slit_map = NULL;
GHashTable *slit_app_map = NULL;
static Slit *slit;
static int nslits;
static guint slit_hide_timeout = 3000; /* XXX make a config option */
static void slit_configure(Slit *self);
void slit_startup()
{
XSetWindowAttributes attrib;
int i;
slit_map = g_hash_table_new(g_int_hash, g_int_equal);
slit_app_map = g_hash_table_new(g_int_hash, g_int_equal);
nslits = 1;
slit = g_new0(struct Slit, nslits);
slit->obwin.type = Window_Slit;
for (i = 0; i < nslits; ++i) {
slit[i].horz = FALSE;
slit[i].hide = FALSE;
slit[i].hidden = TRUE;
slit[i].pos = SlitPos_TopRight;
slit[i].layer = Layer_Top;
attrib.event_mask = SLIT_EVENT_MASK;
attrib.override_redirect = True;
slit[i].frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
render_depth, InputOutput, render_visual,
CWOverrideRedirect | CWEventMask,
&attrib);
slit[i].a_frame = appearance_copy(theme_a_unfocused_title);
XSetWindowBorder(ob_display, slit[i].frame, theme_b_color->pixel);
XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
g_hash_table_insert(slit_map, &slit[i].frame, &slit[i]);
stacking_add(SLIT_AS_WINDOW(&slit[i]));
stacking_raise(SLIT_AS_WINDOW(&slit[i]));
}
}
void slit_shutdown()
{
int i;
for (i = 0; i < nslits; ++i) {
XDestroyWindow(ob_display, slit[i].frame);
appearance_free(slit[i].a_frame);
g_hash_table_remove(slit_map, &slit[i].frame);
stacking_remove(&slit[i]);
}
g_hash_table_destroy(slit_app_map);
g_hash_table_destroy(slit_map);
}
void slit_add(Window win, XWMHints *wmhints)
{
Slit *s;
SlitApp *app;
XWindowAttributes attrib;
/* XXX pick a slit */
s = &slit[0];
app = g_new0(SlitApp, 1);
app->slit = s;
app->win = win;
app->icon_win = (wmhints->flags & IconWindowHint) ?
wmhints->icon_window : win;
if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
app->w = attrib.width;
app->h = attrib.height;
} else {
app->w = app->h = 64;
}
s->slit_apps = g_list_append(s->slit_apps, app);
slit_configure(s);
XReparentWindow(ob_display, app->icon_win, s->frame, app->x, app->y);
/*
This is the same case as in frame.c for client windows. When Openbox is
starting, the window is already mapped so we see unmap events occur 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)
app->ignore_unmaps += 2;
if (app->win != app->icon_win) {
/* have to map it so that it can be re-managed on a restart */
XMoveWindow(ob_display, app->win, -1000, -1000);
XMapWindow(ob_display, app->win);
}
XMapWindow(ob_display, app->icon_win);
XSync(ob_display, False);
/* specify that if we exit, the window should not be destroyed and should
be reparented back to root automatically */
XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
XSelectInput(ob_display, app->icon_win, SLITAPP_EVENT_MASK);
grab_button_full(2, 0, app->icon_win,
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
GrabModeAsync, ob_cursors.move);
g_hash_table_insert(slit_app_map, &app->icon_win, app);
g_message("Managed Slit App: 0x%lx", app->icon_win);
}
void slit_remove_all()
{
int i;
for (i = 0; i < nslits; ++i)
while (slit[i].slit_apps)
slit_remove(slit[i].slit_apps->data, TRUE);
}
void slit_remove(SlitApp *app, gboolean reparent)
{
ungrab_button(2, 0, app->icon_win);
XSelectInput(ob_display, app->icon_win, NoEventMask);
/* remove the window from our save set */
XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
XSync(ob_display, False);
g_hash_table_remove(slit_app_map, &app->icon_win);
if (reparent)
XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
app->slit->slit_apps = g_list_remove(app->slit->slit_apps, app);
slit_configure(app->slit);
g_message("Unmanaged Slit App: 0x%lx", app->icon_win);
g_free(app);
}
void slit_configure_all()
{
int i; for (i = 0; i < nslits; ++i) slit_configure(&slit[i]);
}
static void slit_configure(Slit *self)
{
GList *it;
int spot;
self->w = self->h = spot = 0;
for (it = self->slit_apps; it; it = it->next) {
struct SlitApp *app = it->data;
if (self->horz) {
app->x = spot;
app->y = 0;
self->w += app->w;
self->h = MAX(self->h, app->h);
spot += app->w;
} else {
app->x = 0;
app->y = spot;
self->w = MAX(self->w, app->w);
self->h += app->h;
spot += app->h;
}
XMoveWindow(ob_display, app->icon_win, app->x, app->y);
}
/* used for calculating offsets */
self->w += theme_bwidth * 2;
self->h += theme_bwidth * 2;
/* calculate position */
switch (self->pos) {
case SlitPos_Floating:
self->x = self->user_x;
self->y = self->user_y;
break;
case SlitPos_TopLeft:
self->x = 0;
self->y = 0;
self->gravity = NorthWestGravity;
break;
case SlitPos_Top:
self->x = screen_physical_size.width / 2;
self->y = 0;
self->gravity = NorthGravity;
break;
case SlitPos_TopRight:
self->x = screen_physical_size.width;
self->y = 0;
self->gravity = NorthEastGravity;
break;
case SlitPos_Left:
self->x = 0;
self->y = screen_physical_size.height / 2;
self->gravity = WestGravity;
break;
case SlitPos_Right:
self->x = screen_physical_size.width;
self->y = screen_physical_size.height / 2;
self->gravity = EastGravity;
break;
case SlitPos_BottomLeft:
self->x = 0;
self->y = screen_physical_size.height;
self->gravity = SouthWestGravity;
break;
case SlitPos_Bottom:
self->x = screen_physical_size.width / 2;
self->y = screen_physical_size.height;
self->gravity = SouthGravity;
break;
case SlitPos_BottomRight:
self->x = screen_physical_size.width;
self->y = screen_physical_size.height;
self->gravity = SouthEastGravity;
break;
}
switch(self->gravity) {
case NorthGravity:
case CenterGravity:
case SouthGravity:
self->x -= self->w / 2;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
self->x -= self->w;
break;
}
switch(self->gravity) {
case WestGravity:
case CenterGravity:
case EastGravity:
self->y -= self->h / 2;
break;
case SouthWestGravity:
case SouthGravity:
case SouthEastGravity:
self->y -= self->h;
break;
}
if (self->hide && self->hidden) {
g_message("hidden");
switch (self->pos) {
case SlitPos_Floating:
break;
case SlitPos_TopLeft:
if (self->horz)
self->y -= self->h - theme_bwidth;
else
self->x -= self->w - theme_bwidth;
break;
case SlitPos_Top:
self->y -= self->h - theme_bwidth;
break;
case SlitPos_TopRight:
if (self->horz)
self->y -= self->h - theme_bwidth;
else
self->x += self->w - theme_bwidth;
break;
case SlitPos_Left:
self->x -= self->w - theme_bwidth;
break;
case SlitPos_Right:
self->x += self->w - theme_bwidth;
break;
case SlitPos_BottomLeft:
if (self->horz)
self->y += self->h - theme_bwidth;
else
self->x -= self->w - theme_bwidth;
break;
case SlitPos_Bottom:
self->y += self->h - theme_bwidth;
break;
case SlitPos_BottomRight:
if (self->horz)
self->y += self->h - theme_bwidth;
else
self->x += self->w - theme_bwidth;
break;
}
}
/* not used for actually sizing shit */
self->w -= theme_bwidth * 2;
self->h -= theme_bwidth * 2;
if (self->w > 0 && self->h > 0) {
RECT_SET(self->a_frame->area, 0, 0, self->w, self->h);
XMoveResizeWindow(ob_display, self->frame,
self->x, self->y, self->w, self->h);
paint(self->frame, self->a_frame);
XMapWindow(ob_display, self->frame);
} else
XUnmapWindow(ob_display, self->frame);
/* but they are useful outside of this function! */
self->w += theme_bwidth * 2;
self->h += theme_bwidth * 2;
}
void slit_app_configure(SlitApp *app, int w, int h)
{
app->w = w;
app->h = h;
slit_configure(app->slit);
}
void slit_app_drag(SlitApp *app, XMotionEvent *e)
{
Slit *src, *dest = NULL;
SlitApp *over = NULL;
GList *it;
int i;
int x, y;
gboolean after;
src = app->slit;
x = e->x_root;
y = e->y_root;
/* which slit are we on top of? */
for (i = 0; i < nslits; ++i)
if (x >= slit[i].x &&
y >= slit[i].y &&
x < slit[i].x + slit[i].w &&
y < slit[i].y + slit[i].h) {
dest = &slit[i];
break;
}
if (!dest) return;
x -= dest->x;
y -= dest->y;
/* which slit app are we on top of? */
for (it = dest->slit_apps; it; it = it->next) {
over = it->data;
if (dest->horz) {
if (x >= over->x && x < over->x + over->w)
break;
} else {
if (y >= over->y && y < over->y + over->h)
break;
}
}
if (!it || app == over) return;
x -= over->x;
y -= over->y;
if (dest->horz)
after = (x > over->w / 2);
else
after = (y > over->h / 2);
/* remove before doing the it->next! */
src->slit_apps = g_list_remove(src->slit_apps, app);
if (src != dest) slit_configure(src);
if (after) it = it->next;
dest->slit_apps = g_list_insert_before(dest->slit_apps, it, app);
slit_configure(dest);
}
static void hide_timeout(Slit *self)
{
/* dont repeat */
timer_stop(self->hide_timer);
self->hide_timer = NULL;
/* hide */
self->hidden = TRUE;
slit_configure(self);
}
void slit_hide(Slit *self, gboolean hide)
{
if (self->hidden == hide || !self->hide)
return;
if (!hide) {
/* show */
self->hidden = FALSE;
slit_configure(self);
/* if was hiding, stop it */
if (self->hide_timer) {
timer_stop(self->hide_timer);
self->hide_timer = NULL;
}
} else {
g_assert(!self->hide_timer);
self->hide_timer = timer_start(slit_hide_timeout * 1000,
(TimeoutHandler)hide_timeout, self);
}
}

View file

@ -1,80 +0,0 @@
#ifndef __slit_h
#define __slit_h
#include "timer.h"
#include "render/render.h"
#include "window.h"
#include "stacking.h"
#include <glib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
typedef enum {
SlitPos_Floating,
SlitPos_TopLeft,
SlitPos_Top,
SlitPos_TopRight,
SlitPos_Right,
SlitPos_BottomRight,
SlitPos_Bottom,
SlitPos_BottomLeft,
SlitPos_Left
} SlitPosition;
typedef struct Slit {
ObWindow obwin;
Window frame;
StackLayer layer;
/* user-requested position stuff */
SlitPosition pos;
int gravity;
int user_x, user_y;
/* actual position (when not auto-hidden) */
int x, y;
int w, h;
gboolean horz;
gboolean hide;
gboolean hidden;
Appearance *a_frame;
Timer *hide_timer;
GList *slit_apps;
} Slit;
typedef struct SlitApp {
int ignore_unmaps;
Slit *slit;
Window icon_win;
Window win;
int x;
int y;
int w;
int h;
} SlitApp;
extern GHashTable *slit_map;
extern GHashTable *slit_app_map;
void slit_startup();
void slit_shutdown();
void slit_configure_all();
void slit_hide(Slit *self, gboolean hide);
void slit_add(Window win, XWMHints *wmhints);
void slit_remove_all();
void slit_remove(SlitApp *app, gboolean reparent);
void slit_app_drag(SlitApp *app, XMotionEvent *e);
void slit_app_configure(SlitApp *app, int w, int h);
#endif

View file

@ -1,16 +1,33 @@
#include "window.h" #include "window.h"
#include "menu.h" #include "menu.h"
#include "slit.h" #include "config.h"
#include "dock.h"
#include "client.h" #include "client.h"
#include "frame.h" #include "frame.h"
GHashTable *window_map;
void window_startup()
{
window_map = g_hash_table_new(g_int_hash, g_int_equal);
}
void window_shutdown()
{
g_hash_table_destroy(window_map);
}
Window window_top(ObWindow *self) Window window_top(ObWindow *self)
{ {
switch (self->type) { switch (self->type) {
case Window_Menu: case Window_Menu:
return ((Menu*)self)->frame; return ((Menu*)self)->frame;
case Window_Slit: case Window_Dock:
return ((Slit*)self)->frame; return ((Dock*)self)->frame;
case Window_DockApp:
/* not to be used for stacking */
g_assert_not_reached();
break;
case Window_Client: case Window_Client:
return ((Client*)self)->frame->window; return ((Client*)self)->frame->window;
case Window_Internal: case Window_Internal:
@ -25,8 +42,12 @@ Window window_layer(ObWindow *self)
switch (self->type) { switch (self->type) {
case Window_Menu: case Window_Menu:
return Layer_Internal; return Layer_Internal;
case Window_Slit: case Window_Dock:
return ((Slit*)self)->layer; return config_dock_layer;
case Window_DockApp:
/* not to be used for stacking */
g_assert_not_reached();
break;
case Window_Client: case Window_Client:
return ((Client*)self)->layer; return ((Client*)self)->layer;
case Window_Internal: case Window_Internal:

View file

@ -2,12 +2,14 @@
#define __window_h #define __window_h
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <glib.h>
typedef enum { typedef enum {
Window_Menu, Window_Menu,
Window_Slit, Window_Dock,
Window_DockApp, /* used for events but not stacking */
Window_Client, Window_Client,
Window_Internal Window_Internal /* used for stacking but not events */
} Window_InternalType; } Window_InternalType;
typedef struct ObWindow { typedef struct ObWindow {
@ -22,24 +24,33 @@ typedef struct InternalWindow {
} InternalWindow; } InternalWindow;
#define WINDOW_IS_MENU(win) (((ObWindow*)win)->type == Window_Menu) #define WINDOW_IS_MENU(win) (((ObWindow*)win)->type == Window_Menu)
#define WINDOW_IS_SLIT(win) (((ObWindow*)win)->type == Window_Slit) #define WINDOW_IS_DOCK(win) (((ObWindow*)win)->type == Window_Dock)
#define WINDOW_IS_DOCKAPP(win) (((ObWindow*)win)->type == Window_DockApp)
#define WINDOW_IS_CLIENT(win) (((ObWindow*)win)->type == Window_Client) #define WINDOW_IS_CLIENT(win) (((ObWindow*)win)->type == Window_Client)
#define WINDOW_IS_INTERNAL(win) (((ObWindow*)win)->type == Window_Internal) #define WINDOW_IS_INTERNAL(win) (((ObWindow*)win)->type == Window_Internal)
struct Menu; struct Menu;
struct Slit; struct Dock;
struct DockApp;
struct Client; struct Client;
#define WINDOW_AS_MENU(win) ((struct Menu*)win) #define WINDOW_AS_MENU(win) ((struct Menu*)win)
#define WINDOW_AS_SLIT(win) ((struct Slit*)win) #define WINDOW_AS_DOCK(win) ((struct Dock*)win)
#define WINDOW_AS_DOCKAPP(win) ((struct DockApp*)win)
#define WINDOW_AS_CLIENT(win) ((struct Client*)win) #define WINDOW_AS_CLIENT(win) ((struct Client*)win)
#define WINDOW_AS_INTERNAL(win) ((struct InternalWindow*)win) #define WINDOW_AS_INTERNAL(win) ((struct InternalWindow*)win)
#define MENU_AS_WINDOW(menu) ((ObWindow*)menu) #define MENU_AS_WINDOW(menu) ((ObWindow*)menu)
#define SLIT_AS_WINDOW(slit) ((ObWindow*)slit) #define DOCK_AS_WINDOW(dock) ((ObWindow*)dock)
#define DOCKAPP_AS_WINDOW(dockapp) ((ObWindow*)dockapp)
#define CLIENT_AS_WINDOW(client) ((ObWindow*)client) #define CLIENT_AS_WINDOW(client) ((ObWindow*)client)
#define INTERNAL_AS_WINDOW(intern) ((ObWindow*)intern) #define INTERNAL_AS_WINDOW(intern) ((ObWindow*)intern)
extern GHashTable *window_map;
void window_startup();
void window_shutdown();
Window window_top(ObWindow *self); Window window_top(ObWindow *self);
Window window_layer(ObWindow *self); Window window_layer(ObWindow *self);