1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/tdgtbase.c,v 1.8 2011/05/16 16:21:59 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_TDGTBASE_C_
22 
23 #include "tgifdefs.h"
24 #include "patchlvl.h"
25 #include "tidget.h"
26 
27 #include "cursor.e"
28 #include "menu.e"
29 #include "msg.e"
30 #include "raster.e"
31 #include "rect.e"
32 #include "setup.e"
33 #include "tdgtbase.e"
34 #include "text.e"
35 #include "tidget.e"
36 #include "util.e"
37 
38 static void RedrawTdgtBase ARGS_DECL((TidgetInfo *pti));
39 static int TdgtBaseEventHandler ARGS_DECL((TidgetInfo *pti, XEvent *input,
40                 TidgetInfo *handling_pti));
41 static int IsTdgtBaseEvent ARGS_DECL((TidgetInfo *pti, XEvent *input,
42                 TidgetInfo **ppti_handler_tidget_return));
43 static void DestroyTdgtBase ARGS_DECL((TidgetInfo *pti));
44 static void MapTdgtBase ARGS_DECL((TidgetInfo *pti));
45 static void TdgtBaseMoveResize ARGS_DECL((TidgetInfo *pti, int x, int y,
46                 int w, int h));
47 static int TdgtBaseSendCmd ARGS_DECL((TidgetInfo *pti, int cmd_type,
48                 int cmd_arg, void *pv_cmd_userdata));
49 
50 /* --------------------- RedrawTdgtBase() --------------------- */
51 
52 static
RedrawTdgtBase(pti)53 void RedrawTdgtBase(pti)
54    TidgetInfo *pti;
55 {
56    TdgtBase *pTdgtBase=(TdgtBase*)(pti->tidget);
57    CVListElem *pElem=NULL;
58 
59    XClearWindow(mainDisplay, pTdgtBase->pti->tci.win);
60 
61    if (threeDLook) {
62       struct BBRec bbox;
63 
64       SetBBRec(&bbox, 0, 0, pTdgtBase->pti->tci.win_info.w,
65             pTdgtBase->pti->tci.win_info.h);
66       switch (pTdgtBase->pti->tci.state) {
67       case TGBS_NORMAL: break;
68       default:
69          TgDrawThreeDButton(mainDisplay, pTdgtBase->pti->tci.win,
70                gTidgetManager.gc, &bbox, pTdgtBase->pti->tci.state, 2, FALSE);
71          break;
72       }
73    } else {
74       XDrawRectangle(mainDisplay, pTdgtBase->pti->tci.win, gTidgetManager.gc, 0,
75             0, pTdgtBase->pti->tci.win_info.w, pTdgtBase->pti->tci.win_info.h);
76    }
77    for (pElem=ListFirst(&pTdgtBase->pti->tci.clist); pElem != NULL;
78          pElem=ListNext(&pTdgtBase->pti->tci.clist, pElem)) {
79       TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
80 
81       if (pti != NULL) {
82          RedrawTidget(pti);
83       }
84    }
85    TidgetManagerResetGC();
86 }
87 
88 /* --------------------- TdgtBaseEventHandler() --------------------- */
89 
90 static
TdgtBaseEventHandler(pti,input,handling_pti)91 int TdgtBaseEventHandler(pti, input, handling_pti)
92    TidgetInfo *pti, *handling_pti;
93    XEvent *input;
94 {
95    TdgtBase *pTdgtBase=(TdgtBase*)(pti->tidget);
96    CVListElem *pElem=NULL;
97 
98    if (pti == handling_pti) {
99       if (input->type == KeyPress &&
100             pTdgtBase->pf_key_press_ev_handler_callback != NULL) {
101          return (pTdgtBase->pf_key_press_ev_handler_callback)(pTdgtBase, input);
102       }
103       if (input->xany.window == pTdgtBase->pti->tci.win) {
104          if (IsWM_DELETE_WINDOW(input)) {
105             if (pTdgtBase->pf_wm_delete_ev_handler_callback != NULL) {
106                (pTdgtBase->pf_wm_delete_ev_handler_callback)(pTdgtBase);
107             }
108          } else if (input->type == Expose) {
109             XEvent ev;
110 
111             RedrawTdgtBase(pTdgtBase->pti);
112             while (XCheckWindowEvent(mainDisplay, pTdgtBase->pti->tci.win,
113                   ExposureMask, &ev)) ;
114          } else if (input->type == EnterNotify) {
115             /* may be we need to do something here */
116          } else if (input->type == LeaveNotify) {
117             /* may be we need to do something here */
118          }
119          return FALSE;
120       }
121    }
122    for (pElem=ListFirst(&pTdgtBase->pti->tci.clist); pElem != NULL;
123          pElem=ListNext(&pTdgtBase->pti->tci.clist, pElem)) {
124       TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
125 
126       if (pti != NULL) {
127          if (TdgtBaseEventHandler(pti, input, handling_pti)) {
128             return TRUE;
129          }
130       }
131    }
132    return FALSE;
133 }
134 
135 /* --------------------- IsTdgtBaseEvent() --------------------- */
136 
137 static
IsTdgtBaseEvent(pti,input,ppti_handler_tidget_return)138 int IsTdgtBaseEvent(pti, input, ppti_handler_tidget_return)
139    TidgetInfo *pti, **ppti_handler_tidget_return;
140    XEvent *input;
141 {
142    TdgtBase *pTdgtBase=(TdgtBase*)(pti->tidget);
143 
144    if (input->type == KeyPress &&
145          pTdgtBase->pf_key_press_ev_handler_callback != NULL) {
146       CVListElem *pElem=NULL;
147 
148       if (input->xany.window == pTdgtBase->pti->tci.win) {
149          *ppti_handler_tidget_return = pti;
150          return TRUE;
151       }
152       for (pElem=ListFirst(&pTdgtBase->pti->tci.clist); pElem != NULL;
153             pElem=ListNext(&pTdgtBase->pti->tci.clist, pElem)) {
154          TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
155 
156          if (pti != NULL) {
157             TidgetInfo *dummy_pti=NULL;
158 
159             if (IsTidgetEvent(pti, input, &dummy_pti)) {
160                *ppti_handler_tidget_return = pti;
161                return TRUE;
162             }
163          }
164       }
165    }
166    return FALSE;
167 }
168 
169 /* --------------------- DestroyTdgtBase() --------------------- */
170 
171 static
DestroyTdgtBase(pti)172 void DestroyTdgtBase(pti)
173    TidgetInfo *pti;
174 {
175    TdgtBase *pTdgtBase=(TdgtBase*)(pti->tidget);
176 
177    TdgtBaseReset(pTdgtBase);
178 
179    free(pTdgtBase);
180 }
181 
182 /* --------------------- MapTdgtBase() --------------------- */
183 
184 static
MapTdgtBase(pti)185 void MapTdgtBase(pti)
186    TidgetInfo *pti;
187 {
188    TdgtBase *pTdgtBase=(TdgtBase*)(pti->tidget);
189    CVListElem *pElem=NULL;
190 
191 #ifdef MAPBEFORESELECT
192    XMapWindow(mainDisplay, pTdgtBase->pti->tci.win);
193    XSelectInput(mainDisplay, pTdgtBase->win, StructureNotifyMask |
194          ButtonReleaseMask | ButtonPressMask | KeyPressMask | ExposureMask |
195          EnterWindowMask | LeaveWindowMask);
196 #else
197    XSelectInput(mainDisplay, pTdgtBase->pti->tci.win, StructureNotifyMask |
198          ButtonReleaseMask | ButtonPressMask | KeyPressMask | ExposureMask |
199          EnterWindowMask | LeaveWindowMask);
200    XMapWindow(mainDisplay, pTdgtBase->pti->tci.win);
201 #endif
202    for (pElem=ListFirst(&pTdgtBase->pti->tci.clist); pElem != NULL;
203          pElem=ListNext(&pTdgtBase->pti->tci.clist, pElem)) {
204       TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
205 
206       if (pti != NULL) {
207          MapTidget(pti);
208       }
209    }
210 }
211 
212 /* --------------------- TdgtBaseMoveResize() --------------------- */
213 
214 static
TdgtBaseMoveResize(pti,x,y,w,h)215 void TdgtBaseMoveResize(pti, x, y, w, h)
216    TidgetInfo *pti;
217    int x, y, w, h;
218 {
219    TdgtBase *pTdgtBase=(TdgtBase*)(pti->tidget);
220 
221    /* there should be no need to resize a button */
222    pTdgtBase->pti->tci.win_info.x = x;
223    pTdgtBase->pti->tci.win_info.y = y;
224    pTdgtBase->pti->tci.win_info.w = w;
225    pTdgtBase->pti->tci.win_info.h = h;
226    XMoveResizeWindow(mainDisplay, pTdgtBase->pti->tci.win, x, y, w, h);
227 }
228 
229 /* --------------------- TdgtBaseSendCmd() --------------------- */
230 
231 static
TdgtBaseSendCmd(pti,cmd_type,cmd_arg,pv_cmd_userdata)232 int TdgtBaseSendCmd(pti, cmd_type, cmd_arg, pv_cmd_userdata)
233    TidgetInfo *pti;
234    int cmd_type, cmd_arg;
235    void *pv_cmd_userdata;
236 {
237    TdgtBase *pTdgtBase=(TdgtBase*)(pti->tidget);
238 
239    if (pTdgtBase != NULL) {
240       switch (cmd_type) {
241       case TDGTCMD_CAN_HANDLE_FOCUS_CHANGE:
242          return (pTdgtBase->pf_focus_callback != NULL);
243       case TDGTCMD_REMOVE_FOCUS:
244          return (pTdgtBase->pf_focus_callback)(pTdgtBase, cmd_type, cmd_arg,
245                pv_cmd_userdata);
246       }
247    }
248    return FALSE;
249 }
250 
251 /* --------------------- TdgtBaseReset() --------------------- */
252 
TdgtBaseReset(pTdgtBase)253 void TdgtBaseReset(pTdgtBase)
254    TdgtBase *pTdgtBase;
255 {
256    CVListElem *pElem=NULL;
257 
258    for (pElem=ListFirst(&pTdgtBase->pti->tci.clist); pElem != NULL;
259          pElem=ListNext(&pTdgtBase->pti->tci.clist, pElem)) {
260       TidgetInfo *pti=(TidgetInfo*)(pElem->obj);
261 
262       if (pti != NULL) {
263          DestroyTidget(&pti);
264       }
265    }
266    ListUnlinkAll(&pTdgtBase->pti->tci.clist);
267 
268    ResetTidgetCommon(&pTdgtBase->pti->tci);
269 }
270 
271 /* --------------------- CreateTdgtBase() --------------------- */
272 
CreateTdgtBase(parent_win,parent_tidgetinfo,ctl_id,x,y,w,h,h_pad,v_pad,state,caption)273 TdgtBase *CreateTdgtBase(parent_win, parent_tidgetinfo, ctl_id, x, y, w, h,
274       h_pad, v_pad, state, caption)
275    Window parent_win;
276    TidgetInfo *parent_tidgetinfo;
277    int ctl_id, x, y, w, h, h_pad, v_pad, state;
278    char *caption;
279 {
280    int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
281    XWMHints wmhints;
282    XSetWindowAttributes win_attrs;
283    TdgtBase *pTdgtBase=NULL;
284 
285    pTdgtBase = (TdgtBase*)malloc(sizeof(TdgtBase));
286    if (pTdgtBase == NULL) FailAllocMessage();
287    memset(pTdgtBase, 0, sizeof(TdgtBase));
288 
289    pTdgtBase->pti = NewTidgetInfo(parent_tidgetinfo, TIDGET_TYPE_BASE,
290          pTdgtBase, ctl_id, NULL);
291    if ((pTdgtBase->pti->tci.win=XCreateSimpleWindow(mainDisplay, parent_win,
292          x, y, w, h, brdrW, myBorderPixel, bg_pixel)) == 0) {
293       FailToCreateWindowMessage("CreateTdgtBase()", NULL, TRUE);
294    }
295    XSelectInput(mainDisplay, pTdgtBase->pti->tci.win, StructureNotifyMask |
296          ButtonReleaseMask | ButtonPressMask | KeyPressMask | ExposureMask |
297          EnterWindowMask | LeaveWindowMask);
298    SetTidgetInfoBasic(pTdgtBase->pti, TIDGET_TYPE_BASE, pTdgtBase, parent_win,
299          x, y, w, h, h_pad, v_pad, state, caption);
300    TidgetCanHaveChildren(pTdgtBase->pti, TRUE);
301    TidgetSetCallbacks(pTdgtBase->pti,
302          RedrawTdgtBase, TdgtBaseEventHandler, IsTdgtBaseEvent, DestroyTdgtBase,
303          MapTdgtBase, TdgtBaseMoveResize, TdgtBaseSendCmd);
304 
305    XDefineCursor(mainDisplay, pTdgtBase->pti->tci.win, defaultCursor);
306 
307    memset(&win_attrs, 0, sizeof(XSetWindowAttributes));
308    win_attrs.save_under = True;
309    win_attrs.colormap = mainColormap;
310    XChangeWindowAttributes(mainDisplay, pTdgtBase->pti->tci.win,
311          CWSaveUnder | CWOverrideRedirect | CWColormap, &win_attrs);
312 
313    memset(&wmhints, 0, sizeof(XWMHints));
314    wmhints.flags = InputHint;
315    wmhints.input = True;
316    XSetWMHints(mainDisplay, pTdgtBase->pti->tci.win, &wmhints);
317 
318    RegisterWM_DELETE_WINDOW(pTdgtBase->pti->tci.win);
319    if (caption != NULL && *caption != '\0') {
320       XStoreName(mainDisplay, pTdgtBase->pti->tci.win, caption);
321    }
322    return pTdgtBase;
323 }
324 
325 /* --------------------- TdgtBaseSetText() --------------------- */
326 
TdgtBaseSetText(pTdgtBase,str)327 int TdgtBaseSetText(pTdgtBase, str)
328    TdgtBase *pTdgtBase;
329    char *str;
330 {
331    RedrawTdgtBase(pTdgtBase->pti);
332    if (str != NULL) {
333       FreeDynStrBuf(&(pTdgtBase->pti->tci.dyn_str));
334       DynStrSet(&(pTdgtBase->pti->tci.dyn_str), str);
335    }
336    return TRUE;
337 }
338 
339 /* --------------------- TdgtBaseGetText() --------------------- */
340 
TdgtBaseGetText(pTdgtBase)341 char *TdgtBaseGetText(pTdgtBase)
342    TdgtBase *pTdgtBase;
343 {
344    return pTdgtBase->pti->tci.dyn_str.s;
345 }
346 
347 /* --------------------- TdgtBaseSetState() --------------------- */
348 
TdgtBaseSetState(pTdgtBase,new_state)349 int TdgtBaseSetState(pTdgtBase, new_state)
350    TdgtBase *pTdgtBase;
351    int new_state;
352 {
353    int need_to_redraw=(pTdgtBase->pti->tci.state != new_state);
354 
355    pTdgtBase->pti->tci.state = new_state;
356    if (need_to_redraw) {
357       RedrawTdgtBase(pTdgtBase->pti);
358    }
359    return TRUE;
360 }
361 
362 /* --------------------- TdgtBaseGetState() --------------------- */
363 
TdgtBaseGetState(pTdgtBase)364 int TdgtBaseGetState(pTdgtBase)
365    TdgtBase *pTdgtBase;
366 {
367    return pTdgtBase->pti->tci.state;
368 }
369 
370 /* --------------------- TdgtBaseAddChild() --------------------- */
371 
TdgtBaseAddChild(pTdgtBase,pChildTidgetInfo)372 int TdgtBaseAddChild(pTdgtBase, pChildTidgetInfo)
373    TdgtBase *pTdgtBase;
374    TidgetInfo *pChildTidgetInfo;
375 {
376    return ListAppend(&pTdgtBase->pti->tci.clist, pChildTidgetInfo);
377 }
378 
379 /* ------------------- TdgtBaseWillHandleKeyPressEvents() ------------------- */
380 
TdgtBaseWillHandleKeyPressEvents(pTdgtBase,pf_key_press_ev_handler_callback)381 void TdgtBaseWillHandleKeyPressEvents(pTdgtBase,
382       pf_key_press_ev_handler_callback)
383    TdgtBase *pTdgtBase;
384    TdgtBaseKeyPressEvHandlerCallbackFunc *pf_key_press_ev_handler_callback;
385 {
386    pTdgtBase->pf_key_press_ev_handler_callback =
387          pf_key_press_ev_handler_callback;
388 }
389 
390 /* ------------------- TdgtBaseSetWmDeleteCallback() ------------------- */
391 
TdgtBaseSetWmDeleteCallback(pTdgtBase,pf_wm_delete_ev_handler_callback)392 void TdgtBaseSetWmDeleteCallback(pTdgtBase,
393       pf_wm_delete_ev_handler_callback)
394    TdgtBase *pTdgtBase;
395    TdgtBaseWmDeleteEvHandlerCallbackFunc *pf_wm_delete_ev_handler_callback;
396 {
397    pTdgtBase->pf_wm_delete_ev_handler_callback =
398          pf_wm_delete_ev_handler_callback;
399 }
400 
401 /* ------------------- TdgtBaseSetFocusCallback() ------------------- */
402 
TdgtBaseSetFocusCallback(pTdgtBase,pf_focus_callback)403 void TdgtBaseSetFocusCallback(pTdgtBase, pf_focus_callback)
404    TdgtBase *pTdgtBase;
405    TdgtBaseFocusCallbackFunc *pf_focus_callback;
406 {
407    pTdgtBase->pf_focus_callback = pf_focus_callback;
408 }
409 
410 /* --------------------- Init & Clean Up --------------------- */
411 
InitTdgtBase()412 int InitTdgtBase()
413 {
414    return TRUE;
415 }
416 
CleanUpTdgtBase()417 void CleanUpTdgtBase()
418 {
419 }
420 
421