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:
parent
6e42b65bda
commit
b77e40e1c7
18 changed files with 744 additions and 608 deletions
33
data/rc3
33
data/rc3
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
382
openbox/dock.c
Normal 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
66
openbox/dock.h
Normal 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
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
extern GHashTable *menu_map;
|
|
||||||
|
|
||||||
struct Menu;
|
struct Menu;
|
||||||
struct MenuEntry;
|
struct MenuEntry;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
424
openbox/slit.c
424
openbox/slit.c
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue