add a slit to the kernel
This commit is contained in:
parent
3716928984
commit
c4a5149016
8 changed files with 352 additions and 9 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
260
openbox/slit.c
Normal 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
46
openbox/slit.h
Normal 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
|
Loading…
Reference in a new issue