]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/utils.cpp
delay setting the window shape until it is realized (slightly modified patch 1935497)
[wxWidgets.git] / src / motif / utils.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/motif/utils.cpp
3// Purpose: Various utilities
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#include "wx/utils.h"
24
25#ifndef WX_PRECOMP
26 #include "wx/app.h"
27 #include "wx/dcmemory.h"
28 #include "wx/bitmap.h"
29#endif
30
31#include "wx/apptrait.h"
32#include "wx/evtloop.h"
33#include "wx/motif/private/timer.h"
34
35#include <string.h>
36
37#if (defined(__SUNCC__) || defined(__CLCC__))
38 #include <sysent.h>
39#endif
40
41#ifdef __VMS__
42#pragma message disable nosimpint
43#endif
44
45#include "wx/unix/execute.h"
46
47#include <Xm/Xm.h>
48#include <Xm/Frame.h>
49
50#include "wx/motif/private.h"
51
52#include "X11/Xutil.h"
53
54#ifdef __VMS__
55#pragma message enable nosimpint
56#endif
57
58
59// ============================================================================
60// implementation
61// ============================================================================
62
63// ----------------------------------------------------------------------------
64// async event processing
65// ----------------------------------------------------------------------------
66
67// Consume all events until no more left
68void wxFlushEvents(WXDisplay* wxdisplay)
69{
70 Display *display = (Display*)wxdisplay;
71 wxEventLoop evtLoop;
72
73 XSync (display, False);
74
75 while (evtLoop.Pending())
76 {
77 XFlush (display);
78 evtLoop.Dispatch();
79 }
80}
81
82// ----------------------------------------------------------------------------
83// wxExecute stuff
84// ----------------------------------------------------------------------------
85
86static void xt_notify_end_process(XtPointer data, int *WXUNUSED(fid),
87 XtInputId *id)
88{
89 wxEndProcessData *proc_data = (wxEndProcessData *)data;
90
91 wxHandleProcessTermination(proc_data);
92
93 // VZ: I think they should be the same...
94 wxASSERT( (int)*id == proc_data->tag );
95
96 XtRemoveInput(*id);
97}
98
99int wxGUIAppTraits::AddProcessCallback(wxEndProcessData *proc_data, int fd)
100{
101 XtInputId id = XtAppAddInput((XtAppContext) wxTheApp->GetAppContext(),
102 fd,
103 (XtPointer *) XtInputReadMask,
104 (XtInputCallbackProc) xt_notify_end_process,
105 (XtPointer) proc_data);
106
107 return (int)id;
108}
109
110// ----------------------------------------------------------------------------
111// misc
112// ----------------------------------------------------------------------------
113
114// Emit a beeeeeep
115#ifndef __EMX__
116// on OS/2, we use the wxBell from wxBase library (src/os2/utils.cpp)
117void wxBell()
118{
119 // Use current setting for the bell
120 XBell (wxGlobalDisplay(), 0);
121}
122#endif
123
124wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const
125{
126 // XmVERSION and XmREVISION are defined in Xm/Xm.h
127 if ( verMaj )
128 *verMaj = XmVERSION;
129 if ( verMin )
130 *verMin = XmREVISION;
131
132 return wxPORT_MOTIF;
133}
134
135wxEventLoopBase* wxGUIAppTraits::CreateEventLoop()
136{
137 return new wxEventLoop;
138}
139
140wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer* timer)
141{
142 return new wxMotifTimerImpl(timer);
143}
144
145// ----------------------------------------------------------------------------
146// display info
147// ----------------------------------------------------------------------------
148
149void wxGetMousePosition( int* x, int* y )
150{
151#if wxUSE_NANOX
152 // TODO
153 *x = 0;
154 *y = 0;
155#else
156 XMotionEvent xev;
157 Window root, child;
158 XQueryPointer(wxGlobalDisplay(),
159 DefaultRootWindow(wxGlobalDisplay()),
160 &root, &child,
161 &(xev.x_root), &(xev.y_root),
162 &(xev.x), &(xev.y),
163 &(xev.state));
164 *x = xev.x_root;
165 *y = xev.y_root;
166#endif
167}
168
169// Return true if we have a colour display
170bool wxColourDisplay()
171{
172 return wxDisplayDepth() > 1;
173}
174
175// Returns depth of screen
176int wxDisplayDepth()
177{
178 Display *dpy = wxGlobalDisplay();
179
180 return DefaultDepth (dpy, DefaultScreen (dpy));
181}
182
183// Get size of display
184void wxDisplaySize(int *width, int *height)
185{
186 Display *dpy = wxGlobalDisplay();
187
188 if ( width )
189 *width = DisplayWidth (dpy, DefaultScreen (dpy));
190 if ( height )
191 *height = DisplayHeight (dpy, DefaultScreen (dpy));
192}
193
194void wxDisplaySizeMM(int *width, int *height)
195{
196 Display *dpy = wxGlobalDisplay();
197
198 if ( width )
199 *width = DisplayWidthMM(dpy, DefaultScreen (dpy));
200 if ( height )
201 *height = DisplayHeightMM(dpy, DefaultScreen (dpy));
202}
203
204// Configurable display in wxX11 and wxMotif
205static WXDisplay *gs_currentDisplay = NULL;
206static wxString gs_displayName;
207
208WXDisplay *wxGetDisplay()
209{
210 if (gs_currentDisplay)
211 return gs_currentDisplay;
212 else if (wxTheApp)
213 return wxTheApp->GetInitialDisplay();
214 return NULL;
215}
216
217bool wxSetDisplay(const wxString& display_name)
218{
219 gs_displayName = display_name;
220
221 if ( display_name.empty() )
222 {
223 gs_currentDisplay = NULL;
224
225 return true;
226 }
227 else
228 {
229 Cardinal argc = 0;
230
231 Display *display = XtOpenDisplay((XtAppContext) wxTheApp->GetAppContext(),
232 display_name.c_str(),
233 wxTheApp->GetAppName().c_str(),
234 wxTheApp->GetClassName().c_str(),
235 NULL,
236#if XtSpecificationRelease < 5
237 0, &argc,
238#else
239 0, (int *)&argc,
240#endif
241 NULL);
242
243 if (display)
244 {
245 gs_currentDisplay = (WXDisplay*) display;
246 return true;
247 }
248 else
249 return false;
250 }
251}
252
253wxString wxGetDisplayName()
254{
255 return gs_displayName;
256}
257
258wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
259{
260 return wxGenericFindWindowAtPoint(pt);
261}
262
263// ----------------------------------------------------------------------------
264// Some colour manipulation routines
265// ----------------------------------------------------------------------------
266
267void wxHSVToXColor(wxHSV *hsv,XColor *rgb)
268{
269 int h = hsv->h;
270 int s = hsv->s;
271 int v = hsv->v;
272 int r = 0, g = 0, b = 0;
273 int i, f;
274 int p, q, t;
275 s = (s * wxMAX_RGB) / wxMAX_SV;
276 v = (v * wxMAX_RGB) / wxMAX_SV;
277 if (h == 360) h = 0;
278 if (s == 0) { h = 0; r = g = b = v; }
279 i = h / 60;
280 f = h % 60;
281 p = v * (wxMAX_RGB - s) / wxMAX_RGB;
282 q = v * (wxMAX_RGB - s * f / 60) / wxMAX_RGB;
283 t = v * (wxMAX_RGB - s * (60 - f) / 60) / wxMAX_RGB;
284 switch (i)
285 {
286 case 0: r = v, g = t, b = p; break;
287 case 1: r = q, g = v, b = p; break;
288 case 2: r = p, g = v, b = t; break;
289 case 3: r = p, g = q, b = v; break;
290 case 4: r = t, g = p, b = v; break;
291 case 5: r = v, g = p, b = q; break;
292 }
293 rgb->red = (unsigned short)(r << 8);
294 rgb->green = (unsigned short)(g << 8);
295 rgb->blue = (unsigned short)(b << 8);
296}
297
298void wxXColorToHSV(wxHSV *hsv,XColor *rgb)
299{
300 int r = rgb->red >> 8;
301 int g = rgb->green >> 8;
302 int b = rgb->blue >> 8;
303 int maxv = wxMax3(r, g, b);
304 int minv = wxMin3(r, g, b);
305 int h = 0, s, v;
306 v = maxv;
307 if (maxv) s = (maxv - minv) * wxMAX_RGB / maxv;
308 else s = 0;
309 if (s == 0) h = 0;
310 else
311 {
312 int rc, gc, bc, hex = 0;
313 rc = (maxv - r) * wxMAX_RGB / (maxv - minv);
314 gc = (maxv - g) * wxMAX_RGB / (maxv - minv);
315 bc = (maxv - b) * wxMAX_RGB / (maxv - minv);
316 if (r == maxv) { h = bc - gc, hex = 0; }
317 else if (g == maxv) { h = rc - bc, hex = 2; }
318 else if (b == maxv) { h = gc - rc, hex = 4; }
319 h = hex * 60 + (h * 60 / wxMAX_RGB);
320 if (h < 0) h += 360;
321 }
322 hsv->h = h;
323 hsv->s = (s * wxMAX_SV) / wxMAX_RGB;
324 hsv->v = (v * wxMAX_SV) / wxMAX_RGB;
325}
326
327void wxAllocNearestColor(Display *d,Colormap cmp,XColor *xc)
328{
329#if !wxUSE_NANOX
330 int llp;
331
332 int screen = DefaultScreen(d);
333 int num_colors = DisplayCells(d,screen);
334
335 XColor *color_defs = new XColor[num_colors];
336 for(llp = 0;llp < num_colors;llp++) color_defs[llp].pixel = llp;
337 XQueryColors(d,cmp,color_defs,num_colors);
338
339 wxHSV hsv_defs, hsv;
340 wxXColorToHSV(&hsv,xc);
341
342 int diff, min_diff = 0, pixel = 0;
343
344 for(llp = 0;llp < num_colors;llp++)
345 {
346 wxXColorToHSV(&hsv_defs,&color_defs[llp]);
347 diff = wxSIGN(wxH_WEIGHT * (hsv.h - hsv_defs.h)) +
348 wxSIGN(wxS_WEIGHT * (hsv.s - hsv_defs.s)) +
349 wxSIGN(wxV_WEIGHT * (hsv.v - hsv_defs.v));
350 if (llp == 0) min_diff = diff;
351 if (min_diff > diff) { min_diff = diff; pixel = llp; }
352 if (min_diff == 0) break;
353 }
354
355 xc -> red = color_defs[pixel].red;
356 xc -> green = color_defs[pixel].green;
357 xc -> blue = color_defs[pixel].blue;
358 xc -> flags = DoRed | DoGreen | DoBlue;
359
360/* FIXME, TODO
361 if (!XAllocColor(d,cmp,xc))
362 cout << "wxAllocNearestColor : Warning : Cannot find nearest color !\n";
363*/
364
365 delete[] color_defs;
366#endif
367}
368
369void wxAllocColor(Display *d,Colormap cmp,XColor *xc)
370{
371 if (!XAllocColor(d,cmp,xc))
372 {
373 // cout << "wxAllocColor : Warning : Can not allocate color, attempt find nearest !\n";
374 wxAllocNearestColor(d,cmp,xc);
375 }
376}
377
378#ifdef __WXDEBUG__
379wxString wxGetXEventName(XEvent& event)
380{
381#if wxUSE_NANOX
382 wxString str(wxT("(some event)"));
383 return str;
384#else
385 int type = event.xany.type;
386 static char* event_name[] = {
387 wxMOTIF_STR(""), wxMOTIF_STR("unknown(-)"), // 0-1
388 wxMOTIF_STR("KeyPress"), wxMOTIF_STR("KeyRelease"), wxMOTIF_STR("ButtonPress"), wxMOTIF_STR("ButtonRelease"), // 2-5
389 wxMOTIF_STR("MotionNotify"), wxMOTIF_STR("EnterNotify"), wxMOTIF_STR("LeaveNotify"), wxMOTIF_STR("FocusIn"), // 6-9
390 wxMOTIF_STR("FocusOut"), wxMOTIF_STR("KeymapNotify"), wxMOTIF_STR("Expose"), wxMOTIF_STR("GraphicsExpose"), // 10-13
391 wxMOTIF_STR("NoExpose"), wxMOTIF_STR("VisibilityNotify"), wxMOTIF_STR("CreateNotify"), // 14-16
392 wxMOTIF_STR("DestroyNotify"), wxMOTIF_STR("UnmapNotify"), wxMOTIF_STR("MapNotify"), wxMOTIF_STR("MapRequest"),// 17-20
393 wxMOTIF_STR("ReparentNotify"), wxMOTIF_STR("ConfigureNotify"), wxMOTIF_STR("ConfigureRequest"), // 21-23
394 wxMOTIF_STR("GravityNotify"), wxMOTIF_STR("ResizeRequest"), wxMOTIF_STR("CirculateNotify"), // 24-26
395 wxMOTIF_STR("CirculateRequest"), wxMOTIF_STR("PropertyNotify"), wxMOTIF_STR("SelectionClear"), // 27-29
396 wxMOTIF_STR("SelectionRequest"), wxMOTIF_STR("SelectionNotify"), wxMOTIF_STR("ColormapNotify"), // 30-32
397 wxMOTIF_STR("ClientMessage"), wxMOTIF_STR("MappingNotify"), // 33-34
398 wxMOTIF_STR("unknown(+)")}; // 35
399 type = wxMin(35, type); type = wxMax(1, type);
400 wxString str(event_name[type]);
401 return str;
402#endif
403}
404#endif
405
406// ----------------------------------------------------------------------------
407// accelerators
408// ----------------------------------------------------------------------------
409
410// Find the letter corresponding to the mnemonic, for Motif
411char wxFindMnemonic (const char *s)
412{
413 char mnem = 0;
414 int len = strlen (s);
415 int i;
416
417 for (i = 0; i < len; i++)
418 {
419 if (s[i] == '&')
420 {
421 // Carefully handle &&
422 if ((i + 1) <= len && s[i + 1] == '&')
423 i++;
424 else
425 {
426 mnem = s[i + 1];
427 break;
428 }
429 }
430 }
431 return mnem;
432}
433
434char* wxFindAccelerator( const char *s )
435{
436#if 1
437 wxUnusedVar(s);
438 // VZ: this function returns incorrect keysym which completely breaks kbd
439 // handling
440 return NULL;
441#else
442 // The accelerator text is after the \t char.
443 s = strchr( s, '\t' );
444
445 if( !s ) return NULL;
446
447 /*
448 Now we need to format it as X standard:
449
450 input output
451
452 F7 --> <Key>F7
453 Ctrl+N --> Ctrl<Key>N
454 Alt+k --> Meta<Key>k
455 Ctrl+Shift+A --> Ctrl Shift<Key>A
456
457 and handle Ctrl-N & similia
458 */
459
460 static char buf[256];
461
462 buf[0] = '\0';
463 wxString tmp = s + 1; // skip TAB
464 size_t index = 0;
465
466 while( index < tmp.length() )
467 {
468 size_t plus = tmp.find( '+', index );
469 size_t minus = tmp.find( '-', index );
470
471 // neither '+' nor '-', add <Key>
472 if( plus == wxString::npos && minus == wxString::npos )
473 {
474 strcat( buf, "<Key>" );
475 strcat( buf, tmp.c_str() + index );
476
477 return buf;
478 }
479
480 // OK: npos is big and positive
481 size_t sep = wxMin( plus, minus );
482 wxString mod = tmp.substr( index, sep - index );
483
484 // Ctrl -> Ctrl
485 // Shift -> Shift
486 // Alt -> Meta
487 if( mod == "Alt" )
488 mod = "Meta";
489
490 if( buf[0] )
491 strcat( buf, " " );
492
493 strcat( buf, mod.c_str() );
494
495 index = sep + 1;
496 }
497
498 return NULL;
499#endif
500}
501
502XmString wxFindAcceleratorText (const char *s)
503{
504#if 1
505 wxUnusedVar(s);
506 // VZ: this function returns incorrect keysym which completely breaks kbd
507 // handling
508 return NULL;
509#else
510 // The accelerator text is after the \t char.
511 s = strchr( s, '\t' );
512
513 if( !s ) return NULL;
514
515 return wxStringToXmString( s + 1 ); // skip TAB!
516#endif
517}
518
519// Change a widget's foreground and background colours.
520void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
521{
522 if (!foregroundColour.Ok())
523 return;
524
525 // When should we specify the foreground, if it's calculated
526 // by wxComputeColours?
527 // Solution: say we start with the default (computed) foreground colour.
528 // If we call SetForegroundColour explicitly for a control or window,
529 // then the foreground is changed.
530 // Therefore SetBackgroundColour computes the foreground colour, and
531 // SetForegroundColour changes the foreground colour. The ordering is
532 // important.
533
534 XtVaSetValues ((Widget) widget,
535 XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
536 NULL);
537}
538
539void wxDoChangeBackgroundColour(WXWidget widget, const wxColour& backgroundColour, bool changeArmColour)
540{
541 if (!backgroundColour.Ok())
542 return;
543
544 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
545 (wxColour*) NULL);
546
547 XtVaSetValues ((Widget) widget,
548 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
549 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
550 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
551 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
552 NULL);
553
554 if (changeArmColour)
555 XtVaSetValues ((Widget) widget,
556 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
557 NULL);
558}
559
560extern void wxDoChangeFont(WXWidget widget, const wxFont& font)
561{
562 // Lesstif 0.87 hangs here, but 0.93 does not; MBN: sometimes it does
563#if !wxCHECK_LESSTIF() // || wxCHECK_LESSTIF_VERSION( 0, 93 )
564 Widget w = (Widget)widget;
565 XtVaSetValues( w,
566 wxFont::GetFontTag(), font.GetFontTypeC( XtDisplay(w) ),
567 NULL );
568#else
569 wxUnusedVar(widget);
570 wxUnusedVar(font);
571#endif
572
573}
574
575wxString wxXmStringToString( const XmString& xmString )
576{
577 char *txt;
578 if( XmStringGetLtoR( xmString, XmSTRING_DEFAULT_CHARSET, &txt ) )
579 {
580 wxString str(txt);
581 XtFree (txt);
582 return str;
583 }
584
585 return wxEmptyString;
586}
587
588XmString wxStringToXmString( const char* str )
589{
590 return XmStringCreateLtoR((char *)str, XmSTRING_DEFAULT_CHARSET);
591}
592
593// ----------------------------------------------------------------------------
594// wxBitmap utility functions
595// ----------------------------------------------------------------------------
596
597// Creates a bitmap with transparent areas drawn in
598// the given colour.
599wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, const wxColour& colour)
600{
601 wxBitmap newBitmap(bitmap.GetWidth(),
602 bitmap.GetHeight(),
603 bitmap.GetDepth());
604 wxMemoryDC destDC;
605 wxMemoryDC srcDC;
606
607 srcDC.SelectObjectAsSource(bitmap);
608 destDC.SelectObject(newBitmap);
609
610 wxBrush brush(colour, wxSOLID);
611 destDC.SetBackground(brush);
612 destDC.Clear();
613 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(),
614 &srcDC, 0, 0, wxCOPY, true);
615
616 return newBitmap;
617}
618
619// ----------------------------------------------------------------------------
620// Miscellaneous functions
621// ----------------------------------------------------------------------------
622
623WXWidget wxCreateBorderWidget( WXWidget parent, long style )
624{
625 Widget borderWidget = (Widget)NULL, parentWidget = (Widget)parent;
626
627 if (style & wxSIMPLE_BORDER)
628 {
629 borderWidget = XtVaCreateManagedWidget
630 (
631 "simpleBorder",
632 xmFrameWidgetClass, parentWidget,
633 XmNshadowType, XmSHADOW_ETCHED_IN,
634 XmNshadowThickness, 1,
635 NULL
636 );
637 }
638 else if ((style & wxSUNKEN_BORDER) || (style & wxBORDER_THEME))
639 {
640 borderWidget = XtVaCreateManagedWidget
641 (
642 "sunkenBorder",
643 xmFrameWidgetClass, parentWidget,
644 XmNshadowType, XmSHADOW_IN,
645 NULL
646 );
647 }
648 else if (style & wxRAISED_BORDER)
649 {
650 borderWidget = XtVaCreateManagedWidget
651 (
652 "raisedBorder",
653 xmFrameWidgetClass, parentWidget,
654 XmNshadowType, XmSHADOW_OUT,
655 NULL
656 );
657 }
658
659 return borderWidget;
660}