siemens-rtl/drawwin.c
2023-07-11 14:40:13 +02:00

758 lines
17 KiB
C

#ifndef lint
static char sccs_id[] = "%W% %H%";
#endif
/*
* Copyright 1988 by Siemens Research and Technology Laboratories, Princeton, NJ
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Siemens Research and Technology
* Laboratories not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
*
*
* SIEMENS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
* SIEMENS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include "copyright.h"
/* The Drawwin package manages Decorated client-windows
*/
#include "basetype.h"
#include "userglobD.h"
#include "uwinD.h"
#include "uwinXD.h"
#include "assoc.h"
#include "draw.h"
#include "control.h"
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "xio.h"
extern void
Drawwin_Config_Borders(), Drawwin_Draw_Borders(), Drawwin_Remove_Borders(),
Drawwin_Config_Header(), Drawwin_Draw_Header(), Drawwin_Remove_Header(),
Drawwin_Config_Gadgets(), Drawwin_Draw_Gadgets(), Drawwin_Remove_Gadgets();
extern GC
fillGC, clearGC, xorGC, invert_body_GC;
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
void Drawwin_Flash()
{
Draw_Flash();
}
/* ------------------------------------------------------------ */
/* Free all subwindows and parent of original Decorated client window
*/
void
Drawwin_Destroy(uwinp)
Userwin *uwinp;
{
Assoc_RemoveDecorations(uwinp);
Control_Destroy(uwinp);
XDestroySubwindows(dpy, Userwin_XParentWin(uwinp));
XDestroyWindow(dpy, Userwin_XParentWin(uwinp));
}
/* ------------------------------------------------------------ */
/*ARGSUSED*/
void
Drawwin_Draw_Background( rect )
TWRectangle rect;
{
/* Sun-version function */
}
/* ------------------------------------------------------------ */
bool
Drawwin_Redraw_All( rect )
TWRectangle rect;
{
Draw_Background_Rectangle(rect.left_x, rect.top_y,
rect.right_x, rect.bottom_y);
return TRUE;
}
/* ------------------------------------------------------------ */
/* Create the Decorated Window.
*/
void
Drawwin_Create(uwinp)
Userwin *uwinp;
{
Draw_Create(uwinp);
}
/* ------------------------------------------------------------ */
/* Start Drawwing.
*/
void
Drawwin_Start()
{
}
/* ------------------------------------------------------------ */
/* Finish Drawwing.
*/
void
Drawwin_Finish()
{
XFlush(dpy);
}
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
void
Drawwin_Display_Focus( uwinp )
Userwin *uwinp;
{
int width, height; /* parent window's dimensions */
TWRectangle rect;
rect = Userwin_Get_Rectangle(uwinp);
width = rect.right_x - rect.left_x + 1;
height = rect.bottom_y - rect.top_y + 1;
if ( UserGlobals_Get_Option(SHOW_FOCUS_IN_BORDERS) )
{
if (Userwin_Get_Window_Option( uwinp, USE_BORDERS ) )
Drawwin_Draw_Borders(uwinp, width, height);
}
if ( UserGlobals_Get_Option(SHOW_FOCUS_IN_HEADER) )
{
if (Userwin_Get_Window_Option( uwinp, USE_HEADER ) )
Drawwin_Draw_Header(uwinp, width, height);
}
}
/* ------------------------------------------------------------ */
void
Drawwin_Retitle(uwinp)
Userwin *uwinp;
{
TWRectangle rect;
rect = Userwin_Get_Rectangle(uwinp);
Drawwin_Draw_Header(uwinp,
rect.right_x - rect.left_x + 1,
rect.bottom_y - rect.top_y + 1);
}
/* ------------------------------------------------------------ */
/* re-configure the dimensions of the X windows composing the
* Decorated Client window (and draw the D.C. window decorations)
*/
void
Drawwin_Display_Wrapping(uwinp)
Userwin *uwinp;
{
int width, height; /* parent window's dimensions */
TWRectangle tw_rect;
tw_rect = Userwin_Get_Rectangle(uwinp);
width = tw_rect.right_x - tw_rect.left_x + 1;
height = tw_rect.bottom_y - tw_rect.top_y + 1;
if (Userwin_Get_Window_Option( uwinp, USE_BORDERS ))
{
Drawwin_Draw_Borders(uwinp, width, height);
}
if (Userwin_Get_Window_Option( uwinp, USE_HEADER ))
{
Drawwin_Draw_Header(uwinp, width, height);
if (Userwin_Get_Window_Option( uwinp, USE_GADGETS ))
{
Drawwin_Draw_Gadgets(uwinp, width, height);
}
}
}
/* Setup the dimensions of the Decorated Window.
*/
static void
Drawwin_Config_Wrapping(uwinp)
Userwin *uwinp;
{
int left_x, top_y;
int width, height, /* parent window's dimensions */
cwidth, cheight; /* client window's dimensions */
TWRectangle tw_rect;
tw_rect = Userwin_Get_Rectangle(uwinp);
left_x = top_y = 0;
cwidth = width = tw_rect.right_x - tw_rect.left_x + 1;
cheight = height = tw_rect.bottom_y - tw_rect.top_y + 1;
if (Userwin_Get_Window_Option( uwinp, USE_BORDERS ))
{
Drawwin_Config_Borders(uwinp, width, height);
left_x += BORDER_SIZE_VAL;
top_y += BORDER_SIZE_VAL;
cwidth -= (2 * BORDER_SIZE_VAL);
cheight -= (2 * BORDER_SIZE_VAL);
}
else
{
Drawwin_Remove_Borders(uwinp);
}
if (Userwin_Get_Window_Option( uwinp, USE_HEADER ))
{
Drawwin_Config_Header(uwinp, width, height);
top_y += (uwinp->header_height + INNER_BORDER_LINEWIDTH_VAL);
cheight -= (uwinp->header_height + INNER_BORDER_LINEWIDTH_VAL);
if (Userwin_Get_Window_Option( uwinp, USE_GADGETS ))
{
Drawwin_Config_Gadgets(uwinp, width, height);
}
else
{
Drawwin_Remove_Gadgets(uwinp);
}
}
else
{
Drawwin_Remove_Gadgets(uwinp);
Drawwin_Remove_Header(uwinp);
}
Draw_ConfigWin(Userwin_XClient(uwinp),
left_x, top_y,
cwidth, cheight);
Draw_ConfigWin(Userwin_XParentWin(uwinp),
tw_rect.left_x, tw_rect.top_y,
width, height);
}
/* Get client position and size relative to its Parent.
* Useful when an annoying client tries to Re-parent itself
* back to the root window!
*
* Code borrowed from Drawwin_Config_Wrapping().
*/
int
Drawwin_Client_Position(uwinp, px, py, pwd, pht)
Userwin *uwinp;
int *px, *py; /* these are all Returned */
unsigned int *pwd, *pht;
{
TWRectangle rect;
rect = Userwin_Get_Rectangle(uwinp);
*pwd = rect.right_x - rect.left_x + 1;
*pht = rect.bottom_y - rect.top_y + 1;
*px = *py = 0;
if (Userwin_Get_Window_Option( uwinp, USE_BORDERS ))
{
*px += BORDER_SIZE_VAL;
*py += BORDER_SIZE_VAL;
}
if (Userwin_Get_Window_Option( uwinp, USE_HEADER ))
{
*py += (uwinp->header_height + INNER_BORDER_LINEWIDTH_VAL);
}
}
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
/* Unmap the Decorated Win if its size changed on the Move
* Operation.
*/
/*ARGSUSED*/
void Drawwin_Move_Close( uwinp, clear )
Userwin *uwinp;
bool clear;
{
/* make it work with X -- always unmap */
/* --- removed for efficiency, and to make focus --- */
/* work correctly */
/* XUnmapWindow(dpy, Userwin_XParentWin(uwinp)); */
}
/* ------------------------------------------------------------ */
void Drawwin_Listener_Move_Close( uwinp, clear )
Userwin *uwinp;
bool clear;
{
int grab_result;
unsigned int ev_mask = PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
grab_result = XGrabPointer(dpy, root, False, ev_mask,
GrabModeAsync, GrabModeAsync,
Userwin_XClient(uwinp), (Cursor) None,
CurrentTime);
Drawwin_Move_Close( uwinp, clear );
}
/* ------------------------------------------------------------ */
/* Redraw the Decorated Window on completion of the Move
* Operation. If the DW's size is unchanged, reconfigure
* PARENT window only, and Notify the client of the Move.
*/
void Drawwin_Move_Open( uwinp )
Userwin *uwinp;
{
TWRectangle window_rect;
int new_x, new_y;
/* find the x-y position for the window */
window_rect = Userwin_Get_Rectangle(uwinp);
new_x = Get_LeftX(window_rect);
new_y = Get_TopY(window_rect);
if ( Userwin_Size_Changed(uwinp) == FALSE )
{
/* Just move it w/o resize */
XMoveWindow(dpy, Userwin_XParentWin(uwinp), new_x, new_y);
}
else
{
Drawwin_Config_Wrapping(uwinp);
}
/* send WM_MOVED message --- needs to be added here */
/* ensure remap of Client when its Icon is Closed...
mike says --- ??????
*/
/* XMapWindow(dpy, Userwin_XParentWin(uwinp)); */
}
/* ------------------------------------------------------------ */
void Drawwin_Listener_Move_Open( uwinp )
Userwin *uwinp;
{
Drawwin_Move_Open( uwinp );
XUngrabPointer(dpy, CurrentTime);
}
/* ------------------------------------------------------------ */
/* Finish Close operation
*/
void Drawwin_Unmap(uwinp)
Userwin *uwinp;
{
XUnmapSubwindows(dpy, Userwin_XParentWin(uwinp));
XUnmapWindow(dpy, Userwin_XParentWin(uwinp));
}
/* ------------------------------------------------------------ */
/* Begin Close operation -
*
* if Window will be covered by other Windows when it's un-mapped,
* then it's not "in the clear" (will cause flashing), so Lower it.
*/
/*ARGSUSED*/
void
Drawwin_Close(uwinp, clear)
Userwin *uwinp;
bool clear;
{
XLowerWindow(dpy, Userwin_XParentWin(uwinp));
}
/* ------------------------------------------------------------ */
void Drawwin_Open( uwinp )
Userwin *uwinp;
{
Drawwin_Config_Wrapping(uwinp);
}
/* ------------------------------------------------------------ */
/* ARGSUSED */
void Drawwin_Draw( uwinp )
Userwin *uwinp;
{
}
/* ------------------------------------------------------------ */
/* This is the only place where X Expose events aren't there
* to make the x-client redraw its window.
*/
void Drawwin_Redraw( uwinp )
Userwin *uwinp;
{
TWRectangle rect;
rect = Userwin_Get_Rectangle(uwinp);
Draw_Background_Rectangle(rect.left_x, rect.top_y,
rect.right_x, rect.bottom_y);
}
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
/* Invert Client Window's image, upon a Move Operation
*/
void Drawwin_Show_Moving( uwinp )
Userwin *uwinp;
{
Size window_size;
window_size = Userwin_Get_Size(uwinp);
XFillRectangle(dpy, (Drawable) Userwin_XParentWin(uwinp), invert_body_GC,
0, 0, window_size.width, window_size.height);
}
/* ------------------------------------------------------------ */
/* Revert Client Window's image to "standard" color - Move
* Operation was completed or cancelled.
*/
void Drawwin_Unshow_Moving( uwinp )
Userwin *uwinp;
{
Drawwin_Show_Moving( uwinp );
}
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
static int old_x0, old_y0, old_x1, old_y1;
int
Drawwin_Draw_Box(x0, y0, x1, y1, draw_x)
int x0, y0, x1, y1;
bool draw_x;
{
XPoint points[8];
XPoint *pt = points;
pt -> x = x0;
pt++ -> y = y0;
pt -> x = x1; /* Box - top side */
pt++ -> y = y0;
pt -> x = x1; /* right side */
pt++ -> y = y1;
pt -> x = x0; /* bottom side */
pt++ -> y = y1;
pt -> x = x0; /* left side */
pt++ -> y = y0;
if (draw_x == TRUE) /* should we draw cross-hatch (X)? */
{
pt -> x = x1;
pt++ -> y = y1;
pt -> x = x0;
pt++ -> y = y1;
pt -> x = x1;
pt++ -> y = y0;
}
XDrawLines(dpy, root, xorGC, points, pt - points, CoordModeOrigin);
pt = points; /* "double" the left, bottom and right sides */
pt -> x = x0 + 1;
pt++ -> y = y0 + 1;
pt -> x = x1 - 1; /* Box - top side */
pt++ -> y = y0 + 1;
pt -> x = x1 - 1; /* right side */
pt++ -> y = y1 - 1;
pt -> x = x0 + 1; /* bottom side */
pt++ -> y = y1 - 1;
pt -> x = x0 + 1; /* left side */
pt++ -> y = y0 + 1;
XDrawLines(dpy, root, xorGC, points, pt - points, CoordModeOrigin);
}
void Drawwin_Good_Open_Box( start_pos, pos )
TWPoint start_pos;
TWPoint pos;
{
old_x0 = start_pos.x;
old_y0 = start_pos.y;
old_x1 = pos.x;
old_y1 = pos.y;
Drawwin_Draw_Box( old_x0, old_y0, old_x1, old_y1,
UserGlobals_Get_Option(DRAW_X_ON_OPEN) );
}
/* ------------------------------------------------------------ */
void Drawwin_Bad_Open_Box( start_pos, pos )
TWPoint start_pos;
TWPoint pos;
{
Drawwin_Good_Open_Box(start_pos, pos);
}
/* ------------------------------------------------------------ */
void Drawwin_Undo_Open_Box()
{
Drawwin_Draw_Box( old_x0, old_y0, old_x1, old_y1,
UserGlobals_Get_Option(DRAW_X_ON_OPEN) );
}
/* ============================================================ */
static void Drawwin_Calc_Move_Rect( pos, siz )
TWPoint pos;
Size siz;
{
int xdif, ydif;
xdif = siz.width/2;
ydif = siz.height/2;
old_x0 = pos.x - xdif + 1;
old_y0 = pos.y - ydif + 1;
old_x1 = pos.x + xdif;
old_y1 = pos.y + ydif;
}
/* ------------------------------------------------------------ */
/*ARGSUSED*/
void Drawwin_Good_Move_Box( uwinp, pos, siz )
Userwin *uwinp;
TWPoint pos;
Size siz;
{
Drawwin_Calc_Move_Rect(pos, siz);
Drawwin_Draw_Box( old_x0, old_y0, old_x1, old_y1,
UserGlobals_Get_Option(DRAW_X_ON_MOVE) );
}
/* ------------------------------------------------------------ */
void Drawwin_Bad_Move_Box( uwinp, pos, siz )
Userwin *uwinp;
TWPoint pos;
Size siz;
{
Drawwin_Good_Move_Box(uwinp, pos, siz);
}
/* ------------------------------------------------------------ */
void Drawwin_Undo_Move_Box()
{
Drawwin_Draw_Box( old_x0, old_y0, old_x1, old_y1,
UserGlobals_Get_Option(DRAW_X_ON_MOVE) );
}
/* ============================================================ */
static void Drawwin_Calc_Edge_Resize( uwinp, side, pos )
Userwin *uwinp;
Side side;
TWPoint pos;
{
old_x0 = Userwin_Get_Rectangle(uwinp).left_x;
old_y0 = Userwin_Get_Rectangle(uwinp).top_y;
old_x1 = Userwin_Get_Rectangle(uwinp).right_x;
old_y1 = Userwin_Get_Rectangle(uwinp).bottom_y;
switch(side)
{
case Left:
old_x0 = pos.x;
break;
case Top:
old_y0 = pos.y;
break;
case Right:
old_x1 = pos.x;
break;
case Bottom:
old_y1 = pos.y;
break;
}
}
/* ------------------------------------------------------------ */
/*ARGSUSED*/
void Drawwin_Edge_Resize( uwinp, side, pos )
Userwin *uwinp;
Side side;
TWPoint pos;
{
Drawwin_Calc_Edge_Resize( uwinp, side, pos );
Drawwin_Draw_Box( old_x0, old_y0, old_x1, old_y1,
UserGlobals_Get_Option(DRAW_X_ON_RESIZE) );
}
/* ------------------------------------------------------------ */
void Drawwin_Undo_Edge_Resize()
{
Drawwin_Draw_Box( old_x0, old_y0, old_x1, old_y1,
UserGlobals_Get_Option(DRAW_X_ON_RESIZE) );
}
/* ============================================================ */
static void Drawwin_Calc_Corner_Resize( uwinp, side, pos )
Userwin *uwinp;
Side side;
TWPoint pos;
{
old_x0 = Userwin_Get_Rectangle(uwinp).left_x;
old_y0 = Userwin_Get_Rectangle(uwinp).top_y;
old_x1 = Userwin_Get_Rectangle(uwinp).right_x;
old_y1 = Userwin_Get_Rectangle(uwinp).bottom_y;
switch(side)
{
case Top_Left:
old_x0 = pos.x;
old_y0 = pos.y;
break;
case Bottom_Left:
old_x0 = pos.x;
old_y1 = pos.y;
break;
case Top_Right:
old_x1 = pos.x;
old_y0 = pos.y;
break;
case Bottom_Right:
old_x1 = pos.x;
old_y1 = pos.y;
break;
}
}
/* ------------------------------------------------------------ */
/*ARGSUSED*/
void Drawwin_Corner_Resize( uwinp, side, pos )
Userwin *uwinp;
Side side;
TWPoint pos;
{
Drawwin_Calc_Corner_Resize(uwinp, side, pos);
Drawwin_Draw_Box( old_x0, old_y0, old_x1, old_y1,
UserGlobals_Get_Option(DRAW_X_ON_RESIZE) );
}
/* ------------------------------------------------------------ */
void Drawwin_Undo_Corner_Resize()
{
Drawwin_Draw_Box( old_x0, old_y0, old_x1, old_y1,
UserGlobals_Get_Option(DRAW_X_ON_RESIZE) );
}
void Drawwin_Insert(uwinp)
Userwin *uwinp;
{
XChangeSaveSet(dpy, Userwin_XClient(uwinp), SetModeInsert);
XReparentWindow(dpy, Userwin_XClient(uwinp),
Userwin_XParentWin(uwinp), 0, 0);
}
void Drawwin_Withdraw(uwinp)
Userwin *uwinp;
{
XChangeSaveSet(dpy, Userwin_XClient(uwinp), SetModeDelete);
XReparentWindow(dpy, Userwin_XClient(uwinp),
RootWindow(dpy, scrn), 0, 0);
}
void Drawwin_Prepare(uwinp)
Userwin *uwinp;
{
}