]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormBaseDeprecated.C
Fix leaking pixmap icon.
[lyx.git] / src / frontends / xforms / FormBaseDeprecated.C
1 /**
2  * \file FormBaseDeprecated.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming 
7  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include "Dialogs.h"
18 #include "FormBaseDeprecated.h"
19 #include "xformsBC.h"
20 #include "xforms_resize.h"
21 #include "Tooltips.h"
22 #include FORMS_H_LOCATION
23
24 #include "lyxrc.h"
25
26 #include "frontends/LyXView.h"
27
28 #include "support/LAssert.h"
29 #include "support/filetools.h" //  LibFileSearch
30
31 #include <boost/bind.hpp>
32
33 extern "C" {
34
35 // Callback function invoked by xforms when the dialog is closed by the
36 // window manager
37 static int C_WMHideCB(FL_FORM *, void *);
38
39 // Callback function invoked by the xforms pre- and post-handler routines
40 static int C_PrehandlerCB(FL_OBJECT *, int, FL_Coord, FL_Coord, int, void *);
41
42 } // extern "C"
43
44
45 FormBaseDeprecated::FormBaseDeprecated(LyXView & lv, Dialogs & d,
46                                        string const & t, bool allowResize)
47         : lv_(lv), d_(d), title_(t), icon_pixmap_(0), icon_mask_(0),
48           minw_(0), minh_(0), allow_resize_(allowResize),
49           tooltips_(new Tooltips())
50 {}
51
52
53 FormBaseDeprecated::~FormBaseDeprecated()
54 {
55         if (icon_pixmap_)
56                 XFreePixmap(fl_get_display(), icon_pixmap_);
57
58         delete tooltips_;
59 }
60
61
62 Tooltips & FormBaseDeprecated::tooltips()
63 {
64         return *tooltips_;
65 }
66
67
68 void FormBaseDeprecated::redraw()
69 {
70         if (form() && form()->visible)
71                 fl_redraw_form(form());
72 }
73
74
75 void FormBaseDeprecated::connect()
76 {
77         fl_set_form_minsize(form(), minw_, minh_);
78         r_ = d_.redrawGUI().connect(boost::bind(&FormBaseDeprecated::redraw, this));
79 }
80
81
82 void FormBaseDeprecated::disconnect()
83 {
84         h_.disconnect();
85         r_.disconnect();
86 }
87
88
89 void FormBaseDeprecated::prepare_to_show()
90 {
91         build();
92
93         double const scale = scale_to_fit_tabs(form());
94         if (scale > 1.001)
95                 scale_form(form(), scale);
96
97         bc().refresh();
98
99         // work around dumb xforms sizing bug
100         minw_ = form()->w;
101         minh_ = form()->h;
102
103         fl_set_form_atclose(form(), C_WMHideCB, 0);
104
105         // set the title for the minimized form
106         if (!lyxrc.dialogs_iconify_with_main)
107                 fl_winicontitle(form()->window, title_.c_str());
108
109         //  assign an icon to the form
110         string const iconname = LibFileSearch("images", "lyx", "xpm");
111         if (!iconname.empty()) {
112                 unsigned int w, h;
113                 icon_pixmap_ = fl_read_pixmapfile(fl_root,
114                                                   iconname.c_str(),
115                                                   &w,
116                                                   &h,
117                                                   &icon_mask_,
118                                                   0, 0, 0);
119                 fl_set_form_icon(form(), icon_pixmap_, icon_mask_);
120         }
121 }
122
123
124 void FormBaseDeprecated::show()
125 {
126         if (!form()) {
127                 prepare_to_show();
128         }
129
130         // make sure the form is up to date.
131         fl_freeze_form(form());
132         update();
133         fl_unfreeze_form(form());
134
135         if (form()->visible) {
136                 fl_raise_form(form());
137                 /* This XMapWindow() will hopefully ensure that
138                  * iconified dialogs are de-iconified. Mad props
139                  * out to those crazy Xlib guys for forgetting a
140                  * XDeiconifyWindow(). At least WindowMaker, when
141                  * being notified of the redirected MapRequest will
142                  * specifically de-iconify. From source, fvwm2 seems
143                  * to do the same.
144                  */
145                 XMapWindow(fl_get_display(), form()->window);
146         } else {
147                 connect();
148
149                 // calls to fl_set_form_minsize/maxsize apply only to the next
150                 // fl_show_form(), so this comes first.
151                 fl_set_form_minsize(form(), minw_, minh_);
152                 if (!allow_resize_)
153                         fl_set_form_maxsize(form(), minw_, minh_);
154
155                 string const maximize_title = "LyX: " + title_;
156                 int const iconify_policy =
157                         lyxrc.dialogs_iconify_with_main ? FL_TRANSIENT : 0;
158
159                 fl_show_form(form(),
160                              FL_PLACE_MOUSE | FL_FREE_SIZE,
161                              iconify_policy,
162                              maximize_title.c_str());
163         }
164
165         // For some strange reason known only to xforms, the tooltips can only
166         // be set on a form that is already visible...
167         tooltips().set();
168 }
169
170
171 void FormBaseDeprecated::hide()
172 {
173         // xforms sometimes tries to process a hint-type MotionNotify, and
174         // use XQueryPointer, without verifying if the window still exists.
175         // So we try to clear out motion events in the queue before the
176         // DestroyNotify
177         XSync(fl_get_display(), false);
178
179         if (form() && form()->visible) {
180                 // some dialogs might do things to the form first
181                 // such as the nested tabfolder problem in Preferences
182                 disconnect();
183                 fl_hide_form(form());
184         }
185 }
186
187
188 void FormBaseDeprecated::setPrehandler(FL_OBJECT * ob)
189 {
190         lyx::Assert(ob);
191         fl_set_object_prehandler(ob, C_PrehandlerCB);
192 }
193
194
195 void FormBaseDeprecated::WMHideCB()
196 {
197         hide();
198         bc().hide();
199 }
200
201
202 void FormBaseDeprecated::ApplyCB()
203 {
204         apply();
205         bc().apply();
206 }
207
208
209 void FormBaseDeprecated::OKCB()
210 {
211         ok();
212         bc().ok();
213 }
214
215
216 void FormBaseDeprecated::CancelCB()
217 {
218         cancel();
219         bc().cancel();
220 }
221
222
223 void FormBaseDeprecated::InputCB(FL_OBJECT * ob, long data)
224 {
225         // It is possible to set the choice to 0 when using the
226         // keyboard shortcuts. This work-around deals with the problem.
227         if (ob && ob->objclass == FL_CHOICE && fl_get_choice(ob) < 1) {
228                 fl_set_choice(ob, 1);
229         }
230
231         bc().valid(input(ob, data));
232 }
233
234
235 void FormBaseDeprecated::RestoreCB()
236 {
237         bc().restore();
238         restore();
239 }
240
241
242 FormBaseBI::FormBaseBI(LyXView & lv, Dialogs & d, string const & t,
243                        bool allowResize)
244         : FormBaseDeprecated(lv, d, t, allowResize)
245 {}
246
247
248 void FormBaseBI::connect()
249 {
250         h_ = d_.hideAll.connect(boost::bind(&FormBaseBI::hide, this));
251         FormBaseDeprecated::connect();
252 }
253
254
255 FormBaseBD::FormBaseBD(LyXView & lv, Dialogs & d, string const & t,
256                        bool allowResize)
257         : FormBaseDeprecated(lv, d, t, allowResize)
258 {}
259
260
261 void FormBaseBD::connect()
262 {
263         u_ = d_.updateBufferDependent.
264                 connect(boost::bind(&FormBaseBD::updateSlot, this, _1));
265         h_ = d_.hideBufferDependent.
266                 connect(boost::bind(&FormBaseBD::hide, this));
267         FormBaseDeprecated::connect();
268 }
269
270
271 void FormBaseBD::disconnect()
272 {
273         u_.disconnect();
274         FormBaseDeprecated::disconnect();
275 }
276
277
278 namespace {
279
280 FormBaseDeprecated * GetForm(FL_OBJECT * ob)
281 {
282         lyx::Assert(ob && ob->form && ob->form->u_vdata);
283         FormBaseDeprecated * ptr =
284                 static_cast<FormBaseDeprecated *>(ob->form->u_vdata);
285         return ptr;
286 }
287
288 } // namespace anon
289
290
291 extern "C" {
292
293 void C_FormBaseDeprecatedApplyCB(FL_OBJECT * ob, long)
294 {
295         GetForm(ob)->ApplyCB();
296 }
297
298
299 void C_FormBaseDeprecatedOKCB(FL_OBJECT * ob, long)
300 {
301         GetForm(ob)->OKCB();
302 }
303
304
305 void C_FormBaseDeprecatedCancelCB(FL_OBJECT * ob, long)
306 {
307         GetForm(ob)->CancelCB();
308 }
309
310
311 void C_FormBaseDeprecatedInputCB(FL_OBJECT * ob, long d)
312 {
313         GetForm(ob)->InputCB(ob, d);
314 }
315
316
317 void C_FormBaseDeprecatedRestoreCB(FL_OBJECT * ob, long)
318 {
319         GetForm(ob)->RestoreCB();
320 }
321
322 static int C_WMHideCB(FL_FORM * form, void *)
323 {
324         // Close the dialog cleanly, even if the WM is used to do so.
325         lyx::Assert(form && form->u_vdata);
326         FormBaseDeprecated * ptr =
327                 static_cast<FormBaseDeprecated *>(form->u_vdata);
328         ptr->WMHideCB();
329         return FL_CANCEL;
330 }
331
332 static int C_PrehandlerCB(FL_OBJECT * ob, int event,
333                           FL_Coord, FL_Coord, int key, void *)
334 {
335         // Note that the return value is important in the pre-emptive handler.
336         // Don't return anything other than 0.
337         lyx::Assert(ob);
338
339         // Don't Assert this one, as it can happen quite naturally when things
340         // are being deleted in the d-tor.
341         //Assert(ob->form);
342         if (!ob->form) return 0;
343
344         FormBaseDeprecated * ptr =
345                 static_cast<FormBaseDeprecated *>(ob->form->u_vdata);
346
347         if (ptr)
348                 ptr->PrehandlerCB(ob, event, key);
349
350         return 0;
351 }
352
353 } // extern "C"