add a slit to the kernel

This commit is contained in:
Dana Jansens 2003-05-10 20:52:32 +00:00
parent 3716928984
commit c4a5149016
8 changed files with 352 additions and 9 deletions

View file

@ -26,12 +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 \
openbox.c framerender.c parse.c plugin.c prop.c screen.c \
stacking.c dispatch.c event.c group.c timer.c xerror.c \
moveresize.c startup.c popup.c
moveresize.c startup.c popup.c slit.c
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 \
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
# kill the implicit .c.y rule
%.c: %.y

View file

@ -1,4 +1,5 @@
#include "client.h"
#include "slit.h"
#include "startup.h"
#include "screen.h"
#include "moveresize.h"
@ -176,7 +177,7 @@ void client_manage(Window window)
XEvent e;
XWindowAttributes attrib;
XSetWindowAttributes attrib_set;
/* XWMHints *wmhint; */
XWMHints *wmhint;
grab_server(TRUE);
@ -197,18 +198,18 @@ void client_manage(Window window)
return; /* don't manage it */
}
/* /\* is the window a docking app *\/
/* is the window a docking app */
if ((wmhint = XGetWMHints(ob_display, window))) {
if ((wmhint->flags & StateHint) &&
wmhint->initial_state == WithdrawnState) {
/\* XXX: make dock apps work! *\/
slit_add(window, wmhint, &attrib);
grab_server(FALSE);
XFree(wmhint);
return;
}
XFree(wmhint);
}
*/
g_message("Managing window: %lx", window);
/* choose the events we want to receive on the CLIENT window */

View file

@ -1,4 +1,5 @@
#include "openbox.h"
#include "slit.h"
#include "client.h"
#include "xerror.h"
#include "prop.h"
@ -23,6 +24,7 @@
static void event_process(XEvent *e);
static void event_handle_root(XEvent *e);
static void event_handle_slitapp(SlitApp *app, XEvent *e);
static void event_handle_client(Client *c, XEvent *e);
static void event_handle_menu(Menu *menu, XEvent *e);
@ -373,12 +375,14 @@ static gboolean event_ignore(XEvent *e, Client *client)
static void event_process(XEvent *e)
{
Window window;
Client *client;
Client *client = NULL;
SlitApp *slitapp = NULL;
Menu *menu = NULL;
window = event_get_window(e);
if (!(client = g_hash_table_lookup(client_map, &window)))
menu = g_hash_table_lookup(menu_map, &window);
if (!(slitapp = g_hash_table_lookup(slit_map, &window)))
menu = g_hash_table_lookup(menu_map, &window);
event_set_lasttime(e);
event_hack_mods(e);
@ -391,6 +395,8 @@ static void event_process(XEvent *e)
return;
} else if (client)
event_handle_client(client, e);
else if (slitapp)
event_handle_slitapp(slitapp, e);
else if (window == ob_root)
event_handle_root(e);
else if (e->type == MapRequest)
@ -901,3 +907,22 @@ static void event_handle_menu(Menu *menu, XEvent *e)
}
}
}
static void event_handle_slitapp(SlitApp *app, XEvent *e)
{
switch (e->type) {
case UnmapNotify:
if (app->ignore_unmaps) {
app->ignore_unmaps--;
break;
}
slit_remove(app, TRUE);
break;
case DestroyNotify:
slit_remove(app, FALSE);
break;
case ReparentNotify:
slit_remove(app, FALSE);
break;
}
}

View file

