13#include "ctwm_atoms.h"
18# include "ewmh_atoms.h"
44 XSizeHints *hints = &tmp->
hints;
46 if(!XGetWMNormalHints(
dpy, tmp->
w, hints, &supplied)) {
50 if(hints->flags & PResizeInc) {
51 if(hints->width_inc == 0) {
54 if(hints->height_inc == 0) {
55 hints->height_inc = 1;
59 if(!(supplied & PWinGravity) && (hints->flags & USPosition)) {
60 static int gravs[] = { SouthEastGravity, SouthWestGravity,
61 NorthEastGravity, NorthWestGravity
66 gravs[((
Scr->rooth - bottom <
68 ((
Scr->rootw - right <
70 hints->flags |= PWinGravity;
74 if((hints->flags & (PMinSize | PMaxSize)) == (PMinSize | PMaxSize)) {
75 if(hints->max_width < hints->min_width) {
76 if(hints->max_width > 0) {
77 hints->min_width = hints->max_width;
79 else if(hints->min_width > 0) {
80 hints->max_width = hints->min_width;
83 hints->max_width = hints->min_width = 1;
87 if(hints->max_height < hints->min_height) {
88 if(hints->max_height > 0) {
89 hints->min_height = hints->max_height;
91 else if(hints->min_height > 0) {
92 hints->max_height = hints->min_height;
95 hints->max_height = hints->min_height = 1;
110 unsigned long flags = 0L;
111 Atom *protocols = NULL;
114 if(XGetWMProtocols(
dpy, tmp->
w, &protocols, &n)) {
118 for(i = 0, ap = protocols; i < n; i++, ap++) {
119 if(*ap == XA_WM_TAKE_FOCUS) {
122 if(*ap == XA_WM_SAVE_YOURSELF) {
125 if(*ap == XA_WM_DELETE_WINDOW) {
151 static struct _gravity_offset {
153 } gravity_offsets[] = {
154 [ForgetGravity] = { 0, 0 },
155 [NorthWestGravity] = { -1, -1 },
156 [NorthGravity] = { 0, -1 },
157 [NorthEastGravity] = { 1, -1 },
158 [WestGravity] = { -1, 0 },
159 [CenterGravity] = { 0, 0 },
160 [EastGravity] = { 1, 0 },
161 [SouthWestGravity] = { -1, 1 },
162 [SouthGravity] = { 0, 1 },
163 [SouthEastGravity] = { 1, 1 },
164 [StaticGravity] = { 0, 0 },
166 int g = ((tmp->
hints.flags & PWinGravity)
167 ? tmp->
hints.win_gravity : NorthWestGravity);
169 if(g < ForgetGravity || g > StaticGravity) {
173 *xp = gravity_offsets[g].x;
174 *yp = gravity_offsets[g].y;
195 stat = XFindContext(
dpy, w,
TwmContext, (XPointer *)&twmwin);
196 if(stat == XCNOENT) {
224 XTextProperty text_prop;
227 XGetTextProperty(
dpy, w, &text_prop, prop);
228 if(text_prop.value == NULL) {
232 if(text_prop.encoding == XA_STRING
233 || text_prop.encoding == XA_UTF8_STRING
234 || text_prop.encoding == XA_COMPOUND_TEXT) {
241 if(
Scr->StrictWinNameEncoding) {
244 if((prop == XA_WM_NAME || prop == XA_WM_ICON_NAME)
245 && text_prop.encoding != XA_STRING
246 && text_prop.encoding != XA_COMPOUND_TEXT) {
251 if((prop == XA__NET_WM_NAME || prop == XA__NET_WM_ICON_NAME)
252 && text_prop.encoding != XA_UTF8_STRING) {
258 fprintf(stderr,
"%s: Invalid encoding for property %s "
260 XGetAtomName(
dpy, prop), w);
261 XFree(text_prop.value);
267 status = XmbTextPropertyToTextList(
dpy, &text_prop, &text_list,
269 if(text_list_count == 0
271 || text_list[0] == NULL) {
273 XFree(text_prop.value);
276 else if(status < 0 || text_list_count < 0) {
279 case XConverterNotFound:
281 "%s: Converter not found; unable to convert property %s of window ID %lx.\n",
286 "%s: Insufficient memory; unable to convert property %s of window ID %lx.\n",
289 case XLocaleNotSupported:
291 "%s: Locale not supported; unable to convert property %s of window ID %lx.\n",
304 stringptr = strdup(text_list[0]);
305 XFreeStringList(text_list);
311 "%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n",
315 XFree(text_prop.value);
329 if(prop && prop !=
NoName) {
343 return (tmp_win->
vs != NULL);
368 XWindowAttributes wattr;
371 if(XGetWindowAttributes(
dpy, w, &wattr) == 0) {
380 if(ignore_event == 0) {
381 return wattr.your_event_mask;
392 XSelectInput(
dpy, w, (curmask & ~ignore_event));
401 return XSelectInput(
dpy, w, restore);
417 unsigned long data[2];
419 data[0] = (
unsigned long) state;
421 (tmp_win->
icon ? tmp_win->
icon->
w : None));
423 XChangeProperty(
dpy, tmp_win->
w, XA_WM_STATE, XA_WM_STATE, 32,
424 PropModeReplace, (
unsigned char *) data, 2);
433 unsigned long nitems, bytesafter;
434 unsigned long *datap = NULL;
437 if(XGetWindowProperty(
dpy, w, XA_WM_STATE, 0L, 2L, False, XA_WM_STATE,
438 &actual_type, &actual_format, &nitems, &bytesafter,
439 (
unsigned char **) &datap) != Success || !datap) {
444 *statep = (int) datap[0];
445 *iwp = (Window) datap[1];
480 sprintf(str,
" %c%-4d %c%-4d ", signx,
x, signy,
y);
481 XRaiseWindow(
dpy,
Scr->SizeWindow);
486 2,
Scr->DefaultC,
off,
false,
false);
488 FB(
Scr->DefaultC.fore,
Scr->DefaultC.back);
489 XmbDrawImageString(
dpy,
Scr->SizeWindow,
Scr->SizeFont.font_set,
490 Scr->NormalGC,
Scr->SizeStringOffset,
497 XResizeWindow(
dpy,
Scr->SizeWindow, width, height);
499 if(
Scr->CenterFeedbackWindow) {
502 XMoveWindow(
dpy,
Scr->SizeWindow,
503 monitor.
x + monitor.
width / 2 - width / 2,
504 monitor.
y + monitor.
height / 2 - height / 2);
518 if(final->x >= cur_win->
x + cur_win->
width) {
521 if(final->y >= cur_win->
y + cur_win->
height) {
524 if(final->x + final->width <= cur_win->
x) {
527 if(final->y + final->height <= cur_win->
y) {
531 if(final->x +
Scr->MovePackResistance > cur_win->
x +
533 final->x =
MAX(final->x, cur_win->
x + cur_win->
width);
536 if(final->x + final->width < cur_win->
x +
537 Scr->MovePackResistance) {
538 final->x =
MIN(final->x, cur_win->
x - final->width);
541 if(final->y +
Scr->MovePackResistance > cur_win->
y +
543 final->y =
MAX(final->y, cur_win->
y + cur_win->
height);
546 if(final->y + final->height < cur_win->
y +
547 Scr->MovePackResistance) {
548 final->y =
MIN(final->y, cur_win->
y - final->height);
570 if(
Scr->BorderedLayout->horiz->len > 1) {
575 for(t =
Scr->FirstWindow; t != NULL; t = t->
next) {
580 if(t->winbox != tmp_win->winbox) {
584 if(t->
vs != tmp_win->
vs) {
626 int newx, newy, ndir;
632 for(t =
Scr->FirstWindow; t != NULL; t = t->
next) {
637 if(t->winbox != tmp_win->winbox) {
641 if(t->
vs != tmp_win->
vs) {
656 if(
x + winw <= t->frame_x) {
659 if(
y + winh <= t->frame_y) {
672 (
x + winw < t->frame_x +
Scr->MovePackResistance)) {
686 (
y + winh < t->frame_y +
Scr->MovePackResistance)) {
709 int grav = ((tmp_win->
hints.flags & PWinGravity)
710 ? tmp_win->
hints.win_gravity : NorthWestGravity);
715 case NorthWestGravity :
719 *
x = ((*
x -
Scr->BorderLeft) /
Scr->XMoveGrid) *
Scr->XMoveGrid
721 *
y = ((*
y -
Scr->BorderTop) /
Scr->YMoveGrid) *
Scr->YMoveGrid
724 case NorthEastGravity :
726 *
x = (((*
x + w -
Scr->BorderLeft) /
Scr->XMoveGrid) *
727 Scr->XMoveGrid) - w +
Scr->BorderLeft;
728 *
y = ((*
y -
Scr->BorderTop) /
Scr->YMoveGrid) *
729 Scr->YMoveGrid +
Scr->BorderTop;
731 case SouthWestGravity :
733 *
x = ((*
x -
Scr->BorderLeft) /
Scr->XMoveGrid) *
Scr->XMoveGrid
735 *
y = (((*
y + h -
Scr->BorderTop) /
Scr->YMoveGrid) *
Scr->YMoveGrid)
736 - h +
Scr->BorderTop;
738 case SouthEastGravity :
739 *
x = (((*
x + w -
Scr->BorderLeft) /
Scr->XMoveGrid) *
740 Scr->XMoveGrid) - w +
Scr->BorderLeft;
741 *
y = (((*
y + h -
Scr->BorderTop) /
Scr->YMoveGrid) *
742 Scr->YMoveGrid) - h +
Scr->BorderTop;
755static void ConstrainLeftTop(
int *value,
int border);
756static void ConstrainRightBottom(
int *value,
int size1,
int border,
int size2);
761 int *top,
int height)
765 bool clipped =
false;
769 if(move_off_res >= 0 && area.
y >= limit + move_off_res) {
770 area.
y -= move_off_res;
780 if(move_off_res >= 0 && area.
x >= limit + move_off_res) {
781 area.
x -= move_off_res;
791 if(move_off_res >= 0 && area.
x <= limit - move_off_res) {
792 area.
x += move_off_res;
802 if(move_off_res >= 0 && area.
y <= limit - move_off_res) {
803 area.
y += move_off_res;
821 left, width, top, height);
826 int *top,
int height)
832 else if(twmwin->winbox) {
833 XWindowAttributes attr;
834 XGetWindowAttributes(
dpy, twmwin->winbox->window, &attr);
835 ConstrainRightBottom(left, width, 0, attr.width);
836 ConstrainLeftTop(left, 0);
837 ConstrainRightBottom(top, height, 0, attr.height);
838 ConstrainLeftTop(top, 0);
848ConstrainLeftTop(
int *value,
int border)
850 if(*value < border) {
851 if(
Scr->MoveOffResistance < 0 ||
852 *value > border -
Scr->MoveOffResistance) {
855 else if(
Scr->MoveOffResistance > 0 &&
856 *value <= border - Scr->MoveOffResistance) {
857 *value = *value +
Scr->MoveOffResistance;
863ConstrainRightBottom(
int *value,
int size1,
int border,
int size2)
865 if(*value + size1 > size2 - border) {
866 if(
Scr->MoveOffResistance < 0 ||
867 *value + size1 < size2 - border + Scr->MoveOffResistance) {
868 *value = size2 - size1 - border;
870 else if(
Scr->MoveOffResistance > 0 &&
871 *value + size1 >= size2 - border +
Scr->MoveOffResistance) {
872 *value = *value -
Scr->MoveOffResistance;
891 fprintf(stderr,
"WarpToWindow: cursor_valid; x == %d, y == %d\n",
x,
y);
911 fprintf(stderr,
"WarpToWindow: adjusted ; x := %d, y := %d\n",
x,
y);
918 fprintf(stderr,
"WarpToWindow: middle; x := %d, y := %d\n",
x,
y);
935 if(XTranslateCoordinates(
dpy, t->
frame,
Scr->Root,
x,
y, &dest_x, &dest_y,
937 if(child != t->
frame) {
948 for(wlist =
Scr->workSpaceMgr.workSpaceList; wlist != NULL;
949 wlist = wlist->
next) {
970 unsigned int mask_return;
972 if(XQueryPointer(
dpy, t->
frame, &root_return, &child_return, &root_x_return,
973 &root_y_return, &win_x_return, &win_y_return, &mask_return)) {
975 "XQueryPointer: root_return=%x, child_return=%x, root_x_return=%d, root_y_return=%d, win_x_return=%d, win_y_return=%d\n",
976 root_return, child_return, root_x_return, root_y_return, win_x_return,
998 XClientMessageEvent ev;
1000 ev.type = ClientMessage;
1002 ev.message_type = XA_WM_PROTOCOLS;
1005 ev.data.l[1] = timestamp;
1006 XSendEvent(
dpy, w, False, 0L, (XEvent *) &ev);
1034 hints = XAllocWMHints();
1044 hints->flags = InputHint | StateHint;
1045 hints->input = True;
1046 hints->initial_state = NormalState;
1069 if(!(hints->flags & InputHint)) {
1070 hints->input = True;
1081 hints->input = True;
1086 if(hints->flags & WindowGroupHint) {
1087 win->
group = hints->window_group;
1128 char *newname = NULL;
1130 if(newname == NULL && win->names.fld != NULL) { \
1131 newname = win->names.fld; \
1141 if(newname == NULL) {
1144 if(win->
name == newname) {
1149 win->
name = newname;
1167 XChangeProperty(
dpy, win->
w, XA__NET_WM_VISIBLE_NAME, XA_UTF8_STRING,
1168 8, PropModeReplace, (
unsigned char *)win->
name,
1172 XDeleteProperty(
dpy, win->
w, XA__NET_WM_VISIBLE_NAME);
1199 XRectangle inc_rect;
1200 XRectangle logical_rect;
1202 XmbTextExtents(
Scr->TitleBarFont.font_set,
1204 &inc_rect, &logical_rect);
1209 if(
Scr->AutoPriority) {
1217 XClearArea(
dpy, win->
title_w, 0, 0, 0, 0, True);
1219 if(
Scr->AutoOccupy) {
1234 if(
Scr->use3Dtitles && !
Scr->BeNiceToColormap) {
1244 if(
Scr->use3Dborders && !
Scr->BeNiceToColormap) {
1255 if(
Scr->use3Dborders && !
Scr->BeNiceToColormap) {
1290 char *newname = NULL;
1292 if(newname == NULL && win->names.fld != NULL) { \
1293 newname = win->names.fld; \
1294 win->names.icon_set = true; \
1297 TRY(ctwm_wm_icon_name)
1299 TRY(net_wm_icon_name)
1307 if(newname == NULL) {
1308 newname = win->
name;
1326 XChangeProperty(
dpy, win->
w, XA__NET_WM_VISIBLE_ICON_NAME,
1328 8, PropModeReplace, (
unsigned char *)win->
icon_name,
1332 XDeleteProperty(
dpy, win->
w, XA__NET_WM_VISIBLE_ICON_NAME);
#define DoesWmDeleteWindow
#define DoesWmSaveYourself
#define FB(fix_fore, fix_back)
void Draw3DBorder(Window w, int x, int y, int width, int height, int bw, ColorPair cp, ButtonState state, bool fill, bool forcebw)
void AutoPopupMaybe(TwmWindow *tmp)
void AutoRaiseWindow(TwmWindow *tmp)
int frame_x
X position on screen of frame.
int frame_y
Y position on screen of frame.
unsigned int name_width
width of name text
Window frame
The X window for the overall frame.
int frame_bw
2d border width.
unsigned int title_height
Height of the full title bar.
Window title_w
The title bar Window.
unsigned int frame_width
Width of frame.
unsigned int frame_height
Height of frame.
int frame_bw3D
3d border width.
void RedoIcon(TwmWindow *win)
bool GetColorFromList(name_list *list_head, char *name, XClassHint *class, Pixel *ptr)
bool IsInList(name_list *list_head, TwmWindow *twin)
void WmgrRedoOccupation(TwmWindow *win)
void OtpRecomputePrefs(TwmWindow *twm_win)
RArea RAreaNew(int x, int y, int width, int height)
Construct an RArea from given components.
void RAreaListForeach(const RAreaList *self, bool(*func)(const RArea *cur_area, void *data), void *data)
Run a function over each RArea in an RAreaList until one returns true, allowing them a place to stash...
int RLayoutFindBottomEdge(const RLayout *self, const RArea *area)
Find the bottom of the top stripe of self that area fits into.
RArea RLayoutGetAreaAtXY(const RLayout *self, int x, int y)
Find the RArea in a RLayout that a given coordinate falls into.
int RLayoutFindRightEdge(const RLayout *self, const RArea *area)
Find the right edge of the left-most stripe of self that area fits into.
int RLayoutFindLeftEdge(const RLayout *self, const RArea *area)
Find the left edge of the right-most stripe of self that area fits into.
int RLayoutFindTopEdge(const RLayout *self, const RArea *area)
Find the top of the bottom stripe of self that area fits into.
#define SIZE_VINDENT
Internal padding in the size window.
#define SIZE_HINDENT
Internal padding in the size window.
A particular extent of space.
The layout of our display.
bool icon_set
Whether an icon name property has been set.
char * wm_name
Name from ICCCM WM_NAME property.
char * wm_icon_name
Icon name from WM_ICON_NAME property.
int curs_x
Stored cursor position in the window.
int curs_y
Stored cursor position in the window.
bool cursor_valid
Whether curs_x and curs_y are usable.
Info and control for every X Window we take over.
ColorPair border_tile
ColorPair for non-focused window borders.
unsigned long protocols
Which protocols this window handles.
struct TwmWindow * next
Next TwmWindow on the Screen.
Window w
The actual X Window handle.
bool auto_raise
Should we auto-raise this window ?
bool nameChanged
Has TwmWindow::name ever changed? Used only in session saving.
int old_bw
Original window border width before we took it over and made our own bordering.
struct TwmWindow::_ring ring
Window ring connectivity. "
char * name
Current window name. Points into TwmWindow::names.
struct Icon * icon
The current icon.
char * icon_name
Current icon name. Points into TwmWindow::names.
struct VirtualScreen * vs
Where the window is currently mapped (may be NULL).
bool mapped
Is the window mapped ?
XClassHint class
Window class info. From XGetClassHint().
XSizeHints hints
Window size hints.
ColorPair borderC
ColorPair for focused window borders.
ColorPair title
ColorPair for various other titlebar bits.
struct TwmWindow::_names names
Various sources of window/icon names. "
XWindowAttributes attr
Window attributes from XGetWindowAttributes().
Window group
Window group, from WM hints.
bool iconify_by_unmapping
Unmap window to iconify it.
void GetShadeColors(ColorPair *cp)
Try and create a 'shaded' version of a color for prettier UI.
void SetupWindow(TwmWindow *tmp_win, int x, int y, int w, int h, int bw)
void SetFocus(TwmWindow *tmp_win, Time tim)
void apply_window_icon_name(TwmWindow *win)
[Re]set and apply changes to a window's icon name.
void GetWindowSizeHints(TwmWindow *tmp)
void send_clientmessage(Window w, Atom a, Time timestamp)
bool set_window_name(TwmWindow *win)
[Re]set a window's name.
XWMHints * munge_wmhints(TwmWindow *win, XWMHints *hints)
Perform whatever adaptations of WM_HINTS info we do.
void DisplayPosition(const TwmWindow *_unused_tmp_win, int x, int y)
void FreeWMPropertyString(char *prop)
bool visible(const TwmWindow *tmp_win)
void MoveResizeSizeWindow(int x, int y, unsigned int width, unsigned int height)
bool GetWMState(Window w, int *statep, Window *iwp)
static void _tryToPack(RArea *final, const RArea *cur_win)
static bool _tryToPackVsEachMonitor(const RArea *monitor_area, void *vfinal)
TwmWindow * GetTwmWindow(Window w)
void ConstrainByBorders(TwmWindow *twmwin, int *left, int width, int *top, int height)
XWMHints * gen_synthetic_wmhints(TwmWindow *win)
int restore_mask(Window w, long restore)
bool ConstrainByLayout(RLayout *layout, int move_off_res, int *left, int width, int *top, int height)
void ConstrainByBorders1(int *left, int width, int *top, int height)
long mask_out_event_mask(Window w, long ignore_event, long curmask)
void FetchWmProtocols(TwmWindow *tmp)
long mask_out_event(Window w, long ignore_event)
void SetMapStateProp(TwmWindow *tmp_win, int state)
void TryToPush(TwmWindow *tmp_win, int x, int y)
void WarpToWindow(TwmWindow *t, bool must_raise)
void apply_window_name(TwmWindow *win)
[Re]set and apply changes to a window's name.
void TryToGrid(TwmWindow *tmp_win, int *x, int *y)
void TryToPack(TwmWindow *tmp_win, int *x, int *y)
char * GetWMPropertyString(Window w, Atom prop)
static void TryToPush_be(TwmWindow *tmp_win, int x, int y, PushDirection dir)
void GetGravityOffsets(TwmWindow *tmp, int *xp, int *yp)
bool set_window_icon_name(TwmWindow *win)
[Re]set a window's icon name.
void GotoWorkSpace(VirtualScreen *vs, WorkSpace *ws)