1///////////////////////////////////////////////////////////////////////////// 2// Name: src/x11/window.cpp 3// Purpose: wxWindow 4// Author: Julian Smart 5// Modified by: 6// Created: 17/09/98 7// RCS-ID: $Id: window.cpp 51785 2008-02-14 11:11:48Z JS $ 8// Copyright: (c) Julian Smart 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// for compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#if defined(__BORLANDC__) 16 #pragma hdrstop 17#endif 18 19// ============================================================================ 20// declarations 21// ============================================================================ 22 23// ---------------------------------------------------------------------------- 24// headers 25// ---------------------------------------------------------------------------- 26 27#include "wx/window.h" 28 29#ifndef WX_PRECOMP 30 #include "wx/hash.h" 31 #include "wx/log.h" 32 #include "wx/app.h" 33 #include "wx/utils.h" 34 #include "wx/panel.h" 35 #include "wx/frame.h" 36 #include "wx/dc.h" 37 #include "wx/dcclient.h" 38 #include "wx/button.h" 39 #include "wx/menu.h" 40 #include "wx/dialog.h" 41 #include "wx/timer.h" 42 #include "wx/settings.h" 43 #include "wx/msgdlg.h" 44 #include "wx/scrolbar.h" 45 #include "wx/listbox.h" 46 #include "wx/scrolwin.h" 47 #include "wx/layout.h" 48 #include "wx/menuitem.h" 49 #include "wx/module.h" 50#endif 51 52#include "wx/fontutil.h" 53#include "wx/univ/renderer.h" 54 55#if wxUSE_DRAG_AND_DROP 56 #include "wx/dnd.h" 57#endif 58 59#include "wx/x11/private.h" 60#include "X11/Xutil.h" 61 62#include <string.h> 63 64// ---------------------------------------------------------------------------- 65// global variables for this module 66// ---------------------------------------------------------------------------- 67 68static wxWindow* g_captureWindow = NULL; 69static GC g_eraseGC; 70 71// ---------------------------------------------------------------------------- 72// macros 73// ---------------------------------------------------------------------------- 74 75#define event_left_is_down(x) ((x)->xbutton.state & Button1Mask) 76#define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask) 77#define event_right_is_down(x) ((x)->xbutton.state & Button3Mask) 78 79// ---------------------------------------------------------------------------- 80// event tables 81// ---------------------------------------------------------------------------- 82 83IMPLEMENT_ABSTRACT_CLASS(wxWindowX11, wxWindowBase) 84 85BEGIN_EVENT_TABLE(wxWindowX11, wxWindowBase) 86 EVT_SYS_COLOUR_CHANGED(wxWindowX11::OnSysColourChanged) 87END_EVENT_TABLE() 88 89// ============================================================================ 90// implementation 91// ============================================================================ 92 93// ---------------------------------------------------------------------------- 94// helper functions 95// ---------------------------------------------------------------------------- 96 97// ---------------------------------------------------------------------------- 98// constructors 99// ---------------------------------------------------------------------------- 100 101void wxWindowX11::Init() 102{ 103 // X11-specific 104 m_mainWindow = (WXWindow) 0; 105 m_clientWindow = (WXWindow) 0; 106 m_insertIntoMain = false; 107 m_updateNcArea = false; 108 109 m_winCaptured = false; 110 m_needsInputFocus = false; 111 m_isShown = true; 112 m_lastTS = 0; 113 m_lastButton = 0; 114} 115 116// real construction (Init() must have been called before!) 117bool wxWindowX11::Create(wxWindow *parent, wxWindowID id, 118 const wxPoint& pos, 119 const wxSize& size, 120 long style, 121 const wxString& name) 122{ 123 wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") ); 124 125 CreateBase(parent, id, pos, size, style, wxDefaultValidator, name); 126 127 parent->AddChild(this); 128 129 Display *xdisplay = (Display*) wxGlobalDisplay(); 130 int xscreen = DefaultScreen( xdisplay ); 131 Visual *xvisual = DefaultVisual( xdisplay, xscreen ); 132 Colormap cm = DefaultColormap( xdisplay, xscreen ); 133 134 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); 135 m_backgroundColour.CalcPixel( (WXColormap) cm ); 136 137 m_foregroundColour = *wxBLACK; 138 m_foregroundColour.CalcPixel( (WXColormap) cm ); 139 140 Window xparent = (Window) parent->GetClientAreaWindow(); 141 142 // Add window's own scrollbars to main window, not to client window 143 if (parent->GetInsertIntoMain()) 144 { 145 // wxLogDebug( "Inserted into main: %s", GetName().c_str() ); 146 xparent = (Window) parent->GetMainWindow(); 147 } 148 149 // Size (not including the border) must be nonzero (or a Value error results)! 150 // Note: The Xlib manual doesn't mention this restriction of XCreateWindow. 151 wxSize size2(size); 152 if (size2.x <= 0) 153 size2.x = 20; 154 if (size2.y <= 0) 155 size2.y = 20; 156 157 wxPoint pos2(pos); 158 if (pos2.x == wxDefaultCoord) 159 pos2.x = 0; 160 if (pos2.y == wxDefaultCoord) 161 pos2.y = 0; 162 163 AdjustForParentClientOrigin(pos2.x, pos2.y); 164 165#if wxUSE_TWO_WINDOWS 166 bool need_two_windows = 167 ((( wxSUNKEN_BORDER | wxRAISED_BORDER | wxSIMPLE_BORDER | wxHSCROLL | wxVSCROLL ) & m_windowStyle) != 0); 168#else 169 bool need_two_windows = false; 170#endif 171 172#if wxUSE_NANOX 173 long xattributes = 0; 174#else 175 XSetWindowAttributes xattributes; 176 long xattributes_mask = 0; 177 178 xattributes_mask |= CWBackPixel; 179 xattributes.background_pixel = m_backgroundColour.GetPixel(); 180 181 xattributes_mask |= CWBorderPixel; 182 xattributes.border_pixel = BlackPixel( xdisplay, xscreen ); 183 184 xattributes_mask |= CWEventMask; 185#endif 186 187 if (need_two_windows) 188 { 189#if wxUSE_NANOX 190 long backColor, foreColor; 191 backColor = GR_RGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue()); 192 foreColor = GR_RGB(m_foregroundColour.Red(), m_foregroundColour.Green(), m_foregroundColour.Blue()); 193 194 Window xwindow = XCreateWindowWithColor( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, 195 0, 0, InputOutput, xvisual, backColor, foreColor); 196 XSelectInput( xdisplay, xwindow, 197 GR_EVENT_MASK_CLOSE_REQ | ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | 198 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | 199 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask | 200 PropertyChangeMask ); 201 202#else 203 // Normal X11 204 xattributes.event_mask = 205 ExposureMask | StructureNotifyMask | ColormapChangeMask; 206 207 Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, 208 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes ); 209 210#endif 211 212 XSetWindowBackgroundPixmap( xdisplay, xwindow, None ); 213 214 m_mainWindow = (WXWindow) xwindow; 215 wxAddWindowToTable( xwindow, (wxWindow*) this ); 216 217 XMapWindow( xdisplay, xwindow ); 218 219#if !wxUSE_NANOX 220 xattributes.event_mask = 221 ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | 222 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | 223 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask | 224 PropertyChangeMask | VisibilityChangeMask ; 225 226 if (!HasFlag( wxFULL_REPAINT_ON_RESIZE )) 227 { 228 xattributes_mask |= CWBitGravity; 229 xattributes.bit_gravity = StaticGravity; 230 } 231#endif 232 233 if (HasFlag( wxSUNKEN_BORDER) || HasFlag( wxRAISED_BORDER)) 234 { 235 pos2.x = 2; 236 pos2.y = 2; 237 size2.x -= 4; 238 size2.y -= 4; 239 } 240 else if (HasFlag( wxSIMPLE_BORDER )) 241 { 242 pos2.x = 1; 243 pos2.y = 1; 244 size2.x -= 2; 245 size2.y -= 2; 246 } 247 else 248 { 249 pos2.x = 0; 250 pos2.y = 0; 251 } 252 253 // Make again sure the size is nonzero. 254 if (size2.x <= 0) 255 size2.x = 1; 256 if (size2.y <= 0) 257 size2.y = 1; 258 259#if wxUSE_NANOX 260 backColor = GR_RGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue()); 261 foreColor = GR_RGB(m_foregroundColour.Red(), m_foregroundColour.Green(), m_foregroundColour.Blue()); 262 263 xwindow = XCreateWindowWithColor( xdisplay, xwindow, pos2.x, pos2.y, size2.x, size2.y, 264 0, 0, InputOutput, xvisual, backColor, foreColor); 265 XSelectInput( xdisplay, xwindow, 266 GR_EVENT_MASK_CLOSE_REQ | ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | 267 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | 268 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask | 269 PropertyChangeMask ); 270 271#else 272 xwindow = XCreateWindow( xdisplay, xwindow, pos2.x, pos2.y, size2.x, size2.y, 273 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes ); 274#endif 275 276 XSetWindowBackgroundPixmap( xdisplay, xwindow, None ); 277 278 m_clientWindow = (WXWindow) xwindow; 279 wxAddClientWindowToTable( xwindow, (wxWindow*) this ); 280 281 XMapWindow( xdisplay, xwindow ); 282 } 283 else 284 { 285 // wxLogDebug( "No two windows needed %s", GetName().c_str() ); 286#if wxUSE_NANOX 287 long backColor, foreColor; 288 backColor = GR_RGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue()); 289 foreColor = GR_RGB(m_foregroundColour.Red(), m_foregroundColour.Green(), m_foregroundColour.Blue()); 290 291 Window xwindow = XCreateWindowWithColor( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, 292 0, 0, InputOutput, xvisual, backColor, foreColor); 293 XSelectInput( xdisplay, xwindow, 294 GR_EVENT_MASK_CLOSE_REQ | ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | 295 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | 296 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask | 297 PropertyChangeMask ); 298 299#else 300 xattributes.event_mask = 301 ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | 302 ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | 303 KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask | 304 PropertyChangeMask | VisibilityChangeMask ; 305 306 if (!HasFlag( wxFULL_REPAINT_ON_RESIZE )) 307 { 308 xattributes_mask |= CWBitGravity; 309 xattributes.bit_gravity = NorthWestGravity; 310 } 311 312 Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, 313 0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes ); 314#endif 315 316 XSetWindowBackgroundPixmap( xdisplay, xwindow, None ); 317 318 m_mainWindow = (WXWindow) xwindow; 319 m_clientWindow = m_mainWindow; 320 wxAddWindowToTable( xwindow, (wxWindow*) this ); 321 322 XMapWindow( xdisplay, xwindow ); 323 } 324 325 // Is a subwindow, so map immediately 326 m_isShown = true; 327 328 // Without this, the cursor may not be restored properly (e.g. in splitter 329 // sample). 330 SetCursor(*wxSTANDARD_CURSOR); 331 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); 332 333 // Don't call this, it can have nasty repercussions for composite controls, 334 // for example 335 // SetSize(pos.x, pos.y, size.x, size.y); 336 337 return true; 338} 339 340// Destructor 341wxWindowX11::~wxWindowX11() 342{ 343 SendDestroyEvent(); 344 345 if (g_captureWindow == this) 346 g_captureWindow = NULL; 347 348 m_isBeingDeleted = true; 349 350 DestroyChildren(); 351 352 if (m_clientWindow != m_mainWindow) 353 { 354 // Destroy the cleint window 355 Window xwindow = (Window) m_clientWindow; 356 wxDeleteClientWindowFromTable( xwindow ); 357 XDestroyWindow( wxGlobalDisplay(), xwindow ); 358 m_clientWindow = NULL; 359 } 360 361 // Destroy the window 362 if ( m_mainWindow ) 363 { 364 Window xwindow = (Window) m_mainWindow; 365 wxDeleteWindowFromTable( xwindow ); 366 XDestroyWindow( wxGlobalDisplay(), xwindow ); 367 m_mainWindow = NULL; 368 } 369} 370 371// --------------------------------------------------------------------------- 372// basic operations 373// --------------------------------------------------------------------------- 374 375void wxWindowX11::SetFocus() 376{ 377 Window xwindow = (Window) m_clientWindow; 378 379 wxCHECK_RET( xwindow, wxT("invalid window") ); 380 381 // Don't assert; we might be trying to set the focus for a panel 382 // with only static controls, so the panel returns false from AcceptsFocus. 383 // The app should be not be expected to deal with this. 384 if (!AcceptsFocus()) 385 return; 386 387#if 0 388 if (GetName() == "scrollBar") 389 { 390 char *crash = NULL; 391 *crash = 0; 392 } 393#endif 394 395 if (wxWindowIsVisible(xwindow)) 396 { 397 wxLogTrace( _T("focus"), _T("wxWindowX11::SetFocus: %s"), GetClassInfo()->GetClassName()); 398 // XSetInputFocus( wxGlobalDisplay(), xwindow, RevertToParent, CurrentTime ); 399 XSetInputFocus( wxGlobalDisplay(), xwindow, RevertToNone, CurrentTime ); 400 m_needsInputFocus = false; 401 } 402 else 403 { 404 m_needsInputFocus = true; 405 } 406} 407 408// Get the window with the focus 409wxWindow *wxWindowBase::DoFindFocus() 410{ 411 Window xfocus = (Window) 0; 412 int revert = 0; 413 414 XGetInputFocus( wxGlobalDisplay(), &xfocus, &revert); 415 if (xfocus) 416 { 417 wxWindow *win = wxGetWindowFromTable( xfocus ); 418 if (!win) 419 { 420 win = wxGetClientWindowFromTable( xfocus ); 421 } 422 423 return win; 424 } 425 426 return NULL; 427} 428 429// Enabling/disabling handled by event loop, and not sending events 430// if disabled. 431bool wxWindowX11::Enable(bool enable) 432{ 433 if ( !wxWindowBase::Enable(enable) ) 434 return false; 435 436 return true; 437} 438 439bool wxWindowX11::Show(bool show) 440{ 441 wxWindowBase::Show(show); 442 443 Window xwindow = (Window) m_mainWindow; 444 Display *xdisp = wxGlobalDisplay(); 445 if (show) 446 { 447 // wxLogDebug( "Mapping window of type %s", GetName().c_str() ); 448 XMapWindow(xdisp, xwindow); 449 } 450 else 451 { 452 // wxLogDebug( "Unmapping window of type %s", GetName().c_str() ); 453 XUnmapWindow(xdisp, xwindow); 454 } 455 456 return true; 457} 458 459// Raise the window to the top of the Z order 460void wxWindowX11::Raise() 461{ 462 if (m_mainWindow) 463 XRaiseWindow( wxGlobalDisplay(), (Window) m_mainWindow ); 464} 465 466// Lower the window to the bottom of the Z order 467void wxWindowX11::Lower() 468{ 469 if (m_mainWindow) 470 XLowerWindow( wxGlobalDisplay(), (Window) m_mainWindow ); 471} 472 473void wxWindowX11::SetLabel(const wxString& WXUNUSED(label)) 474{ 475 // TODO 476} 477 478wxString wxWindowX11::GetLabel() const 479{ 480 // TODO 481 return wxEmptyString; 482} 483 484void wxWindowX11::DoCaptureMouse() 485{ 486 if ((g_captureWindow != NULL) && (g_captureWindow != this)) 487 { 488 wxFAIL_MSG(wxT("Trying to capture before mouse released.")); 489 490 // Core dump now 491 int *tmp = NULL; 492 (*tmp) = 1; 493 return; 494 } 495 496 if (m_winCaptured) 497 return; 498 499 Window xwindow = (Window) m_clientWindow; 500 501 wxCHECK_RET( xwindow, wxT("invalid window") ); 502 503 g_captureWindow = (wxWindow*) this; 504 505 if (xwindow) 506 { 507 int res = XGrabPointer(wxGlobalDisplay(), xwindow, 508 FALSE, 509 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask, 510 GrabModeAsync, 511 GrabModeAsync, 512 None, 513 None, /* cursor */ // TODO: This may need to be set to the cursor of this window 514 CurrentTime ); 515 516 if (res != GrabSuccess) 517 { 518 wxString msg; 519 msg.Printf(wxT("Failed to grab pointer for window %s"), this->GetClassInfo()->GetClassName()); 520 wxLogDebug(msg); 521 if (res == GrabNotViewable) 522 wxLogDebug( wxT("This is not a viewable window - perhaps not shown yet?") ); 523 524 g_captureWindow = NULL; 525 return; 526 } 527 528 m_winCaptured = true; 529 } 530} 531 532void wxWindowX11::DoReleaseMouse() 533{ 534 g_captureWindow = NULL; 535 536 if ( !m_winCaptured ) 537 return; 538 539 Window xwindow = (Window) m_clientWindow; 540 541 if (xwindow) 542 { 543 XUngrabPointer( wxGlobalDisplay(), CurrentTime ); 544 } 545 546 // wxLogDebug( "Ungrabbed pointer in %s", GetName().c_str() ); 547 548 m_winCaptured = false; 549} 550 551bool wxWindowX11::SetFont(const wxFont& font) 552{ 553 if ( !wxWindowBase::SetFont(font) ) 554 { 555 // nothing to do 556 return false; 557 } 558 559 return true; 560} 561 562bool wxWindowX11::SetCursor(const wxCursor& cursor) 563{ 564 if ( !wxWindowBase::SetCursor(cursor) ) 565 { 566 // no change 567 return false; 568 } 569 570 Window xwindow = (Window) m_clientWindow; 571 572 wxCHECK_MSG( xwindow, false, wxT("invalid window") ); 573 574 wxCursor cursorToUse; 575 if (m_cursor.Ok()) 576 cursorToUse = m_cursor; 577 else 578 cursorToUse = *wxSTANDARD_CURSOR; 579 580 Cursor xcursor = (Cursor) cursorToUse.GetCursor(); 581 582 XDefineCursor( wxGlobalDisplay(), xwindow, xcursor ); 583 584 return true; 585} 586 587// Coordinates relative to the window 588void wxWindowX11::WarpPointer (int x, int y) 589{ 590 Window xwindow = (Window) m_clientWindow; 591 592 wxCHECK_RET( xwindow, wxT("invalid window") ); 593 594 XWarpPointer( wxGlobalDisplay(), None, xwindow, 0, 0, 0, 0, x, y); 595} 596 597// Does a physical scroll 598void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect) 599{ 600 // No scrolling requested. 601 if ((dx == 0) && (dy == 0)) return; 602 603 if (!m_updateRegion.IsEmpty()) 604 { 605 m_updateRegion.Offset( dx, dy ); 606 607 int cw = 0; 608 int ch = 0; 609 GetSize( &cw, &ch ); // GetClientSize() ?? 610 m_updateRegion.Intersect( 0, 0, cw, ch ); 611 } 612 613 if (!m_clearRegion.IsEmpty()) 614 { 615 m_clearRegion.Offset( dx, dy ); 616 617 int cw = 0; 618 int ch = 0; 619 GetSize( &cw, &ch ); // GetClientSize() ?? 620 m_clearRegion.Intersect( 0, 0, cw, ch ); 621 } 622 623 Window xwindow = (Window) GetClientAreaWindow(); 624 625 wxCHECK_RET( xwindow, wxT("invalid window") ); 626 627 Display *xdisplay = wxGlobalDisplay(); 628 629 GC xgc = XCreateGC( xdisplay, xwindow, 0, NULL ); 630 XSetGraphicsExposures( xdisplay, xgc, True ); 631 632 int s_x = 0; 633 int s_y = 0; 634 int cw; 635 int ch; 636 if (rect) 637 { 638 s_x = rect->x; 639 s_y = rect->y; 640 641 cw = rect->width; 642 ch = rect->height; 643 } 644 else 645 { 646 s_x = 0; 647 s_y = 0; 648 GetClientSize( &cw, &ch ); 649 } 650 651#if wxUSE_TWO_WINDOWS 652 wxPoint offset( 0,0 ); 653#else 654 wxPoint offset = GetClientAreaOrigin(); 655 s_x += offset.x; 656 s_y += offset.y; 657#endif 658 659 int w = cw - abs(dx); 660 int h = ch - abs(dy); 661 662 if ((h < 0) || (w < 0)) 663 { 664 Refresh(); 665 } 666 else 667 { 668 wxRect rect; 669 if (dx < 0) rect.x = cw+dx + offset.x; else rect.x = s_x; 670 if (dy < 0) rect.y = ch+dy + offset.y; else rect.y = s_y; 671 if (dy != 0) rect.width = cw; else rect.width = abs(dx); 672 if (dx != 0) rect.height = ch; else rect.height = abs(dy); 673 674 int d_x = s_x; 675 int d_y = s_y; 676 677 if (dx < 0) s_x += -dx; 678 if (dy < 0) s_y += -dy; 679 if (dx > 0) d_x += dx + offset.x; 680 if (dy > 0) d_y += dy + offset.y; 681 682 XCopyArea( xdisplay, xwindow, xwindow, xgc, s_x, s_y, w, h, d_x, d_y ); 683 684 // wxLogDebug( "Copy: s_x %d s_y %d w %d h %d d_x %d d_y %d", s_x, s_y, w, h, d_x, d_y ); 685 686 // wxLogDebug( "Update: %d %d %d %d", rect.x, rect.y, rect.width, rect.height ); 687 688 m_updateRegion.Union( rect ); 689 m_clearRegion.Union( rect ); 690 } 691 692 XFreeGC( xdisplay, xgc ); 693 694 // Move Clients, but not the scrollbars 695 // FIXME: There may be a better method to move a lot of Windows within X11 696 wxScrollBar *sbH = ((wxWindow *) this)->GetScrollbar( wxHORIZONTAL ); 697 wxScrollBar *sbV = ((wxWindow *) this)->GetScrollbar( wxVERTICAL ); 698 wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); 699 while ( node ) 700 { 701 // Only propagate to non-top-level windows 702 wxWindow *win = node->GetData(); 703 if ( win->GetParent() && win != sbH && win != sbV ) 704 { 705 wxPoint pos = win->GetPosition(); 706 // Add the delta to the old Position 707 pos.x += dx; 708 pos.y += dy; 709 win->SetPosition(pos); 710 } 711 node = node->GetNext(); 712 } 713} 714 715// --------------------------------------------------------------------------- 716// drag and drop 717// --------------------------------------------------------------------------- 718 719#if wxUSE_DRAG_AND_DROP 720 721void wxWindowX11::SetDropTarget(wxDropTarget * WXUNUSED(pDropTarget)) 722{ 723 // TODO 724} 725 726#endif 727 728// Old style file-manager drag&drop 729void wxWindowX11::DragAcceptFiles(bool WXUNUSED(accept)) 730{ 731 // TODO 732} 733 734// ---------------------------------------------------------------------------- 735// tooltips 736// ---------------------------------------------------------------------------- 737 738#if wxUSE_TOOLTIPS 739 740void wxWindowX11::DoSetToolTip(wxToolTip * WXUNUSED(tooltip)) 741{ 742 // TODO 743} 744 745#endif // wxUSE_TOOLTIPS 746 747// --------------------------------------------------------------------------- 748// moving and resizing 749// --------------------------------------------------------------------------- 750 751bool wxWindowX11::PreResize() 752{ 753 return true; 754} 755 756// Get total size 757void wxWindowX11::DoGetSize(int *x, int *y) const 758{ 759 Window xwindow = (Window) m_mainWindow; 760 761 wxCHECK_RET( xwindow, wxT("invalid window") ); 762 763 //XSync(wxGlobalDisplay(), False); 764 765 XWindowAttributes attr; 766 Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr ); 767 wxASSERT(status); 768 769 if (status) 770 { 771 *x = attr.width /* + 2*m_borderSize */ ; 772 *y = attr.height /* + 2*m_borderSize */ ; 773 } 774} 775 776void wxWindowX11::DoGetPosition(int *x, int *y) const 777{ 778 Window window = (Window) m_mainWindow; 779 if (window) 780 { 781 //XSync(wxGlobalDisplay(), False); 782 XWindowAttributes attr; 783 Status status = XGetWindowAttributes(wxGlobalDisplay(), window, & attr); 784 wxASSERT(status); 785 786 if (status) 787 { 788 *x = attr.x; 789 *y = attr.y; 790 791 // We may be faking the client origin. So a window that's really at (0, 30) 792 // may appear (to wxWin apps) to be at (0, 0). 793 if (GetParent()) 794 { 795 wxPoint pt(GetParent()->GetClientAreaOrigin()); 796 *x -= pt.x; 797 *y -= pt.y; 798 } 799 } 800 } 801} 802 803void wxWindowX11::DoScreenToClient(int *x, int *y) const 804{ 805 Display *display = wxGlobalDisplay(); 806 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display)); 807 Window thisWindow = (Window) m_clientWindow; 808 809 Window childWindow; 810 int xx = *x; 811 int yy = *y; 812 XTranslateCoordinates(display, rootWindow, thisWindow, xx, yy, x, y, &childWindow); 813} 814 815void wxWindowX11::DoClientToScreen(int *x, int *y) const 816{ 817 Display *display = wxGlobalDisplay(); 818 Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display)); 819 Window thisWindow = (Window) m_clientWindow; 820 821 Window childWindow; 822 int xx = *x; 823 int yy = *y; 824 XTranslateCoordinates(display, thisWindow, rootWindow, xx, yy, x, y, &childWindow); 825} 826 827 828// Get size *available for subwindows* i.e. excluding menu bar etc. 829void wxWindowX11::DoGetClientSize(int *x, int *y) const 830{ 831 Window window = (Window) m_mainWindow; 832 833 if (window) 834 { 835 XWindowAttributes attr; 836 Status status = XGetWindowAttributes( wxGlobalDisplay(), window, &attr ); 837 wxASSERT(status); 838 839 if (status) 840 { 841 *x = attr.width ; 842 *y = attr.height ; 843 } 844 } 845} 846 847void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags) 848{ 849 // wxLogDebug("DoSetSize: %s (%ld) %d, %d %dx%d", GetClassInfo()->GetClassName(), GetId(), x, y, width, height); 850 851 Window xwindow = (Window) m_mainWindow; 852 853 wxCHECK_RET( xwindow, wxT("invalid window") ); 854 855 XWindowAttributes attr; 856 Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr ); 857 wxCHECK_RET( status, wxT("invalid window attributes") ); 858 859 int new_x = attr.x; 860 int new_y = attr.y; 861 int new_w = attr.width; 862 int new_h = attr.height; 863 864 if (x != wxDefaultCoord || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) 865 { 866 int yy = 0; 867 AdjustForParentClientOrigin( x, yy, sizeFlags); 868 new_x = x; 869 } 870 if (y != wxDefaultCoord || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) 871 { 872 int xx = 0; 873 AdjustForParentClientOrigin( xx, y, sizeFlags); 874 new_y = y; 875 } 876 if (width != wxDefaultCoord) 877 { 878 new_w = width; 879 if (new_w <= 0) 880 new_w = 20; 881 } 882 if (height != wxDefaultCoord) 883 { 884 new_h = height; 885 if (new_h <= 0) 886 new_h = 20; 887 } 888 889 DoMoveWindow( new_x, new_y, new_w, new_h ); 890} 891 892void wxWindowX11::DoSetClientSize(int width, int height) 893{ 894 // wxLogDebug("DoSetClientSize: %s (%ld) %dx%d", GetClassInfo()->GetClassName(), GetId(), width, height); 895 896 Window xwindow = (Window) m_mainWindow; 897 898 wxCHECK_RET( xwindow, wxT("invalid window") ); 899 900 XResizeWindow( wxGlobalDisplay(), xwindow, width, height ); 901 902 if (m_mainWindow != m_clientWindow) 903 { 904 xwindow = (Window) m_clientWindow; 905 906 wxWindow *window = (wxWindow*) this; 907 wxRenderer *renderer = window->GetRenderer(); 908 if (renderer) 909 { 910 wxRect border = renderer->GetBorderDimensions( (wxBorder)(m_windowStyle & wxBORDER_MASK) ); 911 width -= border.x + border.width; 912 height -= border.y + border.height; 913 } 914 915 XResizeWindow( wxGlobalDisplay(), xwindow, width, height ); 916 } 917} 918 919void wxWindowX11::DoMoveWindow(int x, int y, int width, int height) 920{ 921 Window xwindow = (Window) m_mainWindow; 922 923 wxCHECK_RET( xwindow, wxT("invalid window") ); 924 925#if !wxUSE_NANOX 926 927 XMoveResizeWindow( wxGlobalDisplay(), xwindow, x, y, width, height ); 928 if (m_mainWindow != m_clientWindow) 929 { 930 xwindow = (Window) m_clientWindow; 931 932 wxWindow *window = (wxWindow*) this; 933 wxRenderer *renderer = window->GetRenderer(); 934 if (renderer) 935 { 936 wxRect border = renderer->GetBorderDimensions( (wxBorder)(m_windowStyle & wxBORDER_MASK) ); 937 x = border.x; 938 y = border.y; 939 width -= border.x + border.width; 940 height -= border.y + border.height; 941 } 942 else 943 { 944 x = 0; 945 y = 0; 946 } 947 948 wxScrollBar *sb = window->GetScrollbar( wxHORIZONTAL ); 949 if (sb && sb->IsShown()) 950 { 951 wxSize size = sb->GetSize(); 952 height -= size.y; 953 } 954 sb = window->GetScrollbar( wxVERTICAL ); 955 if (sb && sb->IsShown()) 956 { 957 wxSize size = sb->GetSize(); 958 width -= size.x; 959 } 960 961 XMoveResizeWindow( wxGlobalDisplay(), xwindow, x, y, wxMax(1, width), wxMax(1, height) ); 962 } 963 964#else 965 966 XWindowChanges windowChanges; 967 windowChanges.x = x; 968 windowChanges.y = y; 969 windowChanges.width = width; 970 windowChanges.height = height; 971 windowChanges.stack_mode = 0; 972 int valueMask = CWX | CWY | CWWidth | CWHeight; 973 974 XConfigureWindow( wxGlobalDisplay(), xwindow, valueMask, &windowChanges ); 975 976#endif 977} 978 979void wxWindowX11::DoSetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH) 980{ 981 m_minWidth = minW; 982 m_minHeight = minH; 983 m_maxWidth = maxW; 984 m_maxHeight = maxH; 985 986#if !wxUSE_NANOX 987 XSizeHints sizeHints; 988 sizeHints.flags = 0; 989 990 if (minW > -1 && minH > -1) 991 { 992 sizeHints.flags |= PMinSize; 993 sizeHints.min_width = minW; 994 sizeHints.min_height = minH; 995 } 996 if (maxW > -1 && maxH > -1) 997 { 998 sizeHints.flags |= PMaxSize; 999 sizeHints.max_width = maxW; 1000 sizeHints.max_height = maxH; 1001 } 1002 if (incW > -1 && incH > -1) 1003 { 1004 sizeHints.flags |= PResizeInc; 1005 sizeHints.width_inc = incW; 1006 sizeHints.height_inc = incH; 1007 } 1008 1009 XSetWMNormalHints(wxGlobalDisplay(), (Window) m_mainWindow, &sizeHints ); 1010#endif 1011} 1012 1013// --------------------------------------------------------------------------- 1014// text metrics 1015// --------------------------------------------------------------------------- 1016 1017int wxWindowX11::GetCharHeight() const 1018{ 1019 wxFont font(GetFont()); 1020 wxCHECK_MSG( font.Ok(), 0, wxT("valid window font needed") ); 1021 1022#if wxUSE_UNICODE 1023 // There should be an easier way. 1024 PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() ); 1025 pango_layout_set_font_description( layout, font.GetNativeFontInfo()->description ); 1026 pango_layout_set_text(layout, "H", 1 ); 1027 int w,h; 1028 pango_layout_get_pixel_size(layout, &w, &h); 1029 g_object_unref( G_OBJECT( layout ) ); 1030 1031 return h; 1032#else 1033 WXFontStructPtr pFontStruct = font.GetFontStruct(1.0, wxGlobalDisplay()); 1034 1035 int direction, ascent, descent; 1036 XCharStruct overall; 1037 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent, 1038 &descent, &overall); 1039 1040 // return (overall.ascent + overall.descent); 1041 return (ascent + descent); 1042#endif 1043} 1044 1045int wxWindowX11::GetCharWidth() const 1046{ 1047 wxFont font(GetFont()); 1048 wxCHECK_MSG( font.Ok(), 0, wxT("valid window font needed") ); 1049 1050#if wxUSE_UNICODE 1051 // There should be an easier way. 1052 PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() ); 1053 pango_layout_set_font_description( layout, font.GetNativeFontInfo()->description ); 1054 pango_layout_set_text(layout, "H", 1 ); 1055 int w,h; 1056 pango_layout_get_pixel_size(layout, &w, &h); 1057 g_object_unref( G_OBJECT( layout ) ); 1058 1059 return w; 1060#else 1061 WXFontStructPtr pFontStruct = font.GetFontStruct(1.0, wxGlobalDisplay()); 1062 1063 int direction, ascent, descent; 1064 XCharStruct overall; 1065 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent, 1066 &descent, &overall); 1067 1068 return overall.width; 1069#endif 1070} 1071 1072void wxWindowX11::GetTextExtent(const wxString& string, 1073 int *x, int *y, 1074 int *descent, int *externalLeading, 1075 const wxFont *theFont) const 1076{ 1077 wxFont fontToUse = GetFont(); 1078 if (theFont) fontToUse = *theFont; 1079 1080 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") ); 1081 1082 if (string.empty()) 1083 { 1084 if (x) (*x) = 0; 1085 if (y) (*y) = 0; 1086 return; 1087 } 1088 1089#if wxUSE_UNICODE 1090 PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() ); 1091 1092 PangoFontDescription *desc = fontToUse.GetNativeFontInfo()->description; 1093 pango_layout_set_font_description(layout, desc); 1094 1095 const wxCharBuffer data = wxConvUTF8.cWC2MB( string ); 1096 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); 1097 1098 PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data; 1099 1100 1101 PangoRectangle rect; 1102 pango_layout_line_get_extents(line, NULL, &rect); 1103 1104 if (x) (*x) = (wxCoord) (rect.width / PANGO_SCALE); 1105 if (y) (*y) = (wxCoord) (rect.height / PANGO_SCALE); 1106 if (descent) 1107 { 1108 // Do something about metrics here 1109 (*descent) = 0; 1110 } 1111 if (externalLeading) (*externalLeading) = 0; // ?? 1112 1113 g_object_unref( G_OBJECT( layout ) ); 1114#else 1115 WXFontStructPtr pFontStruct = fontToUse.GetFontStruct(1.0, wxGlobalDisplay()); 1116 1117 int direction, ascent, descent2; 1118 XCharStruct overall; 1119 int slen = string.length(); 1120 1121 XTextExtents((XFontStruct*) pFontStruct, (char*) string.c_str(), slen, 1122 &direction, &ascent, &descent2, &overall); 1123 1124 if ( x ) 1125 *x = (overall.width); 1126 if ( y ) 1127 *y = (ascent + descent2); 1128 if (descent) 1129 *descent = descent2; 1130 if (externalLeading) 1131 *externalLeading = 0; 1132#endif 1133} 1134 1135// ---------------------------------------------------------------------------- 1136// painting 1137// ---------------------------------------------------------------------------- 1138 1139void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect) 1140{ 1141 if (eraseBack) 1142 { 1143 if (rect) 1144 { 1145 // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 1146 m_clearRegion.Union( rect->x, rect->y, rect->width, rect->height ); 1147 } 1148 else 1149 { 1150 int height,width; 1151 GetSize( &width, &height ); 1152 1153 // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 1154 m_clearRegion.Clear(); 1155 m_clearRegion.Union( 0, 0, width, height ); 1156 } 1157 } 1158 1159 if (rect) 1160 { 1161 // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 1162 m_updateRegion.Union( rect->x, rect->y, rect->width, rect->height ); 1163 } 1164 else 1165 { 1166 int height,width; 1167 GetSize( &width, &height ); 1168 1169 // Schedule for later Updating in ::Update() or ::OnInternalIdle(). 1170 m_updateRegion.Clear(); 1171 m_updateRegion.Union( 0, 0, width, height ); 1172 } 1173} 1174 1175void wxWindowX11::Update() 1176{ 1177 if (m_updateNcArea) 1178 { 1179 // wxLogDebug("wxWindowX11::UpdateNC: %s", GetClassInfo()->GetClassName()); 1180 // Send nc paint events. 1181 SendNcPaintEvents(); 1182 } 1183 1184 if (!m_updateRegion.IsEmpty()) 1185 { 1186 // wxLogDebug("wxWindowX11::Update: %s", GetClassInfo()->GetClassName()); 1187 // Actually send erase events. 1188 SendEraseEvents(); 1189 1190 // Actually send paint events. 1191 SendPaintEvents(); 1192 } 1193} 1194 1195void wxWindowX11::SendEraseEvents() 1196{ 1197 if (m_clearRegion.IsEmpty()) return; 1198 1199 wxClientDC dc( (wxWindow*)this ); 1200 dc.SetClippingRegion( m_clearRegion ); 1201 1202 wxEraseEvent erase_event( GetId(), &dc ); 1203 erase_event.SetEventObject( this ); 1204 1205 if (!GetEventHandler()->ProcessEvent(erase_event) ) 1206 { 1207 Display *xdisplay = wxGlobalDisplay(); 1208 Window xwindow = (Window) GetClientAreaWindow(); 1209 XSetForeground( xdisplay, g_eraseGC, m_backgroundColour.GetPixel() ); 1210 1211 wxRegionIterator upd( m_clearRegion ); 1212 while (upd) 1213 { 1214 XFillRectangle( xdisplay, xwindow, g_eraseGC, 1215 upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); 1216 upd ++; 1217 } 1218 } 1219 1220 m_clearRegion.Clear(); 1221} 1222 1223void wxWindowX11::SendPaintEvents() 1224{ 1225 // wxLogDebug("SendPaintEvents: %s (%ld)", GetClassInfo()->GetClassName(), GetId()); 1226 1227 m_clipPaintRegion = true; 1228 1229 wxPaintEvent paint_event( GetId() ); 1230 paint_event.SetEventObject( this ); 1231 GetEventHandler()->ProcessEvent( paint_event ); 1232 1233 m_updateRegion.Clear(); 1234 1235 m_clipPaintRegion = false; 1236} 1237 1238void wxWindowX11::SendNcPaintEvents() 1239{ 1240 wxWindow *window = (wxWindow*) this; 1241 1242 // All this for drawing the small square between the scrollbars. 1243 int width = 0; 1244 int height = 0; 1245 int x = 0; 1246 int y = 0; 1247 wxScrollBar *sb = window->GetScrollbar( wxHORIZONTAL ); 1248 if (sb && sb->IsShown()) 1249 { 1250 height = sb->GetSize().y; 1251 y = sb->GetPosition().y; 1252 1253 sb = window->GetScrollbar( wxVERTICAL ); 1254 if (sb && sb->IsShown()) 1255 { 1256 width = sb->GetSize().x; 1257 x = sb->GetPosition().x; 1258 1259 Display *xdisplay = wxGlobalDisplay(); 1260 Window xwindow = (Window) GetMainWindow(); 1261 Colormap cm = (Colormap) wxTheApp->GetMainColormap( wxGetDisplay() ); 1262 wxColour colour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE); 1263 colour.CalcPixel( (WXColormap) cm ); 1264 1265 XSetForeground( xdisplay, g_eraseGC, colour.GetPixel() ); 1266 1267 XFillRectangle( xdisplay, xwindow, g_eraseGC, x, y, width, height ); 1268 } 1269 } 1270 1271 wxNcPaintEvent nc_paint_event( GetId() ); 1272 nc_paint_event.SetEventObject( this ); 1273 GetEventHandler()->ProcessEvent( nc_paint_event ); 1274 1275 m_updateNcArea = false; 1276} 1277 1278// ---------------------------------------------------------------------------- 1279// event handlers 1280// ---------------------------------------------------------------------------- 1281 1282// Responds to colour changes: passes event on to children. 1283void wxWindowX11::OnSysColourChanged(wxSysColourChangedEvent& event) 1284{ 1285 wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); 1286 while ( node ) 1287 { 1288 // Only propagate to non-top-level windows 1289 wxWindow *win = node->GetData(); 1290 if ( win->GetParent() ) 1291 { 1292 wxSysColourChangedEvent event2; 1293 event.SetEventObject(win); 1294 win->GetEventHandler()->ProcessEvent(event2); 1295 } 1296 1297 node = node->GetNext(); 1298 } 1299} 1300 1301// See handler for InFocus case in app.cpp for details. 1302wxWindow* g_GettingFocus = NULL; 1303 1304void wxWindowX11::OnInternalIdle() 1305{ 1306 // Update invalidated regions. 1307 Update(); 1308 1309 // This calls the UI-update mechanism (querying windows for 1310 // menu/toolbar/control state information) 1311 if (wxUpdateUIEvent::CanUpdate((wxWindow*) this) && IsShownOnScreen()) 1312 UpdateWindowUI(wxUPDATE_UI_FROMIDLE); 1313 1314 // Set the input focus if couldn't do it before 1315 if (m_needsInputFocus) 1316 { 1317#if 0 1318 wxString msg; 1319 msg.Printf("Setting focus for %s from OnInternalIdle\n", GetClassInfo()->GetClassName()); 1320 printf(msg.c_str()); 1321#endif 1322 SetFocus(); 1323 1324 // If it couldn't set the focus now, there's 1325 // no point in trying again. 1326 m_needsInputFocus = false; 1327 } 1328 g_GettingFocus = NULL; 1329} 1330 1331// ---------------------------------------------------------------------------- 1332// function which maintain the global hash table mapping Widgets to wxWidgets 1333// ---------------------------------------------------------------------------- 1334 1335static bool DoAddWindowToTable(wxWindowHash *hash, Window w, wxWindow *win) 1336{ 1337 if ( !hash->insert(wxWindowHash::value_type(w, win)).second ) 1338 { 1339 wxLogDebug( wxT("Widget table clash: new widget is 0x%08x, %s"), 1340 (unsigned int)w, win->GetClassInfo()->GetClassName()); 1341 return false; 1342 } 1343 1344 wxLogTrace( wxT("widget"), wxT("XWindow 0x%08x <-> window %p (%s)"), 1345 (unsigned int) w, win, win->GetClassInfo()->GetClassName()); 1346 1347 return true; 1348} 1349 1350static inline wxWindow *DoGetWindowFromTable(wxWindowHash *hash, Window w) 1351{ 1352 wxWindowHash::iterator i = hash->find(w); 1353 return i == hash->end() ? NULL : i->second; 1354} 1355 1356static inline void DoDeleteWindowFromTable(wxWindowHash *hash, Window w) 1357{ 1358 wxLogTrace( wxT("widget"), wxT("XWindow 0x%08x deleted"), (unsigned int) w); 1359 1360 hash->erase(w); 1361} 1362 1363// ---------------------------------------------------------------------------- 1364// public wrappers 1365// ---------------------------------------------------------------------------- 1366 1367bool wxAddWindowToTable(Window w, wxWindow *win) 1368{ 1369 return DoAddWindowToTable(wxWidgetHashTable, w, win); 1370} 1371 1372wxWindow *wxGetWindowFromTable(Window w) 1373{ 1374 return DoGetWindowFromTable(wxWidgetHashTable, w); 1375} 1376 1377void wxDeleteWindowFromTable(Window w) 1378{ 1379 DoDeleteWindowFromTable(wxWidgetHashTable, w); 1380} 1381 1382bool wxAddClientWindowToTable(Window w, wxWindow *win) 1383{ 1384 return DoAddWindowToTable(wxClientWidgetHashTable, w, win); 1385} 1386 1387wxWindow *wxGetClientWindowFromTable(Window w) 1388{ 1389 return DoGetWindowFromTable(wxClientWidgetHashTable, w); 1390} 1391 1392void wxDeleteClientWindowFromTable(Window w) 1393{ 1394 DoDeleteWindowFromTable(wxClientWidgetHashTable, w); 1395} 1396 1397// ---------------------------------------------------------------------------- 1398// X11-specific accessors 1399// ---------------------------------------------------------------------------- 1400 1401WXWindow wxWindowX11::GetMainWindow() const 1402{ 1403 return m_mainWindow; 1404} 1405 1406WXWindow wxWindowX11::GetClientAreaWindow() const 1407{ 1408 return m_clientWindow; 1409} 1410 1411// ---------------------------------------------------------------------------- 1412// TranslateXXXEvent() functions 1413// ---------------------------------------------------------------------------- 1414 1415bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window, XEvent *xevent) 1416{ 1417 switch (XEventGetType(xevent)) 1418 { 1419 case EnterNotify: 1420 case LeaveNotify: 1421 case ButtonPress: 1422 case ButtonRelease: 1423 case MotionNotify: 1424 { 1425 wxEventType eventType = wxEVT_NULL; 1426 1427 if (XEventGetType(xevent) == EnterNotify) 1428 { 1429 //if (local_event.xcrossing.mode!=NotifyNormal) 1430 // return ; // Ignore grab events 1431 eventType = wxEVT_ENTER_WINDOW; 1432 // canvas->GetEventHandler()->OnSetFocus(); 1433 } 1434 else if (XEventGetType(xevent) == LeaveNotify) 1435 { 1436 //if (local_event.xcrossingr.mode!=NotifyNormal) 1437 // return ; // Ignore grab events 1438 eventType = wxEVT_LEAVE_WINDOW; 1439 // canvas->GetEventHandler()->OnKillFocus(); 1440 } 1441 else if (XEventGetType(xevent) == MotionNotify) 1442 { 1443 eventType = wxEVT_MOTION; 1444 } 1445 else if (XEventGetType(xevent) == ButtonPress) 1446 { 1447 wxevent.SetTimestamp(XButtonEventGetTime(xevent)); 1448 int button = 0; 1449 if (XButtonEventLChanged(xevent)) 1450 { 1451 eventType = wxEVT_LEFT_DOWN; 1452 button = 1; 1453 } 1454 else if (XButtonEventMChanged(xevent)) 1455 { 1456 eventType = wxEVT_MIDDLE_DOWN; 1457 button = 2; 1458 } 1459 else if (XButtonEventRChanged(xevent)) 1460 { 1461 eventType = wxEVT_RIGHT_DOWN; 1462 button = 3; 1463 } 1464 1465 // check for a double click 1466 // TODO: where can we get this value from? 1467 //long dclickTime = XtGetMultiClickTime(wxGlobalDisplay()); 1468 long dclickTime = 200; 1469 long ts = wxevent.GetTimestamp(); 1470 1471 int buttonLast = win->GetLastClickedButton(); 1472 long lastTS = win->GetLastClickTime(); 1473 if ( buttonLast && buttonLast == button && (ts - lastTS) < dclickTime ) 1474 { 1475 // I have a dclick 1476 win->SetLastClick(0, ts); 1477 if ( eventType == wxEVT_LEFT_DOWN ) 1478 eventType = wxEVT_LEFT_DCLICK; 1479 else if ( eventType == wxEVT_MIDDLE_DOWN ) 1480 eventType = wxEVT_MIDDLE_DCLICK; 1481 else if ( eventType == wxEVT_RIGHT_DOWN ) 1482 eventType = wxEVT_RIGHT_DCLICK; 1483 } 1484 else 1485 { 1486 // not fast enough or different button 1487 win->SetLastClick(button, ts); 1488 } 1489 } 1490 else if (XEventGetType(xevent) == ButtonRelease) 1491 { 1492 if (XButtonEventLChanged(xevent)) 1493 { 1494 eventType = wxEVT_LEFT_UP; 1495 } 1496 else if (XButtonEventMChanged(xevent)) 1497 { 1498 eventType = wxEVT_MIDDLE_UP; 1499 } 1500 else if (XButtonEventRChanged(xevent)) 1501 { 1502 eventType = wxEVT_RIGHT_UP; 1503 } 1504 else return false; 1505 } 1506 else 1507 { 1508 return false; 1509 } 1510 1511 wxevent.SetEventType(eventType); 1512 1513 wxevent.m_x = XButtonEventGetX(xevent); 1514 wxevent.m_y = XButtonEventGetY(xevent); 1515 1516 wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN) 1517 || (XButtonEventLIsDown(xevent) 1518 && (eventType != wxEVT_LEFT_UP))); 1519 wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN) 1520 || (XButtonEventMIsDown(xevent) 1521 && (eventType != wxEVT_MIDDLE_UP))); 1522 wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN) 1523 || (XButtonEventRIsDown (xevent) 1524 && (eventType != wxEVT_RIGHT_UP))); 1525 1526 wxevent.m_shiftDown = XButtonEventShiftIsDown(xevent); 1527 wxevent.m_controlDown = XButtonEventCtrlIsDown(xevent); 1528 wxevent.m_altDown = XButtonEventAltIsDown(xevent); 1529 wxevent.m_metaDown = XButtonEventMetaIsDown(xevent); 1530 1531 wxevent.SetId(win->GetId()); 1532 wxevent.SetEventObject(win); 1533 1534 return true; 1535 } 1536 } 1537 return false; 1538} 1539 1540bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent, bool isAscii) 1541{ 1542 switch (XEventGetType(xevent)) 1543 { 1544 case KeyPress: 1545 case KeyRelease: 1546 { 1547 char buf[20]; 1548 1549 KeySym keySym; 1550 (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL); 1551 int id = wxCharCodeXToWX (keySym); 1552 // id may be WXK_xxx code - these are outside ASCII range, so we 1553 // can't just use toupper() on id. 1554 // Only change this if we want the raw key that was pressed, 1555 // and don't change it if we want an ASCII value. 1556 if (!isAscii && (id >= 'a' && id <= 'z')) 1557 { 1558 id = id + 'A' - 'a'; 1559 } 1560 1561 wxevent.m_shiftDown = XKeyEventShiftIsDown(xevent); 1562 wxevent.m_controlDown = XKeyEventCtrlIsDown(xevent); 1563 wxevent.m_altDown = XKeyEventAltIsDown(xevent); 1564 wxevent.m_metaDown = XKeyEventMetaIsDown(xevent); 1565 wxevent.SetEventObject(win); 1566 wxevent.m_keyCode = id; 1567 wxevent.SetTimestamp(XKeyEventGetTime(xevent)); 1568 1569 wxevent.m_x = XKeyEventGetX(xevent); 1570 wxevent.m_y = XKeyEventGetY(xevent); 1571 1572 return id > -1; 1573 } 1574 default: 1575 break; 1576 } 1577 return false; 1578} 1579 1580// ---------------------------------------------------------------------------- 1581// Colour stuff 1582// ---------------------------------------------------------------------------- 1583 1584bool wxWindowX11::SetBackgroundColour(const wxColour& col) 1585{ 1586 wxWindowBase::SetBackgroundColour(col); 1587 1588 Display *xdisplay = (Display*) wxGlobalDisplay(); 1589 int xscreen = DefaultScreen( xdisplay ); 1590 Colormap cm = DefaultColormap( xdisplay, xscreen ); 1591 1592 m_backgroundColour.CalcPixel( (WXColormap) cm ); 1593 1594 // We don't set the background colour as we paint 1595 // the background ourselves. 1596 // XSetWindowBackground( xdisplay, (Window) m_clientWindow, m_backgroundColour.GetPixel() ); 1597 1598 return true; 1599} 1600 1601bool wxWindowX11::SetForegroundColour(const wxColour& col) 1602{ 1603 if ( !wxWindowBase::SetForegroundColour(col) ) 1604 return false; 1605 1606 return true; 1607} 1608 1609// ---------------------------------------------------------------------------- 1610// global functions 1611// ---------------------------------------------------------------------------- 1612 1613wxWindow *wxGetActiveWindow() 1614{ 1615 // TODO 1616 wxFAIL_MSG(wxT("Not implemented")); 1617 return NULL; 1618} 1619 1620/* static */ 1621wxWindow *wxWindowBase::GetCapture() 1622{ 1623 return (wxWindow *)g_captureWindow; 1624} 1625 1626 1627// Find the wxWindow at the current mouse position, returning the mouse 1628// position. 1629wxWindow* wxFindWindowAtPointer(wxPoint& pt) 1630{ 1631 return wxFindWindowAtPoint(wxGetMousePosition()); 1632} 1633 1634void wxGetMouseState(int& rootX, int& rootY, unsigned& maskReturn) 1635{ 1636#if wxUSE_NANOX 1637 /* TODO */ 1638 rootX = rootY = 0; 1639 maskReturn = 0; 1640#else 1641 Display *display = wxGlobalDisplay(); 1642 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display)); 1643 Window rootReturn, childReturn; 1644 int winX, winY; 1645 1646 XQueryPointer (display, 1647 rootWindow, 1648 &rootReturn, 1649 &childReturn, 1650 &rootX, &rootY, &winX, &winY, &maskReturn); 1651#endif 1652} 1653 1654// Get the current mouse position. 1655wxPoint wxGetMousePosition() 1656{ 1657 int x, y; 1658 unsigned mask; 1659 1660 wxGetMouseState(x, y, mask); 1661 return wxPoint(x, y); 1662} 1663 1664wxMouseState wxGetMouseState() 1665{ 1666 wxMouseState ms; 1667 int x, y; 1668 unsigned mask; 1669 1670 wxGetMouseState(x, y, mask); 1671 1672 ms.SetX(x); 1673 ms.SetY(y); 1674 1675 ms.SetLeftDown(mask & Button1Mask); 1676 ms.SetMiddleDown(mask & Button2Mask); 1677 ms.SetRightDown(mask & Button3Mask); 1678 1679 ms.SetControlDown(mask & ControlMask); 1680 ms.SetShiftDown(mask & ShiftMask); 1681 ms.SetAltDown(mask & Mod3Mask); 1682 ms.SetMetaDown(mask & Mod1Mask); 1683 1684 return ms; 1685} 1686 1687 1688// ---------------------------------------------------------------------------- 1689// wxNoOptimize: switch off size optimization 1690// ---------------------------------------------------------------------------- 1691 1692int wxNoOptimize::ms_count = 0; 1693 1694 1695// ---------------------------------------------------------------------------- 1696// wxDCModule 1697// ---------------------------------------------------------------------------- 1698 1699class wxWinModule : public wxModule 1700{ 1701public: 1702 wxWinModule() 1703 { 1704 // we must be cleaned up before the display is closed 1705 AddDependency(wxClassInfo::FindClass(_T("wxX11DisplayModule"))); 1706 } 1707 1708 virtual bool OnInit(); 1709 virtual void OnExit(); 1710 1711private: 1712 DECLARE_DYNAMIC_CLASS(wxWinModule) 1713}; 1714 1715IMPLEMENT_DYNAMIC_CLASS(wxWinModule, wxModule) 1716 1717bool wxWinModule::OnInit() 1718{ 1719 Display *xdisplay = wxGlobalDisplay(); 1720 int xscreen = DefaultScreen( xdisplay ); 1721 Window xroot = RootWindow( xdisplay, xscreen ); 1722 g_eraseGC = XCreateGC( xdisplay, xroot, 0, NULL ); 1723 XSetFillStyle( xdisplay, g_eraseGC, FillSolid ); 1724 1725 return true; 1726} 1727 1728void wxWinModule::OnExit() 1729{ 1730 Display *xdisplay = wxGlobalDisplay(); 1731 XFreeGC( xdisplay, g_eraseGC ); 1732} 1733