@ -456,8 +456,12 @@ void frame_release_client(Frame *self, Client *client)
if (XCheckTypedWindowEvent(ob_display, client->window,
ReparentNotify, &ev)) {
XPutBackEvent(ob_display, &ev);
/* re-map the window since the unmanaging process unmaps it */
XMapWindow(ob_display, client->window);
/* XXX ... um no it doesnt it unmaps its parent, the window itself
retains its mapped state, no?! XXX
XMapWindow(ob_display, client->window); */
} else {
/* according to the ICCCM - if the client doesn't reparent itself,
then we will reparent the window to root for them */

View file

@ -1,4 +1,5 @@
#include "openbox.h"
#include "slit.h"
#include "event.h"
#include "menu.h"
#include "client.h"
@ -191,6 +192,7 @@ int main(int argc, char **argv)
screen_startup();
group_startup();
client_startup();
slit_startup();
/* call startup for all the plugins */
plugin_startall();
@ -203,9 +205,11 @@ int main(int argc, char **argv)
event_loop();
ob_state = State_Exiting;
slit_remove_all();
client_unmanage_all();
plugin_shutdown(); /* calls all the plugins' shutdown functions */
slit_shutdown();
client_shutdown();
group_shutdown();
screen_shutdown();

View file

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

260
openbox/slit.c Normal file
View file

@ -0,0 +1,260 @@
#include "slit.h"
#include "screen.h"
#include "openbox.h"
#include "render/theme.h"
#include "render/render.h"
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#define SLITAPP_EVENT_MASK (StructureNotifyMask)
struct Slit {
Window frame;
/* 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;
Appearance *a_frame;
GList *slit_apps;
};
GHashTable *slit_map = NULL;
static Slit *slit;
static int nslits;
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);
nslits = 1;
slit = g_new0(struct Slit, nslits);
for (i = 0; i < nslits; ++i) {
slit[i].horz = TRUE;
attrib.override_redirect = True;
slit[i].frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
render_depth, InputOutput, render_visual,
CWOverrideRedirect, &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);
}
}
void slit_shutdown()
{
int i;
for (i = 0; i < nslits; ++i) {
XDestroyWindow(ob_display, slit[i].frame);
appearance_free(slit[i].a_frame);
}
}
void slit_add(Window win, XWMHints *wmhints, XWindowAttributes *attrib)
{
Slit *s;
SlitApp *app;
/* 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;
app->w = attrib->width;
app->h = attrib->height;
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)
XMoveWindow(ob_display, app->win, 100, 100);
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);
g_hash_table_insert(slit_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)
{
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_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->h, 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;
switch (self->pos) {
case SlitPos_Floating:
/* calculate position */
self->x = self->user_x;
self->y = self->user_y;
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;
}
break;
case SlitPos_TopLeft:
self->x = 0;
self->y = 0;
break;
case SlitPos_Top:
self->x = (screen_physical_size.width - self->w) / 2;
self->y = 0;
break;
case SlitPos_TopRight:
self->x = screen_physical_size.width - self->w;
self->y = 0;
break;
case SlitPos_Left:
self->x = 0;
self->y = (screen_physical_size.height - self->h) / 2;
break;
case SlitPos_Right:
self->x = screen_physical_size.width - self->w;
self->y = (screen_physical_size.height - self->h) / 2;
break;
case SlitPos_BottomLeft:
self->x = 0;
self->y = screen_physical_size.height - self->h;
break;
case SlitPos_Bottom:
self->x = (screen_physical_size.width - self->w) / 2;
self->y = screen_physical_size.height - self->h;
break;
case SlitPos_BottomRight:
self->x = screen_physical_size.width - self->w;
self->y = screen_physical_size.height - self->h;
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);
}

46
openbox/slit.h Normal file
View file

@ -0,0 +1,46 @@
#ifndef __slit_h
#define __slit_h
#include <glib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
typedef struct Slit Slit;
typedef struct SlitApp {
int ignore_unmaps;
Slit *slit;
Window icon_win;
Window win;
int x;
int y;
int w;
int h;
} SlitApp;
typedef enum {
SlitPos_Floating,
SlitPos_TopLeft,
SlitPos_Top,
SlitPos_TopRight,
SlitPos_Right,
SlitPos_BottomRight,
SlitPos_Bottom,
SlitPos_BottomLeft,
SlitPos_Left
} SlitPosition;
extern GHashTable *slit_map;
void slit_startup();
void slit_shutdown();
void slit_configure_all();
void slit_add(Window win, XWMHints *wmhints, XWindowAttributes *attrib);
void slit_remove_all();
void slit_remove(SlitApp *app, gboolean reparent);
#endif