1804 lines
46 KiB
C
1804 lines
46 KiB
C
|
#include "config.h"
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include "FvwmIconMan.h"
|
||
|
#include "x.h"
|
||
|
#include "xmanager.h"
|
||
|
|
||
|
static char const rcsid[] =
|
||
|
"$Id: xmanager.c,v 1.1.1.1 2006/11/26 10:53:51 matthieu Exp $";
|
||
|
|
||
|
#ifdef SHAPE
|
||
|
#include <X11/extensions/shape.h>
|
||
|
#endif
|
||
|
|
||
|
#ifdef COMPILE_STANDALONE
|
||
|
#include "fvwm.h"
|
||
|
#else
|
||
|
#include "../../fvwm/fvwm.h"
|
||
|
#endif
|
||
|
|
||
|
/* button dirty bits: */
|
||
|
#define ICON_STATE_CHANGED 1
|
||
|
#define STATE_CHANGED 2
|
||
|
#define PICTURE_CHANGED 4
|
||
|
#define WINDOW_CHANGED 8
|
||
|
#define STRING_CHANGED 16
|
||
|
#define REDRAW_BUTTON 32
|
||
|
#define GEOMETRY_CHANGED 64
|
||
|
|
||
|
/* manager dirty bits: */
|
||
|
/* GEOMETRY_CHANGED 64 same as with button */
|
||
|
#define MAPPING_CHANGED 2
|
||
|
#define SHAPE_CHANGED 4
|
||
|
#define REDRAW_MANAGER 8
|
||
|
|
||
|
/* ButtonArray dirty bits: */
|
||
|
#define NUM_BUTTONS_CHANGED 1
|
||
|
#define NUM_WINDOWS_CHANGED 2
|
||
|
|
||
|
#define ALL_CHANGED 0x7f /* high bit is special */
|
||
|
|
||
|
typedef struct {
|
||
|
int button_x, button_y, button_h, button_w; /* dim's of the whole button */
|
||
|
int icon_x, icon_y, icon_h, icon_w; /* what denotes icon state */
|
||
|
int text_x, text_y, text_h, text_w; /* text field */
|
||
|
int text_base; /* text baseline */
|
||
|
} ButtonGeometry;
|
||
|
|
||
|
static void print_button_info (Button *b);
|
||
|
static void insert_windows_button (WinData *win);
|
||
|
|
||
|
/***************************************************************************/
|
||
|
/* Utility leaf functions */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
static int selected_button_in_man (WinManager *man)
|
||
|
{
|
||
|
assert (man);
|
||
|
ConsoleDebug (X11, "selected_button_in_man: %p\n",
|
||
|
globals.select_win);
|
||
|
if (globals.select_win && globals.select_win->button &&
|
||
|
globals.select_win->manager == man) {
|
||
|
return globals.select_win->button->index;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
static void ClipRectangle (WinManager *man, int context,
|
||
|
int x, int y, int w, int h)
|
||
|
{
|
||
|
XRectangle r;
|
||
|
|
||
|
r.x = x;
|
||
|
r.y = y;
|
||
|
r.width = w;
|
||
|
r.height = h;
|
||
|
|
||
|
XSetClipRectangles(theDisplay, man->hiContext[context], 0, 0, &r, 1,
|
||
|
YXBanded);
|
||
|
}
|
||
|
|
||
|
static int num_visible_rows (int n, int cols)
|
||
|
{
|
||
|
return (n - 1) / cols + 1;
|
||
|
}
|
||
|
|
||
|
static int first_row_len (int n, int cols)
|
||
|
{
|
||
|
int ret = n % cols;
|
||
|
if (ret == 0)
|
||
|
ret = cols;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int index_to_box (WinManager *man, int index)
|
||
|
{
|
||
|
int first_len, n, cols;
|
||
|
|
||
|
if (man->geometry.dir & GROW_DOWN) {
|
||
|
return index;
|
||
|
}
|
||
|
else {
|
||
|
n = man->buttons.num_windows;
|
||
|
cols = man->geometry.cols;
|
||
|
first_len = first_row_len (n, cols);
|
||
|
if (index >= first_len)
|
||
|
index += cols - first_len;
|
||
|
index += (man->geometry.rows - num_visible_rows (n, cols)) * cols;
|
||
|
return index;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int box_to_index (WinManager *man, int box)
|
||
|
{
|
||
|
int first_len, n, cols;
|
||
|
|
||
|
if (man->geometry.dir & GROW_DOWN) {
|
||
|
return box;
|
||
|
}
|
||
|
else {
|
||
|
n = man->buttons.num_windows;
|
||
|
cols = man->geometry.cols;
|
||
|
first_len = first_row_len (n, cols);
|
||
|
|
||
|
box -= (man->geometry.rows - num_visible_rows (n, cols)) * cols;
|
||
|
if (!((box >= 0 && box < first_len) || box >= cols))
|
||
|
return -1;
|
||
|
if (box >= first_len)
|
||
|
box -= cols - first_len;
|
||
|
return box;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int index_to_row (WinManager *man, int index)
|
||
|
{
|
||
|
int row;
|
||
|
|
||
|
row = index_to_box (man, index) / man->geometry.cols;
|
||
|
|
||
|
return row;
|
||
|
}
|
||
|
|
||
|
static int index_to_col (WinManager *man, int index)
|
||
|
{
|
||
|
int col;
|
||
|
|
||
|
col = index_to_box (man, index) % man->geometry.cols;
|
||
|
|
||
|
return col;
|
||
|
}
|
||
|
|
||
|
static int rects_equal (XRectangle *x, XRectangle *y)
|
||
|
{
|
||
|
return (x->x == y->x) && (x->y == y->y) && (x->width == y->width) &&
|
||
|
(x->height == y->height);
|
||
|
}
|
||
|
|
||
|
static int top_y_coord (WinManager *man)
|
||
|
{
|
||
|
if (man->buttons.num_windows > 0 && (man->geometry.dir & GROW_UP)) {
|
||
|
return index_to_row (man, 0) * man->geometry.boxheight;
|
||
|
}
|
||
|
else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static ManGeometry *figure_geometry (WinManager *man)
|
||
|
{
|
||
|
/* Given the number of wins in icon_list and width x height, compute
|
||
|
new geometry. */
|
||
|
/* if GROW_FIXED is set, don't change window geometry */
|
||
|
|
||
|
static ManGeometry ret;
|
||
|
ManGeometry *g = &man->geometry;
|
||
|
int n = man->buttons.num_windows;
|
||
|
|
||
|
ret = *g;
|
||
|
|
||
|
ConsoleDebug (X11, "figure_geometry: %s: %d, %d %d %d %d\n",
|
||
|
man->titlename, n,
|
||
|
ret.width, ret.height, ret.cols, ret.rows);
|
||
|
|
||
|
if (n == 0) {
|
||
|
n = 1;
|
||
|
}
|
||
|
|
||
|
if (man->geometry.dir & GROW_FIXED) {
|
||
|
ret.cols = num_visible_rows (n, g->rows);
|
||
|
ret.boxwidth = ret.width / ret.cols;
|
||
|
}
|
||
|
else {
|
||
|
if (man->geometry.dir & GROW_VERT) {
|
||
|
if (g->cols) {
|
||
|
ret.rows = num_visible_rows (n, g->cols);
|
||
|
}
|
||
|
else {
|
||
|
ConsoleMessage ("Internal error in figure_geometry\n");
|
||
|
ret.rows = 1;
|
||
|
}
|
||
|
ret.height = ret.rows * g->boxheight;
|
||
|
ret.width = ret.cols * g->boxwidth;
|
||
|
}
|
||
|
else {
|
||
|
/* need to set resize inc */
|
||
|
if (g->rows) {
|
||
|
ret.cols = num_visible_rows (n, g->rows);
|
||
|
}
|
||
|
else {
|
||
|
ConsoleMessage ("Internal error in figure_geometry\n");
|
||
|
ret.cols = 1;
|
||
|
}
|
||
|
ret.height = ret.rows * g->boxheight;
|
||
|
ret.width = ret.cols * g->boxwidth;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ConsoleDebug (X11, "figure_geometry: %d %d %d %d %d\n",
|
||
|
n, ret.width, ret.height, ret.cols, ret.rows);
|
||
|
|
||
|
return &ret;
|
||
|
}
|
||
|
|
||
|
static ManGeometry *query_geometry (WinManager *man)
|
||
|
{
|
||
|
XWindowAttributes frame_attr, win_attr;
|
||
|
int off_x, off_y;
|
||
|
static ManGeometry g;
|
||
|
|
||
|
assert (man->window_mapped);
|
||
|
|
||
|
off_x = 0;
|
||
|
off_y = 0;
|
||
|
man->theFrame = find_frame_window (man->theWindow, &off_x, &off_y);
|
||
|
XGetWindowAttributes (theDisplay, man->theFrame, &frame_attr);
|
||
|
g.x = frame_attr.x + off_x + frame_attr.border_width;
|
||
|
g.y = frame_attr.y + off_y + frame_attr.border_width;
|
||
|
XGetWindowAttributes (theDisplay, man->theWindow, &win_attr);
|
||
|
g.width = win_attr.width;
|
||
|
g.height = win_attr.height;
|
||
|
|
||
|
return &g;
|
||
|
}
|
||
|
|
||
|
static void fix_manager_size (WinManager *man, int w, int h)
|
||
|
{
|
||
|
XSizeHints size;
|
||
|
long mask;
|
||
|
|
||
|
XGetWMNormalHints (theDisplay, man->theWindow, &size, &mask);
|
||
|
size.min_width = w;
|
||
|
size.max_width = w;
|
||
|
size.min_height = h;
|
||
|
size.max_height = h;
|
||
|
XSetWMNormalHints (theDisplay, man->theWindow, &size);
|
||
|
}
|
||
|
|
||
|
/* Like XMoveResizeWindow(), but can move in arbitary directions */
|
||
|
static void resize_window (WinManager *man)
|
||
|
{
|
||
|
ManGeometry *g;
|
||
|
int x_changed, y_changed, dir;
|
||
|
|
||
|
dir = man->geometry.dir;
|
||
|
fix_manager_size (man, man->geometry.width, man->geometry.height);
|
||
|
|
||
|
if ((dir & GROW_DOWN) && (dir & GROW_RIGHT)) {
|
||
|
XResizeWindow (theDisplay, man->theWindow, man->geometry.width,
|
||
|
man->geometry.height);
|
||
|
}
|
||
|
else {
|
||
|
MyXGrabServer (theDisplay);
|
||
|
g = query_geometry (man);
|
||
|
x_changed = y_changed = 0;
|
||
|
if (dir & GROW_LEFT) {
|
||
|
man->geometry.x = g->x + g->width - man->geometry.width;
|
||
|
x_changed = 1;
|
||
|
}
|
||
|
else {
|
||
|
man->geometry.x = g->x;
|
||
|
}
|
||
|
if (dir & GROW_UP) {
|
||
|
man->geometry.y = g->y + g->height - man->geometry.height;
|
||
|
y_changed = 1;
|
||
|
}
|
||
|
else {
|
||
|
man->geometry.y = g->y;
|
||
|
}
|
||
|
|
||
|
ConsoleDebug (X11, "queried: y: %d, h: %d, queried: %d\n", g->y,
|
||
|
man->geometry.height, g->height);
|
||
|
|
||
|
if (x_changed || y_changed) {
|
||
|
XMoveResizeWindow (theDisplay, man->theWindow,
|
||
|
man->geometry.x,
|
||
|
man->geometry.y,
|
||
|
man->geometry.width, man->geometry.height);
|
||
|
}
|
||
|
else {
|
||
|
XResizeWindow (theDisplay, man->theWindow, man->geometry.width,
|
||
|
man->geometry.height);
|
||
|
}
|
||
|
MyXUngrabServer (theDisplay);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static char *make_display_string (WinData *win, char *format, int len)
|
||
|
{
|
||
|
#define MAX_DISPLAY_SIZE 1024
|
||
|
#define COPY(field) \
|
||
|
temp_p = win->field; \
|
||
|
if (temp_p) \
|
||
|
while (*temp_p && out_p - buf < len - 1) \
|
||
|
*out_p++ = *temp_p++; \
|
||
|
in_p++;
|
||
|
|
||
|
static char buf[MAX_DISPLAY_SIZE];
|
||
|
char *string, *in_p, *out_p, *temp_p;
|
||
|
|
||
|
in_p = format;
|
||
|
out_p = buf;
|
||
|
|
||
|
if (len > MAX_DISPLAY_SIZE || len <= 0)
|
||
|
len = MAX_DISPLAY_SIZE;
|
||
|
|
||
|
while (*in_p && out_p - buf < len - 1) {
|
||
|
if (*in_p == '%') {
|
||
|
switch (*(++in_p)) {
|
||
|
case 'i':
|
||
|
COPY (iconname);
|
||
|
break;
|
||
|
|
||
|
case 't':
|
||
|
COPY (titlename);
|
||
|
break;
|
||
|
|
||
|
case 'r':
|
||
|
COPY (resname);
|
||
|
break;
|
||
|
|
||
|
case 'c':
|
||
|
COPY (classname);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
*out_p++ = *in_p++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
*out_p++ = *in_p++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*out_p++ = '\0';
|
||
|
|
||
|
string = buf;
|
||
|
return string;
|
||
|
|
||
|
#undef COPY
|
||
|
#undef MAX_DISPLAY_SIZE
|
||
|
}
|
||
|
|
||
|
Button *button_above (WinManager *man, Button *b)
|
||
|
{
|
||
|
int n = man->buttons.num_windows, cols = man->geometry.cols;
|
||
|
int i = -1;
|
||
|
|
||
|
if (b) {
|
||
|
i = box_to_index (man, index_to_box (man, b->index) - cols);
|
||
|
}
|
||
|
if (i < 0 || i >= n)
|
||
|
return b;
|
||
|
else
|
||
|
return man->buttons.buttons[i];
|
||
|
}
|
||
|
|
||
|
Button *button_below (WinManager *man, Button *b)
|
||
|
{
|
||
|
int n = man->buttons.num_windows;
|
||
|
int i = -1;
|
||
|
|
||
|
if (b) {
|
||
|
i = box_to_index (man, index_to_box (man, b->index) + man->geometry.cols);
|
||
|
}
|
||
|
if (i < 0 || i >= n)
|
||
|
return b;
|
||
|
else
|
||
|
return man->buttons.buttons[i];
|
||
|
}
|
||
|
|
||
|
Button *button_right (WinManager *man, Button *b)
|
||
|
{
|
||
|
int i = 0;
|
||
|
|
||
|
if (index_to_col (man, b->index) < man->geometry.cols - 1) {
|
||
|
i = box_to_index (man, index_to_box (man, b->index) + 1);
|
||
|
}
|
||
|
|
||
|
if (i < 0 || i >= man->buttons.num_windows)
|
||
|
return b;
|
||
|
else
|
||
|
return man->buttons.buttons[i];
|
||
|
}
|
||
|
|
||
|
Button *button_left (WinManager *man, Button *b)
|
||
|
{
|
||
|
int i;
|
||
|
if (index_to_col (man, b->index) > 0) {
|
||
|
i = box_to_index (man, index_to_box (man, b->index) - 1);
|
||
|
}
|
||
|
|
||
|
if (i < 0 || i >= man->buttons.num_windows)
|
||
|
return b;
|
||
|
else
|
||
|
return man->buttons.buttons[i];
|
||
|
}
|
||
|
|
||
|
Button *button_next (WinManager *man, Button *b)
|
||
|
{
|
||
|
int i = b->index + 1;
|
||
|
|
||
|
if (i >= 0 && i < man->buttons.num_windows)
|
||
|
return man->buttons.buttons[i];
|
||
|
else
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
Button *button_prev (WinManager *man, Button *b)
|
||
|
{
|
||
|
int i = b->index - 1;
|
||
|
|
||
|
if (i >= 0 && i < man->buttons.num_windows)
|
||
|
return man->buttons.buttons[i];
|
||
|
else
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
Button *xy_to_button (WinManager *man, int x, int y)
|
||
|
{
|
||
|
int row = y / man->geometry.boxheight;
|
||
|
int col = x / man->geometry.boxwidth;
|
||
|
int box, index;
|
||
|
|
||
|
if (x >= 0 && x <= man->geometry.width &&
|
||
|
y >= 0 && y <= man->geometry.height) {
|
||
|
box = row * man->geometry.cols + col;
|
||
|
index = box_to_index (man, box);
|
||
|
if (index >= 0 && index < man->buttons.num_windows)
|
||
|
return man->buttons.buttons[index];
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************/
|
||
|
/* Routines which change dirtyable state */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
static void set_button_geometry (WinManager *man, Button *box)
|
||
|
{
|
||
|
box->x = index_to_col (man, box->index) * man->geometry.boxwidth;
|
||
|
box->y = index_to_row (man, box->index) * man->geometry.boxheight;
|
||
|
box->w = man->geometry.boxwidth;
|
||
|
box->h = man->geometry.boxheight;
|
||
|
box->drawn_state.dirty_flags |= GEOMETRY_CHANGED;
|
||
|
}
|
||
|
|
||
|
static void clear_button (Button *b)
|
||
|
{
|
||
|
assert (b);
|
||
|
b->drawn_state.win = NULL;
|
||
|
b->drawn_state.dirty_flags = REDRAW_BUTTON;
|
||
|
}
|
||
|
|
||
|
static void set_window_button (WinData *win, int index)
|
||
|
{
|
||
|
Button *b;
|
||
|
|
||
|
assert (win->manager && index < win->manager->buttons.num_buttons);
|
||
|
|
||
|
b = win->manager->buttons.buttons[index];
|
||
|
|
||
|
/* Can optimize here */
|
||
|
|
||
|
#ifdef MINI_ICONS
|
||
|
b->drawn_state.pic = win->pic;
|
||
|
#endif
|
||
|
|
||
|
b->drawn_state.win = win;
|
||
|
b->drawn_state.display_string = win->display_string;
|
||
|
b->drawn_state.iconified = win->iconified;
|
||
|
b->drawn_state.state = win->state;
|
||
|
b->drawn_state.dirty_flags = ALL_CHANGED;
|
||
|
|
||
|
win->button = b;
|
||
|
}
|
||
|
|
||
|
static void *Realloc (void *ptr, int size)
|
||
|
{
|
||
|
if (ptr == NULL)
|
||
|
return safemalloc (size);
|
||
|
else
|
||
|
return realloc (ptr, size);
|
||
|
}
|
||
|
|
||
|
static void set_num_buttons (ButtonArray *buttons, int n)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
ConsoleDebug (X11, "set_num_buttons: %d %d\n", buttons->num_buttons, n);
|
||
|
|
||
|
if (n > buttons->num_buttons) {
|
||
|
buttons->dirty_flags |= NUM_BUTTONS_CHANGED;
|
||
|
buttons->buttons = (Button **)Realloc (buttons->buttons,
|
||
|
n * sizeof (Button *));
|
||
|
if (buttons->buttons == NULL) {
|
||
|
ConsoleMessage ("Realloc failed! Bailing out\n");
|
||
|
ShutMeDown(1);
|
||
|
}
|
||
|
|
||
|
for (i = buttons->num_buttons; i < n; i++) {
|
||
|
buttons->buttons[i] = (Button *)safemalloc (sizeof (Button));
|
||
|
buttons->buttons[i]->index = i;
|
||
|
buttons->buttons[i]->drawn_state.dirty_flags = 0;
|
||
|
buttons->buttons[i]->drawn_state.w = 0;
|
||
|
buttons->buttons[i]->drawn_state.h = 0;
|
||
|
buttons->buttons[i]->drawn_state.win = NULL;
|
||
|
}
|
||
|
|
||
|
buttons->dirty_flags |= NUM_BUTTONS_CHANGED;
|
||
|
buttons->num_buttons = n;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void increase_num_windows (ButtonArray *buttons, int off)
|
||
|
{
|
||
|
int n;
|
||
|
|
||
|
if (off != 0) {
|
||
|
buttons->num_windows += off;
|
||
|
buttons->dirty_flags |= NUM_WINDOWS_CHANGED;
|
||
|
|
||
|
if (buttons->num_windows > buttons->num_buttons) {
|
||
|
n = buttons->num_windows + 10;
|
||
|
set_num_buttons (buttons, n);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void set_man_gravity_origin (WinManager *man)
|
||
|
{
|
||
|
if (man->gravity == NorthWestGravity || man->gravity == NorthEastGravity)
|
||
|
man->geometry.gravity_y = 0;
|
||
|
else
|
||
|
man->geometry.gravity_y = man->geometry.height;
|
||
|
if (man->gravity == NorthWestGravity || man->gravity == SouthWestGravity)
|
||
|
man->geometry.gravity_x = 0;
|
||
|
else
|
||
|
man->geometry.gravity_x = man->geometry.width;
|
||
|
}
|
||
|
|
||
|
static void set_man_geometry (WinManager *man, ManGeometry *new)
|
||
|
{
|
||
|
int n;
|
||
|
|
||
|
if (man->geometry.width != new->width ||
|
||
|
man->geometry.height != new->height ||
|
||
|
man->geometry.rows != new->rows ||
|
||
|
man->geometry.cols != new->cols ||
|
||
|
man->geometry.boxheight != new->boxheight ||
|
||
|
man->geometry.boxwidth != new->boxwidth) {
|
||
|
man->dirty_flags |= GEOMETRY_CHANGED;
|
||
|
}
|
||
|
|
||
|
man->geometry = *new;
|
||
|
set_man_gravity_origin (man);
|
||
|
n = man->geometry.rows * man->geometry.cols;
|
||
|
if (man->buttons.num_buttons < n)
|
||
|
set_num_buttons (&man->buttons, n + 10);
|
||
|
}
|
||
|
|
||
|
void set_manager_width (WinManager *man, int width)
|
||
|
{
|
||
|
if (width != man->geometry.width) {
|
||
|
ConsoleDebug (X11, "set_manager_width: %d -> %d, %d -> %d\n",
|
||
|
man->geometry.width, width, man->geometry.boxwidth,
|
||
|
width / man->geometry.cols);
|
||
|
man->geometry.width = width;
|
||
|
man->geometry.boxwidth = width / man->geometry.cols;
|
||
|
man->dirty_flags |= GEOMETRY_CHANGED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void force_manager_redraw (WinManager *man)
|
||
|
{
|
||
|
man->dirty_flags |= REDRAW_MANAGER;
|
||
|
draw_manager (man);
|
||
|
}
|
||
|
|
||
|
#ifdef MINI_ICONS
|
||
|
|
||
|
void set_win_picture (WinData *win, Pixmap picture, Pixmap mask,
|
||
|
unsigned int depth, unsigned int width,
|
||
|
unsigned int height)
|
||
|
{
|
||
|
if (win->button)
|
||
|
win->button->drawn_state.dirty_flags |= PICTURE_CHANGED;
|
||
|
win->pic.picture = picture;
|
||
|
win->pic.mask = mask;
|
||
|
win->pic.width = width;
|
||
|
win->pic.height = height;
|
||
|
win->pic.depth = depth;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
void set_win_iconified (WinData *win, int iconified)
|
||
|
{
|
||
|
if (win->button && win->iconified != iconified)
|
||
|
win->button->drawn_state.dirty_flags |= ICON_STATE_CHANGED;
|
||
|
win->iconified = iconified;
|
||
|
}
|
||
|
|
||
|
void set_win_state (WinData *win, int state)
|
||
|
{
|
||
|
if (win->button && win->state != state)
|
||
|
win->button->drawn_state.dirty_flags |= STATE_CHANGED;
|
||
|
win->state = state;
|
||
|
}
|
||
|
|
||
|
void add_win_state (WinData *win, int flag)
|
||
|
{
|
||
|
if (win->button && (win->state & flag) == 0)
|
||
|
win->button->drawn_state.dirty_flags |= STATE_CHANGED;
|
||
|
win->state |= flag;
|
||
|
ConsoleDebug (X11, "add_win_state: %s 0x%x\n", win->titlename, flag);
|
||
|
}
|
||
|
|
||
|
void del_win_state (WinData *win, int flag)
|
||
|
{
|
||
|
if (win->button && (win->state & flag))
|
||
|
win->button->drawn_state.dirty_flags |= STATE_CHANGED;
|
||
|
win->state &= ~flag;
|
||
|
ConsoleDebug (X11, "del_win_state: %s 0x%x\n", win->titlename, flag);
|
||
|
}
|
||
|
|
||
|
void set_win_displaystring (WinData *win)
|
||
|
{
|
||
|
WinManager *man = win->manager;
|
||
|
int maxlen;
|
||
|
|
||
|
if (!man || ((man->format_depend & CLASS_NAME) && !win->classname)
|
||
|
|| ((man->format_depend & ICON_NAME) && !win->iconname)
|
||
|
|| ((man->format_depend & TITLE_NAME) && !win->titlename)
|
||
|
|| ((man->format_depend & RESOURCE_NAME) && !win->resname)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (man->window_up) {
|
||
|
assert (man->geometry.width && man->fontwidth);
|
||
|
maxlen = man->geometry.width / man->fontwidth + 2 /* fudge factor */;
|
||
|
}
|
||
|
else {
|
||
|
maxlen = 0;
|
||
|
}
|
||
|
copy_string (&win->display_string,
|
||
|
make_display_string (win, man->formatstring, maxlen));
|
||
|
if (win->button)
|
||
|
win->button->drawn_state.dirty_flags |= STRING_CHANGED;
|
||
|
}
|
||
|
|
||
|
/* This function is here and not with the other static utility functions
|
||
|
because it basically is the inverse of set_shape() */
|
||
|
|
||
|
static void clear_empty_region (WinManager *man)
|
||
|
{
|
||
|
XRectangle rects[2];
|
||
|
int num_rects = 0, n = man->buttons.num_windows, cols = man->geometry.cols;
|
||
|
int rows = man->geometry.rows;
|
||
|
int boxheight = man->geometry.boxheight;
|
||
|
|
||
|
if (man->shaped)
|
||
|
return;
|
||
|
|
||
|
rects[1].x = rects[1].y = rects[1].width = rects[1].height = 0;
|
||
|
|
||
|
if (n == 0 || rows * cols == 0 /* just be to safe */) {
|
||
|
rects[0].x = 0;
|
||
|
rects[0].y = 0;
|
||
|
rects[0].width = man->geometry.width;
|
||
|
rects[0].height = man->geometry.height;
|
||
|
num_rects = 1;
|
||
|
}
|
||
|
else if (man->geometry.dir & GROW_DOWN) {
|
||
|
assert (cols);
|
||
|
if (n % cols == 0) {
|
||
|
rects[0].x = 0;
|
||
|
rects[0].y = num_visible_rows (n, cols) * man->geometry.boxheight;
|
||
|
rects[0].width = man->geometry.width;
|
||
|
rects[0].height = man->geometry.height - rects[0].y;
|
||
|
num_rects = 1;
|
||
|
}
|
||
|
else {
|
||
|
rects[0].x = (n % cols) * man->geometry.boxwidth;
|
||
|
rects[0].y = (num_visible_rows (n, cols) - 1) * man->geometry.boxheight;
|
||
|
rects[0].width = man->geometry.width - rects[0].y;
|
||
|
rects[0].height = boxheight;
|
||
|
rects[1].x = 0;
|
||
|
rects[1].y = rects[0].y + rects[0].height;
|
||
|
rects[1].width = man->geometry.width;
|
||
|
rects[1].height = man->geometry.height - rects[0].y;
|
||
|
num_rects = 2;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
assert (cols);
|
||
|
/* for shaped windows, we won't see this part of the window */
|
||
|
if (n % cols == 0) {
|
||
|
rects[0].x = 0;
|
||
|
rects[0].y = 0;
|
||
|
rects[0].width = man->geometry.width;
|
||
|
rects[0].height = top_y_coord (man);
|
||
|
num_rects = 1;
|
||
|
}
|
||
|
else {
|
||
|
rects[0].x = 0;
|
||
|
rects[0].y = 0;
|
||
|
rects[0].width = man->geometry.width;
|
||
|
rects[0].height = top_y_coord (man);
|
||
|
rects[1].x = (n % cols) * man->geometry.boxwidth;
|
||
|
rects[1].y = rects[0].height;
|
||
|
rects[1].width = man->geometry.width - rects[1].x;
|
||
|
rects[1].height = boxheight;
|
||
|
num_rects = 2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ConsoleDebug (X11, "Clearing: %d: (%d, %d, %d, %d) + (%d, %d, %d, %d)\n",
|
||
|
num_rects,
|
||
|
rects[0].x, rects[0].y, rects[0].width, rects[0].height,
|
||
|
rects[1].x, rects[1].y, rects[1].width, rects[1].height);
|
||
|
|
||
|
XFillRectangles (theDisplay, man->theWindow,
|
||
|
man->backContext[PLAIN_CONTEXT], rects, num_rects);
|
||
|
}
|
||
|
|
||
|
void set_shape (WinManager *man)
|
||
|
{
|
||
|
#ifdef SHAPE
|
||
|
int n;
|
||
|
XRectangle rects[2];
|
||
|
int cols = man->geometry.cols;
|
||
|
|
||
|
if (!globals.shapes_supported || man->shaped == 0)
|
||
|
return;
|
||
|
|
||
|
ConsoleDebug (X11, "in set_shape: %s\n", man->titlename);
|
||
|
|
||
|
n = man->buttons.num_windows;
|
||
|
if (n == 0)
|
||
|
n = 1;
|
||
|
|
||
|
if (cols == 0 || n % cols == 0) {
|
||
|
rects[0].x = 0;
|
||
|
rects[0].y = top_y_coord (man);
|
||
|
rects[0].width = man->geometry.width;
|
||
|
rects[0].height = num_visible_rows (n, cols) * man->geometry.boxheight;
|
||
|
if (man->shape.num_rects != 1 || !rects_equal (rects, man->shape.rects)) {
|
||
|
man->dirty_flags |= SHAPE_CHANGED;
|
||
|
}
|
||
|
man->shape.num_rects = 1;
|
||
|
man->shape.rects[0] = rects[0];
|
||
|
}
|
||
|
else {
|
||
|
if (man->geometry.dir & GROW_DOWN) {
|
||
|
rects[0].x = 0;
|
||
|
rects[0].y = 0;
|
||
|
rects[0].width = man->geometry.width;
|
||
|
rects[0].height =
|
||
|
(num_visible_rows (n, cols) - 1) * man->geometry.boxheight;
|
||
|
rects[1].x = 0;
|
||
|
rects[1].y = rects[0].height;
|
||
|
rects[1].width = (n % cols) * man->geometry.boxwidth;
|
||
|
rects[1].height = man->geometry.boxheight;
|
||
|
}
|
||
|
else {
|
||
|
rects[0].x = 0;
|
||
|
rects[0].y = top_y_coord (man);
|
||
|
rects[0].width = (n % cols) * man->geometry.boxwidth;
|
||
|
rects[0].height = man->geometry.boxheight;
|
||
|
rects[1].x = 0;
|
||
|
rects[1].y = rects[0].y + rects[0].height;
|
||
|
rects[1].width = man->geometry.width;
|
||
|
rects[1].height = (num_visible_rows (n, cols) - 1) *
|
||
|
man->geometry.boxheight;
|
||
|
}
|
||
|
if (man->shape.num_rects != 2 ||
|
||
|
!rects_equal (rects, man->shape.rects) ||
|
||
|
!rects_equal (rects + 1, man->shape.rects + 1)) {
|
||
|
man->dirty_flags |= SHAPE_CHANGED;
|
||
|
}
|
||
|
man->shape.num_rects = 2;
|
||
|
man->shape.rects[0] = rects[0];
|
||
|
man->shape.rects[1] = rects[1];
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void set_manager_window_mapping (WinManager *man, int flag)
|
||
|
{
|
||
|
if (flag != man->window_mapped) {
|
||
|
man->window_mapped = flag;
|
||
|
man->dirty_flags |= MAPPING_CHANGED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/***************************************************************************/
|
||
|
/* Major exported functions */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
void init_boxes (void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void init_button_array (ButtonArray *array)
|
||
|
{
|
||
|
array->num_buttons = 0;
|
||
|
array->num_windows = 0;
|
||
|
array->buttons = NULL;
|
||
|
}
|
||
|
|
||
|
/* Pretty much like resize_manager, but used only to figure the
|
||
|
correct size when creating the window */
|
||
|
|
||
|
void size_manager (WinManager *man)
|
||
|
{
|
||
|
ManGeometry *new;
|
||
|
int oldwidth, oldheight, w, h;
|
||
|
|
||
|
new = figure_geometry (man);
|
||
|
|
||
|
assert (new->width && new->height);
|
||
|
|
||
|
w = new->width;
|
||
|
h = new->height;
|
||
|
|
||
|
oldwidth = man->geometry.width;
|
||
|
oldheight = man->geometry.height;
|
||
|
|
||
|
set_man_geometry (man, new);
|
||
|
|
||
|
if (oldheight != h || oldwidth != w) {
|
||
|
if (man->geometry.dir & GROW_UP)
|
||
|
man->geometry.y -= h - oldheight;
|
||
|
if (man->geometry.dir & GROW_LEFT)
|
||
|
man->geometry.x -= w - oldwidth;
|
||
|
}
|
||
|
|
||
|
ConsoleDebug (X11, "size_manager %s: %d %d %d %d\n", man->titlename,
|
||
|
man->geometry.x, man->geometry.y, man->geometry.width,
|
||
|
man->geometry.height);
|
||
|
}
|
||
|
|
||
|
static void resize_manager (WinManager *man, int force)
|
||
|
{
|
||
|
ManGeometry *new;
|
||
|
int oldwidth, oldheight, oldrows, oldcols;
|
||
|
int dir;
|
||
|
|
||
|
if (man->can_draw == 0)
|
||
|
return;
|
||
|
|
||
|
oldwidth = man->geometry.width;
|
||
|
oldheight = man->geometry.height;
|
||
|
oldrows = man->geometry.rows;
|
||
|
oldcols = man->geometry.cols;
|
||
|
dir = man->geometry.dir;
|
||
|
|
||
|
if (dir & GROW_FIXED) {
|
||
|
new = figure_geometry (man);
|
||
|
set_man_geometry (man, new);
|
||
|
set_shape (man);
|
||
|
if (force || oldrows != new->rows || oldcols != new->cols ||
|
||
|
oldwidth != new->width || oldheight != new->height) {
|
||
|
man->dirty_flags |= GEOMETRY_CHANGED;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
new = figure_geometry (man);
|
||
|
set_man_geometry (man, new);
|
||
|
set_shape (man);
|
||
|
if (force || oldrows != new->rows || oldcols != new->cols ||
|
||
|
oldwidth != new->width || oldheight != new->height) {
|
||
|
resize_window (man);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int center_padding (int h1, int h2)
|
||
|
{
|
||
|
return (h2 - h1) / 2;
|
||
|
}
|
||
|
|
||
|
static void get_title_geometry (WinManager *man, ButtonGeometry *g)
|
||
|
{
|
||
|
int text_pad;
|
||
|
assert (man);
|
||
|
g->button_x = 0;
|
||
|
g->button_y = 0;
|
||
|
g->button_w = man->geometry.boxwidth;
|
||
|
g->button_h = man->geometry.boxheight;
|
||
|
g->text_x = g->button_x + g->button_h / 2;
|
||
|
g->text_w = g->button_w - 4 - (g->text_x - g->button_x);
|
||
|
g->text_h = man->fontheight;
|
||
|
text_pad = center_padding (man->fontheight, g->button_h);
|
||
|
|
||
|
g->text_y = g->button_y + text_pad;
|
||
|
g->text_base = g->text_y + man->ButtonFont->ascent;
|
||
|
}
|
||
|
|
||
|
static void get_button_geometry (WinManager *man, Button *button,
|
||
|
ButtonGeometry *g)
|
||
|
{
|
||
|
int icon_pad, text_pad;
|
||
|
WinData *win;
|
||
|
|
||
|
assert (man);
|
||
|
|
||
|
win = button->drawn_state.win;
|
||
|
|
||
|
g->button_x = button->x;
|
||
|
g->button_y = button->y;
|
||
|
|
||
|
g->button_w = button->w;
|
||
|
g->button_h = button->h;
|
||
|
|
||
|
/* [BV 16-Apr-97] Mini Icons work on black-and-white too */
|
||
|
#ifdef MINI_ICONS
|
||
|
if (man->draw_icons && win && win->pic.picture) {
|
||
|
/* If no window, then icon_* aren't used, so doesn't matter what
|
||
|
they are */
|
||
|
g->icon_w = min (win->pic.width, g->button_h);
|
||
|
g->icon_h = min (g->button_h - 4, win->pic.height);
|
||
|
icon_pad = center_padding (g->icon_h, g->button_h);
|
||
|
g->icon_x = g->button_x + 4;
|
||
|
g->icon_y = g->button_y + icon_pad;
|
||
|
}
|
||
|
else {
|
||
|
#endif
|
||
|
g->icon_h = man->geometry.boxheight - 8;
|
||
|
g->icon_w = g->icon_h;
|
||
|
|
||
|
icon_pad = center_padding (g->icon_h, g->button_h);
|
||
|
g->icon_x = g->button_x + icon_pad;
|
||
|
g->icon_y = g->button_y + icon_pad;
|
||
|
#ifdef MINI_ICONS
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
g->text_x = g->icon_x + g->icon_w + 2;
|
||
|
g->text_w = g->button_w - 4 - (g->text_x - g->button_x);
|
||
|
g->text_h = man->fontheight;
|
||
|
|
||
|
text_pad = center_padding (man->fontheight, g->button_h);
|
||
|
|
||
|
g->text_y = g->button_y + text_pad;
|
||
|
g->text_base = g->text_y + man->ButtonFont->ascent;
|
||
|
}
|
||
|
|
||
|
static void draw_3d_square (WinManager *man, int x, int y, int w, int h,
|
||
|
GC rgc, GC sgc)
|
||
|
{
|
||
|
int i;
|
||
|
XSegment seg[4];
|
||
|
|
||
|
i=0;
|
||
|
seg[i].x1 = x; seg[i].y1 = y;
|
||
|
seg[i].x2 = w+x-1; seg[i++].y2 = y;
|
||
|
|
||
|
seg[i].x1 = x; seg[i].y1 = y;
|
||
|
seg[i].x2 = x; seg[i++].y2 = h+y-1;
|
||
|
|
||
|
seg[i].x1 = x+1; seg[i].y1 = y+1;
|
||
|
seg[i].x2 = x+w-2; seg[i++].y2 = y+1;
|
||
|
|
||
|
seg[i].x1 = x+1; seg[i].y1 = y+1;
|
||
|
seg[i].x2 = x+1; seg[i++].y2 = y+h-2;
|
||
|
XDrawSegments(theDisplay, man->theWindow, rgc, seg, i);
|
||
|
|
||
|
i=0;
|
||
|
seg[i].x1 = x; seg[i].y1 = y+h-1;
|
||
|
seg[i].x2 = w+x-1; seg[i++].y2 = y+h-1;
|
||
|
|
||
|
seg[i].x1 = x+w-1; seg[i].y1 = y;
|
||
|
seg[i].x2 = x+w-1; seg[i++].y2 = y+h-1;
|
||
|
XDrawSegments(theDisplay, man->theWindow, sgc, seg, i);
|
||
|
|
||
|
i=0;
|
||
|
seg[i].x1 = x+1; seg[i].y1 = y+h-2;
|
||
|
seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2;
|
||
|
|
||
|
seg[i].x1 = x+w-2; seg[i].y1 = y+1;
|
||
|
seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2;
|
||
|
|
||
|
XDrawSegments(theDisplay, man->theWindow, sgc, seg, i);
|
||
|
}
|
||
|
|
||
|
static void draw_3d_icon (WinManager *man, int box, ButtonGeometry *g,
|
||
|
int iconified, int dir, Contexts contextId)
|
||
|
{
|
||
|
if (iconified == 0) {
|
||
|
draw_3d_square (man, g->icon_x, g->icon_y, g->icon_w, g->icon_h,
|
||
|
man->flatContext[contextId],
|
||
|
man->flatContext[contextId]);
|
||
|
}
|
||
|
else {
|
||
|
if (dir == 1) {
|
||
|
draw_3d_square (man, g->icon_x, g->icon_y, g->icon_w, g->icon_h,
|
||
|
man->reliefContext[contextId],
|
||
|
man->shadowContext[contextId]);
|
||
|
}
|
||
|
else {
|
||
|
draw_3d_square (man, g->icon_x, g->icon_y, g->icon_w, g->icon_h,
|
||
|
man->shadowContext[contextId],
|
||
|
man->reliefContext[contextId]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* this routine should only be called from draw_button() */
|
||
|
static void iconify_box (WinManager *man, WinData *win, int box,
|
||
|
ButtonGeometry *g, int iconified,
|
||
|
Contexts contextId, int button_already_cleared)
|
||
|
{
|
||
|
#ifdef MINI_ICONS
|
||
|
XGCValues gcv;
|
||
|
unsigned long gcm;
|
||
|
#endif
|
||
|
|
||
|
if (!man->window_up)
|
||
|
return;
|
||
|
|
||
|
/* [BV 16-Apr-97] Mini Icons work on black-and-white too */
|
||
|
#ifdef MINI_ICONS
|
||
|
if (man->draw_icons && win->pic.picture) {
|
||
|
if (iconified == 0 && man->draw_icons != 2) {
|
||
|
if (!button_already_cleared) {
|
||
|
XFillRectangle (theDisplay, man->theWindow,
|
||
|
man->backContext[contextId], g->icon_x, g->icon_y,
|
||
|
g->icon_w, g->icon_h);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
gcm = GCClipMask|GCClipXOrigin|GCClipYOrigin;
|
||
|
gcv.clip_mask = win->pic.mask;
|
||
|
gcv.clip_x_origin = g->icon_x;
|
||
|
gcv.clip_y_origin = g->icon_y;
|
||
|
XChangeGC (theDisplay, man->hiContext[contextId], gcm, &gcv);
|
||
|
|
||
|
XCopyArea(theDisplay, win->pic.picture, man->theWindow,
|
||
|
man->hiContext[contextId], 0, 0, g->icon_w, g->icon_h,
|
||
|
g->icon_x, g->icon_y);
|
||
|
gcm = GCClipMask;
|
||
|
gcv.clip_mask = None;
|
||
|
XChangeGC(theDisplay, man->hiContext[contextId], gcm, &gcv);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
#endif
|
||
|
if (theDepth > 2) {
|
||
|
draw_3d_icon (man, box, g, iconified, 1, contextId);
|
||
|
}
|
||
|
else {
|
||
|
if (iconified == 0) {
|
||
|
XFillArc (theDisplay, man->theWindow, man->backContext[contextId],
|
||
|
g->icon_x, g->icon_y, g->icon_w, g->icon_h, 0, 360 * 64);
|
||
|
}
|
||
|
else {
|
||
|
XFillArc (theDisplay, man->theWindow, man->hiContext[contextId],
|
||
|
g->icon_x, g->icon_y, g->icon_w, g->icon_h, 0, 360 * 64);
|
||
|
}
|
||
|
}
|
||
|
#ifdef MINI_ICONS
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
int change_windows_manager (WinData *win)
|
||
|
{
|
||
|
WinManager *oldman;
|
||
|
WinManager *newman;
|
||
|
|
||
|
ConsoleDebug (X11, "change_windows_manager: %s\n", win->titlename);
|
||
|
|
||
|
oldman = win->manager;
|
||
|
newman = figure_win_manager (win, ALL_NAME);
|
||
|
if (oldman && newman != oldman && win->button) {
|
||
|
delete_windows_button (win);
|
||
|
}
|
||
|
win->manager = newman;
|
||
|
set_win_displaystring (win);
|
||
|
check_win_complete (win);
|
||
|
check_in_window (win);
|
||
|
ConsoleDebug (X11, "change_windows_manager: returning %d\n",
|
||
|
newman != oldman);
|
||
|
return (newman != oldman);
|
||
|
}
|
||
|
|
||
|
void check_in_window (WinData *win)
|
||
|
{
|
||
|
int in_viewport;
|
||
|
|
||
|
if (win->manager && win->complete &&
|
||
|
!(win->manager->usewinlist && (win->fvwm_flags & WINDOWLISTSKIP))) {
|
||
|
in_viewport = win_in_viewport (win);
|
||
|
if (win->button == NULL && in_viewport) {
|
||
|
insert_windows_button (win);
|
||
|
if (win->manager->window_up == 0 && globals.got_window_list)
|
||
|
create_manager_window (win->manager->index);
|
||
|
}
|
||
|
else if (win->button && !in_viewport) {
|
||
|
delete_windows_button (win);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void get_gcs (WinManager *man, int state, GC *context1, GC *context2)
|
||
|
{
|
||
|
switch (man->buttonState[state]) {
|
||
|
case BUTTON_FLAT:
|
||
|
*context1 = man->flatContext[state];
|
||
|
*context2 = man->flatContext[state];
|
||
|
break;
|
||
|
|
||
|
case BUTTON_UP:
|
||
|
case BUTTON_EDGEUP:
|
||
|
*context1 = man->reliefContext[state];
|
||
|
*context2 = man->shadowContext[state];
|
||
|
break;
|
||
|
|
||
|
case BUTTON_DOWN:
|
||
|
case BUTTON_EDGEDOWN:
|
||
|
*context1 = man->shadowContext[state];
|
||
|
*context2 = man->reliefContext[state];
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ConsoleMessage ("Internal error in draw_button\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void draw_relief (WinManager *man, int button_state, ButtonGeometry *g,
|
||
|
GC context1, GC context2)
|
||
|
{
|
||
|
int state;
|
||
|
state = man->buttonState[button_state];
|
||
|
|
||
|
if (state == BUTTON_EDGEUP || state == BUTTON_EDGEDOWN) {
|
||
|
draw_3d_square (man, g->button_x, g->button_y, g->button_w, g->button_h,
|
||
|
context1, context2);
|
||
|
draw_3d_square (man, g->button_x + 2, g->button_y + 2, g->button_w - 4,
|
||
|
g->button_h - 4, context2, context1);
|
||
|
}
|
||
|
else {
|
||
|
draw_3d_square (man, g->button_x, g->button_y, g->button_w, g->button_h,
|
||
|
context1, context2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void draw_button (WinManager *man, int button, int force)
|
||
|
{
|
||
|
Button *b;
|
||
|
WinData *win;
|
||
|
ButtonGeometry g, old_g;
|
||
|
GC context1, context2;
|
||
|
Contexts button_state;
|
||
|
int cleared_button = 0, dirty;
|
||
|
int draw_background = 0, draw_icon = 0, draw_string = 0, clear_old_pic = 0;
|
||
|
|
||
|
assert (man);
|
||
|
|
||
|
if (!man->window_up) {
|
||
|
ConsoleMessage ("draw_button: manager not up yet\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
b = man->buttons.buttons[button];
|
||
|
win = b->drawn_state.win;
|
||
|
dirty = b->drawn_state.dirty_flags;
|
||
|
|
||
|
if (win && win->button != b) {
|
||
|
ConsoleMessage ("Internal error in draw_button.\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!win) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (force || (dirty & REDRAW_BUTTON)) {
|
||
|
ConsoleDebug (X11, "draw_button: %d forced\n", b->index);
|
||
|
draw_background = 1;
|
||
|
draw_icon = 1;
|
||
|
draw_string = 1;
|
||
|
}
|
||
|
/* figure out what we have to draw */
|
||
|
if (dirty) {
|
||
|
ConsoleDebug (X11, "draw_button: %d dirty\n", b->index);
|
||
|
if (win) {
|
||
|
if (dirty & GEOMETRY_CHANGED) {
|
||
|
ConsoleDebug (X11, "\tGeometry changed\n");
|
||
|
/* Determine if geometry has changed relative to the
|
||
|
window gravity */
|
||
|
if (b->w != b->drawn_state.w || b->h != b->drawn_state.h ||
|
||
|
b->x - man->geometry.gravity_x !=
|
||
|
b->drawn_state.x - man->drawn_geometry.gravity_x ||
|
||
|
b->y - man->geometry.gravity_y !=
|
||
|
b->drawn_state.y - man->drawn_geometry.gravity_y) {
|
||
|
draw_background = 1;
|
||
|
draw_icon = 1;
|
||
|
draw_string = 1;
|
||
|
}
|
||
|
}
|
||
|
if (dirty & STATE_CHANGED) {
|
||
|
ConsoleDebug (X11, "\tState changed\n");
|
||
|
b->drawn_state.state = win->state;
|
||
|
draw_background = 1;
|
||
|
draw_icon = 1;
|
||
|
draw_string = 1;
|
||
|
}
|
||
|
#ifdef MINI_ICONS
|
||
|
if (dirty & PICTURE_CHANGED) {
|
||
|
ConsoleDebug (X11, "\tPicture changed\n");
|
||
|
get_button_geometry (man, b, &old_g);
|
||
|
b->drawn_state.pic = win->pic;
|
||
|
draw_icon = 1;
|
||
|
draw_string = 1;
|
||
|
clear_old_pic = 1;
|
||
|
}
|
||
|
#endif
|
||
|
if ((dirty & ICON_STATE_CHANGED) &&
|
||
|
b->drawn_state.iconified != win->iconified) {
|
||
|
ConsoleDebug (X11, "\tIcon changed\n");
|
||
|
b->drawn_state.iconified = win->iconified;
|
||
|
draw_icon = 1;
|
||
|
}
|
||
|
if (dirty & STRING_CHANGED) {
|
||
|
ConsoleDebug (X11, "\tString changed: %s\n", win->display_string);
|
||
|
b->drawn_state.display_string = win->display_string;
|
||
|
assert (b->drawn_state.display_string);
|
||
|
draw_string = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (win && (draw_background || draw_icon || draw_string)) {
|
||
|
get_button_geometry (man, b, &g);
|
||
|
ConsoleDebug (X11, "\tgeometry: %d %d %d %d\n", g.button_x, g.button_y,
|
||
|
g.button_w, g.button_h);
|
||
|
button_state = b->drawn_state.state;
|
||
|
if (draw_background) {
|
||
|
ConsoleDebug (X11, "\tDrawing background\n");
|
||
|
XFillRectangle (theDisplay, man->theWindow,
|
||
|
man->backContext[button_state], g.button_x,
|
||
|
g.button_y, g.button_w, g.button_h);
|
||
|
cleared_button = 1;
|
||
|
|
||
|
if (theDepth > 2) {
|
||
|
get_gcs (man, button_state, &context1, &context2);
|
||
|
draw_relief (man, button_state, &g, context1, context2);
|
||
|
}
|
||
|
else if (button_state & SELECT_CONTEXT) {
|
||
|
XDrawRectangle (theDisplay, man->theWindow,
|
||
|
man->hiContext[button_state],
|
||
|
g.button_x + 2, g.button_y + 1,
|
||
|
g.button_w - 4, g.button_h - 2);
|
||
|
}
|
||
|
}
|
||
|
if (clear_old_pic) {
|
||
|
ConsoleDebug (X11, "\tClearing old picture\n");
|
||
|
if (!cleared_button) {
|
||
|
XFillRectangle (theDisplay, man->theWindow,
|
||
|
man->backContext[PLAIN_CONTEXT],
|
||
|
old_g.icon_x, old_g.icon_y,
|
||
|
old_g.icon_w + 2, old_g.icon_h);
|
||
|
}
|
||
|
}
|
||
|
if (draw_icon) {
|
||
|
ConsoleDebug (X11, "\tDrawing icon\n");
|
||
|
iconify_box (man, win, button, &g, win->iconified, button_state,
|
||
|
cleared_button);
|
||
|
}
|
||
|
if (draw_string) {
|
||
|
ConsoleDebug (X11, "\tDrawing text: %s\n",
|
||
|
b->drawn_state.display_string);
|
||
|
ClipRectangle (man, button_state, g.text_x, g.text_y, g.text_w,
|
||
|
g.text_h);
|
||
|
if (!cleared_button) {
|
||
|
XFillRectangle (theDisplay, man->theWindow,
|
||
|
man->backContext[button_state],
|
||
|
g.text_x, g.text_y, g.text_w, g.text_h);
|
||
|
}
|
||
|
XDrawString (theDisplay, man->theWindow,
|
||
|
man->hiContext[button_state],
|
||
|
g.text_x, g.text_base, b->drawn_state.display_string,
|
||
|
strlen (b->drawn_state.display_string));
|
||
|
XSetClipMask (theDisplay, man->hiContext[button_state], None);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
b->drawn_state.dirty_flags = 0;
|
||
|
b->drawn_state.x = b->x;
|
||
|
b->drawn_state.y = b->y;
|
||
|
b->drawn_state.w = b->w;
|
||
|
b->drawn_state.h = b->h;
|
||
|
XFlush (theDisplay);
|
||
|
}
|
||
|
|
||
|
void draw_managers (void)
|
||
|
{
|
||
|
int i;
|
||
|
for (i = 0; i < globals.num_managers; i++)
|
||
|
draw_manager (&globals.managers[i]);
|
||
|
}
|
||
|
|
||
|
static void draw_empty_manager (WinManager *man)
|
||
|
{
|
||
|
GC context1, context2;
|
||
|
int state = TITLE_CONTEXT;
|
||
|
ButtonGeometry g;
|
||
|
|
||
|
ConsoleDebug (X11, "draw_empty_manager\n");
|
||
|
get_title_geometry (man, &g);
|
||
|
|
||
|
XFillRectangle (theDisplay, man->theWindow, man->backContext[state],
|
||
|
g.button_x, g.button_y, g.button_w, g.button_h);
|
||
|
if (theDepth > 2) {
|
||
|
get_gcs (man, state, &context1, &context2);
|
||
|
draw_relief (man, state, &g, context1, context2);
|
||
|
}
|
||
|
else {
|
||
|
}
|
||
|
ClipRectangle (man, state, g.text_x, g.text_y, g.text_w, g.text_h);
|
||
|
XDrawString (theDisplay, man->theWindow, man->hiContext[state],
|
||
|
g.text_x, g.text_base, man->titlename, strlen (man->titlename));
|
||
|
XSetClipMask (theDisplay, man->hiContext[state], None);
|
||
|
}
|
||
|
|
||
|
void draw_manager (WinManager *man)
|
||
|
{
|
||
|
int i, force_draw = 0, update_geometry = 0, redraw_all = 0;
|
||
|
int shape_changed = 0;
|
||
|
|
||
|
assert (man->buttons.num_buttons >= 0 && man->buttons.num_windows >= 0);
|
||
|
|
||
|
if (!man->window_up)
|
||
|
return;
|
||
|
|
||
|
ConsoleDebug (X11, "Drawing Manager: %s\n", man->titlename);
|
||
|
redraw_all = man->dirty_flags & REDRAW_MANAGER;
|
||
|
|
||
|
if (redraw_all || (man->buttons.dirty_flags & NUM_WINDOWS_CHANGED)) {
|
||
|
ConsoleDebug (X11, "\tresizing manager\n");
|
||
|
resize_manager (man, redraw_all);
|
||
|
clear_empty_region (man);
|
||
|
update_geometry = 1;
|
||
|
force_draw = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (redraw_all || (man->dirty_flags & MAPPING_CHANGED)) {
|
||
|
force_draw = 1;
|
||
|
ConsoleDebug (X11, "manager %s: mapping changed\n", man->titlename);
|
||
|
}
|
||
|
#ifdef SHAPE
|
||
|
|
||
|
if (man->shaped && (redraw_all || (man->dirty_flags & SHAPE_CHANGED) )){
|
||
|
/* This little piggie waits until past resize requests get processed */
|
||
|
XSync (theDisplay, False);
|
||
|
XShapeCombineRectangles (theDisplay, man->theWindow, ShapeBounding,
|
||
|
0, 0, man->shape.rects, man->shape.num_rects,
|
||
|
ShapeSet, Unsorted);
|
||
|
XShapeCombineRectangles (theDisplay, man->theWindow, ShapeClip,
|
||
|
0, 0, man->shape.rects, man->shape.num_rects,
|
||
|
ShapeSet, Unsorted);
|
||
|
shape_changed = 1;
|
||
|
update_geometry = 1;
|
||
|
/* And this little piggie waits for shape to get processed before
|
||
|
drawing buttons */
|
||
|
XSync (theDisplay, False);
|
||
|
}
|
||
|
#endif
|
||
|
if (redraw_all || (man->dirty_flags & GEOMETRY_CHANGED)) {
|
||
|
ConsoleDebug (X11, "\tredrawing all buttons\n");
|
||
|
update_geometry = 1;
|
||
|
}
|
||
|
|
||
|
if (update_geometry) {
|
||
|
for (i = 0; i < man->buttons.num_windows; i++)
|
||
|
set_button_geometry (man, man->buttons.buttons[i]);
|
||
|
}
|
||
|
|
||
|
man->dirty_flags = 0;
|
||
|
man->buttons.dirty_flags = 0;
|
||
|
man->buttons.drawn_num_buttons = man->buttons.num_buttons;
|
||
|
man->buttons.drawn_num_windows = man->buttons.num_windows;
|
||
|
|
||
|
if (man->buttons.num_windows == 0) {
|
||
|
if (force_draw)
|
||
|
draw_empty_manager (man);
|
||
|
}
|
||
|
else {
|
||
|
/* I was having the problem where when the shape changed the manager
|
||
|
wouldn't get redrawn. It appears we weren't getting the expose.
|
||
|
How can I tell when I am going to reliably get an expose event? */
|
||
|
|
||
|
if (1 || !shape_changed) {
|
||
|
/* if shape changed, we'll catch it on the expose */
|
||
|
for (i = 0; i < man->buttons.num_buttons; i++) {
|
||
|
draw_button (man, i, force_draw);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
man->drawn_geometry = man->geometry;
|
||
|
XFlush (theDisplay);
|
||
|
}
|
||
|
|
||
|
|
||
|
static int compare_windows(SortType type, WinData *a, WinData *b)
|
||
|
{
|
||
|
if (type == SortId) {
|
||
|
return a->app_id - b->app_id;
|
||
|
}
|
||
|
else if (type == SortName) {
|
||
|
return strcasecmp (a->display_string, b->display_string);
|
||
|
}
|
||
|
else if (type == SortNameCase) {
|
||
|
return strcmp (a->display_string, b->display_string);
|
||
|
}
|
||
|
else {
|
||
|
ConsoleMessage ("Internal error in compare_windows\n");
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* find_windows_spot: returns index of button to stick the window in.
|
||
|
* checks win->button to see if it's already in manager.
|
||
|
* if it isn't, then gives spot at which it should be,
|
||
|
* if it were.
|
||
|
*/
|
||
|
|
||
|
static int find_windows_spot (WinData *win)
|
||
|
{
|
||
|
WinManager *man = win->manager;
|
||
|
int num_windows = man->buttons.num_windows;
|
||
|
|
||
|
if (man->sort != SortNone) {
|
||
|
int i, cur, start, finish, cmp_dir, correction;
|
||
|
Button **bp;
|
||
|
|
||
|
bp = man->buttons.buttons;
|
||
|
if (win->button) {
|
||
|
/* start search from our current location */
|
||
|
cur = win->button->index;
|
||
|
|
||
|
if (cur - 1 >= 0 &&
|
||
|
compare_windows (man->sort,
|
||
|
win, bp[cur - 1]->drawn_state.win) < 0) {
|
||
|
start = cur - 1;
|
||
|
finish = -1;
|
||
|
cmp_dir = -1;
|
||
|
correction = 1;
|
||
|
}
|
||
|
else if (cur < num_windows - 1 &&
|
||
|
compare_windows (man->sort,
|
||
|
win, bp[cur + 1]->drawn_state.win) > 0) {
|
||
|
start = cur + 1;
|
||
|
finish = num_windows;
|
||
|
cmp_dir = 1;
|
||
|
correction = -1;
|
||
|
}
|
||
|
else {
|
||
|
return cur;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
start = 0;
|
||
|
finish = num_windows;
|
||
|
cmp_dir = 1;
|
||
|
correction = 0;
|
||
|
}
|
||
|
for (i = start; i != finish && bp[i]->drawn_state.win && cmp_dir *
|
||
|
compare_windows (man->sort, win, bp[i]->drawn_state.win) > 0;
|
||
|
i = i + cmp_dir)
|
||
|
;
|
||
|
i += correction;
|
||
|
ConsoleDebug (X11, "find_windows_spot: %s %d\n", win->display_string, i);
|
||
|
return i;
|
||
|
}
|
||
|
else {
|
||
|
if (win->button) {
|
||
|
/* already have a perfectly fine spot */
|
||
|
return win->button->index;
|
||
|
}
|
||
|
else {
|
||
|
return num_windows;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* shouldn't get here */
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
static void move_window_buttons (WinManager *man, int start, int finish,
|
||
|
int offset)
|
||
|
{
|
||
|
int n = man->buttons.num_buttons, i;
|
||
|
Button **bp;
|
||
|
|
||
|
ConsoleDebug (X11, "move_window_buttons: %s(%d): (%d, %d) + %d\n",
|
||
|
man->titlename, n, start, finish, offset);
|
||
|
|
||
|
if (finish >= n || finish + offset >= n || start < 0 || start + offset < 0) {
|
||
|
ConsoleMessage ("Internal error in move_window_buttons\n");
|
||
|
ConsoleMessage ("\tn = %d, start = %d, finish = %d, offset = %d\n",
|
||
|
n, start, finish, offset);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bp = man->buttons.buttons;
|
||
|
|
||
|
if (offset > 0) {
|
||
|
for (i = finish; i >= start; i--) {
|
||
|
if (bp[i]->drawn_state.win)
|
||
|
bp[i]->drawn_state.win->button = bp[i + offset];
|
||
|
bp[i + offset]->drawn_state = bp[i]->drawn_state;
|
||
|
bp[i + offset]->drawn_state.dirty_flags = ALL_CHANGED;
|
||
|
}
|
||
|
}
|
||
|
else if (offset < 0) {
|
||
|
for (i = start; i <= finish; i++) {
|
||
|
if (bp[i]->drawn_state.win)
|
||
|
bp[i]->drawn_state.win->button = bp[i + offset];
|
||
|
bp[i + offset]->drawn_state = bp[i]->drawn_state;
|
||
|
bp[i + offset]->drawn_state.dirty_flags = ALL_CHANGED;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void insert_windows_button (WinData *win)
|
||
|
{
|
||
|
int spot;
|
||
|
int selected_index = -1;
|
||
|
WinManager *man = win->manager;
|
||
|
ButtonArray *buttons;
|
||
|
|
||
|
ConsoleDebug (X11, "insert_windows_button: %s\n", win->titlename);
|
||
|
|
||
|
assert (man);
|
||
|
selected_index = selected_button_in_man (man);
|
||
|
|
||
|
if (win->button) {
|
||
|
ConsoleDebug (X11, "insert_windows_button: POSSIBLE BUG: "
|
||
|
"already have a button\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!win || !win->complete || !man) {
|
||
|
ConsoleMessage ("Internal error in insert_windows_button\n");
|
||
|
ShutMeDown (1);
|
||
|
}
|
||
|
|
||
|
buttons = &man->buttons;
|
||
|
|
||
|
spot = find_windows_spot (win);
|
||
|
|
||
|
increase_num_windows (buttons, 1);
|
||
|
move_window_buttons (man, spot, buttons->num_windows - 2, 1);
|
||
|
|
||
|
set_window_button (win, spot);
|
||
|
if (selected_index >= 0) {
|
||
|
ConsoleDebug (X11, "insert_windows_button: selected_index = %d, moving\n",
|
||
|
selected_index);
|
||
|
move_highlight (man, man->buttons.buttons[selected_index]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void delete_windows_button (WinData *win)
|
||
|
{
|
||
|
int spot;
|
||
|
int selected_index = -1;
|
||
|
WinManager *man = (win->manager);
|
||
|
ButtonArray *buttons;
|
||
|
|
||
|
ConsoleDebug (X11, "delete_windows_button: %s\n", win->titlename);
|
||
|
|
||
|
assert (man);
|
||
|
|
||
|
buttons = &win->manager->buttons;
|
||
|
|
||
|
assert (win->button);
|
||
|
assert (buttons->buttons);
|
||
|
|
||
|
selected_index = selected_button_in_man (man);
|
||
|
ConsoleDebug (X11, "delete_windows_button: selected_index = %d\n",
|
||
|
selected_index);
|
||
|
|
||
|
spot = win->button->index;
|
||
|
|
||
|
move_window_buttons (win->manager, spot + 1, buttons->num_windows - 1, -1);
|
||
|
clear_button (buttons->buttons[buttons->num_windows - 1]);
|
||
|
increase_num_windows (buttons, -1);
|
||
|
win->button = NULL;
|
||
|
if (globals.focus_win == win) {
|
||
|
globals.focus_win = NULL;
|
||
|
}
|
||
|
if (selected_index >= 0) {
|
||
|
ConsoleDebug (X11, "delete_windows_button: selected_index = %d, moving\n",
|
||
|
selected_index);
|
||
|
move_highlight (man, man->buttons.buttons[selected_index]);
|
||
|
}
|
||
|
win->state = 0;
|
||
|
}
|
||
|
|
||
|
void resort_windows_button (WinData *win)
|
||
|
{
|
||
|
int new_spot, cur_spot;
|
||
|
int selected_index = -1;
|
||
|
WinManager *man = win->manager;
|
||
|
|
||
|
assert (win->button && man);
|
||
|
|
||
|
ConsoleDebug (X11, "In resort_windows_button: %s\n", win->resname);
|
||
|
|
||
|
selected_index = selected_button_in_man (man);
|
||
|
|
||
|
new_spot = find_windows_spot (win);
|
||
|
cur_spot = win->button->index;
|
||
|
|
||
|
print_button_info (win->button);
|
||
|
|
||
|
if (new_spot != cur_spot) {
|
||
|
ConsoleDebug (X11, "resort_windows_button: win moves from %d to %d\n",
|
||
|
cur_spot, new_spot);
|
||
|
if (new_spot < cur_spot) {
|
||
|
move_window_buttons (man, new_spot, cur_spot - 1, +1);
|
||
|
}
|
||
|
else {
|
||
|
move_window_buttons (man, cur_spot + 1, new_spot, -1);
|
||
|
}
|
||
|
set_window_button (win, new_spot);
|
||
|
|
||
|
if (selected_index >= 0) {
|
||
|
move_highlight (man, man->buttons.buttons[selected_index]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void move_highlight (WinManager *man, Button *b)
|
||
|
{
|
||
|
WinData *old;
|
||
|
|
||
|
assert (man);
|
||
|
|
||
|
ConsoleDebug (X11, "move_highlight\n");
|
||
|
|
||
|
old = globals.select_win;
|
||
|
|
||
|
if (old && old->button) {
|
||
|
del_win_state (old, SELECT_CONTEXT);
|
||
|
old->manager->select_button = NULL;
|
||
|
draw_button (old->manager, old->button->index, 0);
|
||
|
}
|
||
|
if (b && b->drawn_state.win) {
|
||
|
add_win_state (b->drawn_state.win, SELECT_CONTEXT);
|
||
|
draw_button (man, b->index, 0);
|
||
|
globals.select_win = b->drawn_state.win;
|
||
|
}
|
||
|
else {
|
||
|
globals.select_win = NULL;
|
||
|
}
|
||
|
|
||
|
man->select_button = b;
|
||
|
}
|
||
|
|
||
|
void man_exposed (WinManager *man, XEvent *theEvent)
|
||
|
{
|
||
|
int x1, y1, w1, h1;
|
||
|
int x2, y2, w2, h2;
|
||
|
int i;
|
||
|
Button **bp;
|
||
|
|
||
|
ConsoleDebug (X11, "manager: %s, got expose\n", man->titlename);
|
||
|
|
||
|
x1 = theEvent->xexpose.x;
|
||
|
y1 = theEvent->xexpose.y;
|
||
|
w1 = theEvent->xexpose.width;
|
||
|
h1 = theEvent->xexpose.height;
|
||
|
|
||
|
w2 = man->geometry.boxwidth;
|
||
|
h2 = man->geometry.boxheight;
|
||
|
|
||
|
bp = man->buttons.buttons;
|
||
|
|
||
|
#ifdef SHAPE
|
||
|
/* There's some weird problem where if we change window shapes, we can't
|
||
|
draw into buttons in the area NewShape intersect (not OldShape) until
|
||
|
we get our Expose event. So, for now, just redraw everything when we
|
||
|
get Expose events. This has the disadvantage of drawing buttons twice,
|
||
|
but avoids having to match which expose event results from which shape
|
||
|
change */
|
||
|
|
||
|
if (man->buttons.num_windows) {
|
||
|
for (i = 0; i < man->buttons.num_windows; i++) {
|
||
|
bp[i]->drawn_state.dirty_flags |= REDRAW_BUTTON;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
draw_empty_manager (man);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
if (man->buttons.num_windows) {
|
||
|
for (i = 0; i < man->buttons.num_windows; i++) {
|
||
|
x2 = index_to_col (man, i) * w2;
|
||
|
y2 = index_to_row (man, i) * h2;
|
||
|
if (RECTANGLES_INTERSECT (x1, y1, w1, h1, x2, y2, w2, h2)) {
|
||
|
bp[i]->drawn_state.dirty_flags |= REDRAW_BUTTON;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
draw_empty_manager (man);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/***************************************************************************/
|
||
|
/* Debugging routines */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
void check_managers_consistency (void)
|
||
|
{
|
||
|
#ifdef PRINT_DEBUG
|
||
|
int i, j;
|
||
|
Button **b;
|
||
|
|
||
|
for (i = 0; i < globals.num_managers; i++) {
|
||
|
for (j = 0, b = globals.managers[i].buttons.buttons;
|
||
|
j < globals.managers[i].buttons.num_buttons; j++, b++) {
|
||
|
if ((*b)->drawn_state.win && (*b)->drawn_state.win->button != *b) {
|
||
|
ConsoleMessage ("manager %d, button %d is confused\n", i, j);
|
||
|
abort ();
|
||
|
}
|
||
|
else if ((*b)->drawn_state.win &&
|
||
|
j >= globals.managers[i].buttons.num_windows) {
|
||
|
ConsoleMessage ("manager %d: button %d has window and shouldn't\n",
|
||
|
i, j);
|
||
|
abort ();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void print_button_info (Button *b)
|
||
|
{
|
||
|
#ifdef PRINT_DEBUG
|
||
|
ConsoleMessage ("button: %d\n", b->index);
|
||
|
ConsoleMessage ("win: 0x%x\n", b->drawn_state.win);
|
||
|
ConsoleMessage ("dirty: 0x%x\n", b->drawn_state.dirty_flags);
|
||
|
if (b->drawn_state.win) {
|
||
|
ConsoleMessage ("name: %s\n", b->drawn_state.display_string);
|
||
|
ConsoleMessage ("iconified: %d state %d\n", b->drawn_state.iconified,
|
||
|
b->drawn_state.state);
|
||
|
ConsoleMessage ("win->button: 0x%x\n", b->drawn_state.win->button);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifdef PRINT_DEBUG
|
||
|
static void print_buttons (WinManager *man)
|
||
|
{
|
||
|
int i;
|
||
|
Button *b;
|
||
|
|
||
|
ConsoleMessage ("Buttons for manager: %s\n", man->titlename);
|
||
|
|
||
|
for (i = 0; i < man->buttons.num_buttons; i++) {
|
||
|
b = man->buttons.buttons[i];
|
||
|
ConsoleMessage ("Button: %d, index = %d\n", i, b->index);
|
||
|
ConsoleMessage ("\tdirty flags: 0x%x\n", b->drawn_state.dirty_flags);
|
||
|
ConsoleMessage ("\twin: 0x%x\n", b->drawn_state.win);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|