win_decorations_init.c revision 0bbfda8a
1/* 2 * Window decoration routines -- initializtion time 3 * 4 * These are funcs that are called during ctwm initialization to setup 5 * bits based on general X stuff and/or config file bits. 6 */ 7 8 9#include "ctwm.h" 10 11#include <stdio.h> 12#include <stdlib.h> 13 14#include "add_window.h" 15#include "functions_defs.h" 16#include "image.h" 17#include "screen.h" 18 19#include "win_decorations_init.h" 20 21 22/* 23 * Global marker used in config file loading to track "which one we're 24 * currently messing with" 25 */ 26static TitleButton *cur_tb = NULL; 27 28 29/* Internal func[s] */ 30static void ComputeCommonTitleOffsets(void); 31 32 33 34/* 35 * InitTitlebarButtons - Do all the necessary stuff to load in a titlebar 36 * button. If we can't find the button, then put in a question; if we can't 37 * find the question mark, something is wrong and we are probably going to be 38 * in trouble later on. 39 */ 40void 41InitTitlebarButtons(void) 42{ 43 TitleButton *tb; 44 int h; 45 46 /* 47 * initialize dimensions 48 */ 49 Scr->TBInfo.width = (Scr->TitleHeight - 50 2 * (Scr->FramePadding + Scr->ButtonIndent)); 51 if(Scr->use3Dtitles) 52 Scr->TBInfo.pad = ((Scr->TitlePadding > 1) 53 ? ((Scr->TitlePadding + 1) / 2) : 0); 54 else 55 Scr->TBInfo.pad = ((Scr->TitlePadding > 1) 56 ? ((Scr->TitlePadding + 1) / 2) : 1); 57 h = Scr->TBInfo.width - 2 * Scr->TBInfo.border; 58 59 /* 60 * add in some useful buttons and bindings so that novices can still 61 * use the system. 62 */ 63 if(!Scr->NoDefaults) { 64 /* insert extra buttons */ 65#define MKBTN(bmap, func, isrt) \ 66 CreateTitleButton(TBPM_##bmap, F_##func, "", NULL, \ 67 isrt, isrt) 68 69 /* Iconify on the left, resize on the right */ 70 if(Scr->use3Dtitles) { 71 MKBTN(3DDOT, ICONIFY, false); 72 MKBTN(3DRESIZE, RESIZE, true); 73 } 74 else { 75 MKBTN(ICONIFY, ICONIFY, false); 76 MKBTN(RESIZE, RESIZE, true); 77 } 78 79#undef MKBTN 80 81 /* Default mouse bindings in titlebar/icon/iconmgr as fallback */ 82 AddDefaultFuncButtons(); 83 } 84 85 /* Init screen-wide dimensions for common titlebar bits */ 86 ComputeCommonTitleOffsets(); 87 88 89 /* 90 * load in images and do appropriate centering 91 */ 92 for(tb = Scr->TBInfo.head; tb; tb = tb->next) { 93 tb->image = GetImage(tb->name, Scr->TitleC); 94 if(!tb->image) { 95 /* Couldn't find it, make a question mark */ 96 tb->image = GetImage(TBPM_QUESTION, Scr->TitleC); 97 if(!tb->image) { 98 /* 99 * (sorta) Can't Happen. Calls a static function that 100 * builds from static data, so could only possibly fail 101 * if XCreateBitmapFromData() failed (which should be 102 * vanishingly rare; memory allocation failures etc). 103 */ 104 fprintf(stderr, "%s: unable to add titlebar button \"%s\"\n", 105 ProgramName, tb->name); 106 continue; 107 } 108 } 109 tb->width = tb->image->width; 110 tb->height = tb->image->height; 111 112 /* Figure centering. Horizontally... */ 113 tb->dstx = (h - tb->width + 1) / 2; 114 if(tb->dstx < 0) { /* clip to minimize copying */ 115 tb->srcx = -(tb->dstx); 116 tb->width = h; 117 tb->dstx = 0; 118 } 119 else { 120 tb->srcx = 0; 121 } 122 123 /* ... and vertically */ 124 tb->dsty = (h - tb->height + 1) / 2; 125 if(tb->dsty < 0) { 126 tb->srcy = -(tb->dsty); 127 tb->height = h; 128 tb->dsty = 0; 129 } 130 else { 131 tb->srcy = 0; 132 } 133 } 134} 135 136 137/* 138 * Figure general sizing/locations for titlebar bits. 139 * 140 * For the session; called during ctwm startup. main() -> 141 * InitTitleBarButtons() -> ComputeCommonTitleOffsets() 142 */ 143static void 144ComputeCommonTitleOffsets(void) 145{ 146 int buttonwidth = (Scr->TBInfo.width + Scr->TBInfo.pad); 147 148 /* Start "+left" and "-right" with our padding */ 149 Scr->TBInfo.leftx = Scr->TBInfo.rightoff = Scr->FramePadding; 150 151 /* 152 * If there are buttons on the left, add a space to clear the right 153 * edge of the last one. 154 */ 155 if(Scr->TBInfo.nleft > 0) { 156 Scr->TBInfo.leftx += Scr->ButtonIndent; 157 } 158 159 /* 160 * Similar on the right, except we need to know how many there are 161 * and account for all of that to leave enough space open for them. 162 * We didn't need to do that above because leftx is already relative 163 * to the end of the window holding them (and so means something like 164 * "move over this much further"), whereas rightoff is relative to 165 * the right side of the titlebar (and so means something like "we 166 * have to leave this much space")? 167 */ 168 if(Scr->TBInfo.nright > 0) { 169 Scr->TBInfo.rightoff += (Scr->ButtonIndent 170 + (Scr->TBInfo.nright * buttonwidth) 171 - Scr->TBInfo.pad); 172 } 173 174 /* 175 * titlex does however go from the far-left of the titlebar, so it 176 * needs to account for the space the left-side buttons use. 177 */ 178 Scr->TBInfo.titlex = (Scr->TBInfo.leftx 179 + (Scr->TBInfo.nleft * buttonwidth) 180 - Scr->TBInfo.pad 181 + Scr->TitlePadding); 182} 183 184 185 186/* 187 * Sets the action for a given {mouse button,set of modifier keys} on the 188 * "current" button. This happens during initialization, in a few 189 * different ways. 190 * 191 * CreateTitleButton() winds up creating a new button, and setting the 192 * cur_tb global we rely on. It calls us then to initialize our action 193 * to what it was told (hardcoded for the !NoDefaults case in 194 * InitTitlebarButtons() for fallback config, from the config file when 195 * it's called via GotTitleButton() for the one-line string form of 196 * *TitleButton spec). 197 * 198 * It's also called directly from the config parsing for the block-form 199 * *TitleButton specs, when the cur_tb was previously set by 200 * CreateTitleButton() at the opening of the block. 201 */ 202void 203SetCurrentTBAction(int button, int nmods, int func, char *action, 204 MenuRoot *menuroot) 205{ 206 TitleButtonFunc *tbf; 207 208 if(!cur_tb) { 209 fprintf(stderr, "%s: can't find titlebutton\n", ProgramName); 210 return; 211 } 212 for(tbf = cur_tb->funs; tbf; tbf = tbf->next) { 213 if(tbf->num == button && tbf->mods == nmods) { 214 break; 215 } 216 } 217 if(!tbf) { 218 tbf = malloc(sizeof(TitleButtonFunc)); 219 if(!tbf) { 220 fprintf(stderr, "%s: out of memory\n", ProgramName); 221 return; 222 } 223 tbf->next = cur_tb->funs; 224 cur_tb->funs = tbf; 225 } 226 tbf->num = button; 227 tbf->mods = nmods; 228 tbf->func = func; 229 tbf->action = action; 230 tbf->menuroot = menuroot; 231} 232 233 234 235/* 236 * XXX This return value is a little pointless. The only failure it 237 * acknowledges is from malloc(), and that Never Fails On Real 238 * Systems(tm). And if it does, we're pretty screwed anyway. 239 */ 240bool 241CreateTitleButton(char *name, int func, char *action, MenuRoot *menuroot, 242 bool rightside, bool append) 243{ 244 int button; 245 cur_tb = calloc(1, sizeof(TitleButton)); 246 247 if(!cur_tb) { 248 fprintf(stderr, 249 "%s: unable to allocate %lu bytes for title button\n", 250 ProgramName, (unsigned long) sizeof(TitleButton)); 251 return false; 252 } 253 254 cur_tb->name = name; /* note that we are not copying */ 255 cur_tb->rightside = rightside; 256 if(rightside) { 257 Scr->TBInfo.nright++; 258 } 259 else { 260 Scr->TBInfo.nleft++; 261 } 262 263 for(button = 0; button < MAX_BUTTONS; button++) { 264 SetCurrentTBAction(button + 1, 0, func, action, menuroot); 265 } 266 267 /* 268 * Cases for list: 269 * 270 * 1. empty list, prepend left put at head of list 271 * 2. append left, prepend right put in between left and right 272 * 3. append right put at tail of list 273 * 274 * Do not refer to widths and heights yet since buttons not created 275 * (since fonts not loaded and heights not known). 276 */ 277 if((!Scr->TBInfo.head) || ((!append) && (!rightside))) { /* 1 */ 278 cur_tb->next = Scr->TBInfo.head; 279 Scr->TBInfo.head = cur_tb; 280 } 281 else if(append && rightside) { /* 3 */ 282 TitleButton *t; 283 for(t = Scr->TBInfo.head; t->next; t = t->next) { 284 /* just walking to tail */; 285 } 286 t->next = cur_tb; 287 cur_tb->next = NULL; 288 } 289 else { /* 2 */ 290 TitleButton *t, *prev = NULL; 291 for(t = Scr->TBInfo.head; t && !t->rightside; t = t->next) { 292 prev = t; 293 } 294 if(prev) { 295 cur_tb->next = prev->next; 296 prev->next = cur_tb; 297 } 298 else { 299 cur_tb->next = Scr->TBInfo.head; 300 Scr->TBInfo.head = cur_tb; 301 } 302 } 303 304 return true; 305} 306