]>
Commit | Line | Data |
---|---|---|
83df96d6 JS |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: windows.cpp | |
3 | // Purpose: wxWindow | |
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 | #ifdef __GNUG__ | |
21 | #pragma implementation "window.h" | |
22 | #endif | |
23 | ||
83df96d6 JS |
24 | #include "wx/setup.h" |
25 | #include "wx/menu.h" | |
26 | #include "wx/dc.h" | |
27 | #include "wx/dcclient.h" | |
28 | #include "wx/utils.h" | |
29 | #include "wx/app.h" | |
30 | #include "wx/panel.h" | |
31 | #include "wx/layout.h" | |
32 | #include "wx/dialog.h" | |
33 | #include "wx/listbox.h" | |
34 | #include "wx/button.h" | |
35 | #include "wx/settings.h" | |
36 | #include "wx/msgdlg.h" | |
37 | #include "wx/frame.h" | |
38 | #include "wx/scrolwin.h" | |
39 | #include "wx/module.h" | |
40 | #include "wx/menuitem.h" | |
41 | #include "wx/log.h" | |
42 | ||
43 | #if wxUSE_DRAG_AND_DROP | |
44 | #include "wx/dnd.h" | |
45 | #endif | |
46 | ||
bc797f4c | 47 | #include "wx/x11/private.h" |
7266b672 | 48 | #include "X11/Xutil.h" |
83df96d6 JS |
49 | |
50 | #include <string.h> | |
51 | ||
52 | // ---------------------------------------------------------------------------- | |
53 | // constants | |
54 | // ---------------------------------------------------------------------------- | |
55 | ||
56 | static const int SCROLL_MARGIN = 4; | |
57 | ||
58 | // ---------------------------------------------------------------------------- | |
59 | // global variables for this module | |
60 | // ---------------------------------------------------------------------------- | |
61 | ||
62 | extern wxHashTable *wxWidgetHashTable; | |
63 | static wxWindow* g_captureWindow = NULL; | |
64 | ||
83df96d6 JS |
65 | // ---------------------------------------------------------------------------- |
66 | // macros | |
67 | // ---------------------------------------------------------------------------- | |
68 | ||
69 | #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask) | |
70 | #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask) | |
71 | #define event_right_is_down(x) ((x)->xbutton.state & Button3Mask) | |
72 | ||
73 | // ---------------------------------------------------------------------------- | |
74 | // event tables | |
75 | // ---------------------------------------------------------------------------- | |
76 | ||
bc797f4c | 77 | IMPLEMENT_DYNAMIC_CLASS(wxWindowX11, wxWindowBase) |
83df96d6 | 78 | |
bc797f4c JS |
79 | BEGIN_EVENT_TABLE(wxWindowX11, wxWindowBase) |
80 | EVT_SYS_COLOUR_CHANGED(wxWindowX11::OnSysColourChanged) | |
81 | EVT_IDLE(wxWindowX11::OnIdle) | |
82 | END_EVENT_TABLE() | |
83df96d6 JS |
83 | |
84 | // ============================================================================ | |
85 | // implementation | |
86 | // ============================================================================ | |
87 | ||
88 | // ---------------------------------------------------------------------------- | |
89 | // helper functions | |
90 | // ---------------------------------------------------------------------------- | |
91 | ||
83df96d6 JS |
92 | // ---------------------------------------------------------------------------- |
93 | // constructors | |
94 | // ---------------------------------------------------------------------------- | |
95 | ||
bc797f4c | 96 | void wxWindowX11::Init() |
83df96d6 JS |
97 | { |
98 | // generic initializations first | |
99 | InitBase(); | |
100 | ||
7266b672 | 101 | // X11-specific |
b513212d | 102 | // TODO: prune those that are no longer needed |
83df96d6 | 103 | m_needsRefresh = TRUE; |
7266b672 | 104 | m_mainWidget = (WXWindow) 0; |
83df96d6 JS |
105 | |
106 | m_button1Pressed = | |
107 | m_button2Pressed = | |
108 | m_button3Pressed = FALSE; | |
109 | ||
110 | m_winCaptured = FALSE; | |
111 | ||
112 | m_isShown = TRUE; | |
113 | m_isBeingDeleted = FALSE; | |
114 | ||
115 | m_hScrollBar = | |
116 | m_vScrollBar = | |
117 | m_borderWidget = | |
118 | m_scrolledWindow = | |
7266b672 | 119 | m_drawingArea = (WXWindow) 0; |
83df96d6 JS |
120 | |
121 | m_hScroll = | |
122 | m_vScroll = FALSE; | |
123 | ||
124 | m_scrollPosX = | |
125 | m_scrollPosY = 0; | |
126 | ||
127 | m_backingPixmap = (WXPixmap) 0; | |
128 | m_pixmapWidth = | |
129 | m_pixmapHeight = 0; | |
130 | ||
131 | m_pixmapOffsetX = | |
132 | m_pixmapOffsetY = 0; | |
133 | ||
134 | m_lastTS = 0; | |
135 | m_lastButton = 0; | |
136 | m_canAddEventHandler = FALSE; | |
b513212d JS |
137 | |
138 | m_borderSize = 0; | |
83df96d6 JS |
139 | } |
140 | ||
141 | // real construction (Init() must have been called before!) | |
bc797f4c | 142 | bool wxWindowX11::Create(wxWindow *parent, wxWindowID id, |
83df96d6 JS |
143 | const wxPoint& pos, |
144 | const wxSize& size, | |
145 | long style, | |
146 | const wxString& name) | |
147 | { | |
148 | wxCHECK_MSG( parent, FALSE, "can't create wxWindow without parent" ); | |
149 | ||
150 | CreateBase(parent, id, pos, size, style, wxDefaultValidator, name); | |
151 | ||
b513212d JS |
152 | if (parent) |
153 | parent->AddChild(this); | |
83df96d6 JS |
154 | |
155 | m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); | |
156 | m_foregroundColour = *wxBLACK; | |
157 | ||
b513212d JS |
158 | // TODO: How to create more interesting borders? |
159 | // Will presumably have to create multiple windows. | |
83df96d6 JS |
160 | if (style & wxSIMPLE_BORDER) |
161 | { | |
b513212d | 162 | m_borderSize = 1; |
83df96d6 JS |
163 | } else if (style & wxSUNKEN_BORDER) |
164 | { | |
b513212d | 165 | m_borderSize = 1; |
83df96d6 JS |
166 | } else if (style & wxRAISED_BORDER) |
167 | { | |
b513212d | 168 | m_borderSize = 1; |
83df96d6 JS |
169 | } |
170 | ||
b513212d JS |
171 | int w = size.GetWidth(); |
172 | int h = size.GetHeight(); | |
173 | int x = size.GetX(); | |
174 | int y = size.GetY(); | |
175 | int h = size.GetHeight(); | |
176 | if (w == -1) w = 10; | |
177 | if (h == -1) h = 10; | |
178 | if (x == -1) x = 0; | |
179 | if (y == -1) y = 0; | |
83df96d6 | 180 | |
b513212d JS |
181 | int innerWidth = w - 2*m_borderSize; |
182 | int innerHeight = h - 2*m_borderSize; | |
183 | ||
184 | int screen = DefaultScreen(wxGlobalDisplay()); | |
185 | ||
186 | Window parentWindow; | |
187 | if (parent) | |
188 | parentWindow = (Window) parent->GetClientWindow(); | |
189 | else | |
190 | parentWindow = RootWindow(wxGlobalDisplay(), screen); | |
191 | ||
192 | Widget window = XCreateSimpleWindow(wxGlobalDisplay(), | |
193 | x, y, innerWidth, innerHeight, borderWidth, | |
194 | m_backgroundColour.AllocColour(wxGlobalDisplay()), | |
195 | m_foregroundColour.AllocColour(wxGlobalDisplay())); | |
196 | ||
197 | // Select event types wanted | |
198 | XSelectInput(wxGlobalDisplay(), window, | |
199 | ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | | |
200 | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | | |
201 | KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask | | |
202 | PropertyChangeMask); | |
203 | ||
204 | m_mainWindow = (WXWindow) window; | |
205 | ||
206 | wxAddWindowToTable(window, (wxWindow*) this); | |
207 | ||
208 | // If a subwindow, show. | |
209 | if (parent && !parent->IsKindOf(CLASSINFO(wxTopLevelWindowX11)) && parent->IsShown()) | |
210 | { | |
211 | m_isShown = TRUE; | |
212 | XMapWindow(wxGlobalDisplay(), window); | |
213 | } | |
83df96d6 JS |
214 | |
215 | // Without this, the cursor may not be restored properly (e.g. in splitter | |
216 | // sample). | |
217 | SetCursor(*wxSTANDARD_CURSOR); | |
218 | SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); | |
219 | SetSize(pos.x, pos.y, size.x, size.y); | |
220 | ||
221 | return TRUE; | |
222 | } | |
223 | ||
224 | // Destructor | |
7266b672 | 225 | wxWindowX11::~wxWindowX11() |
83df96d6 JS |
226 | { |
227 | if (g_captureWindow == this) | |
228 | g_captureWindow = NULL; | |
229 | ||
230 | m_isBeingDeleted = TRUE; | |
231 | ||
7266b672 | 232 | // X11-specific actions first |
bc797f4c | 233 | WXWindow wMain = GetMainWindow(); |
83df96d6 JS |
234 | if ( wMain ) |
235 | { | |
236 | // Removes event handlers | |
bc797f4c | 237 | //DetachWidget(wMain); |
83df96d6 JS |
238 | } |
239 | ||
240 | ClearUpdateRects(); | |
241 | ||
242 | if ( m_parent ) | |
243 | m_parent->RemoveChild( this ); | |
244 | ||
bc797f4c JS |
245 | // TODO |
246 | ||
247 | #if 0 | |
83df96d6 JS |
248 | // If m_drawingArea, we're a fully-fledged window with drawing area, |
249 | // scrollbars etc. (what wxCanvas used to be) | |
250 | if ( m_drawingArea ) | |
251 | { | |
252 | // Destroy children before destroying self | |
253 | DestroyChildren(); | |
254 | ||
255 | if (m_backingPixmap) | |
256 | XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap); | |
257 | ||
258 | Widget w = (Widget) m_drawingArea; | |
259 | wxDeleteWindowFromTable(w); | |
260 | ||
261 | if (w) | |
262 | { | |
263 | XtDestroyWidget(w); | |
264 | m_drawingArea = (WXWidget) 0; | |
265 | } | |
266 | ||
267 | // Only if we're _really_ a canvas (not a dialog box/panel) | |
268 | if (m_scrolledWindow) | |
269 | { | |
270 | wxDeleteWindowFromTable((Widget) m_scrolledWindow); | |
271 | } | |
272 | ||
273 | if (m_hScrollBar) | |
274 | { | |
275 | wxDeleteWindowFromTable((Widget) m_hScrollBar); | |
276 | XtUnmanageChild((Widget) m_hScrollBar); | |
277 | } | |
278 | if (m_vScrollBar) | |
279 | { | |
280 | wxDeleteWindowFromTable((Widget) m_vScrollBar); | |
281 | XtUnmanageChild((Widget) m_vScrollBar); | |
282 | } | |
283 | ||
284 | if (m_hScrollBar) | |
285 | XtDestroyWidget((Widget) m_hScrollBar); | |
286 | if (m_vScrollBar) | |
287 | XtDestroyWidget((Widget) m_vScrollBar); | |
288 | ||
289 | UnmanageAndDestroy(m_scrolledWindow); | |
290 | ||
291 | if (m_borderWidget) | |
292 | { | |
293 | XtDestroyWidget ((Widget) m_borderWidget); | |
294 | m_borderWidget = (WXWidget) 0; | |
295 | } | |
296 | } | |
297 | else // Why wasn't this here before? JACS 8/3/2000 | |
bc797f4c | 298 | #endif |
83df96d6 JS |
299 | DestroyChildren(); |
300 | ||
301 | ||
302 | // Destroy the window | |
bc797f4c JS |
303 | if (GetMainWindow()) |
304 | { | |
b513212d JS |
305 | XSelectInput(wxGlobalDisplay(), (Window) GetMainWindow(), |
306 | NoEventMask); | |
307 | wxDeleteWindowFromTable((Window) GetMainWindow()); | |
308 | XDestroyWindow((Window) GetMainWindow()); | |
bc797f4c | 309 | SetMainWindow((WXWindow) NULL); |
83df96d6 JS |
310 | } |
311 | } | |
312 | ||
313 | // ---------------------------------------------------------------------------- | |
314 | // scrollbar management | |
315 | // ---------------------------------------------------------------------------- | |
316 | ||
317 | // Helper function | |
bc797f4c | 318 | void wxWindowX11::CreateScrollbar(wxOrientation orientation) |
83df96d6 | 319 | { |
bc797f4c JS |
320 | // TODO |
321 | #if 0 | |
83df96d6 JS |
322 | wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" ); |
323 | ||
324 | XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL); | |
325 | ||
326 | // Add scrollbars if required | |
327 | if (orientation == wxHORIZONTAL) | |
328 | { | |
329 | Widget hScrollBar = XtVaCreateManagedWidget ("hsb", | |
330 | xmScrollBarWidgetClass, (Widget) m_scrolledWindow, | |
331 | XmNorientation, XmHORIZONTAL, | |
332 | NULL); | |
333 | XtAddCallback (hScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); | |
334 | XtAddCallback (hScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); | |
335 | XtAddCallback (hScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); | |
336 | XtAddCallback (hScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); | |
337 | XtAddCallback (hScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); | |
338 | XtAddCallback (hScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); | |
339 | XtAddCallback (hScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); | |
340 | XtAddCallback (hScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmHORIZONTAL); | |
341 | ||
342 | XtVaSetValues (hScrollBar, | |
343 | XmNincrement, 1, | |
344 | XmNvalue, 0, | |
345 | NULL); | |
346 | ||
347 | m_hScrollBar = (WXWidget) hScrollBar; | |
348 | ||
349 | wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); | |
350 | DoChangeBackgroundColour(m_hScrollBar, backgroundColour, TRUE); | |
351 | ||
352 | XtRealizeWidget(hScrollBar); | |
353 | ||
354 | XtVaSetValues((Widget) m_scrolledWindow, | |
355 | XmNhorizontalScrollBar, (Widget) m_hScrollBar, | |
356 | NULL); | |
357 | ||
358 | m_hScroll = TRUE; | |
359 | ||
360 | wxAddWindowToTable( hScrollBar, this ); | |
361 | } | |
362 | ||
363 | if (orientation == wxVERTICAL) | |
364 | { | |
365 | Widget vScrollBar = XtVaCreateManagedWidget ("vsb", | |
366 | xmScrollBarWidgetClass, (Widget) m_scrolledWindow, | |
367 | XmNorientation, XmVERTICAL, | |
368 | NULL); | |
369 | XtAddCallback (vScrollBar, XmNvalueChangedCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); | |
370 | XtAddCallback (vScrollBar, XmNdragCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); | |
371 | XtAddCallback (vScrollBar, XmNincrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); | |
372 | XtAddCallback (vScrollBar, XmNdecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); | |
373 | XtAddCallback (vScrollBar, XmNpageIncrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); | |
374 | XtAddCallback (vScrollBar, XmNpageDecrementCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); | |
375 | XtAddCallback (vScrollBar, XmNtoTopCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); | |
376 | XtAddCallback (vScrollBar, XmNtoBottomCallback, (XtCallbackProc) wxScrollBarCallback, (XtPointer) XmVERTICAL); | |
377 | ||
378 | XtVaSetValues (vScrollBar, | |
379 | XmNincrement, 1, | |
380 | XmNvalue, 0, | |
381 | NULL); | |
382 | ||
383 | m_vScrollBar = (WXWidget) vScrollBar; | |
384 | wxColour backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); | |
385 | DoChangeBackgroundColour(m_vScrollBar, backgroundColour, TRUE); | |
386 | ||
387 | XtRealizeWidget(vScrollBar); | |
388 | ||
389 | XtVaSetValues((Widget) m_scrolledWindow, | |
390 | XmNverticalScrollBar, (Widget) m_vScrollBar, | |
391 | NULL); | |
392 | ||
393 | m_vScroll = TRUE; | |
394 | ||
395 | wxAddWindowToTable( vScrollBar, this ); | |
396 | } | |
397 | ||
398 | XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL); | |
bc797f4c | 399 | #endif |
83df96d6 JS |
400 | } |
401 | ||
bc797f4c | 402 | void wxWindowX11::DestroyScrollbar(wxOrientation orientation) |
83df96d6 | 403 | { |
bc797f4c JS |
404 | // TODO |
405 | #if 0 | |
83df96d6 JS |
406 | wxCHECK_RET( m_drawingArea, "this window can't have scrollbars" ); |
407 | ||
408 | XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_NONE, NULL); | |
409 | // Add scrollbars if required | |
410 | if (orientation == wxHORIZONTAL) | |
411 | { | |
412 | if (m_hScrollBar) | |
413 | { | |
414 | wxDeleteWindowFromTable((Widget)m_hScrollBar); | |
415 | XtDestroyWidget((Widget) m_hScrollBar); | |
416 | } | |
417 | m_hScrollBar = (WXWidget) 0; | |
418 | m_hScroll = FALSE; | |
419 | ||
420 | XtVaSetValues((Widget) m_scrolledWindow, | |
421 | XmNhorizontalScrollBar, (Widget) 0, | |
422 | NULL); | |
423 | ||
424 | } | |
425 | ||
426 | if (orientation == wxVERTICAL) | |
427 | { | |
428 | if (m_vScrollBar) | |
429 | { | |
430 | wxDeleteWindowFromTable((Widget)m_vScrollBar); | |
431 | XtDestroyWidget((Widget) m_vScrollBar); | |
432 | } | |
433 | m_vScrollBar = (WXWidget) 0; | |
434 | m_vScroll = FALSE; | |
435 | ||
436 | XtVaSetValues((Widget) m_scrolledWindow, | |
437 | XmNverticalScrollBar, (Widget) 0, | |
438 | NULL); | |
439 | ||
440 | } | |
441 | XtVaSetValues((Widget) m_scrolledWindow, XmNresizePolicy, XmRESIZE_ANY, NULL); | |
bc797f4c | 442 | #endif |
83df96d6 JS |
443 | } |
444 | ||
445 | // --------------------------------------------------------------------------- | |
446 | // basic operations | |
447 | // --------------------------------------------------------------------------- | |
448 | ||
bc797f4c | 449 | void wxWindowX11::SetFocus() |
83df96d6 | 450 | { |
b513212d JS |
451 | Window wMain = (Window) GetMainWidget(); |
452 | if (wMain) | |
453 | { | |
454 | XSetInputFocus(wxGlobalDisplay(), wMain, RevertToParent, CurrentTime); | |
455 | ||
456 | XWMHints wmhints; | |
457 | wmhints.flags = InputHint; | |
458 | wmhints.input = True; | |
459 | XSetWMHints(wxGlobalDisplay(), wMain, &wmhints) | |
460 | } | |
83df96d6 JS |
461 | } |
462 | ||
463 | // Get the window with the focus | |
464 | wxWindow *wxWindowBase::FindFocus() | |
465 | { | |
b513212d JS |
466 | Window wFocus = (Window) 0; |
467 | int revert = 0; | |
bc797f4c | 468 | |
b513212d JS |
469 | XGetInputFocus(wxGlobalDisplay(), & wFocus, & revert); |
470 | if (wFocus) | |
83df96d6 | 471 | { |
b513212d JS |
472 | wxWindow *win = NULL; |
473 | do | |
83df96d6 | 474 | { |
b513212d JS |
475 | win = wxGetWindowFromTable(wFocus); |
476 | wFocus = wxGetWindowParent(wFocus); | |
477 | } while (wFocus && !win); | |
478 | ||
479 | return win; | |
83df96d6 JS |
480 | } |
481 | ||
b513212d | 482 | return NULL; |
83df96d6 JS |
483 | } |
484 | ||
b513212d JS |
485 | // Enabling/disabling handled by event loop, and not sending events |
486 | // if disabled. | |
bc797f4c | 487 | bool wxWindowX11::Enable(bool enable) |
83df96d6 JS |
488 | { |
489 | if ( !wxWindowBase::Enable(enable) ) | |
490 | return FALSE; | |
b513212d | 491 | |
83df96d6 JS |
492 | return TRUE; |
493 | } | |
494 | ||
bc797f4c | 495 | bool wxWindowX11::Show(bool show) |
83df96d6 JS |
496 | { |
497 | if ( !wxWindowBase::Show(show) ) | |
498 | return FALSE; | |
499 | ||
83df96d6 JS |
500 | Window xwin = (Window) GetXWindow(); |
501 | Display *xdisp = (Display*) GetXDisplay(); | |
502 | if (show) | |
b513212d | 503 | { |
83df96d6 | 504 | XMapWindow(xdisp, xwin); |
b513212d | 505 | } |
83df96d6 | 506 | else |
b513212d | 507 | { |
83df96d6 | 508 | XUnmapWindow(xdisp, xwin); |
b513212d | 509 | } |
83df96d6 JS |
510 | |
511 | return TRUE; | |
512 | } | |
513 | ||
514 | // Raise the window to the top of the Z order | |
bc797f4c | 515 | void wxWindowX11::Raise() |
83df96d6 | 516 | { |
7266b672 | 517 | Window window = (Window) GetTopWindow(); |
bc797f4c | 518 | if (window) |
b513212d | 519 | XRaiseWindow(wxGlobalDisplay(), window); |
83df96d6 JS |
520 | } |
521 | ||
522 | // Lower the window to the bottom of the Z order | |
bc797f4c | 523 | void wxWindowX11::Lower() |
83df96d6 | 524 | { |
7266b672 | 525 | Window window = (Window) GetTopWindow(); |
bc797f4c | 526 | if (window) |
b513212d | 527 | XLowerWindow(wxGlobalDisplay(), window); |
83df96d6 JS |
528 | } |
529 | ||
bc797f4c | 530 | void wxWindowX11::DoCaptureMouse() |
83df96d6 | 531 | { |
7266b672 | 532 | g_captureWindow = (wxWindow*) this; |
83df96d6 JS |
533 | if ( m_winCaptured ) |
534 | return; | |
535 | ||
b513212d JS |
536 | // TODO: should we also call XGrabButton, XGrabKeyboard? |
537 | if (GetMainWindow()) | |
538 | { | |
539 | int res = XGrabPointer(wxGlobalDisplay(), (Window) GetMainWindow(), | |
540 | FALSE, | |
541 | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask, | |
542 | GrabModeAsync, | |
543 | GrabModeAsync, | |
544 | None, | |
545 | None, /* cursor */ // TODO: This may need to be set to the cursor of this window | |
546 | CurrentTime); | |
547 | ||
548 | if (res == GrabSuccess) | |
549 | { | |
550 | m_winCaptured = TRUE; | |
551 | } | |
552 | } | |
83df96d6 JS |
553 | } |
554 | ||
bc797f4c | 555 | void wxWindowX11::DoReleaseMouse() |
83df96d6 JS |
556 | { |
557 | g_captureWindow = NULL; | |
558 | if ( !m_winCaptured ) | |
559 | return; | |
560 | ||
561 | Widget wMain = (Widget)GetMainWidget(); | |
b513212d JS |
562 | |
563 | // TODO: should we also call XUngrabButton, XUngrabKeyboard? | |
83df96d6 | 564 | if ( wMain ) |
b513212d | 565 | XUngrabPointer(wxGlobalDisplay(), wMain); |
83df96d6 JS |
566 | |
567 | m_winCaptured = FALSE; | |
568 | } | |
569 | ||
bc797f4c | 570 | bool wxWindowX11::SetFont(const wxFont& font) |
83df96d6 JS |
571 | { |
572 | if ( !wxWindowBase::SetFont(font) ) | |
573 | { | |
574 | // nothing to do | |
575 | return FALSE; | |
576 | } | |
577 | ||
578 | ChangeFont(); | |
579 | ||
580 | return TRUE; | |
581 | } | |
582 | ||
bc797f4c | 583 | bool wxWindowX11::SetCursor(const wxCursor& cursor) |
83df96d6 JS |
584 | { |
585 | if ( !wxWindowBase::SetCursor(cursor) ) | |
586 | { | |
587 | // no change | |
588 | return FALSE; | |
589 | } | |
590 | ||
83df96d6 JS |
591 | wxCursor* cursor2 = NULL; |
592 | if (m_cursor.Ok()) | |
593 | cursor2 = & m_cursor; | |
594 | else | |
595 | cursor2 = wxSTANDARD_CURSOR; | |
596 | ||
597 | WXDisplay *dpy = GetXDisplay(); | |
598 | WXCursor x_cursor = cursor2->GetXCursor(dpy); | |
599 | ||
bc797f4c | 600 | Window win = (Window) GetMainWindow(); |
83df96d6 JS |
601 | XDefineCursor((Display*) dpy, win, (Cursor) x_cursor); |
602 | ||
603 | return TRUE; | |
604 | } | |
605 | ||
606 | // Coordinates relative to the window | |
bc797f4c | 607 | void wxWindowX11::WarpPointer (int x, int y) |
83df96d6 | 608 | { |
bc797f4c | 609 | Window wClient = (Window) GetClientWindow(); |
83df96d6 | 610 | |
b513212d | 611 | XWarpPointer(wxGlobalDisplay(), None, wClient, 0, 0, 0, 0, x, y); |
83df96d6 JS |
612 | } |
613 | ||
614 | // --------------------------------------------------------------------------- | |
615 | // scrolling stuff | |
616 | // --------------------------------------------------------------------------- | |
617 | ||
bc797f4c | 618 | int wxWindowX11::GetScrollPos(int orient) const |
83df96d6 JS |
619 | { |
620 | if (orient == wxHORIZONTAL) | |
621 | return m_scrollPosX; | |
622 | else | |
623 | return m_scrollPosY; | |
83df96d6 JS |
624 | } |
625 | ||
626 | // This now returns the whole range, not just the number of positions that we | |
627 | // can scroll. | |
bc797f4c | 628 | int wxWindowX11::GetScrollRange(int WXUNUSED(orient)) const |
83df96d6 | 629 | { |
bc797f4c JS |
630 | // TODO |
631 | return 0; | |
632 | #if 0 | |
83df96d6 JS |
633 | Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient); |
634 | wxCHECK_MSG( scrollBar, 0, "no such scrollbar" ); | |
635 | ||
636 | int range; | |
637 | XtVaGetValues(scrollBar, XmNmaximum, &range, NULL); | |
638 | return range; | |
bc797f4c | 639 | #endif |
83df96d6 JS |
640 | } |
641 | ||
bc797f4c | 642 | int wxWindowX11::GetScrollThumb(int orient) const |
83df96d6 | 643 | { |
bc797f4c JS |
644 | // TODO |
645 | return 0; | |
646 | ||
647 | #if 0 | |
83df96d6 JS |
648 | Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient); |
649 | wxCHECK_MSG( scrollBar, 0, "no such scrollbar" ); | |
650 | ||
651 | int thumb; | |
652 | XtVaGetValues(scrollBar, XmNsliderSize, &thumb, NULL); | |
653 | return thumb; | |
bc797f4c | 654 | #endif |
83df96d6 JS |
655 | } |
656 | ||
7266b672 | 657 | void wxWindowX11::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) |
83df96d6 | 658 | { |
bc797f4c JS |
659 | // TODO |
660 | ||
661 | #if 0 | |
83df96d6 JS |
662 | Widget scrollBar = (Widget)GetScrollbar((wxOrientation)orient); |
663 | ||
664 | if ( scrollBar ) | |
665 | { | |
666 | XtVaSetValues (scrollBar, XmNvalue, pos, NULL); | |
667 | } | |
bc797f4c | 668 | #endif |
83df96d6 JS |
669 | SetInternalScrollPos((wxOrientation)orient, pos); |
670 | } | |
671 | ||
672 | // New function that will replace some of the above. | |
bc797f4c JS |
673 | void wxWindowX11::SetScrollbar(int WXUNUSED(orient), int WXUNUSED(pos), int WXUNUSED(thumbVisible), |
674 | int WXUNUSED(range), bool WXUNUSED(refresh)) | |
83df96d6 | 675 | { |
bc797f4c JS |
676 | // TODO |
677 | #if 0 | |
83df96d6 JS |
678 | int oldW, oldH; |
679 | GetSize(& oldW, & oldH); | |
680 | ||
681 | if (range == 0) | |
682 | range = 1; | |
683 | if (thumbVisible == 0) | |
684 | thumbVisible = 1; | |
685 | ||
686 | if (thumbVisible > range) | |
687 | thumbVisible = range; | |
688 | ||
689 | // Save the old state to see if it changed | |
690 | WXWidget oldScrollBar = GetScrollbar((wxOrientation)orient); | |
691 | ||
692 | if (orient == wxHORIZONTAL) | |
693 | { | |
694 | if (thumbVisible == range) | |
695 | { | |
696 | if (m_hScrollBar) | |
697 | DestroyScrollbar(wxHORIZONTAL); | |
698 | } | |
699 | else | |
700 | { | |
701 | if (!m_hScrollBar) | |
702 | CreateScrollbar(wxHORIZONTAL); | |
703 | } | |
704 | } | |
705 | if (orient == wxVERTICAL) | |
706 | { | |
707 | if (thumbVisible == range) | |
708 | { | |
709 | if (m_vScrollBar) | |
710 | DestroyScrollbar(wxVERTICAL); | |
711 | } | |
712 | else | |
713 | { | |
714 | if (!m_vScrollBar) | |
715 | CreateScrollbar(wxVERTICAL); | |
716 | } | |
717 | } | |
718 | WXWidget newScrollBar = GetScrollbar((wxOrientation)orient); | |
719 | ||
720 | if (oldScrollBar != newScrollBar) | |
721 | { | |
722 | // This is important! Without it, scrollbars misbehave badly. | |
723 | XtUnrealizeWidget((Widget) m_scrolledWindow); | |
724 | XmScrolledWindowSetAreas ((Widget) m_scrolledWindow, (Widget) m_hScrollBar, (Widget) m_vScrollBar, (Widget) m_drawingArea); | |
725 | XtRealizeWidget((Widget) m_scrolledWindow); | |
726 | XtManageChild((Widget) m_scrolledWindow); | |
727 | } | |
728 | ||
729 | if (newScrollBar) | |
730 | { | |
731 | XtVaSetValues((Widget) newScrollBar, | |
732 | XmNvalue, pos, | |
733 | XmNminimum, 0, | |
734 | XmNmaximum, range, | |
735 | XmNsliderSize, thumbVisible, | |
736 | NULL); | |
737 | } | |
738 | ||
739 | SetInternalScrollPos((wxOrientation)orient, pos); | |
740 | ||
741 | int newW, newH; | |
742 | GetSize(& newW, & newH); | |
743 | ||
744 | // Adjusting scrollbars can resize the canvas accidentally | |
745 | if (newW != oldW || newH != oldH) | |
746 | SetSize(-1, -1, oldW, oldH); | |
bc797f4c | 747 | #endif |
83df96d6 JS |
748 | } |
749 | ||
750 | // Does a physical scroll | |
bc797f4c | 751 | void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect) |
83df96d6 JS |
752 | { |
753 | int x, y, w, h; | |
754 | if (rect) | |
755 | { | |
756 | // Use specified rectangle | |
757 | x = rect->x; y = rect->y; w = rect->width; h = rect->height; | |
758 | } | |
759 | else | |
760 | { | |
761 | // Use whole client area | |
762 | x = 0; y = 0; | |
763 | GetClientSize(& w, & h); | |
764 | } | |
bc797f4c | 765 | |
83df96d6 JS |
766 | wxNode *cnode = m_children.First(); |
767 | while (cnode) | |
768 | { | |
769 | wxWindow *child = (wxWindow*) cnode->Data(); | |
bc797f4c JS |
770 | int sx = 0; |
771 | int sy = 0; | |
772 | child->GetSize( &sx, &sy ); | |
83df96d6 | 773 | wxPoint pos( child->GetPosition() ); |
bc797f4c JS |
774 | child->SetSize( pos.x + dx, pos.y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE ); |
775 | cnode = cnode->Next(); | |
83df96d6 | 776 | } |
bc797f4c | 777 | |
83df96d6 JS |
778 | int x1 = (dx >= 0) ? x : x - dx; |
779 | int y1 = (dy >= 0) ? y : y - dy; | |
780 | int w1 = w - abs(dx); | |
781 | int h1 = h - abs(dy); | |
782 | int x2 = (dx >= 0) ? x + dx : x; | |
783 | int y2 = (dy >= 0) ? y + dy : y; | |
bc797f4c | 784 | |
7266b672 | 785 | wxClientDC dc((wxWindow*) this); |
bc797f4c | 786 | |
83df96d6 | 787 | dc.SetLogicalFunction (wxCOPY); |
bc797f4c JS |
788 | |
789 | Window window = (Window) GetMainWindow(); | |
b513212d | 790 | Display* display = wxGlobalDisplay(); |
bc797f4c | 791 | |
83df96d6 | 792 | XCopyArea(display, window, window, (GC) dc.GetGC(), |
bc797f4c JS |
793 | x1, y1, w1, h1, x2, y2); |
794 | ||
83df96d6 JS |
795 | dc.SetAutoSetting(TRUE); |
796 | wxBrush brush(GetBackgroundColour(), wxSOLID); | |
797 | dc.SetBrush(brush); // FIXME: needed? | |
bc797f4c | 798 | |
83df96d6 JS |
799 | // We'll add rectangles to the list of update rectangles according to which |
800 | // bits we've exposed. | |
801 | wxList updateRects; | |
bc797f4c | 802 | |
83df96d6 JS |
803 | if (dx > 0) |
804 | { | |
805 | wxRect *rect = new wxRect; | |
806 | rect->x = x; | |
807 | rect->y = y; | |
808 | rect->width = dx; | |
809 | rect->height = h; | |
bc797f4c | 810 | |
83df96d6 JS |
811 | XFillRectangle(display, window, |
812 | (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height); | |
bc797f4c | 813 | |
83df96d6 JS |
814 | rect->x = rect->x; |
815 | rect->y = rect->y; | |
816 | rect->width = rect->width; | |
817 | rect->height = rect->height; | |
bc797f4c | 818 | |
83df96d6 JS |
819 | updateRects.Append((wxObject*) rect); |
820 | } | |
821 | else if (dx < 0) | |
822 | { | |
823 | wxRect *rect = new wxRect; | |
bc797f4c | 824 | |
83df96d6 JS |
825 | rect->x = x + w + dx; |
826 | rect->y = y; | |
827 | rect->width = -dx; | |
828 | rect->height = h; | |
bc797f4c | 829 | |
83df96d6 JS |
830 | XFillRectangle(display, window, |
831 | (GC) dc.GetGC(), rect->x, rect->y, rect->width, | |
832 | rect->height); | |
bc797f4c | 833 | |
83df96d6 JS |
834 | rect->x = rect->x; |
835 | rect->y = rect->y; | |
836 | rect->width = rect->width; | |
837 | rect->height = rect->height; | |
bc797f4c | 838 | |
83df96d6 JS |
839 | updateRects.Append((wxObject*) rect); |
840 | } | |
841 | if (dy > 0) | |
842 | { | |
843 | wxRect *rect = new wxRect; | |
bc797f4c | 844 | |
83df96d6 JS |
845 | rect->x = x; |
846 | rect->y = y; | |
847 | rect->width = w; | |
848 | rect->height = dy; | |
bc797f4c | 849 | |
83df96d6 JS |
850 | XFillRectangle(display, window, |
851 | (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height); | |
bc797f4c | 852 | |
83df96d6 JS |
853 | rect->x = rect->x; |
854 | rect->y = rect->y; | |
855 | rect->width = rect->width; | |
856 | rect->height = rect->height; | |
bc797f4c | 857 | |
83df96d6 JS |
858 | updateRects.Append((wxObject*) rect); |
859 | } | |
860 | else if (dy < 0) | |
861 | { | |
862 | wxRect *rect = new wxRect; | |
bc797f4c | 863 | |
83df96d6 JS |
864 | rect->x = x; |
865 | rect->y = y + h + dy; | |
866 | rect->width = w; | |
867 | rect->height = -dy; | |
bc797f4c | 868 | |
83df96d6 JS |
869 | XFillRectangle(display, window, |
870 | (GC) dc.GetGC(), rect->x, rect->y, rect->width, rect->height); | |
bc797f4c | 871 | |
83df96d6 JS |
872 | rect->x = rect->x; |
873 | rect->y = rect->y; | |
874 | rect->width = rect->width; | |
875 | rect->height = rect->height; | |
bc797f4c | 876 | |
83df96d6 JS |
877 | updateRects.Append((wxObject*) rect); |
878 | } | |
879 | dc.SetBrush(wxNullBrush); | |
bc797f4c | 880 | |
83df96d6 | 881 | // Now send expose events |
bc797f4c | 882 | |
83df96d6 JS |
883 | wxNode* node = updateRects.First(); |
884 | while (node) | |
885 | { | |
886 | wxRect* rect = (wxRect*) node->Data(); | |
887 | XExposeEvent event; | |
bc797f4c | 888 | |
83df96d6 JS |
889 | event.type = Expose; |
890 | event.display = display; | |
891 | event.send_event = True; | |
892 | event.window = window; | |
bc797f4c | 893 | |
83df96d6 JS |
894 | event.x = rect->x; |
895 | event.y = rect->y; | |
896 | event.width = rect->width; | |
897 | event.height = rect->height; | |
bc797f4c | 898 | |
83df96d6 | 899 | event.count = 0; |
bc797f4c | 900 | |
83df96d6 | 901 | XSendEvent(display, window, False, ExposureMask, (XEvent *)&event); |
bc797f4c | 902 | |
83df96d6 | 903 | node = node->Next(); |
bc797f4c | 904 | |
83df96d6 | 905 | } |
bc797f4c | 906 | |
83df96d6 JS |
907 | // Delete the update rects |
908 | node = updateRects.First(); | |
909 | while (node) | |
910 | { | |
911 | wxRect* rect = (wxRect*) node->Data(); | |
912 | delete rect; | |
913 | node = node->Next(); | |
914 | } | |
bc797f4c JS |
915 | |
916 | // TODO | |
83df96d6 | 917 | |
bc797f4c | 918 | // XmUpdateDisplay((Widget) GetMainWidget()); |
83df96d6 JS |
919 | } |
920 | ||
921 | // --------------------------------------------------------------------------- | |
922 | // drag and drop | |
923 | // --------------------------------------------------------------------------- | |
924 | ||
925 | #if wxUSE_DRAG_AND_DROP | |
926 | ||
bc797f4c | 927 | void wxWindowX11::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget)) |
83df96d6 JS |
928 | { |
929 | // TODO | |
930 | } | |
931 | ||
932 | #endif | |
933 | ||
934 | // Old style file-manager drag&drop | |
bc797f4c | 935 | void wxWindowX11::DragAcceptFiles(bool WXUNUSED(accept)) |
83df96d6 JS |
936 | { |
937 | // TODO | |
938 | } | |
939 | ||
940 | // ---------------------------------------------------------------------------- | |
941 | // tooltips | |
942 | // ---------------------------------------------------------------------------- | |
943 | ||
944 | #if wxUSE_TOOLTIPS | |
945 | ||
bc797f4c | 946 | void wxWindowX11::DoSetToolTip(wxToolTip * WXUNUSED(tooltip)) |
83df96d6 JS |
947 | { |
948 | // TODO | |
949 | } | |
950 | ||
951 | #endif // wxUSE_TOOLTIPS | |
952 | ||
83df96d6 JS |
953 | // --------------------------------------------------------------------------- |
954 | // moving and resizing | |
955 | // --------------------------------------------------------------------------- | |
956 | ||
bc797f4c | 957 | bool wxWindowX11::PreResize() |
83df96d6 JS |
958 | { |
959 | return TRUE; | |
960 | } | |
961 | ||
962 | // Get total size | |
bc797f4c | 963 | void wxWindowX11::DoGetSize(int *x, int *y) const |
83df96d6 | 964 | { |
b513212d JS |
965 | Window window = (Window) GetTopWindow(); |
966 | if (window) | |
83df96d6 | 967 | { |
b513212d JS |
968 | XWindowAttributes attr; |
969 | Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr); | |
970 | wxASSERT(status); | |
971 | ||
972 | if (status) | |
973 | { | |
974 | *x = attr.width + 2*m_borderSize; | |
975 | *y = attr.height + 2*m_borderSize; | |
976 | } | |
83df96d6 | 977 | } |
83df96d6 JS |
978 | } |
979 | ||
bc797f4c | 980 | void wxWindowX11::DoGetPosition(int *x, int *y) const |
83df96d6 | 981 | { |
b513212d JS |
982 | Window window = (Window) GetTopWindow(); |
983 | if (window) | |
83df96d6 | 984 | { |
b513212d JS |
985 | XWindowAttributes attr; |
986 | Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr); | |
987 | wxASSERT(status); | |
988 | ||
989 | if (status) | |
990 | { | |
991 | *x = attr.x; | |
992 | *y = attr.y; | |
993 | ||
994 | // We may be faking the client origin. So a window that's really at (0, 30) | |
995 | // may appear (to wxWin apps) to be at (0, 0). | |
996 | if (GetParent()) | |
997 | { | |
998 | wxPoint pt(GetParent()->GetClientAreaOrigin()); | |
999 | *x -= pt.x; | |
1000 | *y -= pt.y; | |
1001 | } | |
1002 | } | |
83df96d6 | 1003 | } |
83df96d6 JS |
1004 | } |
1005 | ||
bc797f4c | 1006 | void wxWindowX11::DoScreenToClient(int *x, int *y) const |
83df96d6 | 1007 | { |
b513212d | 1008 | Display *display = wxGlobalDisplay(); |
bc797f4c JS |
1009 | Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display)); |
1010 | Window thisWindow = (Window) GetClientWindow(); | |
83df96d6 JS |
1011 | |
1012 | Window childWindow; | |
1013 | int xx = *x; | |
1014 | int yy = *y; | |
1015 | XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow); | |
1016 | } | |
1017 | ||
bc797f4c | 1018 | void wxWindowX11::DoClientToScreen(int *x, int *y) const |
83df96d6 | 1019 | { |
b513212d | 1020 | Display *display = wxGlobalDisplay(); |
bc797f4c JS |
1021 | Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display)); |
1022 | Window thisWindow = (Window) GetClientWindow(); | |
83df96d6 JS |
1023 | |
1024 | Window childWindow; | |
1025 | int xx = *x; | |
1026 | int yy = *y; | |
1027 | XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow); | |
1028 | } | |
1029 | ||
1030 | ||
1031 | // Get size *available for subwindows* i.e. excluding menu bar etc. | |
bc797f4c | 1032 | void wxWindowX11::DoGetClientSize(int *x, int *y) const |
83df96d6 | 1033 | { |
b513212d JS |
1034 | Window window = (Window) GetClientWindow(); |
1035 | ||
1036 | if (window) | |
1037 | { | |
1038 | XWindowAttributes attr; | |
1039 | Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr); | |
1040 | wxASSERT(status); | |
1041 | ||
1042 | if (status) | |
1043 | { | |
1044 | *x = attr.width ; | |
1045 | *y = attr.height ; | |
1046 | } | |
1047 | } | |
83df96d6 JS |
1048 | } |
1049 | ||
bc797f4c | 1050 | void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags) |
83df96d6 | 1051 | { |
b513212d JS |
1052 | if (!GetMainWindow()) |
1053 | return; | |
83df96d6 | 1054 | |
b513212d JS |
1055 | XWindowChanges windowChanges; |
1056 | int valueMask = 0; | |
1057 | ||
1058 | if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) | |
83df96d6 | 1059 | { |
b513212d JS |
1060 | windowChanges.x = x; |
1061 | valueMask |= CWX; | |
83df96d6 | 1062 | } |
b513212d | 1063 | if (y != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) |
83df96d6 | 1064 | { |
b513212d JS |
1065 | windowChanges.y = y; |
1066 | valueMask |= CWY; | |
83df96d6 | 1067 | } |
b513212d | 1068 | if (width != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) |
83df96d6 | 1069 | { |
b513212d JS |
1070 | windowChanges.width = width - m_borderSize*2; |
1071 | valueMask |= CWWidth; | |
83df96d6 | 1072 | } |
b513212d JS |
1073 | if (height != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) |
1074 | { | |
1075 | windowChanges.height = height - m_borderSize*2; | |
1076 | valueMask |= CWHeight; | |
1077 | } | |
1078 | AdjustForParentClientOrigin(valueMask.x, valueMask.y, sizeFlags); | |
1079 | ||
1080 | XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(), | |
1081 | valueMask, & windowChanges); | |
83df96d6 JS |
1082 | } |
1083 | ||
bc797f4c | 1084 | void wxWindowX11::DoSetClientSize(int width, int height) |
83df96d6 | 1085 | { |
b513212d | 1086 | if (!GetMainWindow()) |
83df96d6 | 1087 | return; |
83df96d6 | 1088 | |
b513212d JS |
1089 | XWindowChanges windowChanges; |
1090 | int valueMask = 0; | |
83df96d6 | 1091 | |
b513212d JS |
1092 | if (width != -1) |
1093 | { | |
1094 | windowChanges.width = width ; | |
1095 | valueMask |= CWWidth; | |
1096 | } | |
1097 | if (height != -1) | |
1098 | { | |
1099 | windowChanges.height = height ; | |
1100 | valueMask |= CWHeight; | |
1101 | } | |
1102 | XConfigureWindow(wxGlobalDisplay(), (Window) GetMainWindow(), | |
1103 | valueMask, & windowChanges); | |
83df96d6 JS |
1104 | } |
1105 | ||
1106 | // For implementation purposes - sometimes decorations make the client area | |
1107 | // smaller | |
bc797f4c | 1108 | wxPoint wxWindowX11::GetClientAreaOrigin() const |
83df96d6 JS |
1109 | { |
1110 | return wxPoint(0, 0); | |
1111 | } | |
1112 | ||
1113 | // Makes an adjustment to the window position (for example, a frame that has | |
1114 | // a toolbar that it manages itself). | |
bc797f4c | 1115 | void wxWindowX11::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) |
83df96d6 JS |
1116 | { |
1117 | if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent()) | |
1118 | { | |
1119 | wxPoint pt(GetParent()->GetClientAreaOrigin()); | |
1120 | x += pt.x; y += pt.y; | |
1121 | } | |
1122 | } | |
1123 | ||
bc797f4c | 1124 | void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH) |
83df96d6 JS |
1125 | { |
1126 | m_minWidth = minW; | |
1127 | m_minHeight = minH; | |
1128 | m_maxWidth = maxW; | |
1129 | m_maxHeight = maxH; | |
1130 | ||
b513212d JS |
1131 | XSizeHints sizeHints; |
1132 | sizeHints.flags = 0; | |
1133 | ||
1134 | if (minW > -1 && minH > -1) | |
83df96d6 | 1135 | { |
b513212d JS |
1136 | sizeHints.flags |= PMinSize; |
1137 | sizeHints.min_width = minW; | |
1138 | sizeHints.min_height = minH; | |
1139 | } | |
1140 | if (maxW > -1 && maxH > -1) | |
1141 | { | |
1142 | sizeHints.flags |= PMaxSize; | |
1143 | sizeHints.max_width = maxW; | |
1144 | sizeHints.max_height = maxH; | |
1145 | } | |
1146 | if (incW > -1 && incH > -1) | |
1147 | { | |
1148 | sizeHints.flags |= PResizeInc; | |
1149 | sizeHints.width_inc = incW; | |
1150 | sizeHints.height_inc = incH; | |
83df96d6 JS |
1151 | } |
1152 | ||
b513212d | 1153 | XSetWMNormalHints(wxGlobalDisplay(), (Window) GetMainWindow(), & sizeHints) |
83df96d6 JS |
1154 | } |
1155 | ||
bc797f4c | 1156 | void wxWindowX11::DoMoveWindow(int x, int y, int width, int height) |
83df96d6 | 1157 | { |
b513212d | 1158 | DoSetSize(x, y, width, height); |
83df96d6 JS |
1159 | } |
1160 | ||
1161 | // --------------------------------------------------------------------------- | |
1162 | // text metrics | |
1163 | // --------------------------------------------------------------------------- | |
1164 | ||
bc797f4c | 1165 | int wxWindowX11::GetCharHeight() const |
83df96d6 JS |
1166 | { |
1167 | wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" ); | |
1168 | ||
1169 | WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay()); | |
1170 | ||
1171 | int direction, ascent, descent; | |
1172 | XCharStruct overall; | |
1173 | XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent, | |
1174 | &descent, &overall); | |
1175 | ||
1176 | // return (overall.ascent + overall.descent); | |
1177 | return (ascent + descent); | |
1178 | } | |
1179 | ||
bc797f4c | 1180 | int wxWindowX11::GetCharWidth() const |
83df96d6 JS |
1181 | { |
1182 | wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" ); | |
1183 | ||
1184 | WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay()); | |
1185 | ||
1186 | int direction, ascent, descent; | |
1187 | XCharStruct overall; | |
1188 | XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent, | |
1189 | &descent, &overall); | |
1190 | ||
1191 | return overall.width; | |
1192 | } | |
1193 | ||
bc797f4c | 1194 | void wxWindowX11::GetTextExtent(const wxString& string, |
83df96d6 JS |
1195 | int *x, int *y, |
1196 | int *descent, int *externalLeading, | |
1197 | const wxFont *theFont) const | |
1198 | { | |
1199 | wxFont *fontToUse = (wxFont *)theFont; | |
1200 | if (!fontToUse) | |
1201 | fontToUse = (wxFont *) & m_font; | |
1202 | ||
1203 | wxCHECK_RET( fontToUse->Ok(), "valid window font needed" ); | |
1204 | ||
1205 | WXFontStructPtr pFontStruct = theFont->GetFontStruct(1.0, GetXDisplay()); | |
1206 | ||
1207 | int direction, ascent, descent2; | |
1208 | XCharStruct overall; | |
1209 | int slen = string.Len(); | |
1210 | ||
1211 | #if 0 | |
1212 | if (use16) | |
1213 | XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction, | |
1214 | &ascent, &descent2, &overall); | |
1215 | #endif | |
1216 | ||
1217 | XTextExtents((XFontStruct*) pFontStruct, string, slen, | |
1218 | &direction, &ascent, &descent2, &overall); | |
1219 | ||
1220 | if ( x ) | |
1221 | *x = (overall.width); | |
1222 | if ( y ) | |
1223 | *y = (ascent + descent2); | |
1224 | if (descent) | |
1225 | *descent = descent2; | |
1226 | if (externalLeading) | |
1227 | *externalLeading = 0; | |
1228 | ||
1229 | } | |
1230 | ||
1231 | // ---------------------------------------------------------------------------- | |
1232 | // painting | |
1233 | // ---------------------------------------------------------------------------- | |
1234 | ||
bc797f4c | 1235 | void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect) |
83df96d6 JS |
1236 | { |
1237 | m_needsRefresh = TRUE; | |
b513212d | 1238 | Display *display = wxGlobalDisplay(); |
7266b672 | 1239 | Window thisWindow = (Window) GetMainWindow(); |
83df96d6 JS |
1240 | |
1241 | XExposeEvent dummyEvent; | |
1242 | int width, height; | |
1243 | GetSize(&width, &height); | |
1244 | ||
1245 | dummyEvent.type = Expose; | |
1246 | dummyEvent.display = display; | |
1247 | dummyEvent.send_event = True; | |
1248 | dummyEvent.window = thisWindow; | |
1249 | if (rect) | |
1250 | { | |
1251 | dummyEvent.x = rect->x; | |
1252 | dummyEvent.y = rect->y; | |
1253 | dummyEvent.width = rect->width; | |
1254 | dummyEvent.height = rect->height; | |
1255 | } | |
1256 | else | |
1257 | { | |
1258 | dummyEvent.x = 0; | |
1259 | dummyEvent.y = 0; | |
1260 | dummyEvent.width = width; | |
1261 | dummyEvent.height = height; | |
1262 | } | |
1263 | dummyEvent.count = 0; | |
1264 | ||
1265 | if (eraseBack) | |
1266 | { | |
7266b672 | 1267 | wxClientDC dc((wxWindow*) this); |
83df96d6 JS |
1268 | wxBrush backgroundBrush(GetBackgroundColour(), wxSOLID); |
1269 | dc.SetBackground(backgroundBrush); | |
1270 | if (rect) | |
1271 | dc.Clear(*rect); | |
1272 | else | |
1273 | dc.Clear(); | |
1274 | } | |
1275 | ||
1276 | XSendEvent(display, thisWindow, False, ExposureMask, (XEvent *)&dummyEvent); | |
1277 | } | |
1278 | ||
bc797f4c | 1279 | void wxWindowX11::Clear() |
83df96d6 | 1280 | { |
7266b672 | 1281 | wxClientDC dc((wxWindow*) this); |
83df96d6 JS |
1282 | wxBrush brush(GetBackgroundColour(), wxSOLID); |
1283 | dc.SetBackground(brush); | |
1284 | dc.Clear(); | |
1285 | } | |
1286 | ||
bc797f4c | 1287 | void wxWindowX11::ClearUpdateRects() |
83df96d6 JS |
1288 | { |
1289 | wxRectList::Node* node = m_updateRects.GetFirst(); | |
1290 | while (node) | |
1291 | { | |
1292 | wxRect* rect = node->GetData(); | |
1293 | delete rect; | |
1294 | node = node->GetNext(); | |
1295 | } | |
1296 | ||
1297 | m_updateRects.Clear(); | |
1298 | } | |
1299 | ||
bc797f4c | 1300 | void wxWindowX11::DoPaint() |
83df96d6 | 1301 | { |
bc797f4c JS |
1302 | // Set an erase event first |
1303 | wxEraseEvent eraseEvent(GetId()); | |
1304 | eraseEvent.SetEventObject(this); | |
1305 | GetEventHandler()->ProcessEvent(eraseEvent); | |
1306 | ||
1307 | wxPaintEvent event(GetId()); | |
1308 | event.SetEventObject(this); | |
1309 | GetEventHandler()->ProcessEvent(event); | |
1310 | ||
1311 | m_needsRefresh = FALSE; | |
83df96d6 JS |
1312 | } |
1313 | ||
1314 | // ---------------------------------------------------------------------------- | |
1315 | // event handlers | |
1316 | // ---------------------------------------------------------------------------- | |
1317 | ||
1318 | // Responds to colour changes: passes event on to children. | |
bc797f4c | 1319 | void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event) |
83df96d6 JS |
1320 | { |
1321 | wxWindowList::Node *node = GetChildren().GetFirst(); | |
1322 | while ( node ) | |
1323 | { | |
1324 | // Only propagate to non-top-level windows | |
1325 | wxWindow *win = node->GetData(); | |
1326 | if ( win->GetParent() ) | |
1327 | { | |
1328 | wxSysColourChangedEvent event2; | |
1329 | event.m_eventObject = win; | |
1330 | win->GetEventHandler()->ProcessEvent(event2); | |
1331 | } | |
1332 | ||
1333 | node = node->GetNext(); | |
1334 | } | |
1335 | } | |
1336 | ||
bc797f4c | 1337 | void wxWindowX11::OnIdle(wxIdleEvent& WXUNUSED(event)) |
83df96d6 JS |
1338 | { |
1339 | // This calls the UI-update mechanism (querying windows for | |
1340 | // menu/toolbar/control state information) | |
1341 | UpdateWindowUI(); | |
1342 | } | |
1343 | ||
1344 | // ---------------------------------------------------------------------------- | |
1345 | // accelerators | |
1346 | // ---------------------------------------------------------------------------- | |
1347 | ||
bc797f4c | 1348 | bool wxWindowX11::ProcessAccelerator(wxKeyEvent& event) |
83df96d6 JS |
1349 | { |
1350 | if (!m_acceleratorTable.Ok()) | |
1351 | return FALSE; | |
1352 | ||
7266b672 JS |
1353 | const wxAcceleratorEntry* entry = m_acceleratorTable.GetEntry(event); |
1354 | if (entry) | |
83df96d6 | 1355 | { |
83df96d6 JS |
1356 | // Bingo, we have a match. Now find a control that matches the |
1357 | // entry command id. | |
1358 | ||
1359 | // Need to go up to the top of the window hierarchy, since it might | |
1360 | // be e.g. a menu item | |
7266b672 | 1361 | wxWindow* parent = (wxWindow*) this; |
83df96d6 JS |
1362 | while ( parent && !parent->IsTopLevel() ) |
1363 | parent = parent->GetParent(); | |
1364 | ||
1365 | if (!parent) | |
1366 | return FALSE; | |
1367 | ||
1368 | wxFrame* frame = wxDynamicCast(parent, wxFrame); | |
1369 | if ( frame ) | |
1370 | { | |
1371 | // Try for a menu command | |
1372 | if (frame->GetMenuBar()) | |
1373 | { | |
1374 | wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand()); | |
1375 | if (item) | |
1376 | { | |
1377 | wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand()); | |
1378 | commandEvent.SetEventObject(frame); | |
1379 | ||
1380 | // If ProcessEvent returns TRUE (it was handled), then | |
1381 | // the calling code will skip the event handling. | |
1382 | return frame->GetEventHandler()->ProcessEvent(commandEvent); | |
1383 | } | |
1384 | } | |
1385 | } | |
1386 | ||
1387 | // Find a child matching the command id | |
1388 | wxWindow* child = parent->FindWindow(entry->GetCommand()); | |
1389 | ||
1390 | // No such child | |
1391 | if (!child) | |
1392 | return FALSE; | |
1393 | ||
1394 | // Now we process those kinds of windows that we can. | |
1395 | // For now, only buttons. | |
1396 | if ( wxDynamicCast(child, wxButton) ) | |
1397 | { | |
1398 | wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId()); | |
1399 | commandEvent.SetEventObject(child); | |
1400 | return child->GetEventHandler()->ProcessEvent(commandEvent); | |
1401 | } | |
1402 | ||
1403 | return FALSE; | |
7266b672 JS |
1404 | |
1405 | }// if | |
83df96d6 JS |
1406 | |
1407 | // We didn't match the key event against an accelerator. | |
1408 | return FALSE; | |
1409 | } | |
1410 | ||
1411 | // ============================================================================ | |
bc797f4c | 1412 | // X11-specific stuff from here on |
83df96d6 JS |
1413 | // ============================================================================ |
1414 | ||
1415 | // ---------------------------------------------------------------------------- | |
1416 | // function which maintain the global hash table mapping Widgets to wxWindows | |
1417 | // ---------------------------------------------------------------------------- | |
1418 | ||
bc797f4c | 1419 | bool wxAddWindowToTable(Window w, wxWindow *win) |
83df96d6 JS |
1420 | { |
1421 | wxWindow *oldItem = NULL; | |
1422 | if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w))) | |
1423 | { | |
1424 | wxLogDebug("Widget table clash: new widget is %ld, %s", | |
1425 | (long)w, win->GetClassInfo()->GetClassName()); | |
1426 | return FALSE; | |
1427 | } | |
1428 | ||
1429 | wxWidgetHashTable->Put((long) w, win); | |
1430 | ||
bc797f4c | 1431 | wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)", |
83df96d6 JS |
1432 | w, win, win->GetClassInfo()->GetClassName()); |
1433 | ||
1434 | return TRUE; | |
1435 | } | |
1436 | ||
bc797f4c | 1437 | wxWindow *wxGetWindowFromTable(Window w) |
83df96d6 JS |
1438 | { |
1439 | return (wxWindow *)wxWidgetHashTable->Get((long) w); | |
1440 | } | |
1441 | ||
bc797f4c | 1442 | void wxDeleteWindowFromTable(Window w) |
83df96d6 JS |
1443 | { |
1444 | wxWidgetHashTable->Delete((long)w); | |
1445 | } | |
1446 | ||
1447 | // ---------------------------------------------------------------------------- | |
1448 | // add/remove window from the table | |
1449 | // ---------------------------------------------------------------------------- | |
1450 | ||
83df96d6 | 1451 | // ---------------------------------------------------------------------------- |
bc797f4c | 1452 | // X11-specific accessors |
83df96d6 JS |
1453 | // ---------------------------------------------------------------------------- |
1454 | ||
1455 | // Get the underlying X window | |
bc797f4c | 1456 | WXWindow wxWindowX11::GetXWindow() const |
83df96d6 | 1457 | { |
bc797f4c | 1458 | return GetMainWindow(); |
83df96d6 JS |
1459 | } |
1460 | ||
1461 | // Get the underlying X display | |
bc797f4c | 1462 | WXDisplay *wxWindowX11::GetXDisplay() const |
83df96d6 | 1463 | { |
bc797f4c | 1464 | return wxGetDisplay(); |
83df96d6 JS |
1465 | } |
1466 | ||
bc797f4c | 1467 | WXWindow wxWindowX11::GetMainWindow() const |
83df96d6 JS |
1468 | { |
1469 | if (m_drawingArea) | |
1470 | return m_drawingArea; | |
1471 | else | |
1472 | return m_mainWidget; | |
1473 | } | |
1474 | ||
7266b672 | 1475 | WXWindow wxWindowX11::GetClientWindow() const |
83df96d6 | 1476 | { |
bc797f4c | 1477 | if (m_drawingArea != (WXWindow) 0) |
83df96d6 JS |
1478 | return m_drawingArea; |
1479 | else | |
bc797f4c | 1480 | return GetMainWindow(); |
83df96d6 JS |
1481 | } |
1482 | ||
bc797f4c | 1483 | WXWindow wxWindowX11::GetTopWindow() const |
83df96d6 | 1484 | { |
bc797f4c | 1485 | return GetMainWindow(); |
83df96d6 JS |
1486 | } |
1487 | ||
bc797f4c | 1488 | WXWindow wxWindowX11::GetLabelWindow() const |
83df96d6 | 1489 | { |
bc797f4c | 1490 | return GetMainWindow(); |
83df96d6 JS |
1491 | } |
1492 | ||
1493 | // ---------------------------------------------------------------------------- | |
bc797f4c | 1494 | // callbacks |
83df96d6 JS |
1495 | // ---------------------------------------------------------------------------- |
1496 | ||
1b0fb34b | 1497 | // TODO: implement wxWindow scrollbar, presumably using wxScrollBar |
83df96d6 | 1498 | #if 0 |
83df96d6 JS |
1499 | static void wxScrollBarCallback(Widget scrollbar, |
1500 | XtPointer clientData, | |
1501 | XmScrollBarCallbackStruct *cbs) | |
1502 | { | |
1503 | wxWindow *win = wxGetWindowFromTable(scrollbar); | |
1504 | int orientation = (int) clientData; | |
1505 | ||
1506 | wxEventType eventType = wxEVT_NULL; | |
1507 | switch (cbs->reason) | |
1508 | { | |
1509 | case XmCR_INCREMENT: | |
1510 | { | |
1511 | eventType = wxEVT_SCROLLWIN_LINEDOWN; | |
1512 | break; | |
1513 | } | |
1514 | case XmCR_DECREMENT: | |
1515 | { | |
1516 | eventType = wxEVT_SCROLLWIN_LINEUP; | |
1517 | break; | |
1518 | } | |
1519 | case XmCR_DRAG: | |
1520 | { | |
1521 | eventType = wxEVT_SCROLLWIN_THUMBTRACK; | |
1522 | break; | |
1523 | } | |
1524 | case XmCR_VALUE_CHANGED: | |
1525 | { | |
1526 | eventType = wxEVT_SCROLLWIN_THUMBRELEASE; | |
1527 | break; | |
1528 | } | |
1529 | case XmCR_PAGE_INCREMENT: | |
1530 | { | |
1531 | eventType = wxEVT_SCROLLWIN_PAGEDOWN; | |
1532 | break; | |
1533 | } | |
1534 | case XmCR_PAGE_DECREMENT: | |
1535 | { | |
1536 | eventType = wxEVT_SCROLLWIN_PAGEUP; | |
1537 | break; | |
1538 | } | |
1539 | case XmCR_TO_TOP: | |
1540 | { | |
1541 | eventType = wxEVT_SCROLLWIN_TOP; | |
1542 | break; | |
1543 | } | |
1544 | case XmCR_TO_BOTTOM: | |
1545 | { | |
1546 | eventType = wxEVT_SCROLLWIN_BOTTOM; | |
1547 | break; | |
1548 | } | |
1549 | default: | |
1550 | { | |
1551 | // Should never get here | |
1552 | wxFAIL_MSG("Unknown scroll event."); | |
1553 | break; | |
1554 | } | |
1555 | } | |
1556 | ||
1557 | wxScrollWinEvent event(eventType, | |
1558 | cbs->value, | |
1559 | ((orientation == XmHORIZONTAL) ? | |
1560 | wxHORIZONTAL : wxVERTICAL)); | |
1561 | event.SetEventObject( win ); | |
1562 | win->GetEventHandler()->ProcessEvent(event); | |
1563 | } | |
bc797f4c | 1564 | #endif |
1b0fb34b | 1565 | |
83df96d6 JS |
1566 | // ---------------------------------------------------------------------------- |
1567 | // TranslateXXXEvent() functions | |
1568 | // ---------------------------------------------------------------------------- | |
1569 | ||
1b0fb34b | 1570 | bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent) |
83df96d6 JS |
1571 | { |
1572 | switch (xevent->xany.type) | |
1573 | { | |
1b0fb34b JS |
1574 | case EnterNotify: |
1575 | case LeaveNotify: | |
83df96d6 JS |
1576 | case ButtonPress: |
1577 | case ButtonRelease: | |
1578 | case MotionNotify: | |
1579 | { | |
1580 | wxEventType eventType = wxEVT_NULL; | |
1581 | ||
1b0fb34b | 1582 | if (xevent->xany.type == EnterNotify) |
83df96d6 | 1583 | { |
1b0fb34b JS |
1584 | //if (local_event.xcrossing.mode!=NotifyNormal) |
1585 | // return ; // Ignore grab events | |
1586 | eventType = wxEVT_ENTER_WINDOW; | |
1587 | // canvas->GetEventHandler()->OnSetFocus(); | |
1588 | } | |
1589 | else if (xevent->xany.type == LeaveNotify) | |
1590 | { | |
1591 | //if (local_event.xcrossingr.mode!=NotifyNormal) | |
1592 | // return ; // Ignore grab events | |
1593 | eventType = wxEVT_LEAVE_WINDOW; | |
1594 | // canvas->GetEventHandler()->OnKillFocus(); | |
83df96d6 JS |
1595 | } |
1596 | else if (xevent->xany.type == MotionNotify) | |
1597 | { | |
1598 | eventType = wxEVT_MOTION; | |
1599 | } | |
1600 | else if (xevent->xany.type == ButtonPress) | |
1601 | { | |
1602 | wxevent.SetTimestamp(xevent->xbutton.time); | |
1603 | int button = 0; | |
1604 | if (xevent->xbutton.button == Button1) | |
1605 | { | |
1606 | eventType = wxEVT_LEFT_DOWN; | |
1607 | win->SetButton1(TRUE); | |
1608 | button = 1; | |
1609 | } | |
1610 | else if (xevent->xbutton.button == Button2) | |
1611 | { | |
1612 | eventType = wxEVT_MIDDLE_DOWN; | |
1613 | win->SetButton2(TRUE); | |
1614 | button = 2; | |
1615 | } | |
1616 | else if (xevent->xbutton.button == Button3) | |
1617 | { | |
1618 | eventType = wxEVT_RIGHT_DOWN; | |
1619 | win->SetButton3(TRUE); | |
1620 | button = 3; | |
1621 | } | |
1622 | ||
1623 | // check for a double click | |
1b0fb34b | 1624 | // TODO: where can we get this value from? |
b513212d | 1625 | //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay()); |
7266b672 | 1626 | long dclickTime = 200; |
83df96d6 JS |
1627 | long ts = wxevent.GetTimestamp(); |
1628 | ||
1629 | int buttonLast = win->GetLastClickedButton(); | |
1630 | long lastTS = win->GetLastClickTime(); | |
1631 | if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime ) | |
1632 | { | |
1633 | // I have a dclick | |
1634 | win->SetLastClick(0, ts); | |
1635 | if ( eventType == wxEVT_LEFT_DOWN ) | |
1636 | eventType = wxEVT_LEFT_DCLICK; | |
1637 | else if ( eventType == wxEVT_MIDDLE_DOWN ) | |
1638 | eventType = wxEVT_MIDDLE_DCLICK; | |
1639 | else if ( eventType == wxEVT_RIGHT_DOWN ) | |
1640 | eventType = wxEVT_RIGHT_DCLICK; | |
1641 | } | |
1642 | else | |
1643 | { | |
1644 | // not fast enough or different button | |
1645 | win->SetLastClick(button, ts); | |
1646 | } | |
1647 | } | |
1648 | else if (xevent->xany.type == ButtonRelease) | |
1649 | { | |
1650 | if (xevent->xbutton.button == Button1) | |
1651 | { | |
1652 | eventType = wxEVT_LEFT_UP; | |
1653 | win->SetButton1(FALSE); | |
1654 | } | |
1655 | else if (xevent->xbutton.button == Button2) | |
1656 | { | |
1657 | eventType = wxEVT_MIDDLE_UP; | |
1658 | win->SetButton2(FALSE); | |
1659 | } | |
1660 | else if (xevent->xbutton.button == Button3) | |
1661 | { | |
1662 | eventType = wxEVT_RIGHT_UP; | |
1663 | win->SetButton3(FALSE); | |
1664 | } | |
1665 | else return FALSE; | |
1666 | } | |
1667 | else | |
1668 | { | |
1669 | return FALSE; | |
1670 | } | |
1671 | ||
1672 | wxevent.SetEventType(eventType); | |
1673 | ||
1b0fb34b JS |
1674 | wxevent.m_x = xevent->xbutton.x; |
1675 | wxevent.m_y = xevent->xbutton.y; | |
83df96d6 JS |
1676 | |
1677 | wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN) | |
1678 | || (event_left_is_down (xevent) | |
1679 | && (eventType != wxEVT_LEFT_UP))); | |
1680 | wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN) | |
1681 | || (event_middle_is_down (xevent) | |
1682 | && (eventType != wxEVT_MIDDLE_UP))); | |
1683 | wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN) | |
1684 | || (event_right_is_down (xevent) | |
1685 | && (eventType != wxEVT_RIGHT_UP))); | |
1686 | ||
1687 | wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask; | |
1688 | wxevent.m_controlDown = xevent->xbutton.state & ControlMask; | |
1689 | wxevent.m_altDown = xevent->xbutton.state & Mod3Mask; | |
1690 | wxevent.m_metaDown = xevent->xbutton.state & Mod1Mask; | |
1691 | ||
1692 | wxevent.SetId(win->GetId()); | |
1693 | wxevent.SetEventObject(win); | |
1694 | ||
1695 | return TRUE; | |
1696 | } | |
1697 | } | |
1698 | return FALSE; | |
1699 | } | |
1700 | ||
7eaac9f5 | 1701 | bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent) |
83df96d6 JS |
1702 | { |
1703 | switch (xevent->xany.type) | |
1704 | { | |
1705 | case KeyPress: | |
1706 | case KeyRelease: | |
1707 | { | |
1708 | char buf[20]; | |
1709 | ||
1710 | KeySym keySym; | |
83df96d6 JS |
1711 | (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL); |
1712 | int id = wxCharCodeXToWX (keySym); | |
1713 | ||
1714 | if (xevent->xkey.state & ShiftMask) | |
1715 | wxevent.m_shiftDown = TRUE; | |
1716 | if (xevent->xkey.state & ControlMask) | |
1717 | wxevent.m_controlDown = TRUE; | |
1718 | if (xevent->xkey.state & Mod3Mask) | |
1719 | wxevent.m_altDown = TRUE; | |
1720 | if (xevent->xkey.state & Mod1Mask) | |
1721 | wxevent.m_metaDown = TRUE; | |
1722 | wxevent.SetEventObject(win); | |
1723 | wxevent.m_keyCode = id; | |
1724 | wxevent.SetTimestamp(xevent->xkey.time); | |
1725 | ||
1726 | wxevent.m_x = xevent->xbutton.x; | |
1727 | wxevent.m_y = xevent->xbutton.y; | |
1728 | ||
1729 | if (id > -1) | |
1730 | return TRUE; | |
1731 | else | |
1732 | return FALSE; | |
1733 | break; | |
1734 | } | |
1735 | default: | |
1736 | break; | |
1737 | } | |
1738 | return FALSE; | |
1739 | } | |
1740 | ||
1741 | // ---------------------------------------------------------------------------- | |
1742 | // Colour stuff | |
1743 | // ---------------------------------------------------------------------------- | |
1744 | ||
bc797f4c JS |
1745 | #if 0 |
1746 | ||
83df96d6 JS |
1747 | #define YAllocColor XAllocColor |
1748 | XColor g_itemColors[5]; | |
1749 | int wxComputeColours (Display *display, wxColour * back, wxColour * fore) | |
1750 | { | |
1751 | int result; | |
1752 | static XmColorProc colorProc; | |
1753 | ||
1754 | result = wxNO_COLORS; | |
1755 | ||
1756 | if (back) | |
1757 | { | |
1758 | g_itemColors[0].red = (((long) back->Red ()) << 8); | |
1759 | g_itemColors[0].green = (((long) back->Green ()) << 8); | |
1760 | g_itemColors[0].blue = (((long) back->Blue ()) << 8); | |
1761 | g_itemColors[0].flags = DoRed | DoGreen | DoBlue; | |
1762 | if (colorProc == (XmColorProc) NULL) | |
1763 | { | |
1764 | // Get a ptr to the actual function | |
1765 | colorProc = XmSetColorCalculation ((XmColorProc) NULL); | |
1766 | // And set it back to motif. | |
1767 | XmSetColorCalculation (colorProc); | |
1768 | } | |
1769 | (*colorProc) (&g_itemColors[wxBACK_INDEX], | |
1770 | &g_itemColors[wxFORE_INDEX], | |
1771 | &g_itemColors[wxSELE_INDEX], | |
1772 | &g_itemColors[wxTOPS_INDEX], | |
1773 | &g_itemColors[wxBOTS_INDEX]); | |
1774 | result = wxBACK_COLORS; | |
1775 | } | |
1776 | if (fore) | |
1777 | { | |
1778 | g_itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8); | |
1779 | g_itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8); | |
1780 | g_itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8); | |
1781 | g_itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue; | |
1782 | if (result == wxNO_COLORS) | |
1783 | result = wxFORE_COLORS; | |
1784 | } | |
1785 | ||
1786 | Display *dpy = display; | |
1787 | Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy); | |
1788 | ||
1789 | if (back) | |
1790 | { | |
1791 | /* 5 Colours to allocate */ | |
1792 | for (int i = 0; i < 5; i++) | |
1793 | if (!YAllocColor (dpy, cmap, &g_itemColors[i])) | |
1794 | result = wxNO_COLORS; | |
1795 | } | |
1796 | else if (fore) | |
1797 | { | |
1798 | /* Only 1 colour to allocate */ | |
1799 | if (!YAllocColor (dpy, cmap, &g_itemColors[wxFORE_INDEX])) | |
1800 | result = wxNO_COLORS; | |
1801 | } | |
1802 | ||
1803 | return (result); | |
1804 | ||
1805 | } | |
bc797f4c | 1806 | #endif |
83df96d6 JS |
1807 | |
1808 | // Changes the foreground and background colours to be derived from the current | |
1809 | // background colour. To change the foreground colour, you must call | |
1810 | // SetForegroundColour explicitly. | |
bc797f4c | 1811 | void wxWindowX11::ChangeBackgroundColour() |
83df96d6 | 1812 | { |
bc797f4c JS |
1813 | // TODO |
1814 | #if 0 | |
83df96d6 JS |
1815 | WXWidget mainWidget = GetMainWidget(); |
1816 | if ( mainWidget ) | |
1817 | DoChangeBackgroundColour(mainWidget, m_backgroundColour); | |
83df96d6 JS |
1818 | #endif |
1819 | } | |
1820 | ||
bc797f4c | 1821 | void wxWindowX11::ChangeForegroundColour() |
83df96d6 | 1822 | { |
bc797f4c JS |
1823 | // TODO |
1824 | #if 0 | |
83df96d6 JS |
1825 | WXWidget mainWidget = GetMainWidget(); |
1826 | if ( mainWidget ) | |
1827 | DoChangeForegroundColour(mainWidget, m_foregroundColour); | |
1828 | if ( m_scrolledWindow && mainWidget != m_scrolledWindow ) | |
1829 | DoChangeForegroundColour(m_scrolledWindow, m_foregroundColour); | |
bc797f4c | 1830 | #endif |
83df96d6 JS |
1831 | } |
1832 | ||
1833 | // Change a widget's foreground and background colours. | |
bc797f4c | 1834 | void wxWindowX11::DoChangeForegroundColour(WXWindow widget, wxColour& foregroundColour) |
83df96d6 | 1835 | { |
bc797f4c JS |
1836 | // TODO |
1837 | #if 0 | |
83df96d6 JS |
1838 | // When should we specify the foreground, if it's calculated |
1839 | // by wxComputeColours? | |
1840 | // Solution: say we start with the default (computed) foreground colour. | |
1841 | // If we call SetForegroundColour explicitly for a control or window, | |
1842 | // then the foreground is changed. | |
1843 | // Therefore SetBackgroundColour computes the foreground colour, and | |
1844 | // SetForegroundColour changes the foreground colour. The ordering is | |
1845 | // important. | |
1846 | ||
1847 | Widget w = (Widget)widget; | |
1848 | XtVaSetValues( | |
1849 | w, | |
1850 | XmNforeground, foregroundColour.AllocColour(XtDisplay(w)), | |
1851 | NULL | |
1852 | ); | |
bc797f4c | 1853 | #endif |
83df96d6 JS |
1854 | } |
1855 | ||
bc797f4c | 1856 | void wxWindowX11::DoChangeBackgroundColour(WXWindow widget, wxColour& backgroundColour, bool changeArmColour) |
83df96d6 | 1857 | { |
bc797f4c JS |
1858 | // TODO |
1859 | #if 0 | |
83df96d6 JS |
1860 | wxComputeColours (XtDisplay((Widget) widget), & backgroundColour, |
1861 | (wxColour*) NULL); | |
1862 | ||
1863 | XtVaSetValues ((Widget) widget, | |
1864 | XmNbackground, g_itemColors[wxBACK_INDEX].pixel, | |
1865 | XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel, | |
1866 | XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel, | |
1867 | XmNforeground, g_itemColors[wxFORE_INDEX].pixel, | |
1868 | NULL); | |
1869 | ||
1870 | if (changeArmColour) | |
1871 | XtVaSetValues ((Widget) widget, | |
1872 | XmNarmColor, g_itemColors[wxSELE_INDEX].pixel, | |
1873 | NULL); | |
bc797f4c | 1874 | #endif |
83df96d6 JS |
1875 | } |
1876 | ||
bc797f4c | 1877 | bool wxWindowX11::SetBackgroundColour(const wxColour& col) |
83df96d6 JS |
1878 | { |
1879 | if ( !wxWindowBase::SetBackgroundColour(col) ) | |
1880 | return FALSE; | |
1881 | ||
1882 | ChangeBackgroundColour(); | |
1883 | ||
1884 | return TRUE; | |
1885 | } | |
1886 | ||
bc797f4c | 1887 | bool wxWindowX11::SetForegroundColour(const wxColour& col) |
83df96d6 JS |
1888 | { |
1889 | if ( !wxWindowBase::SetForegroundColour(col) ) | |
1890 | return FALSE; | |
1891 | ||
1892 | ChangeForegroundColour(); | |
1893 | ||
1894 | return TRUE; | |
1895 | } | |
1896 | ||
bc797f4c | 1897 | void wxWindowX11::ChangeFont(bool keepOriginalSize) |
83df96d6 | 1898 | { |
bc797f4c JS |
1899 | // TODO |
1900 | #if 0 | |
83df96d6 JS |
1901 | // Note that this causes the widget to be resized back |
1902 | // to its original size! We therefore have to set the size | |
1903 | // back again. TODO: a better way in Motif? | |
1904 | Widget w = (Widget) GetLabelWidget(); // Usually the main widget | |
1905 | if (w && m_font.Ok()) | |
1906 | { | |
1907 | int width, height, width1, height1; | |
1908 | GetSize(& width, & height); | |
1909 | ||
1910 | // lesstif 0.87 hangs here | |
1911 | #ifndef LESSTIF_VERSION | |
1912 | XtVaSetValues (w, | |
1913 | XmNfontList, (XmFontList) m_font.GetFontList(1.0, XtDisplay(w)), | |
1914 | NULL); | |
1915 | #endif | |
1916 | ||
1917 | GetSize(& width1, & height1); | |
1918 | if (keepOriginalSize && (width != width1 || height != height1)) | |
1919 | { | |
1920 | SetSize(-1, -1, width, height); | |
1921 | } | |
1922 | } | |
bc797f4c | 1923 | #endif |
83df96d6 JS |
1924 | } |
1925 | ||
1926 | // ---------------------------------------------------------------------------- | |
1927 | // global functions | |
1928 | // ---------------------------------------------------------------------------- | |
1929 | ||
1930 | wxWindow *wxGetActiveWindow() | |
1931 | { | |
1932 | // TODO | |
1933 | wxFAIL_MSG("Not implemented"); | |
1934 | return NULL; | |
1935 | } | |
1936 | ||
1937 | /* static */ | |
1938 | wxWindow *wxWindowBase::GetCapture() | |
1939 | { | |
1940 | return (wxWindow *)g_captureWindow; | |
1941 | } | |
1942 | ||
1943 | ||
1944 | // Find the wxWindow at the current mouse position, returning the mouse | |
1945 | // position. | |
1946 | wxWindow* wxFindWindowAtPointer(wxPoint& pt) | |
1947 | { | |
1948 | return wxFindWindowAtPoint(wxGetMousePosition()); | |
1949 | } | |
1950 | ||
1951 | // Get the current mouse position. | |
1952 | wxPoint wxGetMousePosition() | |
1953 | { | |
b513212d | 1954 | Display *display = wxGlobalDisplay(); |
83df96d6 JS |
1955 | Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display)); |
1956 | Window rootReturn, childReturn; | |
1957 | int rootX, rootY, winX, winY; | |
1958 | unsigned int maskReturn; | |
1959 | ||
1960 | XQueryPointer (display, | |
1961 | rootWindow, | |
1962 | &rootReturn, | |
1963 | &childReturn, | |
1964 | &rootX, &rootY, &winX, &winY, &maskReturn); | |
1965 | return wxPoint(rootX, rootY); | |
1966 | } | |
1967 | ||
1968 | ||
1969 | // ---------------------------------------------------------------------------- | |
1970 | // wxNoOptimize: switch off size optimization | |
1971 | // ---------------------------------------------------------------------------- | |
1972 | ||
1973 | int wxNoOptimize::ms_count = 0; | |
1974 |