814 lines
23 KiB
C
814 lines
23 KiB
C
|
#include "config.h"
|
||
|
#include "FvwmIconMan.h"
|
||
|
#include "readconfig.h"
|
||
|
#include "x.h"
|
||
|
#include "xmanager.h"
|
||
|
|
||
|
static char const rcsid[] =
|
||
|
"$Id: x.c,v 1.1.1.1 2006/11/26 10:53:50 matthieu Exp $";
|
||
|
|
||
|
#define GRAB_EVENTS (ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|EnterWindowMask|LeaveWindowMask)
|
||
|
|
||
|
#ifdef SHAPE
|
||
|
static int shapeEventBase, shapeErrorBase;
|
||
|
#endif
|
||
|
|
||
|
Display *theDisplay;
|
||
|
Window theRoot;
|
||
|
int theDepth, theScreen;
|
||
|
|
||
|
static enum {
|
||
|
NOT_GRABBED = 0,
|
||
|
NEED_TO_GRAB = 1,
|
||
|
HAVE_GRABBED = 2
|
||
|
} grab_state = NOT_GRABBED;
|
||
|
|
||
|
static void reparentnotify_event (WinManager *man, XEvent *ev);
|
||
|
|
||
|
static void grab_pointer (WinManager *man)
|
||
|
{
|
||
|
/* This should only be called after we get our EXPOSE event */
|
||
|
if (grab_state == NEED_TO_GRAB) {
|
||
|
if (XGrabPointer (theDisplay, man->theWindow, True, GRAB_EVENTS,
|
||
|
GrabModeAsync, GrabModeAsync, None,
|
||
|
None, CurrentTime) != GrabSuccess) {
|
||
|
ConsoleMessage ("Couldn't grab pointer\n");
|
||
|
ShutMeDown (0);
|
||
|
}
|
||
|
grab_state = HAVE_GRABBED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int lookup_color (char *name, Pixel *ans)
|
||
|
{
|
||
|
XColor color;
|
||
|
XWindowAttributes attributes;
|
||
|
|
||
|
XGetWindowAttributes(theDisplay, theRoot, &attributes);
|
||
|
color.pixel = 0;
|
||
|
if (!XParseColor (theDisplay, attributes.colormap, name, &color)) {
|
||
|
ConsoleDebug(X11, "Could not parse color '%s'\n", name);
|
||
|
return 0;
|
||
|
}
|
||
|
else if(!XAllocColor (theDisplay, attributes.colormap, &color)) {
|
||
|
ConsoleDebug(X11, "Could not allocate color '%s'\n", name);
|
||
|
return 0;
|
||
|
}
|
||
|
*ans = color.pixel;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
WinManager *find_windows_manager (Window win)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < globals.num_managers; i++) {
|
||
|
if (globals.managers[i].theWindow == win)
|
||
|
return &globals.managers[i];
|
||
|
}
|
||
|
|
||
|
/* ConsoleMessage ("error in find_windows_manager:\n");
|
||
|
ConsoleMessage ("Window: %x\n", win);
|
||
|
for (i = 0; i < globals.num_managers; i++) {
|
||
|
ConsoleMessage ("manager: %d %x\n", i, globals.managers[i].theWindow);
|
||
|
}
|
||
|
*/
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static void handle_buttonevent (XEvent *theEvent, WinManager *man)
|
||
|
{
|
||
|
Button *b;
|
||
|
WinData *win;
|
||
|
unsigned int modifier;
|
||
|
Binding *MouseEntry;
|
||
|
|
||
|
b = xy_to_button (man, theEvent->xbutton.x, theEvent->xbutton.y);
|
||
|
if (b && theEvent->xbutton.button >= 1 && theEvent->xbutton.button <= 3) {
|
||
|
win = b->drawn_state.win;
|
||
|
if (win != NULL) {
|
||
|
ConsoleDebug (X11, "Found the window:\n");
|
||
|
ConsoleDebug (X11, "\tid: %ld\n", win->app_id);
|
||
|
ConsoleDebug (X11, "\tdesknum: %ld\n", win->desknum);
|
||
|
ConsoleDebug (X11, "\tx, y: %ld %ld\n", win->x, win->y);
|
||
|
ConsoleDebug (X11, "\ticon: %p\n", win->iconname);
|
||
|
ConsoleDebug (X11, "\ticonified: %d\n", win->iconified);
|
||
|
ConsoleDebug (X11, "\tcomplete: %d\n", win->complete);
|
||
|
|
||
|
modifier = (theEvent->xbutton.state & MODS_USED);
|
||
|
/* need to search for an appropriate mouse binding */
|
||
|
for (MouseEntry = man->bindings[MOUSE]; MouseEntry != NULL;
|
||
|
MouseEntry= MouseEntry->NextBinding) {
|
||
|
if(((MouseEntry->Button_Key == theEvent->xbutton.button)||
|
||
|
(MouseEntry->Button_Key == 0))&&
|
||
|
((MouseEntry->Modifier == AnyModifier)||
|
||
|
(MouseEntry->Modifier == (modifier& (~LockMask)))))
|
||
|
{
|
||
|
Function *ftype = MouseEntry->Function;
|
||
|
ConsoleDebug (X11, "\tgot a mouse binding\n");
|
||
|
if (ftype && ftype->func) {
|
||
|
run_function_list (ftype);
|
||
|
draw_managers();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Window find_frame_window (Window win, int *off_x, int *off_y)
|
||
|
{
|
||
|
Window root, parent, *junkw;
|
||
|
int junki;
|
||
|
XWindowAttributes attr;
|
||
|
|
||
|
ConsoleDebug (X11, "In find_frame_window: 0x%x\n", (unsigned int)win);
|
||
|
|
||
|
while (1) {
|
||
|
XQueryTree (theDisplay, win, &root, &parent, &junkw, &junki);
|
||
|
if (junkw)
|
||
|
XFree (junkw);
|
||
|
if (parent == root)
|
||
|
break;
|
||
|
XGetWindowAttributes (theDisplay, win, &attr);
|
||
|
ConsoleDebug (X11, "Adding (%d, %d) += (%d, %d)\n",
|
||
|
*off_x, *off_y, attr.x + attr.border_width,
|
||
|
attr.y + attr.border_width);
|
||
|
*off_x += attr.x + attr.border_width;
|
||
|
*off_y += attr.y + attr.border_width;
|
||
|
win = parent;
|
||
|
}
|
||
|
|
||
|
return win;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************/
|
||
|
/* Event handler routines */
|
||
|
/* everything which has its own routine can be processed recursively */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
static void reparentnotify_event (WinManager *man, XEvent *ev)
|
||
|
{
|
||
|
ConsoleDebug (X11, "XEVENT: ReparentNotify\n");
|
||
|
#if 0
|
||
|
ConsoleMessage ("seen %d expected %d\n", num_reparents_seen,
|
||
|
num_reparents_expected);
|
||
|
man->off_x = ev->xreparent.x;
|
||
|
man->off_y = ev->xreparent.y;
|
||
|
ConsoleDebug (X11, "reparent: off = (%d, %d)\n",man->off_x, man->off_y);
|
||
|
man->theFrame = find_frame_window (ev->xany.window,
|
||
|
&man->off_x, &man->off_y);
|
||
|
ConsoleMessage ("\twin = 0x%x, frame = 0x%x\n", man->theWindow,
|
||
|
man->theFrame);
|
||
|
#endif
|
||
|
if (man->can_draw == 0) {
|
||
|
man->can_draw = 1;
|
||
|
force_manager_redraw (man);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void xevent_loop (void)
|
||
|
{
|
||
|
XEvent theEvent;
|
||
|
unsigned int modifier;
|
||
|
Binding *key;
|
||
|
Button *b;
|
||
|
static int flag = 0;
|
||
|
WinManager *man;
|
||
|
|
||
|
if (flag == 0) {
|
||
|
flag = 1;
|
||
|
ConsoleDebug (X11, "A virgin event loop\n");
|
||
|
}
|
||
|
while (XPending (theDisplay)) {
|
||
|
XNextEvent (theDisplay, &theEvent);
|
||
|
if (theEvent.type == MappingNotify) {
|
||
|
ConsoleDebug (X11, "XEVENT: MappingNotify\n");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
man = find_windows_manager (theEvent.xany.window);
|
||
|
if (!man) {
|
||
|
ConsoleDebug (X11, "Event doesn't belong to a manager\n");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (theEvent.type) {
|
||
|
case ReparentNotify:
|
||
|
reparentnotify_event (man, &theEvent);
|
||
|
break;
|
||
|
|
||
|
case KeyPress:
|
||
|
ConsoleDebug (X11, "XEVENT: KeyPress\n");
|
||
|
/* Here's a real hack - some systems have two keys with the
|
||
|
* same keysym and different keycodes. This converts all
|
||
|
* the cases to one keycode. */
|
||
|
theEvent.xkey.keycode =
|
||
|
XKeysymToKeycode (theDisplay,
|
||
|
XKeycodeToKeysym(theDisplay,
|
||
|
theEvent.xkey.keycode,0));
|
||
|
modifier = (theEvent.xkey.state & MODS_USED);
|
||
|
ConsoleDebug (X11, "\tKeyPress: %d\n", theEvent.xkey.keycode);
|
||
|
|
||
|
for (key = man->bindings[KEYPRESS]; key != NULL; key = key->NextBinding)
|
||
|
{
|
||
|
if ((key->Button_Key == theEvent.xkey.keycode) &&
|
||
|
((key->Modifier == (modifier&(~LockMask)))||
|
||
|
(key->Modifier == AnyModifier)))
|
||
|
{
|
||
|
Function *ftype = key->Function;
|
||
|
if (ftype && ftype->func) {
|
||
|
run_function_list (ftype);
|
||
|
draw_managers();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case Expose:
|
||
|
ConsoleDebug (X11, "XEVENT: Expose\n");
|
||
|
if (theEvent.xexpose.count == 0) {
|
||
|
man_exposed (man, &theEvent);
|
||
|
draw_manager (man);
|
||
|
if (globals.transient) {
|
||
|
grab_pointer (man);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ButtonPress:
|
||
|
ConsoleDebug (X11, "XEVENT: ButtonPress\n");
|
||
|
if (!globals.transient)
|
||
|
handle_buttonevent (&theEvent, man);
|
||
|
break;
|
||
|
|
||
|
case ButtonRelease:
|
||
|
ConsoleDebug (X11, "XEVENT: ButtonRelease\n");
|
||
|
if (globals.transient) {
|
||
|
handle_buttonevent (&theEvent, man);
|
||
|
ShutMeDown (0);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case EnterNotify:
|
||
|
ConsoleDebug (X11, "XEVENT: EnterNotify\n");
|
||
|
man->cursor_in_window = 1;
|
||
|
b = xy_to_button (man, theEvent.xcrossing.x, theEvent.xcrossing.y);
|
||
|
move_highlight (man, b);
|
||
|
run_binding (man, SELECT);
|
||
|
draw_managers();
|
||
|
break;
|
||
|
|
||
|
case LeaveNotify:
|
||
|
ConsoleDebug (X11, "XEVENT: LeaveNotify\n");
|
||
|
move_highlight (man, NULL);
|
||
|
break;
|
||
|
|
||
|
case ConfigureNotify:
|
||
|
ConsoleDebug (X11, "XEVENT: Configure Notify: %d %d %d %d\n",
|
||
|
theEvent.xconfigure.x, theEvent.xconfigure.y,
|
||
|
theEvent.xconfigure.width, theEvent.xconfigure.height);
|
||
|
ConsoleDebug (X11, "\tcurrent geometry: %d %d %d %d\n",
|
||
|
man->geometry.x, man->geometry.y,
|
||
|
man->geometry.width, man->geometry.height);
|
||
|
ConsoleDebug (X11, "\tborderwidth = %d\n",
|
||
|
theEvent.xconfigure.border_width);
|
||
|
ConsoleDebug (X11, "\tsendevent = %d\n", theEvent.xconfigure.send_event);
|
||
|
#if 0
|
||
|
set_manager_width (man, theEvent.xconfigure.width);
|
||
|
ConsoleDebug (X11, "\tboxwidth = %d\n", man->geometry.boxwidth);
|
||
|
draw_manager (man);
|
||
|
|
||
|
/* pointer may not be in the same box as before */
|
||
|
if (XQueryPointer (theDisplay, man->theWindow, &root, &child, &glob_x,
|
||
|
&glob_y,
|
||
|
&x, &y, &mask)) {
|
||
|
b = xy_to_button (man, x, y);
|
||
|
if (b != man->select_button) {
|
||
|
move_highlight (man, b);
|
||
|
run_binding (man, SELECT);
|
||
|
draw_managers();
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (man->select_button != NULL)
|
||
|
move_highlight (NULL, NULL);
|
||
|
}
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case MotionNotify:
|
||
|
/* ConsoleDebug (X11, "XEVENT: MotionNotify\n"); */
|
||
|
b = xy_to_button (man, theEvent.xmotion.x, theEvent.xmotion.y);
|
||
|
if (b != man->select_button) {
|
||
|
ConsoleDebug (X11, "\tmoving select\n");
|
||
|
move_highlight (man, b);
|
||
|
run_binding (man, SELECT);
|
||
|
draw_managers();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case MapNotify:
|
||
|
ConsoleDebug (X11, "XEVENT: MapNotify\n");
|
||
|
force_manager_redraw (man);
|
||
|
break;
|
||
|
|
||
|
case UnmapNotify:
|
||
|
ConsoleDebug (X11, "XEVENT: UnmapNotify\n");
|
||
|
break;
|
||
|
|
||
|
case DestroyNotify:
|
||
|
ConsoleDebug(X11, "XEVENT: DestroyNotify\n");
|
||
|
DeadPipe(0);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
#ifdef SHAPE
|
||
|
if (theEvent.type == shapeEventBase + ShapeNotify) {
|
||
|
XShapeEvent *xev = (XShapeEvent *)&theEvent;
|
||
|
ConsoleDebug (X11, "XEVENT: ShapeNotify\n");
|
||
|
ConsoleDebug (X11, "\tx, y, w, h = %d, %d, %d, %d\n",
|
||
|
xev->x, xev->y, xev->width, xev->height);
|
||
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
ConsoleDebug (X11, "XEVENT: unknown\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
check_managers_consistency();
|
||
|
XFlush (theDisplay);
|
||
|
}
|
||
|
|
||
|
static void set_window_properties (Window win, char *name, char *icon,
|
||
|
XSizeHints *sizehints)
|
||
|
{
|
||
|
XTextProperty win_name;
|
||
|
XTextProperty win_icon;
|
||
|
XClassHint class;
|
||
|
XWMHints wmhints = {0};
|
||
|
|
||
|
wmhints.initial_state = NormalState;
|
||
|
wmhints.flags = StateHint;
|
||
|
|
||
|
if (XStringListToTextProperty (&name, 1, &win_name) == 0) {
|
||
|
ConsoleMessage ("%s: cannot allocate window name.\n",Module);
|
||
|
return;
|
||
|
}
|
||
|
if (XStringListToTextProperty (&icon, 1, &win_icon) == 0) {
|
||
|
ConsoleMessage ("%s: cannot allocate window icon.\n",Module);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
class.res_name = Module + 1;
|
||
|
class.res_class = "FvwmModule";
|
||
|
|
||
|
|
||
|
XSetWMProperties (theDisplay, win, &win_name, &win_icon, NULL, 0,
|
||
|
sizehints, &wmhints, &class);
|
||
|
|
||
|
XFree (win_name.value);
|
||
|
XFree (win_icon.value);
|
||
|
}
|
||
|
|
||
|
static int load_default_context_fore (WinManager *man, int i)
|
||
|
{
|
||
|
int j = 0;
|
||
|
|
||
|
if (theDepth > 2)
|
||
|
j = 1;
|
||
|
|
||
|
ConsoleDebug (X11, "Loading: %s\n", contextDefaults[i].backcolor[j]);
|
||
|
|
||
|
return lookup_color (contextDefaults[i].forecolor[j], &man->forecolor[i]);
|
||
|
}
|
||
|
|
||
|
static int load_default_context_back (WinManager *man, int i)
|
||
|
{
|
||
|
int j = 0;
|
||
|
|
||
|
if (theDepth > 2)
|
||
|
j = 1;
|
||
|
|
||
|
ConsoleDebug (X11, "Loading: %s\n", contextDefaults[i].backcolor[j]);
|
||
|
|
||
|
return lookup_color (contextDefaults[i].backcolor[j], &man->backcolor[i]);
|
||
|
}
|
||
|
|
||
|
void map_manager (WinManager *man)
|
||
|
{
|
||
|
if (man->window_mapped == 0 && man->geometry.height > 0) {
|
||
|
XMapWindow (theDisplay, man->theWindow);
|
||
|
set_manager_window_mapping (man, 1);
|
||
|
XFlush (theDisplay);
|
||
|
if (globals.transient) {
|
||
|
/* wait for an expose event to actually do the grab */
|
||
|
grab_state = NEED_TO_GRAB;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void unmap_manager (WinManager *man)
|
||
|
{
|
||
|
if (man->window_mapped == 1) {
|
||
|
XUnmapWindow (theDisplay, man->theWindow);
|
||
|
set_manager_window_mapping (man, 0);
|
||
|
XFlush (theDisplay);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
void read_all_reparent_events (WinManager *man, int block)
|
||
|
{
|
||
|
XEvent evs[2];
|
||
|
int i = 0, got_one = 0, the_event;
|
||
|
|
||
|
/* We're going to be junking ConfigureNotify events, but that's ok,
|
||
|
since this is only going to be called from resize_manager() */
|
||
|
/* This shouldn't slow things down terribly, since we'd just have to read
|
||
|
these events anyway */
|
||
|
|
||
|
assert (man->can_draw);
|
||
|
|
||
|
if (block) {
|
||
|
while (1) {
|
||
|
XWindowEvent (theDisplay, man->theWindow, StructureNotifyMask, &evs[0]);
|
||
|
if (evs[0].type == ReparentNotify) {
|
||
|
the_event = 0;
|
||
|
got_one = 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
while (XCheckWindowEvent (theDisplay, man->theWindow, StructureNotifyMask,
|
||
|
&evs[i])) {
|
||
|
if (evs[i].type == ReparentNotify) {
|
||
|
got_one = 1;
|
||
|
the_event = i;
|
||
|
i ^= 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (got_one) {
|
||
|
reparentnotify_event (man, &evs[the_event]);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void X_init_manager (int man_id)
|
||
|
{
|
||
|
WinManager *man;
|
||
|
int width, height;
|
||
|
int i, x, y, geometry_mask;
|
||
|
ConsoleDebug (X11, "In X_init_manager\n");
|
||
|
|
||
|
man = &globals.managers[man_id];
|
||
|
|
||
|
man->geometry.cols = DEFAULT_NUM_COLS;
|
||
|
man->geometry.rows = DEFAULT_NUM_ROWS;
|
||
|
man->geometry.x = 0;
|
||
|
man->geometry.y = 0;
|
||
|
man->gravity = NorthWestGravity;
|
||
|
|
||
|
man->select_button = NULL;
|
||
|
man->cursor_in_window = 0;
|
||
|
man->sizehints_flags = 0;
|
||
|
|
||
|
ConsoleDebug (X11, "boxwidth = %d\n", man->geometry.boxwidth);
|
||
|
|
||
|
if (man->fontname) {
|
||
|
man->ButtonFont = XLoadQueryFont (theDisplay, man->fontname);
|
||
|
if (!man->ButtonFont) {
|
||
|
if (!(man->ButtonFont = XLoadQueryFont (theDisplay, FONT_STRING))) {
|
||
|
ConsoleMessage ("Can't get font\n");
|
||
|
ShutMeDown (1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!(man->ButtonFont = XLoadQueryFont (theDisplay, FONT_STRING))) {
|
||
|
ConsoleMessage ("Can't get font\n");
|
||
|
ShutMeDown (1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for ( i = 0; i < NUM_CONTEXTS; i++ ) {
|
||
|
if (man->backColorName[i]) {
|
||
|
if (!lookup_color (man->backColorName[i], &man->backcolor[i])) {
|
||
|
if (!load_default_context_back (man, i)) {
|
||
|
ConsoleMessage ("Can't load %s background color\n",
|
||
|
contextDefaults[i].name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (!load_default_context_back (man, i)) {
|
||
|
ConsoleMessage ("Can't load %s background color\n",
|
||
|
contextDefaults[i].name);
|
||
|
}
|
||
|
|
||
|
if (man->foreColorName[i]) {
|
||
|
if (!lookup_color (man->foreColorName[i], &man->forecolor[i])) {
|
||
|
if (!load_default_context_fore (man, i)) {
|
||
|
ConsoleMessage ("Can't load %s foreground color\n",
|
||
|
contextDefaults[i].name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (!load_default_context_fore (man, i)) {
|
||
|
ConsoleMessage ("Can't load %s foreground color\n",
|
||
|
contextDefaults[i].name);
|
||
|
}
|
||
|
|
||
|
if (theDepth > 2) {
|
||
|
man->shadowcolor[i] = GetShadow(man->backcolor[i]);
|
||
|
man->hicolor[i] = GetHilite(man->backcolor[i]);
|
||
|
#if 0
|
||
|
/* thing about message id bg vs fg */
|
||
|
if (!lookup_shadow_color (man->backcolor[i], &man->shadowcolor[i])) {
|
||
|
ConsoleMessage ("Can't load %s shadow color\n",
|
||
|
contextDefaults[i].name);
|
||
|
}
|
||
|
if (!lookup_hilite_color (man->backcolor[i], &man->hicolor[i])) {
|
||
|
ConsoleMessage ("Can't load %s hilite color\n",
|
||
|
contextDefaults[i].name);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
man->fontheight = man->ButtonFont->ascent +
|
||
|
man->ButtonFont->descent;
|
||
|
|
||
|
/* silly hack to guess the minimum char width of the font
|
||
|
doesn't have to be perfect. */
|
||
|
|
||
|
man->fontwidth = XTextWidth (man->ButtonFont, ".", 1);
|
||
|
|
||
|
/* First: get button geometry
|
||
|
Second: get geometry from geometry string
|
||
|
Third: determine the final width and height
|
||
|
Fourth: determine final x, y coords */
|
||
|
|
||
|
man->geometry.boxwidth = DEFAULT_BUTTON_WIDTH;
|
||
|
man->geometry.boxheight = man->fontheight + 4;;
|
||
|
man->geometry.dir = 0;
|
||
|
|
||
|
geometry_mask = 0;
|
||
|
|
||
|
if (man->button_geometry_str) {
|
||
|
int val;
|
||
|
val = XParseGeometry (man->button_geometry_str, &x, &y, &width, &height);
|
||
|
ConsoleDebug (X11, "button x, y, w, h = %d %d %d %d\n", x, y, width,
|
||
|
height);
|
||
|
if (val & WidthValue)
|
||
|
man->geometry.boxwidth = width;
|
||
|
if (val & HeightValue)
|
||
|
man->geometry.boxheight = max (man->geometry.boxheight, height);
|
||
|
}
|
||
|
if (man->geometry_str) {
|
||
|
geometry_mask = XParseGeometry (man->geometry_str, &man->geometry.x,
|
||
|
&man->geometry.y, &man->geometry.cols,
|
||
|
&man->geometry.rows);
|
||
|
|
||
|
if ((geometry_mask & XValue) || (geometry_mask & YValue)) {
|
||
|
man->sizehints_flags |= USPosition;
|
||
|
if (geometry_mask & XNegative)
|
||
|
man->geometry.dir |= GROW_LEFT;
|
||
|
else
|
||
|
man->geometry.dir |= GROW_RIGHT;
|
||
|
if (geometry_mask & YNegative)
|
||
|
man->geometry.dir |= GROW_UP;
|
||
|
else
|
||
|
man->geometry.dir |= GROW_DOWN;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (man->geometry.rows == 0) {
|
||
|
if (man->geometry.cols == 0) {
|
||
|
ConsoleMessage ("You specified a 0x0 window\n");
|
||
|
ShutMeDown (0);
|
||
|
}
|
||
|
else {
|
||
|
man->geometry.dir |= GROW_VERT;
|
||
|
}
|
||
|
man->geometry.rows = 1;
|
||
|
}
|
||
|
else {
|
||
|
if (man->geometry.cols == 0) {
|
||
|
man->geometry.dir |= GROW_HORIZ;
|
||
|
man->geometry.cols = 1;
|
||
|
}
|
||
|
else {
|
||
|
man->geometry.dir |= GROW_HORIZ | GROW_FIXED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
man->geometry.width = man->geometry.cols * man->geometry.boxwidth;
|
||
|
man->geometry.height = man->geometry.rows * man->geometry.boxheight;
|
||
|
|
||
|
if ((geometry_mask & XValue) && (geometry_mask & XNegative))
|
||
|
man->geometry.x += globals.screenx - man->geometry.width;
|
||
|
if ((geometry_mask & YValue) && (geometry_mask & YNegative))
|
||
|
man->geometry.y += globals.screeny - man->geometry.height;
|
||
|
|
||
|
if (globals.transient) {
|
||
|
Window dummyroot, dummychild;
|
||
|
int junk;
|
||
|
|
||
|
XQueryPointer(theDisplay, theRoot, &dummyroot, &dummychild,
|
||
|
&man->geometry.x,
|
||
|
&man->geometry.y, &junk, &junk, &junk);
|
||
|
man->geometry.dir |= GROW_DOWN | GROW_RIGHT;
|
||
|
man->sizehints_flags |= USPosition;
|
||
|
}
|
||
|
|
||
|
if (man->sizehints_flags & USPosition) {
|
||
|
if (man->geometry.dir & GROW_DOWN) {
|
||
|
if (man->geometry.dir & GROW_RIGHT)
|
||
|
man->gravity = NorthWestGravity;
|
||
|
else if (man->geometry.dir & GROW_LEFT)
|
||
|
man->gravity = NorthEastGravity;
|
||
|
else
|
||
|
ConsoleMessage ("Internal error in X_init_manager\n");
|
||
|
}
|
||
|
else if (man->geometry.dir & GROW_UP) {
|
||
|
if (man->geometry.dir & GROW_RIGHT)
|
||
|
man->gravity = SouthWestGravity;
|
||
|
else if (man->geometry.dir & GROW_LEFT)
|
||
|
man->gravity = SouthEastGravity;
|
||
|
else
|
||
|
ConsoleMessage ("Internal error in X_init_manager\n");
|
||
|
}
|
||
|
else {
|
||
|
ConsoleMessage ("Internal error in X_init_manager\n");
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
man->geometry.dir |= GROW_DOWN | GROW_RIGHT;
|
||
|
man->gravity = NorthWestGravity;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void create_manager_window (int man_id)
|
||
|
{
|
||
|
XSizeHints sizehints;
|
||
|
XGCValues gcval;
|
||
|
unsigned long gcmask = 0;
|
||
|
unsigned long winattrmask = CWBackPixel| CWBorderPixel | CWEventMask |
|
||
|
CWBackingStore | CWBitGravity;
|
||
|
XSetWindowAttributes winattr;
|
||
|
unsigned int line_width = 1;
|
||
|
int line_style = LineSolid;
|
||
|
int cap_style = CapRound;
|
||
|
int join_style = JoinRound;
|
||
|
int i;
|
||
|
WinManager *man;
|
||
|
ConsoleDebug (X11, "In create_manager_window\n");
|
||
|
|
||
|
man = &globals.managers[man_id];
|
||
|
|
||
|
if (man->window_up)
|
||
|
return;
|
||
|
|
||
|
size_manager (man);
|
||
|
|
||
|
sizehints.flags = man->sizehints_flags;
|
||
|
|
||
|
|
||
|
sizehints.base_width = sizehints.width = man->geometry.width;
|
||
|
sizehints.base_height = sizehints.height = man->geometry.height;
|
||
|
sizehints.min_width = 0;
|
||
|
sizehints.max_width = globals.screenx;
|
||
|
sizehints.min_height = man->geometry.height;
|
||
|
sizehints.max_height = man->geometry.height;
|
||
|
sizehints.win_gravity = man->gravity;
|
||
|
sizehints.flags |= PBaseSize | PMinSize | PMaxSize | PWinGravity;
|
||
|
sizehints.x = man->geometry.x;
|
||
|
sizehints.y = man->geometry.y;
|
||
|
|
||
|
|
||
|
ConsoleDebug (X11, "hints: x, y, w, h = %d %d %d %d)\n",
|
||
|
sizehints.x, sizehints.y,
|
||
|
sizehints.base_width, sizehints.base_height);
|
||
|
ConsoleDebug (X11, "gravity: %d %d\n", sizehints.win_gravity, man->gravity);
|
||
|
|
||
|
|
||
|
winattr.background_pixel = man->backcolor[PLAIN_CONTEXT];
|
||
|
winattr.border_pixel = man->forecolor[PLAIN_CONTEXT];
|
||
|
winattr.backing_store = WhenMapped;
|
||
|
winattr.bit_gravity = man->gravity;
|
||
|
winattr.event_mask = ExposureMask | PointerMotionMask | EnterWindowMask |
|
||
|
LeaveWindowMask | KeyPressMask | StructureNotifyMask;
|
||
|
|
||
|
if (globals.transient)
|
||
|
winattr.event_mask |= ButtonReleaseMask;
|
||
|
else
|
||
|
winattr.event_mask |= ButtonPressMask;
|
||
|
|
||
|
man->theWindow = XCreateWindow (theDisplay, theRoot, sizehints.x,
|
||
|
sizehints.y, man->geometry.width,
|
||
|
man->geometry.height,
|
||
|
0, CopyFromParent, InputOutput,
|
||
|
(Visual *)CopyFromParent, winattrmask,
|
||
|
&winattr);
|
||
|
#ifdef SHAPE
|
||
|
XShapeSelectInput (theDisplay, man->theWindow, ShapeNotifyMask);
|
||
|
#endif
|
||
|
|
||
|
/* We really want the bit gravity to be NorthWest, so that can minimize
|
||
|
redraws. But, we had to have an appropriate bit gravity when creating
|
||
|
the window so that fvwm would place the window correctly if it has
|
||
|
a border. I don't know if I should wait until an event is received
|
||
|
before doing this. Sigh */
|
||
|
winattr.bit_gravity = NorthWestGravity;
|
||
|
XChangeWindowAttributes (theDisplay, man->theWindow,
|
||
|
CWBitGravity, &winattr);
|
||
|
set_shape (man);
|
||
|
|
||
|
man->theFrame = man->theWindow;
|
||
|
man->off_x = 0;
|
||
|
man->off_y = 0;
|
||
|
|
||
|
for (i = 0; i < NUM_CONTEXTS; i++) {
|
||
|
man->backContext[i] =
|
||
|
XCreateGC (theDisplay, man->theWindow, gcmask, &gcval);
|
||
|
XSetForeground (theDisplay, man->backContext[i], man->backcolor[i]);
|
||
|
XSetLineAttributes (theDisplay, man->backContext[i], line_width,
|
||
|
line_style, cap_style,
|
||
|
join_style);
|
||
|
|
||
|
man->hiContext[i] =
|
||
|
XCreateGC (theDisplay, man->theWindow, gcmask, &gcval);
|
||
|
XSetFont (theDisplay, man->hiContext[i], man->ButtonFont->fid);
|
||
|
XSetForeground (theDisplay, man->hiContext[i], man->forecolor[i]);
|
||
|
|
||
|
gcmask = GCForeground | GCBackground;
|
||
|
gcval.foreground = man->backcolor[i];
|
||
|
gcval.background = man->forecolor[i];
|
||
|
man->flatContext[i] = XCreateGC (theDisplay, man->theWindow,
|
||
|
gcmask, &gcval);
|
||
|
if (theDepth > 2) {
|
||
|
gcmask = GCForeground | GCBackground;
|
||
|
gcval.foreground = man->hicolor[i];
|
||
|
gcval.background = man->backcolor[i];
|
||
|
man->reliefContext[i] = XCreateGC (theDisplay, man->theWindow,
|
||
|
gcmask, &gcval);
|
||
|
|
||
|
gcmask = GCForeground | GCBackground;
|
||
|
gcval.foreground = man->shadowcolor[i];
|
||
|
gcval.background = man->backcolor[i];
|
||
|
man->shadowContext[i] = XCreateGC (theDisplay, man->theWindow,
|
||
|
gcmask, &gcval);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set_window_properties (man->theWindow, man->titlename,
|
||
|
man->iconname, &sizehints);
|
||
|
man->window_up = 1;
|
||
|
map_manager (man);
|
||
|
}
|
||
|
|
||
|
static int handle_error (Display *d, XErrorEvent *ev)
|
||
|
{
|
||
|
ConsoleMessage ("X Error:\n");
|
||
|
ConsoleMessage (" error code: %d\n", ev->error_code);
|
||
|
ConsoleMessage (" request code: %d\n", ev->request_code);
|
||
|
ConsoleMessage (" minor code: %d\n", ev->minor_code);
|
||
|
ConsoleMessage ("Leaving a core dump now\n");
|
||
|
abort();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void init_display (void)
|
||
|
{
|
||
|
theDisplay = XOpenDisplay ("");
|
||
|
if (theDisplay == NULL) {
|
||
|
ConsoleMessage ("Can't open display: %s\n", XDisplayName (""));
|
||
|
ShutMeDown (1);
|
||
|
}
|
||
|
XSetErrorHandler (handle_error);
|
||
|
x_fd = XConnectionNumber (theDisplay);
|
||
|
theScreen = DefaultScreen (theDisplay);
|
||
|
theRoot = RootWindow (theDisplay, theScreen);
|
||
|
theDepth = DefaultDepth (theDisplay, theScreen);
|
||
|
#ifdef TEST_MONO
|
||
|
theDepth = 2;
|
||
|
#endif
|
||
|
globals.screenx = DisplayWidth (theDisplay, theScreen);
|
||
|
globals.screeny = DisplayHeight (theDisplay, theScreen);
|
||
|
|
||
|
#ifdef SHAPE
|
||
|
globals.shapes_supported = XShapeQueryExtension (theDisplay, &shapeEventBase,
|
||
|
&shapeErrorBase);
|
||
|
#endif
|
||
|
|
||
|
InitPictureCMap (theDisplay, theRoot);
|
||
|
|
||
|
ConsoleDebug (X11, "screen width: %ld\n", globals.screenx);
|
||
|
ConsoleDebug (X11, "screen height: %ld\n", globals.screeny);
|
||
|
}
|