Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Various operations done on windows.
      3  */
      4 
      5 #include "ctwm.h"
      6 
      7 #include <stdio.h>
      8 
      9 #include "animate.h"
     10 #include "colormaps.h"
     11 #include "drawing.h"
     12 #include "events.h"
     13 #include "iconmgr.h"
     14 #include "image.h"
     15 #include "otp.h"
     16 #include "screen.h"
     17 #include "win_decorations.h"
     18 #include "win_iconify.h"
     19 #include "win_ops.h"
     20 #include "win_utils.h"
     21 
     22 
     23 /*
     24  * Update the visuals of a window (e.g., its own decorations and its
     25  * representation in the icon manager) for having/losing focus.
     26  *
     27  * Formerly in util.c
     28  */
     29 void
     30 SetFocusVisualAttributes(TwmWindow *tmp_win, bool focus)
     31 {
     32 	if(! tmp_win) {
     33 		return;
     34 	}
     35 
     36 	if(focus == tmp_win->hasfocusvisible) {
     37 		return;
     38 	}
     39 	if(tmp_win->highlight) {
     40 		if(Scr->use3Dborders) {
     41 			PaintBorders(tmp_win, focus);
     42 		}
     43 		else {
     44 			if(focus) {
     45 				XSetWindowBorder(dpy, tmp_win->frame, tmp_win->borderC.back);
     46 				if(tmp_win->title_w) {
     47 					XSetWindowBorder(dpy, tmp_win->title_w, tmp_win->borderC.back);
     48 				}
     49 			}
     50 			else {
     51 				/*
     52 				 * XXX It seems possible this could be replaced by a
     53 				 * single global 'gray' pixmap; I don't think it actually
     54 				 * varies per window, and I don't see any obvious reason
     55 				 * it can't be reused, so we may be able to save an
     56 				 * allocation for each window by doing so...
     57 				 */
     58 				XSetWindowBorderPixmap(dpy, tmp_win->frame, tmp_win->gray);
     59 				if(tmp_win->title_w) {
     60 					XSetWindowBorderPixmap(dpy, tmp_win->title_w, tmp_win->gray);
     61 				}
     62 			}
     63 		}
     64 	}
     65 
     66 	if(focus) {
     67 		bool hil = false;
     68 
     69 		if(tmp_win->lolite_wl) {
     70 			XUnmapWindow(dpy, tmp_win->lolite_wl);
     71 		}
     72 		if(tmp_win->lolite_wr) {
     73 			XUnmapWindow(dpy, tmp_win->lolite_wr);
     74 		}
     75 		if(tmp_win->hilite_wl) {
     76 			XMapWindow(dpy, tmp_win->hilite_wl);
     77 			hil = true;
     78 		}
     79 		if(tmp_win->hilite_wr) {
     80 			XMapWindow(dpy, tmp_win->hilite_wr);
     81 			hil = true;
     82 		}
     83 		if(hil && tmp_win->HiliteImage && tmp_win->HiliteImage->next) {
     84 			MaybeAnimate = true;
     85 		}
     86 		if(tmp_win->iconmanagerlist) {
     87 			ActiveIconManager(tmp_win->iconmanagerlist);
     88 		}
     89 	}
     90 	else {
     91 		if(tmp_win->hilite_wl) {
     92 			XUnmapWindow(dpy, tmp_win->hilite_wl);
     93 		}
     94 		if(tmp_win->hilite_wr) {
     95 			XUnmapWindow(dpy, tmp_win->hilite_wr);
     96 		}
     97 		if(tmp_win->lolite_wl) {
     98 			XMapWindow(dpy, tmp_win->lolite_wl);
     99 		}
    100 		if(tmp_win->lolite_wr) {
    101 			XMapWindow(dpy, tmp_win->lolite_wr);
    102 		}
    103 		if(tmp_win->iconmanagerlist) {
    104 			NotActiveIconManager(tmp_win->iconmanagerlist);
    105 		}
    106 	}
    107 	if(Scr->use3Dtitles && Scr->SunkFocusWindowTitle && tmp_win->title_height) {
    108 		ButtonState bs;
    109 
    110 		bs = focus ? on : off;
    111 		Draw3DBorder(tmp_win->title_w, Scr->TBInfo.titlex, 0,
    112 		             tmp_win->title_width - Scr->TBInfo.titlex -
    113 		             Scr->TBInfo.rightoff - Scr->TitlePadding,
    114 		             Scr->TitleHeight, Scr->TitleShadowDepth,
    115 		             tmp_win->title, bs, false, false);
    116 	}
    117 	tmp_win->hasfocusvisible = focus;
    118 }
    119 
    120 
    121 /*
    122  * Shift the focus to a given window, and do whatever subsidiary ops that
    123  * entails.
    124  *
    125  * Formerly in util.c
    126  */
    127 void
    128 SetFocus(TwmWindow *tmp_win, Time tim)
    129 {
    130 	Window w = (tmp_win ? tmp_win->w : PointerRoot);
    131 	bool f_iconmgr = false;
    132 
    133 	if(Scr->Focus && (Scr->Focus->isiconmgr)) {
    134 		f_iconmgr = true;
    135 	}
    136 	if(Scr->SloppyFocus && (w == PointerRoot) && (!f_iconmgr)) {
    137 		return;
    138 	}
    139 
    140 	XSetInputFocus(dpy, w, RevertToPointerRoot, tim);
    141 #ifdef EWMH
    142 	EwmhSet_NET_ACTIVE_WINDOW(w);
    143 #endif
    144 	if(Scr->Focus == tmp_win) {
    145 		return;
    146 	}
    147 
    148 	if(Scr->Focus) {
    149 		if(Scr->Focus->AutoSqueeze && !Scr->Focus->squeezed) {
    150 			AutoSqueeze(Scr->Focus);
    151 		}
    152 		SetFocusVisualAttributes(Scr->Focus, false);
    153 #ifdef EWMH
    154 		// Priority may change when focus does
    155 		if(OtpIsFocusDependent(Scr->Focus)) {
    156 			OtpUnfocusWindow(Scr->Focus);
    157 			// That Scr->Focus = NULL's internally for us, but we don't
    158 			// care, since we're about to reset it if we need to.
    159 		}
    160 #endif
    161 	}
    162 
    163 	if(tmp_win) {
    164 		if(tmp_win->AutoSqueeze && tmp_win->squeezed) {
    165 			AutoSqueeze(tmp_win);
    166 		}
    167 		SetFocusVisualAttributes(tmp_win, true);
    168 #ifdef EWMH
    169 		// Priority may change when focus does
    170 		if(OtpIsFocusDependent(tmp_win)) {
    171 			OtpFocusWindow(tmp_win);
    172 			// Pre-sets Scr->Focus
    173 		}
    174 #endif
    175 	}
    176 
    177 	// in the EWMH cases, this was already done.
    178 	Scr->Focus = tmp_win;
    179 
    180 	return;
    181 }
    182 
    183 
    184 /*
    185  * Move the focus straight to the root, with associated cleanup.
    186  *
    187  * Formerly in menus.c
    188  */
    189 void FocusOnRoot(void)
    190 {
    191 	SetFocus(NULL, EventTime);
    192 	InstallColormaps(0, &Scr->RootColormaps);
    193 	if(! Scr->ClickToFocus) {
    194 		Scr->FocusRoot = true;
    195 	}
    196 }
    197 
    198 
    199 /*
    200  * Handle doing squeezing bits for AutoSqueeze{} windows.
    201  *
    202  * Formerly in menus.c
    203  */
    204 void
    205 AutoSqueeze(TwmWindow *tmp_win)
    206 {
    207 	if(tmp_win->isiconmgr) {
    208 		return;
    209 	}
    210 	if(Scr->RaiseWhenAutoUnSqueeze && tmp_win->squeezed) {
    211 		OtpRaise(tmp_win, WinWin);
    212 	}
    213 	Squeeze(tmp_win);
    214 }
    215 
    216 
    217 /*
    218  * Toggle a window's squeezed state.
    219  *
    220  * Formerly in menus.c
    221  */
    222 void
    223 Squeeze(TwmWindow *tmp_win)
    224 {
    225 	long fx, fy, savex, savey;
    226 	int  neww, newh;
    227 	bool south;
    228 	int  grav = ((tmp_win->hints.flags & PWinGravity)
    229 	             ? tmp_win->hints.win_gravity : NorthWestGravity);
    230 	long eventMask;
    231 	if(tmp_win->squeezed) {
    232 		tmp_win->squeezed = false;
    233 #ifdef EWMH
    234 		EwmhSet_NET_WM_STATE(tmp_win, EWMH_STATE_SHADED);
    235 #endif /* EWMH */
    236 		if(!tmp_win->isicon) {
    237 			XMapWindow(dpy, tmp_win->w);
    238 		}
    239 		SetupWindow(tmp_win, tmp_win->actual_frame_x, tmp_win->actual_frame_y,
    240 		            tmp_win->actual_frame_width, tmp_win->actual_frame_height, -1);
    241 		ReMapTransients(tmp_win);
    242 		return;
    243 	}
    244 
    245 	newh = tmp_win->title_height + 2 * tmp_win->frame_bw3D;
    246 	if(newh < 3) {
    247 		XBell(dpy, 0);
    248 		return;
    249 	}
    250 	switch(grav) {
    251 		case SouthWestGravity :
    252 		case SouthGravity :
    253 		case SouthEastGravity :
    254 			south = true;
    255 			break;
    256 		default :
    257 			south = false;
    258 			break;
    259 	}
    260 	if(tmp_win->title_height && !tmp_win->AlwaysSqueezeToGravity) {
    261 		south = false;
    262 	}
    263 
    264 	tmp_win->squeezed = true;
    265 	tmp_win->actual_frame_width  = tmp_win->frame_width;
    266 	tmp_win->actual_frame_height = tmp_win->frame_height;
    267 	savex = fx = tmp_win->frame_x;
    268 	savey = fy = tmp_win->frame_y;
    269 	neww  = tmp_win->actual_frame_width;
    270 	if(south) {
    271 		fy += tmp_win->frame_height - newh;
    272 	}
    273 	if(tmp_win->squeeze_info) {
    274 		fx  += tmp_win->title_x + tmp_win->frame_bw - tmp_win->frame_bw3D;
    275 		neww = tmp_win->title_width + 2 * tmp_win->frame_bw3D;
    276 	}
    277 
    278 	eventMask = mask_out_event(tmp_win->w, StructureNotifyMask);
    279 #ifdef EWMH
    280 	EwmhSet_NET_WM_STATE(tmp_win, EWMH_STATE_SHADED);
    281 #endif /* EWMH */
    282 	XUnmapWindow(dpy, tmp_win->w);
    283 	restore_mask(tmp_win->w, eventMask);
    284 
    285 	if(fx + neww >= Scr->rootw - Scr->BorderRight) {
    286 		fx = Scr->rootw - Scr->BorderRight - neww;
    287 	}
    288 	if(fy + newh >= Scr->rooth - Scr->BorderBottom) {
    289 		fy = Scr->rooth - Scr->BorderBottom - newh;
    290 	}
    291 	SetupWindow(tmp_win, fx, fy, neww, newh, -1);
    292 	tmp_win->actual_frame_x = savex;
    293 	tmp_win->actual_frame_y = savey;
    294 
    295 	/* Now make the group members disappear */
    296 	UnmapTransients(tmp_win, false, eventMask);
    297 }
    298 
    299 
    300 /***********************************************************************
    301  *
    302  *  Procedure:
    303  *      MoveOutline - move a window outline
    304  *
    305  *  Inputs:
    306  *      root        - the window we are outlining
    307  *      x           - upper left x coordinate
    308  *      y           - upper left y coordinate
    309  *      width       - the width of the rectangle
    310  *      height      - the height of the rectangle
    311  *      bw          - the border width of the frame
    312  *      th          - title height
    313  *
    314  ***********************************************************************
    315  */
    316 void
    317 MoveOutline(Window root, int x, int y, int width, int height, int bw, int th)
    318 {
    319 	static int  lastx = 0;
    320 	static int  lasty = 0;
    321 	static int  lastWidth = 0;
    322 	static int  lastHeight = 0;
    323 	static int  lastBW = 0;
    324 	static int  lastTH = 0;
    325 	int         xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb;
    326 	int         xthird, ythird;
    327 	XSegment    outline[18];
    328 	XSegment   *r;
    329 
    330 	if(x == lastx && y == lasty && width == lastWidth && height == lastHeight
    331 	                && lastBW == bw && th == lastTH) {
    332 		return;
    333 	}
    334 
    335 	r = outline;
    336 
    337 #define DRAWIT() \
    338     if (lastWidth || lastHeight)                        \
    339     {                                                   \
    340         xl = lastx;                                     \
    341         xr = lastx + lastWidth - 1;                     \
    342         yt = lasty;                                     \
    343         yb = lasty + lastHeight - 1;                    \
    344         xinnerl = xl + lastBW;                          \
    345         xinnerr = xr - lastBW;                          \
    346         yinnert = yt + lastTH + lastBW;                 \
    347         yinnerb = yb - lastBW;                          \
    348         xthird = (xinnerr - xinnerl) / 3;               \
    349         ythird = (yinnerb - yinnert) / 3;               \
    350                                                         \
    351         r->x1 = xl;                                     \
    352         r->y1 = yt;                                     \
    353         r->x2 = xr;                                     \
    354         r->y2 = yt;                                     \
    355         r++;                                            \
    356                                                         \
    357         r->x1 = xl;                                     \
    358         r->y1 = yb;                                     \
    359         r->x2 = xr;                                     \
    360         r->y2 = yb;                                     \
    361         r++;                                            \
    362                                                         \
    363         r->x1 = xl;                                     \
    364         r->y1 = yt;                                     \
    365         r->x2 = xl;                                     \
    366         r->y2 = yb;                                     \
    367         r++;                                            \
    368                                                         \
    369         r->x1 = xr;                                     \
    370         r->y1 = yt;                                     \
    371         r->x2 = xr;                                     \
    372         r->y2 = yb;                                     \
    373         r++;                                            \
    374                                                         \
    375         r->x1 = xinnerl + xthird;                       \
    376         r->y1 = yinnert;                                \
    377         r->x2 = r->x1;                                  \
    378         r->y2 = yinnerb;                                \
    379         r++;                                            \
    380                                                         \
    381         r->x1 = xinnerl + (2 * xthird);                 \
    382         r->y1 = yinnert;                                \
    383         r->x2 = r->x1;                                  \
    384         r->y2 = yinnerb;                                \
    385         r++;                                            \
    386                                                         \
    387         r->x1 = xinnerl;                                \
    388         r->y1 = yinnert + ythird;                       \
    389         r->x2 = xinnerr;                                \
    390         r->y2 = r->y1;                                  \
    391         r++;                                            \
    392                                                         \
    393         r->x1 = xinnerl;                                \
    394         r->y1 = yinnert + (2 * ythird);                 \
    395         r->x2 = xinnerr;                                \
    396         r->y2 = r->y1;                                  \
    397         r++;                                            \
    398                                                         \
    399         if (lastTH != 0) {                              \
    400             r->x1 = xl;                                 \
    401             r->y1 = yt + lastTH;                        \
    402             r->x2 = xr;                                 \
    403             r->y2 = r->y1;                              \
    404             r++;                                        \
    405         }                                               \
    406     }
    407 
    408 	/* undraw the old one, if any */
    409 	DRAWIT();
    410 
    411 	lastx = x;
    412 	lasty = y;
    413 	lastWidth = width;
    414 	lastHeight = height;
    415 	lastBW = bw;
    416 	lastTH = th;
    417 
    418 	/* draw the new one, if any */
    419 	DRAWIT();
    420 
    421 #undef DRAWIT
    422 
    423 
    424 	if(r != outline) {
    425 		XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline);
    426 	}
    427 }
    428