1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: Window.cpp 23 // Author: Adrian Oanca (e2joseph@hotpop.com) 24 // Description: A BWindow object represents a window that can be displayed 25 // on the screen, and that can be the target of user events 26 //------------------------------------------------------------------------------ 27 28 // System Includes ------------------------------------------------------------- 29 #include <BeBuild.h> 30 #include <InterfaceDefs.h> 31 #include <PropertyInfo.h> 32 #include <Handler.h> 33 #include <Looper.h> 34 #include <Application.h> 35 #include <Window.h> 36 #include <View.h> 37 #include <MenuBar.h> 38 #include <String.h> 39 #include <Screen.h> 40 #include <Button.h> 41 #include <MessageQueue.h> 42 #include <MessageRunner.h> 43 #include <Roster.h> 44 45 // Project Includes ------------------------------------------------------------ 46 #include <AppMisc.h> 47 #include <PortLink.h> 48 #include <PortMessage.h> 49 #include <Session.h> 50 #include <ServerProtocol.h> 51 #include <TokenSpace.h> 52 #include <MessageUtils.h> 53 #include <WindowAux.h> 54 55 // Standard Includes ----------------------------------------------------------- 56 #include <stdio.h> 57 #include <math.h> 58 #include <posix/math.h> 59 60 // Local Includes -------------------------------------------------------------- 61 62 // Local Defines --------------------------------------------------------------- 63 //#define DEBUG_WIN 64 #ifdef DEBUG_WIN 65 # include <stdio.h> 66 # define STRACE(x) printf x 67 #else 68 # define STRACE(x) ; 69 #endif 70 71 // Globals --------------------------------------------------------------------- 72 static property_info windowPropInfo[] = 73 { 74 { "Feel", { B_GET_PROPERTY, 0 }, 75 { B_DIRECT_SPECIFIER, 0 }, "Returns the current feel of the window.",0 }, 76 77 { "Feel", { B_SET_PROPERTY, 0 }, 78 { B_DIRECT_SPECIFIER, 0 }, "Sets the feel of the window.",0 }, 79 80 { "Flags", { B_GET_PROPERTY, 0 }, 81 { B_DIRECT_SPECIFIER, 0 }, "Returns the current flags of the window.",0 }, 82 83 { "Flags", { B_SET_PROPERTY, 0 }, 84 { B_DIRECT_SPECIFIER, 0 }, "Sets the window flags.",0 }, 85 86 { "Frame", { B_GET_PROPERTY, 0 }, 87 { B_DIRECT_SPECIFIER, 0 }, "Returns the window's frame rectangle.",0}, 88 89 { "Frame", { B_SET_PROPERTY, 0 }, 90 { B_DIRECT_SPECIFIER, 0 }, "Sets the window's frame rectangle.",0 }, 91 92 { "Hidden", { B_GET_PROPERTY, 0 }, 93 { B_DIRECT_SPECIFIER, 0 }, "Returns true if the window is hidden; false otherwise.",0}, 94 95 { "Hidden", { B_SET_PROPERTY, 0 }, 96 { B_DIRECT_SPECIFIER, 0 }, "Hides or shows the window.",0 }, 97 98 { "Look", { B_GET_PROPERTY, 0 }, 99 { B_DIRECT_SPECIFIER, 0 }, "Returns the current look of the window.",0}, 100 101 { "Look", { B_SET_PROPERTY, 0 }, 102 { B_DIRECT_SPECIFIER, 0 }, "Sets the look of the window.",0 }, 103 104 { "Title", { B_GET_PROPERTY, 0 }, 105 { B_DIRECT_SPECIFIER, 0 }, "Returns a string containing the window title.",0}, 106 107 { "Title", { B_SET_PROPERTY, 0 }, 108 { B_DIRECT_SPECIFIER, 0 }, "Sets the window title.",0 }, 109 110 { "Workspaces", { B_GET_PROPERTY, 0 }, 111 { B_DIRECT_SPECIFIER, 0 }, "Returns int32 bitfield of the workspaces in which the window appears.",0}, 112 113 { "Workspaces", { B_SET_PROPERTY, 0 }, 114 { B_DIRECT_SPECIFIER, 0 }, "Sets the workspaces in which the window appears.",0 }, 115 116 { "MenuBar", { 0 }, 117 { B_DIRECT_SPECIFIER, 0 }, "Directs the scripting message to the key menu bar.",0 }, 118 119 { "View", { 0 }, 120 { 0 }, "Directs the scripting message to the top view without popping the current specifier.",0 }, 121 122 { "Minimize", { B_SET_PROPERTY, 0 }, 123 { B_DIRECT_SPECIFIER, 0 }, "Minimizes the window if \"data\" is true; restores otherwise.",0 }, 124 125 { 0, { 0 }, { 0 }, 0, 0 } 126 }; 127 //------------------------------------------------------------------------------ 128 129 // Constructors 130 //------------------------------------------------------------------------------ 131 BWindow::BWindow(BRect frame, 132 const char* title, 133 window_type type, 134 uint32 flags, 135 uint32 workspace) 136 : BLooper( title ) 137 { 138 #ifdef DEBUG_WIN 139 printf("BWindow::BWindow()\n"); 140 #endif 141 window_look look; 142 window_feel feel; 143 144 decomposeType(type, &look, &feel); 145 146 InitData( frame, title, look, feel, flags, workspace); 147 } 148 149 //------------------------------------------------------------------------------ 150 151 BWindow::BWindow(BRect frame, 152 const char* title, 153 window_look look, 154 window_feel feel, 155 uint32 flags, 156 uint32 workspace) 157 : BLooper( title ) 158 { 159 InitData( frame, title, look, feel, flags, workspace ); 160 } 161 162 //------------------------------------------------------------------------------ 163 164 BWindow::BWindow(BMessage* data) 165 : BLooper(data) 166 { 167 BMessage msg; 168 BArchivable *obj; 169 const char *title; 170 window_look look; 171 window_feel feel; 172 uint32 type; 173 uint32 workspaces; 174 175 data->FindRect("_frame", &fFrame); 176 data->FindString("_title", &title); 177 data->FindInt32("_wlook", (int32*)&look); 178 data->FindInt32("_wfeel", (int32*)&feel); 179 if ( data->FindInt32("_flags", (int32*)&fFlags) == B_OK ) 180 { } 181 else 182 fFlags = 0; 183 data->FindInt32("_wspace", (int32*)&workspaces); 184 185 if ( data->FindInt32("_type", (int32*)&type) == B_OK ){ 186 decomposeType( (window_type)type, &fLook, &fFeel ); 187 } 188 189 // connect to app_server and initialize data 190 InitData( fFrame, title, look, feel, fFlags, workspaces ); 191 192 if ( data->FindFloat("_zoom", 0, &fMaxZoomWidth) == B_OK ) 193 if ( data->FindFloat("_zoom", 1, &fMaxZoomHeight) == B_OK) 194 SetZoomLimits( fMaxZoomWidth, fMaxZoomHeight ); 195 196 if (data->FindFloat("_sizel", 0, &fMinWindWidth) == B_OK ) 197 if (data->FindFloat("_sizel", 1, &fMinWindHeight) == B_OK ) 198 if (data->FindFloat("_sizel", 2, &fMaxWindWidth) == B_OK ) 199 if (data->FindFloat("_sizel", 3, &fMaxWindHeight) == B_OK ) 200 SetSizeLimits( fMinWindWidth, fMaxWindWidth, 201 fMinWindHeight, fMaxWindHeight ); 202 203 if (data->FindInt64("_pulse", &fPulseRate) == B_OK ) 204 SetPulseRate( fPulseRate ); 205 206 int i = 0; 207 while ( data->FindMessage("_views", i++, &msg) == B_OK){ 208 obj = instantiate_object(&msg); 209 210 BView *child; 211 child = dynamic_cast<BView *>(obj); 212 if (child) 213 AddChild( child ); 214 } 215 } 216 217 //------------------------------------------------------------------------------ 218 219 BWindow::~BWindow(){ 220 // the following lines, remove all existing shortcuts and delete accelList 221 int32 noOfItems; 222 223 noOfItems = accelList.CountItems(); 224 for ( int index = noOfItems-1; index >= 0; index-- ) { 225 _BCmdKey *cmdKey; 226 227 cmdKey = (_BCmdKey*)accelList.ItemAt( index ); 228 229 accelList.RemoveItem(index); 230 231 delete cmdKey->message; 232 delete cmdKey; 233 } 234 235 // TODO: release other dinamicaly alocated objects 236 237 // disable pulsing 238 SetPulseRate( 0 ); 239 240 delete session; 241 delete_port( receive_port ); 242 } 243 244 //------------------------------------------------------------------------------ 245 246 BArchivable* BWindow::Instantiate(BMessage* data){ 247 248 if ( !validate_instantiation( data , "BWindow" ) ) 249 return NULL; 250 return new BWindow(data); 251 } 252 253 //------------------------------------------------------------------------------ 254 255 status_t BWindow::Archive(BMessage* data, bool deep) const{ 256 257 status_t retval; 258 259 retval = BLooper::Archive( data, deep ); 260 if (retval != B_OK) 261 return retval; 262 263 data->AddRect("_frame", fFrame); 264 data->AddString("_title", fTitle); 265 data->AddInt32("_wlook", fLook); 266 data->AddInt32("_wfeel", fFeel); 267 if (fFlags) 268 data->AddInt32("_flags", fFlags); 269 data->AddInt32("_wspace", (uint32)Workspaces()); 270 271 if ( !composeType(fLook, fFeel) ) 272 data->AddInt32("_type", (uint32)Type()); 273 274 if (fMaxZoomWidth != 32768.0 || fMaxZoomHeight != 32768.0) 275 { 276 data->AddFloat("_zoom", fMaxZoomWidth); 277 data->AddFloat("_zoom", fMaxZoomHeight); 278 } 279 280 if (fMinWindWidth != 0.0 || fMinWindHeight != 0.0 || 281 fMaxWindWidth != 32768.0 || fMaxWindHeight != 32768.0) 282 { 283 data->AddFloat("_sizel", fMinWindWidth); 284 data->AddFloat("_sizel", fMinWindHeight); 285 data->AddFloat("_sizel", fMaxWindWidth); 286 data->AddFloat("_sizel", fMaxWindHeight); 287 } 288 289 if (fPulseRate != 500000) 290 data->AddInt64("_pulse", fPulseRate); 291 292 if (deep) 293 { 294 int32 noOfViews = CountChildren(); 295 for (int i=0; i<noOfViews; i++){ 296 BMessage childArchive; 297 298 retval = ChildAt(i)->Archive( &childArchive, deep ); 299 if (retval == B_OK) 300 data->AddMessage( "_views", &childArchive ); 301 } 302 } 303 304 return B_OK; 305 } 306 307 //------------------------------------------------------------------------------ 308 309 void BWindow::Quit(){ 310 311 if (!IsLocked()) 312 { 313 const char* name = Name(); 314 if (!name) 315 name = "no-name"; 316 317 printf("ERROR - you must Lock a looper before calling Quit(), " 318 "team=%ld, looper=%s\n", Team(), name); 319 } 320 321 // Try to lock 322 if (!Lock()){ 323 // We're toast already 324 return; 325 } 326 327 while (!IsHidden()) { Hide(); } 328 329 // ... also its children 330 //detachTopView(); 331 STRACE(("Trying to stop connection...\n")); 332 // tell app_server, this window will finish execution 333 stopConnection(); 334 STRACE(("Connection stopped!\n")); 335 if (fFlags & B_QUIT_ON_WINDOW_CLOSE) 336 be_app->PostMessage( B_QUIT_REQUESTED ); 337 338 BLooper::Quit(); 339 } 340 341 //------------------------------------------------------------------------------ 342 343 void BWindow::AddChild(BView *child, BView *before){ 344 top_view->AddChild( child, before ); 345 } 346 347 //------------------------------------------------------------------------------ 348 349 bool BWindow::RemoveChild(BView *child){ 350 return top_view->RemoveChild( child ); 351 } 352 353 //------------------------------------------------------------------------------ 354 355 int32 BWindow::CountChildren() const{ 356 return top_view->CountChildren(); 357 } 358 359 //------------------------------------------------------------------------------ 360 361 BView* BWindow::ChildAt(int32 index) const{ 362 return top_view->ChildAt( index ); 363 } 364 365 //------------------------------------------------------------------------------ 366 367 void BWindow::Minimize(bool minimize){ 368 if (IsModal()) 369 return; 370 371 if (IsFloating()) 372 return; 373 374 Lock(); 375 session->WriteInt32( AS_WINDOW_MINIMIZE ); 376 session->WriteBool( minimize ); 377 session->Sync( ); 378 Unlock(); 379 } 380 //------------------------------------------------------------------------------ 381 382 status_t BWindow::SendBehind(const BWindow* window){ 383 384 if (!window) 385 return B_ERROR; 386 387 int32 rCode; 388 389 Lock(); 390 session->WriteInt32( AS_SEND_BEHIND ); 391 session->WriteInt32( _get_object_token_(window) ); 392 session->Sync(); 393 session->ReadInt32( &rCode ); 394 Unlock(); 395 396 return rCode == SERVER_TRUE? B_OK : B_ERROR; 397 } 398 399 //------------------------------------------------------------------------------ 400 401 void BWindow::Flush() const{ 402 const_cast<BWindow*>(this)->Lock(); 403 session->Sync(); 404 const_cast<BWindow*>(this)->Unlock(); 405 } 406 407 //------------------------------------------------------------------------------ 408 409 void BWindow::Sync() const{ 410 411 int32 rCode; 412 413 const_cast<BWindow*>(this)->Lock(); 414 session->WriteInt32( AS_SYNC ); 415 session->Sync(); 416 session->ReadInt32( &rCode ); 417 const_cast<BWindow*>(this)->Unlock(); 418 } 419 420 //------------------------------------------------------------------------------ 421 422 void BWindow::DisableUpdates(){ 423 424 Lock(); 425 session->WriteInt32( AS_DISABLE_UPDATES ); 426 session->Sync(); 427 Unlock(); 428 } 429 430 //------------------------------------------------------------------------------ 431 432 void BWindow::EnableUpdates(){ 433 434 Lock(); 435 session->WriteInt32( AS_ENABLE_UPDATES ); 436 session->Sync( ); 437 Unlock(); 438 } 439 440 //------------------------------------------------------------------------------ 441 442 void BWindow::BeginViewTransaction(){ 443 if ( !fInTransaction ){ 444 Lock(); 445 session->WriteInt32( AS_BEGIN_TRANSACTION ); 446 Unlock(); 447 448 fInTransaction = true; 449 } 450 } 451 452 //------------------------------------------------------------------------------ 453 454 void BWindow::EndViewTransaction(){ 455 if ( fInTransaction ){ 456 Lock(); 457 session->WriteInt32( AS_END_TRANSACTION ); 458 session->Sync(); 459 Unlock(); 460 461 fInTransaction = false; 462 } 463 } 464 465 //------------------------------------------------------------------------------ 466 467 bool BWindow::IsFront() const{ 468 if (IsActive()) 469 return true; 470 471 if (IsModal()) 472 return true; 473 474 return false; 475 } 476 477 //------------------------------------------------------------------------------ 478 479 void BWindow::MessageReceived( BMessage *msg ) 480 { 481 BMessage specifier; 482 int32 what; 483 const char* prop; 484 int32 index; 485 status_t err; 486 487 if (msg->HasSpecifiers()){ 488 489 err = msg->GetCurrentSpecifier(&index, &specifier, &what, &prop); 490 if (err == B_OK) 491 { 492 BMessage replyMsg; 493 494 switch (msg->what) 495 { 496 case B_GET_PROPERTY:{ 497 replyMsg.what = B_NO_ERROR; 498 replyMsg.AddInt32( "error", B_OK ); 499 500 if (strcmp(prop, "Feel") ==0 ) 501 { 502 replyMsg.AddInt32( "result", (uint32)Feel()); 503 } 504 else if (strcmp(prop, "Flags") ==0 ) 505 { 506 replyMsg.AddInt32( "result", Flags()); 507 } 508 else if (strcmp(prop, "Frame") ==0 ) 509 { 510 replyMsg.AddRect( "result", Frame()); 511 } 512 else if (strcmp(prop, "Hidden") ==0 ) 513 { 514 replyMsg.AddBool( "result", IsHidden()); 515 } 516 else if (strcmp(prop, "Look") ==0 ) 517 { 518 replyMsg.AddInt32( "result", (uint32)Look()); 519 } 520 else if (strcmp(prop, "Title") ==0 ) 521 { 522 replyMsg.AddString( "result", Title()); 523 } 524 else if (strcmp(prop, "Workspaces") ==0 ) 525 { 526 replyMsg.AddInt32( "result", Workspaces()); 527 } 528 }break; 529 530 case B_SET_PROPERTY:{ 531 if (strcmp(prop, "Feel") ==0 ) 532 { 533 uint32 newFeel; 534 if (msg->FindInt32( "data", (int32*)&newFeel ) == B_OK){ 535 SetFeel( (window_feel)newFeel ); 536 537 replyMsg.what = B_NO_ERROR; 538 replyMsg.AddInt32( "error", B_OK ); 539 } 540 else{ 541 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 542 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 543 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 544 } 545 } 546 547 else if (strcmp(prop, "Flags") ==0 ) 548 { 549 uint32 newFlags; 550 if (msg->FindInt32( "data", (int32*)&newFlags ) == B_OK){ 551 SetFlags( newFlags ); 552 553 replyMsg.what = B_NO_ERROR; 554 replyMsg.AddInt32( "error", B_OK ); 555 } 556 else{ 557 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 558 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 559 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 560 } 561 } 562 563 else if (strcmp(prop, "Frame") ==0 ) 564 { 565 BRect newFrame; 566 if (msg->FindRect( "data", &newFrame ) == B_OK){ 567 MoveTo( newFrame.LeftTop() ); 568 ResizeTo( newFrame.right, newFrame.bottom); 569 570 replyMsg.what = B_NO_ERROR; 571 replyMsg.AddInt32( "error", B_OK ); 572 } 573 else{ 574 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 575 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 576 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 577 } 578 } 579 580 else if (strcmp(prop, "Hidden") ==0 ) 581 { 582 bool newHiddenState; 583 if (msg->FindBool( "data", &newHiddenState ) == B_OK){ 584 if ( !IsHidden() && newHiddenState == true ){ 585 Hide(); 586 587 replyMsg.what = B_NO_ERROR; 588 replyMsg.AddInt32( "error", B_OK ); 589 590 } 591 else if ( IsHidden() && newHiddenState == false ){ 592 Show(); 593 594 replyMsg.what = B_NO_ERROR; 595 replyMsg.AddInt32( "error", B_OK ); 596 } 597 else{ 598 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 599 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 600 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 601 } 602 } 603 else{ 604 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 605 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 606 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 607 } 608 } 609 610 else if (strcmp(prop, "Look") ==0 ) 611 { 612 uint32 newLook; 613 if (msg->FindInt32( "data", (int32*)&newLook ) == B_OK){ 614 SetLook( (window_look)newLook ); 615 616 replyMsg.what = B_NO_ERROR; 617 replyMsg.AddInt32( "error", B_OK ); 618 } 619 else{ 620 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 621 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 622 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 623 } 624 } 625 626 else if (strcmp(prop, "Title") ==0 ) 627 { 628 const char *newTitle = NULL; 629 if (msg->FindString( "data", &newTitle ) == B_OK){ 630 SetTitle( newTitle ); 631 632 replyMsg.what = B_NO_ERROR; 633 replyMsg.AddInt32( "error", B_OK ); 634 } 635 else{ 636 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 637 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 638 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 639 } 640 delete newTitle; 641 } 642 643 else if (strcmp(prop, "Workspaces") ==0 ) 644 { 645 uint32 newWorkspaces; 646 if (msg->FindInt32( "data", (int32*)&newWorkspaces ) == B_OK){ 647 SetWorkspaces( newWorkspaces ); 648 649 replyMsg.what = B_NO_ERROR; 650 replyMsg.AddInt32( "error", B_OK ); 651 } 652 else{ 653 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 654 replyMsg.AddInt32( "error", B_BAD_SCRIPT_SYNTAX ); 655 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 656 } 657 } 658 659 }break; 660 } 661 msg->SendReply( &replyMsg ); 662 } 663 else{ 664 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 665 replyMsg.AddInt32( "error" , B_BAD_SCRIPT_SYNTAX ); 666 replyMsg.AddString( "message", "Didn't understand the specifier(s)" ); 667 668 msg->SendReply( &replyMsg ); 669 } 670 671 } // END: if (msg->HasSpecifiers()) 672 else 673 BLooper::MessageReceived( msg ); 674 } 675 676 //------------------------------------------------------------------------------ 677 678 void BWindow::DispatchMessage(BMessage *msg, BHandler *target) 679 { 680 if (!msg){ 681 BLooper::DispatchMessage( msg, target ); 682 return; 683 } 684 685 switch ( msg->what ) { 686 case B_ZOOM:{ 687 Zoom(); 688 break;} 689 690 case B_MINIMIZE:{ 691 bool minimize; 692 693 msg->FindBool("minimize", &minimize); 694 695 fMinimized = minimize; 696 Minimize( minimize ); 697 break;} 698 699 case B_WINDOW_RESIZED:{ 700 BPoint offset; 701 int32 width, height; 702 703 msg->FindInt32("width", &width); 704 msg->FindInt32("height", &height); 705 offset.x = width; 706 offset.y = height; 707 708 fFrame.SetRightBottom( fFrame.LeftTop() + offset ); 709 FrameResized( offset.x, offset.y ); 710 break;} 711 712 case B_WINDOW_MOVED:{ 713 BPoint origin; 714 715 msg->FindPoint("where", &origin); 716 717 fFrame.OffsetTo( origin ); 718 FrameMoved( origin ); 719 break;} 720 721 // this is NOT an app_server message and we have to be cautious 722 case B_WINDOW_MOVE_BY:{ 723 BPoint offset; 724 725 if (msg->FindPoint("data", &offset) == B_OK) 726 MoveBy( offset.x, offset.y ); 727 else 728 msg->SendReply( B_MESSAGE_NOT_UNDERSTOOD ); 729 break;} 730 731 // this is NOT an app_server message and we have to be cautious 732 case B_WINDOW_MOVE_TO:{ 733 BPoint origin; 734 735 if (msg->FindPoint("data", &origin) == B_OK) 736 MoveTo( origin ); 737 else 738 msg->SendReply( B_MESSAGE_NOT_UNDERSTOOD ); 739 break;} 740 741 case B_WINDOW_ACTIVATED:{ 742 bool active; 743 744 msg->FindBool("active", &active); 745 746 fActive = active; 747 handleActivation( active ); 748 break;} 749 750 case B_SCREEN_CHANGED:{ 751 BRect frame; 752 uint32 mode; 753 754 msg->FindRect("frame", &frame); 755 msg->FindInt32("mode", (int32*)&mode); 756 ScreenChanged( frame, (color_space)mode ); 757 break;} 758 759 case B_WORKSPACE_ACTIVATED:{ 760 uint32 workspace; 761 bool active; 762 763 msg->FindInt32( "workspace", (int32*)&workspace ); 764 msg->FindBool( "active", &active ); 765 WorkspaceActivated( workspace, active ); 766 break;} 767 768 case B_WORKSPACES_CHANGED:{ 769 uint32 oldWorkspace; 770 uint32 newWorkspace; 771 772 msg->FindInt32( "old", (int32*)&oldWorkspace ); 773 msg->FindInt32( "new", (int32*)&newWorkspace ); 774 WorkspacesChanged( oldWorkspace, newWorkspace ); 775 break;} 776 777 case B_KEY_DOWN:{ 778 uint32 modifiers; 779 int32 raw_char; 780 const char *string; 781 782 msg->FindInt32( "modifiers", (int32*)&modifiers ); 783 msg->FindInt32( "raw_char", &raw_char ); 784 msg->FindString( "bytes", &string ); 785 // TODO: it is NOT "bytes" field you should pass to KeyDown(), it is "byte" field. 786 if ( !handleKeyDown( raw_char, (uint32)modifiers) ) 787 fFocus->KeyDown( string, strlen(string)-1 ); 788 break;} 789 790 case B_KEY_UP:{ 791 const char *string; 792 793 msg->FindString( "bytes", &string ); 794 fFocus->KeyUp( string, strlen(string)-1 ); 795 break;} 796 797 case B_UNMAPPED_KEY_DOWN:{ 798 if (fFocus) 799 fFocus->MessageReceived( msg ); 800 break;} 801 802 case B_UNMAPPED_KEY_UP:{ 803 if (fFocus) 804 fFocus->MessageReceived( msg ); 805 break;} 806 807 case B_MODIFIERS_CHANGED:{ 808 if (fFocus) 809 fFocus->MessageReceived( msg ); 810 break;} 811 812 case B_MOUSE_WHEEL_CHANGED:{ 813 if (fFocus) 814 fFocus->MessageReceived( msg ); 815 break;} 816 817 case B_MOUSE_DOWN:{ 818 BPoint where; 819 uint32 modifiers; 820 uint32 buttons; 821 int32 clicks; 822 823 msg->FindPoint( "where", &where ); 824 msg->FindInt32( "modifiers", (int32*)&modifiers ); 825 msg->FindInt32( "buttons", (int32*)&buttons ); 826 msg->FindInt32( "clicks", &clicks ); 827 828 sendMessageUsingEventMask( B_MOUSE_DOWN, where ); 829 break;} 830 831 case B_MOUSE_UP:{ 832 BPoint where; 833 uint32 modifiers; 834 835 msg->FindPoint( "where", &where ); 836 msg->FindInt32( "modifiers", (int32*)&modifiers ); 837 838 sendMessageUsingEventMask( B_MOUSE_UP, where ); 839 break;} 840 841 case B_MOUSE_MOVED:{ 842 BPoint where; 843 uint32 buttons; 844 845 msg->FindPoint( "where", &where ); 846 msg->FindInt32( "buttons", (int32*)&buttons ); 847 848 sendMessageUsingEventMask( B_MOUSE_MOVED, where ); 849 break;} 850 851 case B_PULSE:{ 852 if (fPulseEnabled) 853 sendPulse( top_view ); 854 break;} 855 856 case B_QUIT_REQUESTED:{ 857 if (QuitRequested()) 858 Quit(); 859 break;} 860 861 case _UPDATE_:{ 862 BRect updateRect; 863 msg->FindRect("_rect", &updateRect); 864 865 // TODO: ADD this method: 866 //DrawViews( updateRect ); 867 break;} 868 869 case B_VIEW_MOVED:{ 870 BPoint where; 871 int32 token = B_NULL_TOKEN; 872 BView *view; 873 874 msg->FindPoint("where", &where); 875 msg->FindInt32("_token", &token); 876 msg->RemoveName("_token"); 877 878 view = findView(top_view, token); 879 if (view){ 880 STRACE(("Calling BView(%s)::FrameMoved( %f, %f )\n", view->Name(), where.x, where.y)); 881 view->FrameMoved( where ); 882 } 883 else 884 printf("***PANIC: BW: Can't find view with ID: %ld !***\n", token); 885 886 break;} 887 888 case B_VIEW_RESIZED:{ 889 float newWidth, 890 newHeight; 891 BPoint where; 892 int32 token = B_NULL_TOKEN; 893 BView *view; 894 895 msg->FindFloat("width", &newWidth); 896 msg->FindFloat("height", &newHeight); 897 msg->FindPoint("where", &where); 898 msg->FindInt32("_token", &token); 899 msg->RemoveName("_token"); 900 901 view = findView(top_view, token); 902 if (view){ 903 STRACE(("Calling BView(%s)::FrameResized( %f, %f )\n", view->Name(), newWidth, newHeight)); 904 view->FrameResized( newWidth, newHeight ); 905 } 906 else 907 printf("***PANIC: BW: Can't find view with ID: %ld !***\n", token); 908 909 break;} 910 911 default:{ 912 BLooper::DispatchMessage(msg, target); 913 break;} 914 } 915 } 916 917 //------------------------------------------------------------------------------ 918 919 void BWindow::FrameMoved(BPoint new_position){ 920 // does nothing 921 // Hook function 922 } 923 924 //------------------------------------------------------------------------------ 925 926 void BWindow::FrameResized(float new_width, float new_height){ 927 // does nothing 928 // Hook function 929 } 930 931 //------------------------------------------------------------------------------ 932 933 void BWindow::WorkspacesChanged(uint32 old_ws, uint32 new_ws){ 934 // does nothing 935 // Hook function 936 } 937 938 //------------------------------------------------------------------------------ 939 940 void BWindow::WorkspaceActivated(int32 ws, bool state){ 941 // does nothing 942 // Hook function 943 } 944 945 //------------------------------------------------------------------------------ 946 947 void BWindow::MenusBeginning(){ 948 // does nothing 949 // Hook function 950 } 951 952 //------------------------------------------------------------------------------ 953 954 void BWindow::MenusEnded(){ 955 // does nothing 956 // Hook function 957 } 958 959 //------------------------------------------------------------------------------ 960 961 void BWindow::SetSizeLimits(float minWidth, float maxWidth, 962 float minHeight, float maxHeight){ 963 int32 rCode; 964 965 if (minWidth > maxWidth) 966 return; 967 if (minHeight > maxHeight) 968 return; 969 970 Lock(); 971 session->WriteInt32( AS_SET_SIZE_LIMITS ); 972 session->WriteFloat( fMinWindWidth ); 973 session->WriteFloat( fMaxWindWidth ); 974 session->WriteFloat( fMinWindHeight ); 975 session->WriteFloat( fMaxWindHeight ); 976 session->Sync(); 977 session->ReadInt32( &rCode ); 978 Unlock(); 979 980 if (rCode == SERVER_TRUE){ 981 fMinWindHeight = minHeight; 982 fMinWindWidth = minWidth; 983 fMaxWindHeight = maxHeight; 984 fMaxWindWidth = maxWidth; 985 } 986 } 987 988 //------------------------------------------------------------------------------ 989 990 void BWindow::GetSizeLimits(float *minWidth, float *maxWidth, 991 float *minHeight, float *maxHeight){ 992 *minHeight = fMinWindHeight; 993 *minWidth = fMinWindWidth; 994 *maxHeight = fMaxWindHeight; 995 *maxWidth = fMaxWindWidth; 996 } 997 998 //------------------------------------------------------------------------------ 999 1000 void BWindow::SetZoomLimits(float maxWidth, float maxHeight){ 1001 if (maxWidth > fMaxWindWidth) 1002 maxWidth = fMaxWindWidth; 1003 else 1004 fMaxZoomWidth = maxWidth; 1005 1006 if (maxHeight > fMaxWindHeight) 1007 maxHeight = fMaxWindHeight; 1008 else 1009 fMaxZoomHeight = maxHeight; 1010 } 1011 1012 //------------------------------------------------------------------------------ 1013 1014 void BWindow::Zoom( BPoint rec_position, float rec_width, float rec_height){ 1015 1016 // this is also a Hook function! 1017 1018 MoveTo( rec_position ); 1019 ResizeTo( rec_width, rec_height ); 1020 } 1021 1022 //------------------------------------------------------------------------------ 1023 1024 void BWindow::Zoom(){ 1025 float minWidth, minHeight; 1026 BScreen screen; 1027 /* from BeBook: 1028 However, if the window's rectangle already matches these "zoom" dimensions 1029 (give or take a few pixels), Zoom() passes the window's previous 1030 ("non-zoomed") size and location. (??????) 1031 */ 1032 if (Frame().Width() == fMaxZoomWidth && Frame().Height() == fMaxZoomHeight) { 1033 BPoint position( Frame().left, Frame().top); 1034 Zoom( position, fMaxZoomWidth, fMaxZoomHeight ); 1035 return; 1036 } 1037 1038 /* from BeBook: 1039 The dimensions that non-virtual Zoom() passes to hook Zoom() are deduced from 1040 the smallest of three rectangles: 3) the screen rectangle, 1) the rectangle 1041 defined by SetZoomLimits(), 2) the rectangle defined by SetSizeLimits() 1042 */ 1043 // 1 1044 minHeight = fMaxZoomHeight; 1045 minWidth = fMaxZoomWidth; 1046 1047 // 2 1048 if ( fMaxWindHeight < minHeight ) { minHeight = fMaxWindHeight; } 1049 if ( fMaxWindWidth < minWidth ) { minWidth = fMaxWindWidth; } 1050 1051 // 3 1052 if ( screen.Frame().Width() < minWidth ) { minWidth = screen.Frame().Width(); } 1053 if ( screen.Frame().Height() < minHeight ) { minHeight = screen.Frame().Height(); } 1054 1055 Zoom( Frame().LeftTop(), minWidth, minHeight ); 1056 } 1057 1058 //------------------------------------------------------------------------------ 1059 1060 void BWindow::ScreenChanged(BRect screen_size, color_space depth){ 1061 // Hook function 1062 // does nothing 1063 } 1064 1065 //------------------------------------------------------------------------------ 1066 1067 void BWindow::SetPulseRate(bigtime_t rate){ 1068 if ( rate < 0 ) 1069 return; 1070 1071 if (fPulseRate == 0 && !fPulseEnabled){ 1072 fPulseRunner = new BMessageRunner( BMessenger(this), 1073 new BMessage( B_PULSE ), 1074 rate); 1075 fPulseRate = rate; 1076 fPulseEnabled = true; 1077 1078 return; 1079 } 1080 1081 if (rate == 0 && fPulseEnabled){ 1082 delete fPulseRunner; 1083 fPulseRunner = NULL; 1084 1085 fPulseRate = rate; 1086 fPulseEnabled = false; 1087 1088 return; 1089 } 1090 1091 fPulseRunner->SetInterval( rate ); 1092 } 1093 1094 //------------------------------------------------------------------------------ 1095 1096 bigtime_t BWindow::PulseRate() const{ 1097 return fPulseRate; 1098 } 1099 1100 //------------------------------------------------------------------------------ 1101 1102 void BWindow::AddShortcut( uint32 key, uint32 modifiers, BMessage* msg){ 1103 AddShortcut( key, modifiers, msg, this); 1104 } 1105 1106 //------------------------------------------------------------------------------ 1107 1108 void BWindow::AddShortcut( uint32 key, uint32 modifiers, BMessage* msg, BHandler* target){ 1109 /* 1110 NOTE: I'm not sure if it is OK to use 'key' 1111 */ 1112 if ( !msg ) 1113 return; 1114 1115 int64 when; 1116 _BCmdKey *cmdKey; 1117 1118 when = real_time_clock_usecs(); 1119 msg->AddInt64("when", when); 1120 1121 // TODO: make sure key is a lowercase char !!! 1122 1123 modifiers = modifiers | B_COMMAND_KEY; 1124 1125 cmdKey = new _BCmdKey; 1126 cmdKey->key = key; 1127 cmdKey->modifiers = modifiers; 1128 cmdKey->message = msg; 1129 if (target == NULL) 1130 cmdKey->targetToken = B_ANY_TOKEN; 1131 else 1132 cmdKey->targetToken = _get_object_token_(target); 1133 1134 // removes the shortcut from accelList if it exists! 1135 RemoveShortcut( key, modifiers ); 1136 1137 accelList.AddItem( cmdKey ); 1138 1139 } 1140 1141 //------------------------------------------------------------------------------ 1142 1143 void BWindow::RemoveShortcut(uint32 key, uint32 modifiers){ 1144 int32 index; 1145 1146 modifiers = modifiers | B_COMMAND_KEY; 1147 1148 index = findShortcut( key, modifiers ); 1149 if ( index >=0 ) { 1150 _BCmdKey *cmdKey; 1151 1152 cmdKey = (_BCmdKey*)accelList.ItemAt( index ); 1153 1154 accelList.RemoveItem(index); 1155 1156 delete cmdKey->message; 1157 delete cmdKey; 1158 } 1159 } 1160 1161 //------------------------------------------------------------------------------ 1162 1163 BButton* BWindow::DefaultButton() const{ 1164 return fDefaultButton; 1165 } 1166 1167 //------------------------------------------------------------------------------ 1168 1169 void BWindow::SetDefaultButton(BButton* button){ 1170 /* 1171 Note: for developers! 1172 He he, if you really want to understand what is happens here, take a piece of 1173 paper and start taking possible values and then walk with them through 1174 the code. 1175 */ 1176 BButton *aux; 1177 1178 if ( fDefaultButton == button ) 1179 return; 1180 1181 if ( fDefaultButton ){ 1182 aux = fDefaultButton; 1183 fDefaultButton = NULL; 1184 aux->MakeDefault( false ); 1185 aux->Invalidate(); 1186 } 1187 1188 if ( button == NULL ){ 1189 fDefaultButton = NULL; 1190 return; 1191 } 1192 1193 fDefaultButton = button; 1194 fDefaultButton->MakeDefault( true ); 1195 fDefaultButton->Invalidate(); 1196 } 1197 1198 //------------------------------------------------------------------------------ 1199 1200 bool BWindow::NeedsUpdate() const{ 1201 1202 int32 rCode; 1203 1204 const_cast<BWindow*>(this)->Lock(); 1205 session->WriteInt32( AS_NEEDS_UPDATE ); 1206 session->Sync(); 1207 session->ReadInt32( &rCode ); 1208 const_cast<BWindow*>(this)->Unlock(); 1209 1210 return rCode == SERVER_TRUE; 1211 } 1212 1213 //------------------------------------------------------------------------------ 1214 1215 void BWindow::UpdateIfNeeded(){ 1216 // works only from this thread 1217 if (find_thread(NULL) == Thread()){ 1218 Sync(); 1219 drawAllViews( top_view ); 1220 } 1221 } 1222 1223 //------------------------------------------------------------------------------ 1224 1225 BView* BWindow::FindView(const char* viewName) const{ 1226 1227 return findView( top_view, viewName ); 1228 } 1229 1230 //------------------------------------------------------------------------------ 1231 1232 BView* BWindow::FindView(BPoint point) const{ 1233 1234 return findView( top_view, point ); 1235 } 1236 1237 //------------------------------------------------------------------------------ 1238 1239 BView* BWindow::CurrentFocus() const{ 1240 return fFocus; 1241 } 1242 1243 //------------------------------------------------------------------------------ 1244 1245 void BWindow::Activate(bool active){ 1246 if (IsHidden()) 1247 return; 1248 1249 Lock(); 1250 session->WriteInt32( AS_ACTIVATE_WINDOW ); 1251 session->WriteBool( active ); 1252 session->Sync( ); 1253 Unlock(); 1254 } 1255 1256 //------------------------------------------------------------------------------ 1257 1258 void BWindow::WindowActivated(bool state){ 1259 // hook function 1260 // does nothing 1261 } 1262 1263 //------------------------------------------------------------------------------ 1264 1265 void BWindow::ConvertToScreen(BPoint* pt) const{ 1266 pt->x += fFrame.left; 1267 pt->y += fFrame.top; 1268 } 1269 1270 //------------------------------------------------------------------------------ 1271 1272 BPoint BWindow::ConvertToScreen(BPoint pt) const{ 1273 pt.x += fFrame.left; 1274 pt.y += fFrame.top; 1275 1276 return pt; 1277 } 1278 1279 //------------------------------------------------------------------------------ 1280 1281 void BWindow::ConvertFromScreen(BPoint* pt) const{ 1282 pt->x -= fFrame.left; 1283 pt->y -= fFrame.top; 1284 } 1285 1286 //------------------------------------------------------------------------------ 1287 1288 BPoint BWindow::ConvertFromScreen(BPoint pt) const{ 1289 pt.x -= fFrame.left; 1290 pt.y -= fFrame.top; 1291 1292 return pt; 1293 } 1294 1295 //------------------------------------------------------------------------------ 1296 1297 void BWindow::ConvertToScreen(BRect* rect) const{ 1298 rect->top += fFrame.top; 1299 rect->left += fFrame.left; 1300 rect->bottom += fFrame.top; 1301 rect->right += fFrame.left; 1302 } 1303 1304 //------------------------------------------------------------------------------ 1305 1306 BRect BWindow::ConvertToScreen(BRect rect) const{ 1307 rect.top += fFrame.top; 1308 rect.left += fFrame.left; 1309 rect.bottom += fFrame.top; 1310 rect.right += fFrame.left; 1311 1312 return rect; 1313 } 1314 1315 //------------------------------------------------------------------------------ 1316 1317 void BWindow::ConvertFromScreen(BRect* rect) const{ 1318 rect->top -= fFrame.top; 1319 rect->left -= fFrame.left; 1320 rect->bottom -= fFrame.top; 1321 rect->right -= fFrame.left; 1322 } 1323 1324 //------------------------------------------------------------------------------ 1325 1326 BRect BWindow::ConvertFromScreen(BRect rect) const{ 1327 rect.top -= fFrame.top; 1328 rect.left -= fFrame.left; 1329 rect.bottom -= fFrame.top; 1330 rect.right -= fFrame.left; 1331 1332 return rect; 1333 } 1334 1335 //------------------------------------------------------------------------------ 1336 1337 bool BWindow::IsMinimized() const{ 1338 // Hiding takes precendence over minimization!!! 1339 if ( IsHidden() ) 1340 return false; 1341 1342 return fMinimized; 1343 } 1344 1345 //------------------------------------------------------------------------------ 1346 1347 BRect BWindow::Bounds() const{ 1348 BRect bounds( 0.0, 0.0, fFrame.Width(), fFrame.Height() ); 1349 return bounds; 1350 } 1351 1352 //------------------------------------------------------------------------------ 1353 1354 BRect BWindow::Frame() const{ 1355 return fFrame; 1356 } 1357 1358 //------------------------------------------------------------------------------ 1359 1360 const char* BWindow::Title() const{ 1361 return fTitle; 1362 } 1363 1364 //------------------------------------------------------------------------------ 1365 1366 void BWindow::SetTitle(const char* title){ 1367 if (!title) 1368 return; 1369 1370 if (fTitle){ 1371 delete fTitle; 1372 fTitle = NULL; 1373 } 1374 1375 fTitle = strdup( title ); 1376 1377 // we will change BWindow's thread name to "w>window_title" 1378 int32 length; 1379 length = strlen( fTitle ); 1380 1381 char *threadName; 1382 threadName = new char[32]; 1383 strcpy(threadName, "w>"); 1384 strncat(threadName, fTitle, (length>=29) ? 29: length); 1385 1386 // if the message loop has been started... 1387 if (Thread() != B_ERROR ){ 1388 SetName( threadName ); 1389 rename_thread( Thread(), threadName ); 1390 1391 // we notify the app_server so we can actually see the change 1392 Lock(); 1393 session->WriteInt32( AS_WINDOW_TITLE); 1394 session->WriteString( fTitle ); 1395 session->Sync( ); 1396 Unlock(); 1397 } 1398 else 1399 SetName( threadName ); 1400 } 1401 1402 //------------------------------------------------------------------------------ 1403 1404 bool BWindow::IsActive() const{ 1405 return fActive; 1406 } 1407 1408 //------------------------------------------------------------------------------ 1409 1410 void BWindow::SetKeyMenuBar(BMenuBar* bar){ 1411 fKeyMenuBar = bar; 1412 } 1413 1414 //------------------------------------------------------------------------------ 1415 1416 BMenuBar* BWindow::KeyMenuBar() const{ 1417 return fKeyMenuBar; 1418 } 1419 1420 //------------------------------------------------------------------------------ 1421 1422 bool BWindow::IsModal() const{ 1423 if ( fFeel == B_MODAL_SUBSET_WINDOW_FEEL) 1424 return true; 1425 if ( fFeel == B_MODAL_APP_WINDOW_FEEL) 1426 return true; 1427 if ( fFeel == B_MODAL_ALL_WINDOW_FEEL) 1428 return true; 1429 1430 return false; 1431 1432 } 1433 1434 //------------------------------------------------------------------------------ 1435 1436 bool BWindow::IsFloating() const{ 1437 if ( fFeel == B_FLOATING_SUBSET_WINDOW_FEEL) 1438 return true; 1439 if ( fFeel == B_FLOATING_APP_WINDOW_FEEL) 1440 return true; 1441 if ( fFeel == B_FLOATING_ALL_WINDOW_FEEL) 1442 return true; 1443 1444 return false; 1445 } 1446 1447 //------------------------------------------------------------------------------ 1448 1449 status_t BWindow::AddToSubset(BWindow* window){ 1450 if ( !window ) 1451 return B_ERROR; 1452 1453 int32 rCode; 1454 1455 if (window->Feel() == B_NORMAL_WINDOW_FEEL && 1456 (fFeel == B_MODAL_SUBSET_WINDOW_FEEL || 1457 fFeel == B_FLOATING_SUBSET_WINDOW_FEEL)){ 1458 1459 team_id team = Team(); 1460 1461 Lock(); 1462 session->WriteInt32( AS_ADD_TO_SUBSET ); 1463 session->WriteInt32( _get_object_token_(window) ); 1464 session->WriteData( &team, sizeof(team_id) ); 1465 session->Sync(); 1466 session->ReadInt32( &rCode ); 1467 Unlock(); 1468 1469 return rCode == SERVER_TRUE? B_OK : B_ERROR; 1470 } 1471 1472 return B_ERROR; 1473 } 1474 1475 //------------------------------------------------------------------------------ 1476 1477 status_t BWindow::RemoveFromSubset(BWindow* window){ 1478 if ( !window ) 1479 return B_ERROR; 1480 1481 int32 rCode; 1482 1483 if (window->Feel() == B_NORMAL_WINDOW_FEEL && 1484 (fFeel == B_MODAL_SUBSET_WINDOW_FEEL || 1485 fFeel == B_FLOATING_SUBSET_WINDOW_FEEL)){ 1486 1487 team_id team = Team(); 1488 1489 Lock(); 1490 session->WriteInt32( AS_REM_FROM_SUBSET ); 1491 session->WriteInt32( _get_object_token_(window) ); 1492 session->WriteData( &team, sizeof(team_id) ); 1493 session->Sync(); 1494 session->ReadInt32( &rCode ); 1495 Unlock(); 1496 1497 return rCode == SERVER_TRUE? B_OK : B_ERROR; 1498 } 1499 1500 return B_ERROR; 1501 } 1502 1503 //------------------------------------------------------------------------------ 1504 1505 status_t BWindow::Perform(perform_code d, void* arg){ 1506 return BLooper::Perform( d, arg ); 1507 } 1508 1509 //------------------------------------------------------------------------------ 1510 1511 status_t BWindow::SetType(window_type type){ 1512 decomposeType(type, &fLook, &fFeel); 1513 status_t stat1, stat2; 1514 1515 stat1=SetLook( fLook ); 1516 stat2=SetFeel( fFeel ); 1517 1518 if(stat1==B_OK && stat2==B_OK) 1519 return B_OK; 1520 return B_ERROR; 1521 } 1522 1523 //------------------------------------------------------------------------------ 1524 1525 window_type BWindow::Type() const{ 1526 return composeType( fLook, fFeel ); 1527 } 1528 1529 //------------------------------------------------------------------------------ 1530 1531 status_t BWindow::SetLook(window_look look){ 1532 1533 int32 rCode; 1534 1535 Lock(); 1536 session->WriteInt32( AS_SET_LOOK ); 1537 session->WriteInt32( (int32)look ); 1538 session->Sync(); 1539 session->ReadInt32( &rCode ); 1540 Unlock(); 1541 1542 if (rCode == SERVER_TRUE){ 1543 fLook = look; 1544 return B_OK; 1545 } 1546 1547 return B_ERROR; 1548 } 1549 1550 //------------------------------------------------------------------------------ 1551 1552 window_look BWindow::Look() const{ 1553 return fLook; 1554 } 1555 1556 //------------------------------------------------------------------------------ 1557 1558 status_t BWindow::SetFeel(window_feel feel){ 1559 /* TODO: See what happens when a window that is part of a subset, changes its 1560 feel!? should it be removed from the subset??? 1561 */ 1562 int32 rCode; 1563 1564 Lock(); 1565 session->WriteInt32( AS_SET_FEEL ); 1566 session->WriteInt32( (int32)feel ); 1567 session->Sync(); 1568 session->ReadInt32( &rCode ); 1569 Unlock(); 1570 1571 if (rCode == SERVER_TRUE){ 1572 fFeel = feel; 1573 return B_OK; 1574 } 1575 1576 return B_ERROR; 1577 } 1578 1579 //------------------------------------------------------------------------------ 1580 1581 window_feel BWindow::Feel() const{ 1582 return fFeel; 1583 } 1584 1585 //------------------------------------------------------------------------------ 1586 1587 status_t BWindow::SetFlags(uint32 flags){ 1588 1589 int32 rCode; 1590 1591 Lock(); 1592 session->WriteInt32( AS_SET_FLAGS ); 1593 session->WriteUInt32( flags ); 1594 session->Sync(); 1595 session->ReadInt32( &rCode ); 1596 Unlock(); 1597 1598 if (rCode == SERVER_TRUE){ 1599 fFlags = flags; 1600 return B_OK; 1601 } 1602 1603 return B_ERROR; 1604 } 1605 1606 //------------------------------------------------------------------------------ 1607 1608 uint32 BWindow::Flags() const{ 1609 return fFlags; 1610 } 1611 1612 //------------------------------------------------------------------------------ 1613 1614 status_t BWindow::SetWindowAlignment(window_alignment mode, 1615 int32 h, int32 hOffset, 1616 int32 width, int32 widthOffset, 1617 int32 v, int32 vOffset, 1618 int32 height, int32 heightOffset) 1619 { 1620 if ( !( (mode && B_BYTE_ALIGNMENT) || 1621 (mode && B_PIXEL_ALIGNMENT) ) ) 1622 { 1623 return B_ERROR; 1624 } 1625 1626 if ( 0 <= hOffset && hOffset <=h ) 1627 return B_ERROR; 1628 1629 if ( 0 <= vOffset && vOffset <=v ) 1630 return B_ERROR; 1631 1632 if ( 0 <= widthOffset && widthOffset <=width ) 1633 return B_ERROR; 1634 1635 if ( 0 <= heightOffset && heightOffset <=height ) 1636 return B_ERROR; 1637 1638 // TODO: test if hOffset = 0 and set it to 1 if true. 1639 int32 rCode; 1640 1641 Lock(); 1642 session->WriteInt32( AS_SET_ALIGNMENT ); 1643 session->WriteInt32( (int32)mode ); 1644 session->WriteInt32( h ); 1645 session->WriteInt32( hOffset ); 1646 session->WriteInt32( width ); 1647 session->WriteInt32( widthOffset ); 1648 session->WriteInt32( v ); 1649 session->WriteInt32( vOffset ); 1650 session->WriteInt32( height ); 1651 session->WriteInt32( heightOffset ); 1652 session->Sync(); 1653 session->ReadInt32( &rCode ); 1654 Unlock(); 1655 1656 if ( rCode == SERVER_TRUE){ 1657 return B_NO_ERROR; 1658 } 1659 1660 return B_ERROR; 1661 } 1662 1663 //------------------------------------------------------------------------------ 1664 1665 status_t BWindow::GetWindowAlignment(window_alignment* mode, 1666 int32* h, int32* hOffset, 1667 int32* width, int32* widthOffset, 1668 int32* v, int32* vOffset, 1669 int32* height, int32* heightOffset) const 1670 { 1671 int32 rCode; 1672 1673 const_cast<BWindow*>(this)->Lock(); 1674 session->WriteInt32( AS_GET_ALIGNMENT ); 1675 session->Sync(); 1676 session->ReadInt32( &rCode ); 1677 1678 if (rCode == SERVER_TRUE){ 1679 session->ReadInt32( (int32*)mode ); 1680 session->ReadInt32( h ); 1681 session->ReadInt32( hOffset ); 1682 session->ReadInt32( width ); 1683 session->ReadInt32( widthOffset ); 1684 session->ReadInt32( v ); 1685 session->ReadInt32( hOffset ); 1686 session->ReadInt32( height ); 1687 session->ReadInt32( heightOffset ); 1688 1689 return B_NO_ERROR; 1690 } 1691 const_cast<BWindow*>(this)->Unlock(); 1692 1693 return B_ERROR; 1694 } 1695 1696 //------------------------------------------------------------------------------ 1697 1698 uint32 BWindow::Workspaces() const{ 1699 uint32 workspaces; 1700 1701 const_cast<BWindow*>(this)->Lock(); 1702 session->WriteInt32( AS_GET_WORKSPACES ); 1703 session->Sync(); 1704 session->ReadInt32( (int32*)&workspaces ); 1705 const_cast<BWindow*>(this)->Unlock(); 1706 1707 return workspaces; 1708 } 1709 1710 //------------------------------------------------------------------------------ 1711 1712 void BWindow::SetWorkspaces(uint32 workspaces){ 1713 1714 Lock(); 1715 session->WriteInt32( AS_SET_WORKSPACES ); 1716 session->WriteInt32( (int32)workspaces ); 1717 session->Sync( ); 1718 Unlock(); 1719 } 1720 1721 //------------------------------------------------------------------------------ 1722 1723 BView* BWindow::LastMouseMovedView() const{ 1724 return fLastMouseMovedView; 1725 } 1726 1727 //------------------------------------------------------------------------------ 1728 1729 void BWindow::MoveBy(float dx, float dy){ 1730 1731 BPoint offset( dx, dy ); 1732 1733 MoveTo( fFrame.LeftTop() + offset ); 1734 } 1735 1736 //------------------------------------------------------------------------------ 1737 1738 void BWindow::MoveTo( BPoint point ){ 1739 MoveTo( point.x, point.y ); 1740 } 1741 1742 //------------------------------------------------------------------------------ 1743 1744 void BWindow::MoveTo(float x, float y){ 1745 1746 Lock(); 1747 session->WriteInt32( AS_WINDOW_MOVE ); 1748 session->WriteFloat( x ); 1749 session->WriteFloat( y ); 1750 session->Sync(); 1751 Unlock(); 1752 } 1753 1754 //------------------------------------------------------------------------------ 1755 1756 void BWindow::ResizeBy(float dx, float dy){ 1757 1758 // stay in minimum & maximum frame limits 1759 (fFrame.Width() + dx) < fMinWindWidth ? fMinWindWidth : fFrame.Width() + dx; 1760 (fFrame.Width() + dx) > fMaxWindWidth ? fMaxWindWidth : fFrame.Width() + dx; 1761 1762 (fFrame.Height() + dy) < fMinWindHeight ? fMinWindHeight : fFrame.Height() + dy; 1763 (fFrame.Height() + dy) > fMaxWindHeight ? fMaxWindHeight : fFrame.Height() + dy; 1764 1765 ResizeTo( fFrame.Width() + dx, fFrame.Height() + dy ); 1766 } 1767 1768 //------------------------------------------------------------------------------ 1769 1770 void BWindow::ResizeTo(float width, float height){ 1771 1772 // stay in minimum & maximum frame limits 1773 width = (width < fMinWindWidth) ? fMinWindWidth : width; 1774 width = (width > fMaxWindWidth) ? fMaxWindWidth : width; 1775 1776 height = (height < fMinWindHeight) ? fMinWindHeight : height; 1777 height = (height > fMaxWindHeight) ? fMaxWindHeight : height; 1778 1779 Lock(); 1780 session->WriteInt32( AS_WINDOW_RESIZE ); 1781 session->WriteFloat( width ); 1782 session->WriteFloat( height ); 1783 session->Sync( ); 1784 Unlock(); 1785 } 1786 1787 //------------------------------------------------------------------------------ 1788 1789 void BWindow::Show(){ 1790 bool isLocked = this->IsLocked(); 1791 1792 fShowLevel--; 1793 1794 if (fShowLevel == 0){ 1795 STRACE(("BWindow(%s): sending AS_SHOW_WINDOW message...\n", Name() )); 1796 if ( !isLocked ) Lock(); 1797 session->WriteInt32( AS_SHOW_WINDOW ); 1798 session->Sync( ); 1799 if ( !isLocked) Unlock(); 1800 } 1801 1802 // if it's the fist time Show() is called... start the Looper thread. 1803 if ( Thread() == B_ERROR ) 1804 { 1805 // normaly this won't happen, but I want to be sure! 1806 if ( !isLocked ) Lock(); 1807 Run(); 1808 } 1809 1810 } 1811 1812 //------------------------------------------------------------------------------ 1813 1814 void BWindow::Hide(){ 1815 if (fShowLevel == 0){ 1816 Lock(); 1817 session->WriteInt32( AS_HIDE_WINDOW ); 1818 session->Sync(); 1819 Unlock(); 1820 } 1821 fShowLevel++; 1822 } 1823 1824 //------------------------------------------------------------------------------ 1825 1826 bool BWindow::IsHidden() const{ 1827 return fShowLevel > 0; 1828 } 1829 1830 //------------------------------------------------------------------------------ 1831 1832 bool BWindow::QuitRequested(){ 1833 return BLooper::QuitRequested(); 1834 } 1835 1836 //------------------------------------------------------------------------------ 1837 1838 thread_id BWindow::Run(){ 1839 return BLooper::Run(); 1840 } 1841 1842 //------------------------------------------------------------------------------ 1843 1844 status_t BWindow::GetSupportedSuites(BMessage* data){ 1845 status_t err = B_OK; 1846 if (!data) 1847 err = B_BAD_VALUE; 1848 1849 if (!err){ 1850 err = data->AddString("Suites", "suite/vnd.Be-window"); 1851 if (!err){ 1852 BPropertyInfo propertyInfo(windowPropInfo); 1853 err = data->AddFlat("message", &propertyInfo); 1854 if (!err){ 1855 err = BLooper::GetSupportedSuites(data); 1856 } 1857 } 1858 } 1859 return err; 1860 } 1861 1862 //------------------------------------------------------------------------------ 1863 1864 BHandler* BWindow::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 1865 int32 what, const char* property) 1866 { 1867 if (msg->what == B_WINDOW_MOVE_BY) 1868 return this; 1869 if (msg->what == B_WINDOW_MOVE_TO) 1870 return this; 1871 1872 BPropertyInfo propertyInfo(windowPropInfo); 1873 switch (propertyInfo.FindMatch(msg, index, specifier, what, property)) 1874 { 1875 case B_ERROR: 1876 break; 1877 case 0: 1878 case 1: 1879 case 2: 1880 case 3: 1881 case 4: 1882 case 5: 1883 case 6: 1884 case 7: 1885 case 8: 1886 case 9: 1887 case 10: 1888 case 11: 1889 case 12: 1890 case 13: 1891 return this; 1892 1893 case 14: 1894 if (fKeyMenuBar){ 1895 msg->PopSpecifier(); 1896 return fKeyMenuBar; 1897 } 1898 else{ 1899 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 1900 replyMsg.AddInt32( "error", B_NAME_NOT_FOUND ); 1901 replyMsg.AddString( "message", "This window doesn't have a main MenuBar"); 1902 msg->SendReply( &replyMsg ); 1903 return NULL; 1904 } 1905 case 15: 1906 // we will NOT pop the current specifier 1907 return top_view; 1908 1909 case 16: 1910 return this; 1911 } 1912 1913 return BLooper::ResolveSpecifier(msg, index, specifier, what, property); 1914 } 1915 1916 // PRIVATE 1917 //--------------------Private Methods------------------------------------------- 1918 // PRIVATE 1919 1920 void BWindow::InitData( BRect frame, 1921 const char* title, 1922 window_look look, 1923 window_feel feel, 1924 uint32 flags, 1925 uint32 workspace){ 1926 1927 STRACE(("BWindow::InitData(...)\n")); 1928 1929 fTitle=NULL; 1930 if ( be_app == NULL ){ 1931 debugger("You need a valid BApplication object before interacting with the app_server"); 1932 return; 1933 } 1934 1935 fFrame = frame; 1936 1937 if (title) 1938 SetTitle( title ); 1939 1940 fFeel = feel; 1941 fLook = look; 1942 fFlags = flags; 1943 1944 1945 fInTransaction = false; 1946 fActive = false; 1947 fShowLevel = 1; 1948 1949 top_view = NULL; 1950 fFocus = NULL; 1951 fLastMouseMovedView = NULL; 1952 fKeyMenuBar = NULL; 1953 fDefaultButton = NULL; 1954 1955 // accelList = new BList( 10 ); 1956 AddShortcut('X', B_COMMAND_KEY, new BMessage(B_CUT), NULL); 1957 AddShortcut('C', B_COMMAND_KEY, new BMessage(B_COPY), NULL); 1958 AddShortcut('V', B_COMMAND_KEY, new BMessage(B_PASTE), NULL); 1959 AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), NULL); 1960 AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); 1961 1962 fPulseEnabled = false; 1963 fPulseRate = 0; 1964 fPulseRunner = NULL; 1965 1966 // TODO: is this correct??? should the thread loop be started??? 1967 //SetPulseRate( 500000 ); 1968 1969 // TODO: see if you can use 'fViewsNeedPulse' 1970 1971 fIsFilePanel = false; 1972 1973 // TODO: see WHEN is this used! 1974 fMaskActivated = false; 1975 1976 // TODO: see WHEN is this used! 1977 fWaitingForMenu = false; 1978 1979 fMinimized = false; 1980 1981 // TODO: see WHERE you can use 'fMenuSem' 1982 1983 fMaxZoomHeight = 32768.0; 1984 fMaxZoomWidth = 32768.0; 1985 fMinWindHeight = 0.0; 1986 fMinWindWidth = 0.0; 1987 fMaxWindHeight = 32768.0; 1988 fMaxWindWidth = 32768.0; 1989 1990 fLastViewToken = B_NULL_TOKEN; 1991 // TODO: other initializations! 1992 1993 /* 1994 Here, we will contact app_server and let him know that a window has 1995 been created 1996 */ 1997 receive_port = create_port( B_LOOPER_PORT_DEFAULT_CAPACITY , 1998 "w_rcv_port"); 1999 if (receive_port==B_BAD_VALUE || receive_port==B_NO_MORE_PORTS){ 2000 debugger("Could not create BWindow's receive port, used for interacting with the app_server!"); 2001 delete this; 2002 } 2003 2004 STRACE(("BWindow::InitData(): contacting app_server...\n")); 2005 // let app_server to know that a window has been created. 2006 2007 session = new BSession( receive_port, be_app->fServerFrom ); 2008 2009 // HERE we are in BApplication's thread, so for locking we use be_app variable 2010 // we'll lock the be_app to be sure we're the only one writing at BApplication's server port 2011 bool locked = false; 2012 if ( !(be_app->IsLocked()) ) 2013 { be_app->Lock(); locked = true; } 2014 2015 PortMessage pmsg; 2016 PortLink link(be_app->fServerFrom); 2017 link.SetOpCode(AS_CREATE_WINDOW); 2018 2019 link.Attach<BRect>( fFrame ); 2020 link.Attach<int32>( (int32)fLook ); 2021 link.Attach<int32>( (int32)fFeel ); 2022 link.Attach<uint32>( fFlags ); 2023 link.Attach<uint32>( workspace ); 2024 link.Attach<int32>( _get_object_token_(this) ); 2025 link.Attach<port_id>( receive_port ); 2026 link.Attach<port_id>( fMsgPort ); 2027 link.AttachString( title ); 2028 link.FlushWithReply(&pmsg); 2029 2030 pmsg.Read<port_id>(&send_port); 2031 /* 2032 session->WriteInt32( AS_CREATE_WINDOW ); 2033 session->WriteRect( fFrame ); 2034 session->WriteInt32( (int32)fLook ); 2035 session->WriteInt32( (int32)fFeel ); 2036 session->WriteUInt32( fFlags ); 2037 session->WriteUInt32( workspace ); 2038 session->WriteData( &team, sizeof(team_id)); 2039 session->WriteInt32( _get_object_token_(this) ); 2040 session->WriteData( &receive_port, sizeof(port_id) ); 2041 session->WriteData( &fMsgPort, sizeof(port_id) ); 2042 session->WriteString( title ); 2043 2044 printf("look: %ld\n", (int32)fLook); 2045 printf("title: %s\n", title); 2046 session->Sync(); 2047 // The port on witch app_server will listen for us 2048 STRACE(("here\n")); 2049 session->ReadData( &send_port, sizeof(port_id) ); 2050 */ 2051 // unlock, so other threads can do their job. 2052 if( locked ) 2053 be_app->Unlock(); 2054 2055 session->SetSendPort(send_port); 2056 2057 STRACE(("\tapp_server link established.\n")); 2058 STRACE(("Window locked?: %s\n", IsLocked()?"True":"False")); 2059 2060 // build and register top_view with app_server 2061 BuildTopView(); 2062 // top_view->PrintToStream(); 2063 } 2064 2065 //------------------------------------------------------------------------------ 2066 2067 void BWindow::task_looper(){ 2068 2069 // Check that looper is locked (should be) 2070 AssertLocked(); 2071 2072 Unlock(); 2073 2074 using namespace BPrivate; 2075 bool dispatchNextMessage = false; 2076 BMessage *msg; 2077 2078 // loop: As long as we are not terminating. 2079 while (!fTerminating) 2080 { 2081 msg = MessageFromPort(); 2082 2083 // Did we get a message? 2084 if (msg){ 2085 // Add to queue 2086 fQueue->Lock(); 2087 fQueue->AddMessage(msg); 2088 fQueue->Unlock(); 2089 } 2090 2091 // Get message count from port 2092 int32 msgCount = port_count(fMsgPort); 2093 if (msgCount > 0){ 2094 fQueue->Lock(); 2095 for (int32 i = 0; i < msgCount; ++i) 2096 { 2097 // Read 'count' messages from port (so we will not block) 2098 // We use zero as our timeout since we know there is stuff there 2099 msg = MessageFromPort(0); 2100 // Add messages to queue 2101 if (msg) 2102 fQueue->AddMessage(msg); 2103 } 2104 fQueue->Unlock(); 2105 } 2106 2107 // loop: As long as there are messages in the queue and 2108 // and we are not terminating. 2109 dispatchNextMessage = true; 2110 while (!fTerminating && dispatchNextMessage) 2111 { 2112 fQueue->Lock(); 2113 fLastMessage = fQueue->NextMessage(); 2114 fQueue->Unlock(); 2115 2116 Lock(); 2117 2118 // TODO: add code for drag & drop 2119 if (!fLastMessage) 2120 { 2121 // No more messages: Unlock the looper and terminate the 2122 // dispatch loop. 2123 dispatchNextMessage = false; 2124 } 2125 else 2126 { 2127 // Get the target handler 2128 BHandler* handler; 2129 if (_use_preferred_target_(fLastMessage)) 2130 handler = fPreferred; 2131 else 2132 gDefaultTokens.GetToken(_get_message_target_(fLastMessage), 2133 B_HANDLER_TOKEN, 2134 (void**)&handler); 2135 2136 if (!handler) 2137 handler = this; 2138 2139 // Is this a scripting message? 2140 if (fLastMessage->HasSpecifiers()) 2141 { 2142 int32 index = 0; 2143 // Make sure the current specifier is kosher 2144 if (fLastMessage->GetCurrentSpecifier(&index) == B_OK) 2145 handler = resolve_specifier(handler, fLastMessage); 2146 } 2147 2148 if (handler) 2149 { 2150 // Do filtering 2151 handler = top_level_filter(fLastMessage, handler); 2152 if (handler && handler->Looper() == this) 2153 DispatchMessage(fLastMessage, handler); 2154 } 2155 } 2156 // empty our message buffer 2157 session->Sync(); 2158 2159 Unlock(); 2160 printf("Lock released\n"); 2161 // Delete the current message (fLastMessage) 2162 if (fLastMessage) 2163 { 2164 delete fLastMessage; 2165 fLastMessage = NULL; 2166 } 2167 2168 // Are any messages on the port? 2169 if (port_count(fMsgPort) > 0) 2170 { 2171 // Do outer loop 2172 dispatchNextMessage = false; 2173 } 2174 } 2175 } 2176 2177 } 2178 2179 //------------------------------------------------------------------------------ 2180 2181 BMessage* BWindow::ReadMessageFromPort(bigtime_t tout){ 2182 // TODO: remove! 2183 } 2184 2185 //------------------------------------------------------------------------------ 2186 2187 window_type BWindow::composeType(window_look look, 2188 window_feel feel) const 2189 { 2190 window_type returnValue = B_UNTYPED_WINDOW; 2191 2192 switch(feel) 2193 { 2194 case B_NORMAL_WINDOW_FEEL: 2195 switch (look) 2196 { 2197 case B_TITLED_WINDOW_LOOK: 2198 returnValue = B_TITLED_WINDOW; 2199 break; 2200 2201 case B_DOCUMENT_WINDOW_LOOK: 2202 returnValue = B_DOCUMENT_WINDOW; 2203 break; 2204 2205 case B_BORDERED_WINDOW_LOOK: 2206 returnValue = B_BORDERED_WINDOW; 2207 break; 2208 2209 default: 2210 returnValue = B_UNTYPED_WINDOW; 2211 } 2212 break; 2213 2214 case B_MODAL_APP_WINDOW_FEEL: 2215 if (look == B_MODAL_WINDOW_LOOK) 2216 returnValue = B_MODAL_WINDOW; 2217 break; 2218 2219 case B_FLOATING_APP_WINDOW_FEEL: 2220 if (look == B_FLOATING_WINDOW_LOOK) 2221 returnValue = B_FLOATING_WINDOW; 2222 break; 2223 2224 default: 2225 returnValue = B_UNTYPED_WINDOW; 2226 } 2227 2228 return returnValue; 2229 } 2230 2231 //------------------------------------------------------------------------------ 2232 2233 void BWindow::decomposeType(window_type type, 2234 window_look* look, 2235 window_feel* feel) const 2236 { 2237 switch (type) 2238 { 2239 case B_TITLED_WINDOW: 2240 *look = B_TITLED_WINDOW_LOOK; 2241 *feel = B_NORMAL_WINDOW_FEEL; 2242 break; 2243 case B_DOCUMENT_WINDOW: 2244 *look = B_DOCUMENT_WINDOW_LOOK; 2245 *feel = B_NORMAL_WINDOW_FEEL; 2246 break; 2247 case B_MODAL_WINDOW: 2248 *look = B_MODAL_WINDOW_LOOK; 2249 *feel = B_MODAL_APP_WINDOW_FEEL; 2250 break; 2251 case B_FLOATING_WINDOW: 2252 *look = B_FLOATING_WINDOW_LOOK; 2253 *feel = B_FLOATING_APP_WINDOW_FEEL; 2254 break; 2255 case B_BORDERED_WINDOW: 2256 *look = B_BORDERED_WINDOW_LOOK; 2257 *feel = B_NORMAL_WINDOW_FEEL; 2258 break; 2259 case B_UNTYPED_WINDOW: 2260 *look = B_TITLED_WINDOW_LOOK; 2261 *feel = B_NORMAL_WINDOW_FEEL; 2262 break; 2263 default: 2264 *look = B_TITLED_WINDOW_LOOK; 2265 *feel = B_NORMAL_WINDOW_FEEL; 2266 break; 2267 } 2268 } 2269 2270 //------------------------------------------------------------------------------ 2271 2272 void BWindow::BuildTopView(){ 2273 2274 top_view = new BView( fFrame.OffsetToCopy(0,0), "top_view", 2275 B_FOLLOW_ALL, B_WILL_DRAW); 2276 top_view->top_level_view = true; 2277 //top_view->fShowLevel = 1; 2278 2279 // set top_view's owner, add it to window's eligible handler list 2280 // and also set its next handler to be this window. 2281 top_view->setOwner( this ); 2282 2283 PortLink link(send_port); 2284 link.SetOpCode(AS_LAYER_CREATE_ROOT); 2285 link.Attach<int32>(_get_object_token_( top_view )); 2286 link.Attach<BRect>(top_view->Frame()); 2287 link.Attach<int32>(top_view->ResizingMode()); 2288 link.Attach<int32>(top_view->Flags()); 2289 link.AttachString(top_view->Name()); 2290 link.Flush(); 2291 /* 2292 // send top_view's information to app_server 2293 session->WriteInt32( AS_LAYER_CREATE_ROOT ); 2294 session->WriteInt32( _get_object_token_( top_view ) ); 2295 session->WriteRect( top_view->Frame() ); 2296 session->WriteInt32( top_view->ResizingMode() ); 2297 session->WriteInt32( top_view->Flags() ); 2298 session->WriteString( top_view->Name() ); 2299 // we DO NOT send our current state; the server knows the default values! 2300 session->Sync(); 2301 */ 2302 fLastViewToken = _get_object_token_( top_view ); 2303 STRACE(("BuildTopView ended\n")); 2304 } 2305 2306 //------------------------------------------------------------------------------ 2307 2308 void BWindow::stopConnection(){ 2309 Lock(); 2310 session->WriteInt32( B_QUIT_REQUESTED ); 2311 session->Sync(); 2312 Unlock(); 2313 } 2314 2315 //------------------------------------------------------------------------------ 2316 2317 void BWindow::prepareView(BView *aView){ 2318 2319 // TODO: implement 2320 2321 } 2322 2323 //------------------------------------------------------------------------------ 2324 2325 void BWindow::attachView(BView *aView){ 2326 2327 // TODO: implement 2328 2329 } 2330 2331 //------------------------------------------------------------------------------ 2332 2333 void BWindow::detachView(BView *aView){ 2334 2335 // TODO: implement 2336 2337 } 2338 //------------------------------------------------------------------------------ 2339 2340 void BWindow::setFocus(BView *focusView, bool notifyInputServer){ 2341 BView* previousFocus = fFocus; 2342 2343 if (previousFocus == focusView) 2344 return; 2345 2346 fFocus = NULL; 2347 2348 if (previousFocus != NULL) 2349 previousFocus->Invalidate(); 2350 2351 fFocus = focusView; 2352 2353 if (focusView != NULL) 2354 focusView->Invalidate(); 2355 2356 // TODO: find out why do we have to notify input server. 2357 if (notifyInputServer){ 2358 // what am I suppose to do here?? 2359 } 2360 } 2361 2362 //------------------------------------------------------------------------------ 2363 2364 void BWindow::handleActivation( bool active ){ 2365 2366 if (active){ 2367 // TODO: talk to Ingo to make BWindow a friend for BRoster 2368 // be_roster->UpdateActiveApp( be_app->Team() ); 2369 } 2370 2371 WindowActivated( active ); 2372 2373 // recursively call hook function 'WindowActivated(bool)' 2374 // for all views attached to this window. 2375 activateView( top_view, active ); 2376 } 2377 2378 //------------------------------------------------------------------------------ 2379 2380 void BWindow::activateView( BView *aView, bool active ){ 2381 2382 aView->WindowActivated( active ); 2383 2384 BView *child; 2385 if ( (child = aView->first_child) ){ 2386 while ( child ) { 2387 activateView( child, active ); 2388 child = child->next_sibling; 2389 } 2390 } 2391 } 2392 2393 //------------------------------------------------------------------------------ 2394 2395 bool BWindow::handleKeyDown( int32 raw_char, uint32 modifiers){ 2396 2397 // TODO: ask people if using 'raw_char' is OK ? 2398 2399 // handle BMenuBar key 2400 if ( (raw_char == B_ESCAPE) && (modifiers & B_COMMAND_KEY) 2401 && fKeyMenuBar) 2402 { 2403 2404 // TODO: ask Marc about 'fWaitingForMenu' member! 2405 2406 // fWaitingForMenu = true; 2407 fKeyMenuBar->StartMenuBar(0, true, false, NULL); 2408 return true; 2409 } 2410 2411 // Command+q has been pressed, so, we will quit 2412 if ( (raw_char == 'Q' || raw_char == 'q') && modifiers & B_COMMAND_KEY){ 2413 be_app->PostMessage(B_QUIT_REQUESTED); 2414 return true; 2415 } 2416 2417 // Keyboard navigation through views!!!! 2418 if ( raw_char == B_TAB){ 2419 2420 // even if we have no focus view, we'll say that we will handle TAB key 2421 if (!fFocus) 2422 return true; 2423 2424 BView *nextFocus; 2425 2426 if (modifiers & B_CONTROL_KEY & B_SHIFT_KEY){ 2427 nextFocus = findPrevView( fFocus, B_NAVIGABLE_JUMP ); 2428 } 2429 else 2430 if (modifiers & B_CONTROL_KEY){ 2431 nextFocus = findNextView( fFocus, B_NAVIGABLE_JUMP ); 2432 } 2433 else 2434 if (modifiers & B_SHIFT_KEY){ 2435 nextFocus = findPrevView( fFocus, B_NAVIGABLE ); 2436 } 2437 else 2438 nextFocus = findNextView( fFocus, B_NAVIGABLE ); 2439 2440 if ( nextFocus ) 2441 setFocus( nextFocus, false ); 2442 2443 return true; 2444 } 2445 2446 // Handle shortcuts 2447 int index; 2448 if ( (index = findShortcut(raw_char, modifiers)) >=0){ 2449 _BCmdKey *cmdKey; 2450 2451 cmdKey = (_BCmdKey*)accelList.ItemAt( index ); 2452 2453 // we'll give the message to the focus view 2454 if (cmdKey->targetToken == B_ANY_TOKEN){ 2455 fFocus->MessageReceived( cmdKey->message ); 2456 return true; 2457 } 2458 else{ 2459 BHandler *handler; 2460 BHandler *aHandler; 2461 int noOfHandlers; 2462 2463 // search for a match through BLooper's list of eligible handlers 2464 handler = NULL; 2465 noOfHandlers = CountHandlers(); 2466 for( int i=0; i < noOfHandlers; i++ ) 2467 // do we have a match? 2468 if ( _get_object_token_( aHandler = HandlerAt(i) ) 2469 == cmdKey->targetToken) 2470 { 2471 // yes, we do. 2472 handler = aHandler; 2473 break; 2474 } 2475 2476 if ( handler ) 2477 handler->MessageReceived( cmdKey->message ); 2478 else 2479 // if no handler was found, BWindow will handle the message 2480 MessageReceived( cmdKey->message ); 2481 } 2482 return true; 2483 } 2484 2485 // if <ENTER> is pressed and we have a default button 2486 if (DefaultButton() && (raw_char == B_ENTER)){ 2487 const char *chars; // just to be sure 2488 CurrentMessage()->FindString("bytes", &chars); 2489 2490 DefaultButton()->KeyDown( chars, strlen(chars)-1 ); 2491 return true; 2492 } 2493 2494 2495 return false; 2496 } 2497 2498 //------------------------------------------------------------------------------ 2499 2500 BView* BWindow::sendMessageUsingEventMask2( BView* aView, int32 message, BPoint where ){ 2501 2502 BView *destView; 2503 destView = NULL; 2504 2505 if ( aView->fBounds.Contains( aView->ConvertFromScreen(where) ) && 2506 !aView->first_child ){ 2507 return aView; 2508 } 2509 2510 // Code for Event Masks 2511 BView *child; 2512 if ( (child = aView->first_child) ){ 2513 while ( child ) { 2514 // see if a BView registered for mouse events and it's not the current focus view 2515 if ( child->fEventMask & B_POINTER_EVENTS && 2516 aView != fFocus ){ 2517 switch (message){ 2518 case B_MOUSE_DOWN:{ 2519 child->MouseDown( child->ConvertFromScreen( where ) ); 2520 } 2521 break; 2522 2523 case B_MOUSE_UP:{ 2524 child->MouseUp( child->ConvertFromScreen( where ) ); 2525 } 2526 break; 2527 2528 case B_MOUSE_MOVED:{ 2529 BMessage *dragMessage; 2530 2531 // TODO: get the dragMessage if any 2532 // for now... 2533 dragMessage = NULL; 2534 2535 /* TODO: after you have an example working, see if a view that registered for such events, 2536 does reveive B_MOUSE_MOVED with other options than B_OUTDIDE_VIEW !!! 2537 like: B_INSIDE_VIEW, B_ENTERED_VIEW, B_EXITED_VIEW 2538 */ 2539 child->MouseMoved( ConvertFromScreen(where), B_OUTSIDE_VIEW , dragMessage); 2540 } 2541 break; 2542 } 2543 } 2544 if (destView == NULL) 2545 destView = sendMessageUsingEventMask2( child, message, where ); 2546 else 2547 sendMessageUsingEventMask2( child, message, where ); 2548 child = child->next_sibling; 2549 } 2550 } 2551 2552 return destView; 2553 } 2554 2555 //------------------------------------------------------------------------------ 2556 2557 void BWindow::sendMessageUsingEventMask( int32 message, BPoint where ){ 2558 BView* destView; 2559 2560 destView = sendMessageUsingEventMask2(top_view, message, where); 2561 2562 // I'm SURE this is NEVER going to happen, but, durring development of BWindow, it may slip a NULL value 2563 if (!destView){ 2564 // debugger("There is no BView under the mouse;"); 2565 return; 2566 } 2567 2568 switch( message ){ 2569 case B_MOUSE_DOWN:{ 2570 setFocus( destView ); 2571 destView->MouseDown( destView->ConvertFromScreen( where ) ); 2572 break;} 2573 2574 case B_MOUSE_UP:{ 2575 destView->MouseUp( destView->ConvertFromScreen( where ) ); 2576 break;} 2577 2578 case B_MOUSE_MOVED:{ 2579 BMessage *dragMessage; 2580 2581 // TODO: add code for drag and drop 2582 // for now... 2583 dragMessage = NULL; 2584 2585 if (destView != fLastMouseMovedView){ 2586 fLastMouseMovedView->MouseMoved( destView->ConvertFromScreen( where ), B_EXITED_VIEW , dragMessage); 2587 destView->MouseMoved( ConvertFromScreen( where ), B_ENTERED_VIEW, dragMessage); 2588 fLastMouseMovedView = destView; 2589 } 2590 else{ 2591 destView->MouseMoved( ConvertFromScreen( where ), B_INSIDE_VIEW , dragMessage); 2592 } 2593 2594 // I'm guessing that B_OUTSIDE_VIEW is given to the view that has focus, I'll have to check 2595 // TODO: Do a research on mouse capturing, maybe it has something to do with this 2596 if (fFocus != destView) 2597 fFocus->MouseMoved( ConvertFromScreen( where ), B_OUTSIDE_VIEW , dragMessage); 2598 break;} 2599 } 2600 } 2601 2602 //------------------------------------------------------------------------------ 2603 2604 BMessage* BWindow::ConvertToMessage(void* raw1, int32 code){ 2605 2606 BMessage *msg; 2607 msg = new BMessage(); 2608 // time since 01/01/70 2609 int64 when; 2610 2611 switch(code){ 2612 case B_WINDOW_ACTIVATED:{ 2613 bool active; 2614 2615 session->ReadInt64( &when ); 2616 session->ReadBool( &active ); 2617 2618 msg->what = B_WINDOW_ACTIVATED; 2619 msg->AddInt64("when", when); 2620 msg->AddBool("active", active); 2621 2622 break;} 2623 2624 case B_QUIT_REQUESTED:{ 2625 2626 msg->what = B_QUIT_REQUESTED; 2627 msg->AddBool("shortcut", false); 2628 2629 break;} 2630 2631 case B_KEY_DOWN:{ 2632 int32 physicalKeyCode, 2633 repeat, 2634 modifiers, 2635 ASCIIcode; 2636 char *bytes = NULL; 2637 uint8 states; 2638 int8 UTF8_1, UTF8_2, UTF8_3; 2639 2640 session->ReadInt64( &when ); 2641 session->ReadInt32( &physicalKeyCode ); 2642 session->ReadInt32( &repeat ); 2643 session->ReadInt32( &modifiers ); 2644 session->ReadUInt8( &states ); 2645 session->ReadInt8( &UTF8_1 ); 2646 session->ReadInt8( &UTF8_2 ); 2647 session->ReadInt8( &UTF8_3 ); 2648 session->ReadInt32( &ASCIIcode ); 2649 bytes = session->ReadString(); 2650 2651 msg->what = B_KEY_DOWN; 2652 msg->AddInt64("when", when); 2653 msg->AddInt32("key", physicalKeyCode); 2654 msg->AddInt32("be:key_repeat", repeat); 2655 msg->AddInt32("modifiers", modifiers); 2656 msg->AddInt8("states", states); 2657 msg->AddInt8("byte", UTF8_1); 2658 msg->AddInt8("byte", UTF8_2); 2659 msg->AddInt8("byte", UTF8_3); 2660 msg->AddInt32("raw_char", ASCIIcode); 2661 msg->AddString("bytes", bytes); 2662 2663 if (bytes) 2664 delete bytes; 2665 2666 break;} 2667 2668 case B_KEY_UP:{ 2669 int32 physicalKeyCode, 2670 modifiers, 2671 ASCIIcode; 2672 char *bytes; 2673 uint8 states; 2674 int8 UTF8_1, UTF8_2, UTF8_3; 2675 2676 session->ReadInt64( &when ); 2677 session->ReadInt32( &physicalKeyCode ); 2678 session->ReadInt32( &modifiers ); 2679 session->ReadUInt8( &states ); 2680 session->ReadInt8( &UTF8_1 ); 2681 session->ReadInt8( &UTF8_2 ); 2682 session->ReadInt8( &UTF8_3 ); 2683 session->ReadInt32( &ASCIIcode ); 2684 bytes = session->ReadString(); 2685 2686 msg->what = B_KEY_UP; 2687 msg->AddInt64("when", when); 2688 msg->AddInt32("key", physicalKeyCode); 2689 msg->AddInt32("modifiers", modifiers); 2690 msg->AddInt8("states", states); 2691 msg->AddInt8("byte", UTF8_1); 2692 msg->AddInt8("byte", UTF8_2); 2693 msg->AddInt8("byte", UTF8_3); 2694 msg->AddInt32("raw_char", ASCIIcode); 2695 msg->AddString("bytes", bytes); 2696 2697 if (bytes) 2698 delete bytes; 2699 2700 break;} 2701 2702 case B_UNMAPPED_KEY_DOWN:{ 2703 int32 physicalKeyCode, 2704 modifiers; 2705 uint8 states; 2706 2707 session->ReadInt64( &when ); 2708 session->ReadInt32( &physicalKeyCode ); 2709 session->ReadInt32( &modifiers ); 2710 session->ReadUInt8( &states ); 2711 2712 msg->what = B_UNMAPPED_KEY_DOWN; 2713 msg->AddInt64("when", when); 2714 msg->AddInt32("key", physicalKeyCode); 2715 msg->AddInt32("modifiers", modifiers); 2716 msg->AddInt8("states", states); 2717 2718 break;} 2719 2720 case B_UNMAPPED_KEY_UP:{ 2721 int32 physicalKeyCode, 2722 modifiers; 2723 uint8 states; 2724 2725 session->ReadInt64( &when ); 2726 session->ReadInt32( &physicalKeyCode ); 2727 session->ReadInt32( &modifiers ); 2728 session->ReadUInt8( &states ); 2729 2730 msg->what = B_UNMAPPED_KEY_UP; 2731 msg->AddInt64("when", when); 2732 msg->AddInt32("key", physicalKeyCode); 2733 msg->AddInt32("modifiers", modifiers); 2734 msg->AddInt8("states", states); 2735 2736 break;} 2737 2738 case B_MODIFIERS_CHANGED:{ 2739 int32 modifiers, 2740 modifiersOld; 2741 uint8 states; 2742 2743 session->ReadInt64( &when ); 2744 session->ReadInt32( &modifiers ); 2745 session->ReadInt32( &modifiersOld ); 2746 session->ReadUInt8( &states ); 2747 2748 msg->what = B_MODIFIERS_CHANGED; 2749 msg->AddInt64("when", when); 2750 msg->AddInt32("modifiers", modifiers); 2751 msg->AddInt32("be:old_modifiers", modifiersOld); 2752 msg->AddInt8("states", states); 2753 2754 break;} 2755 2756 case B_MINIMIZE:{ 2757 bool minimize; 2758 2759 session->ReadInt64( &when ); 2760 session->ReadBool( &minimize ); 2761 2762 msg->what = B_MINIMIZE; 2763 msg->AddInt64("when", when); 2764 msg->AddBool("minimize", minimize); 2765 2766 break;} 2767 2768 case B_MOUSE_DOWN:{ 2769 int32 modifiers, 2770 buttons, 2771 noOfClicks; 2772 BPoint where; 2773 2774 session->ReadInt64( &when ); 2775 session->ReadPoint( &where ); 2776 session->ReadInt32( &modifiers ); 2777 session->ReadInt32( &buttons ); 2778 session->ReadInt32( &noOfClicks ); 2779 2780 msg->what = B_MOUSE_DOWN; 2781 msg->AddInt64("when", when); 2782 msg->AddPoint("where", where); 2783 msg->AddInt32("modifiers", modifiers); 2784 msg->AddInt32("buttons", buttons); 2785 msg->AddInt32("clicks", noOfClicks); 2786 2787 break;} 2788 2789 case B_MOUSE_MOVED:{ 2790 int32 buttons; 2791 int32 modifiers; // added by OBOS Team 2792 BPoint where; 2793 2794 session->ReadInt64( &when ); 2795 session->ReadPoint( &where ); 2796 session->ReadInt32( &buttons ); 2797 session->ReadInt32( &modifiers ); 2798 2799 msg->what = B_MOUSE_MOVED; 2800 msg->AddInt64("when", when); 2801 msg->AddPoint("where", where); 2802 msg->AddInt32("buttons", buttons); 2803 msg->AddInt32("modifiers", modifiers); 2804 2805 break;} 2806 2807 case B_MOUSE_UP:{ 2808 int32 modifiers, 2809 buttons; 2810 BPoint where; 2811 2812 session->ReadInt64( &when ); 2813 session->ReadPoint( &where ); 2814 session->ReadInt32( &buttons ); 2815 session->ReadInt32( &modifiers ); 2816 2817 msg->what = B_MOUSE_UP; 2818 msg->AddInt64("when", when); 2819 msg->AddPoint("where", where); 2820 msg->AddInt32("modifiers", modifiers); 2821 msg->AddInt32("buttons", buttons); 2822 2823 break;} 2824 2825 case B_MOUSE_WHEEL_CHANGED:{ 2826 float whellChangeX, 2827 whellChangeY; 2828 2829 session->ReadInt64( &when ); 2830 session->ReadFloat( &whellChangeX ); 2831 session->ReadFloat( &whellChangeY ); 2832 2833 msg->what = B_MOUSE_WHEEL_CHANGED; 2834 msg->AddInt64("when", when); 2835 msg->AddFloat("be:wheel_delta_x", whellChangeX); 2836 msg->AddFloat("be:wheel_delta_y", whellChangeY); 2837 2838 break;} 2839 2840 case B_SCREEN_CHANGED:{ 2841 int32 colorSpace; 2842 BRect frame; 2843 2844 session->ReadInt64( &when ); 2845 session->ReadRect( &frame ); 2846 session->ReadInt32( &colorSpace ); 2847 2848 msg->what = B_SCREEN_CHANGED; 2849 msg->AddInt64("when", when); 2850 msg->AddRect("frame", frame); 2851 msg->AddInt32("mode", colorSpace); 2852 2853 break;} 2854 2855 case B_WINDOW_MOVED:{ 2856 BPoint where; 2857 2858 session->ReadInt64( &when ); 2859 session->ReadPoint( &where ); 2860 2861 msg->what = B_WINDOW_MOVED; 2862 msg->AddInt64("when", when); 2863 msg->AddPoint("where", where); 2864 2865 break;} 2866 2867 case B_WINDOW_RESIZED:{ 2868 int32 newWidth, 2869 newHeight; 2870 2871 session->ReadInt64( &when ); 2872 session->ReadInt32( &newWidth ); 2873 session->ReadInt32( &newHeight ); 2874 2875 msg->what = B_WINDOW_RESIZED; 2876 msg->AddInt64("when", when); 2877 msg->AddInt32("width", newWidth); 2878 msg->AddInt32("height", newHeight); 2879 2880 break;} 2881 2882 case B_WORKSPACES_CHANGED:{ 2883 int32 newWorkSpace, 2884 oldWorkSpace; 2885 2886 session->ReadInt64( &when ); 2887 session->ReadInt32( &newWorkSpace ); 2888 session->ReadInt32( &oldWorkSpace ); 2889 2890 msg->what = B_WORKSPACES_CHANGED; 2891 msg->AddInt64("when", when); 2892 msg->AddInt32("old", oldWorkSpace); 2893 msg->AddInt32("new", newWorkSpace); 2894 2895 break;} 2896 2897 case B_WORKSPACE_ACTIVATED:{ 2898 int32 workSpace; 2899 bool active; 2900 2901 session->ReadInt64( &when ); 2902 session->ReadInt32( &workSpace ); 2903 session->ReadBool( &active ); 2904 2905 msg->what = B_WORKSPACE_ACTIVATED; 2906 msg->AddInt64("when", when); 2907 msg->AddInt32("workspace", workSpace); 2908 msg->AddBool("active", active); 2909 2910 break;} 2911 2912 case B_ZOOM:{ 2913 2914 session->ReadInt64( &when ); 2915 2916 msg->what = B_ZOOM; 2917 msg->AddInt64("when", when); 2918 2919 break;} 2920 2921 default:{ 2922 delete msg; 2923 2924 msg = BLooper::ConvertToMessage( raw1, code ); 2925 if (!msg) 2926 printf("***PANIC: app_server message NOT understood: '%c%c%c%c'***\n", 2927 (char)((code & 0xFF000000) >> 24), (char)((code & 0x00FF0000) >> 16), 2928 (char)((code & 0x0000FF00) >> 8), (char)(code & 0x000000FF) ); 2929 } 2930 } 2931 2932 return msg; 2933 } 2934 2935 //------------------------------------------------------------------------------ 2936 2937 void BWindow::sendPulse( BView* aView ){ 2938 BView *child; 2939 if ( (child = aView->first_child) ){ 2940 while ( child ) { 2941 if ( child->Flags() & B_PULSE_NEEDED ) child->Pulse(); 2942 sendPulse( child ); 2943 child = child->next_sibling; 2944 } 2945 } 2946 } 2947 2948 //------------------------------------------------------------------------------ 2949 2950 int32 BWindow::findShortcut( uint32 key, uint32 modifiers ){ 2951 int32 index, 2952 noOfItems; 2953 2954 index = -1; 2955 noOfItems = accelList.CountItems(); 2956 2957 for ( int32 i = 0; i < noOfItems; i++ ) { 2958 _BCmdKey* tempCmdKey; 2959 2960 tempCmdKey = (_BCmdKey*)accelList.ItemAt(i); 2961 if (tempCmdKey->key == key && tempCmdKey->modifiers == modifiers){ 2962 index = i; 2963 break; 2964 } 2965 } 2966 2967 return index; 2968 } 2969 2970 //------------------------------------------------------------------------------ 2971 2972 BView* BWindow::findView(BView* aView, int32 token){ 2973 2974 if ( _get_object_token_(aView) == token ) 2975 return aView; 2976 2977 BView *child; 2978 if ( (child = aView->first_child) ){ 2979 while ( child ) { 2980 BView* view; 2981 if ( (view = findView( child, token )) ) 2982 return view; 2983 child = child->next_sibling; 2984 } 2985 } 2986 2987 return NULL; 2988 } 2989 2990 //------------------------------------------------------------------------------ 2991 2992 BView* BWindow::findView(BView* aView, const char* viewName) const{ 2993 2994 if ( strcmp( viewName, aView->Name() ) == 0) 2995 return aView; 2996 2997 BView *child; 2998 if ( (child = aView->first_child) ){ 2999 while ( child ) { 3000 BView* view; 3001 if ( (view = findView( child, viewName )) ) 3002 return view; 3003 child = child->next_sibling; 3004 } 3005 } 3006 3007 return NULL; 3008 } 3009 3010 //------------------------------------------------------------------------------ 3011 3012 BView* BWindow::findView(BView* aView, BPoint point) const{ 3013 3014 if ( aView->Bounds().Contains(point) && 3015 !aView->first_child ) 3016 return aView; 3017 3018 BView *child; 3019 if ( (child = aView->first_child) ){ 3020 while ( child ) { 3021 BView* view; 3022 if ( (view = findView( child, point )) ) 3023 return view; 3024 child = child->next_sibling; 3025 } 3026 } 3027 3028 return NULL; 3029 } 3030 3031 //------------------------------------------------------------------------------ 3032 3033 BView* BWindow::findNextView( BView *focus, uint32 flags){ 3034 bool found; 3035 found = false; 3036 3037 BView *nextFocus; 3038 nextFocus = focus; 3039 3040 /* Ufff... this toked me some time... this is the best form I've reached. 3041 This algorithm searches the tree for BViews that accept focus. 3042 */ 3043 while (!found){ 3044 if (nextFocus->first_child) 3045 nextFocus = nextFocus->first_child; 3046 else 3047 if (nextFocus->next_sibling) 3048 nextFocus = nextFocus->next_sibling; 3049 else{ 3050 while( !nextFocus->next_sibling && nextFocus->parent ){ 3051 nextFocus = nextFocus->parent; 3052 } 3053 3054 if (nextFocus == top_view) 3055 nextFocus = nextFocus->first_child; 3056 else 3057 nextFocus = nextFocus->next_sibling; 3058 } 3059 3060 if (nextFocus->Flags() & flags) 3061 found = true; 3062 3063 /* It means that the hole tree has been searched and there is no 3064 view with B_NAVIGABLE_JUMP flag set! 3065 */ 3066 if (nextFocus == focus) 3067 return NULL; 3068 } 3069 3070 return nextFocus; 3071 } 3072 3073 //------------------------------------------------------------------------------ 3074 3075 BView* BWindow::findPrevView( BView *focus, uint32 flags){ 3076 bool found; 3077 found = false; 3078 3079 BView *prevFocus; 3080 prevFocus = focus; 3081 3082 BView *aView; 3083 3084 while (!found){ 3085 if ( (aView = findLastChild(prevFocus)) ) 3086 prevFocus = aView; 3087 else 3088 if (prevFocus->prev_sibling) 3089 prevFocus = prevFocus->prev_sibling; 3090 else{ 3091 while( !prevFocus->prev_sibling && prevFocus->parent ){ 3092 prevFocus = prevFocus->parent; 3093 } 3094 3095 if (prevFocus == top_view) 3096 prevFocus = findLastChild( prevFocus ); 3097 else 3098 prevFocus = prevFocus->prev_sibling; 3099 } 3100 3101 if (prevFocus->Flags() & flags) 3102 found = true; 3103 3104 3105 /* It means that the hole tree has been searched and there is no 3106 view with B_NAVIGABLE_JUMP flag set! 3107 */ 3108 if (prevFocus == focus) 3109 return NULL; 3110 } 3111 3112 return prevFocus; 3113 } 3114 3115 //------------------------------------------------------------------------------ 3116 3117 BView* BWindow::findLastChild(BView *parent){ 3118 BView *aView; 3119 if ( (aView = parent->first_child) ){ 3120 while (aView->next_sibling) 3121 aView = aView->next_sibling; 3122 3123 return aView; 3124 } 3125 else 3126 return NULL; 3127 } 3128 3129 //------------------------------------------------------------------------------ 3130 3131 void BWindow::drawAllViews(BView* aView){ 3132 3133 BMessageQueue *queue; 3134 BMessage *msg; 3135 3136 queue = MessageQueue(); 3137 3138 // process all update BMessages from message queue 3139 queue->Lock(); 3140 while ( (msg = queue->FindMessage( (uint32)_UPDATE_ )) ) 3141 { 3142 Lock(); 3143 DispatchMessage( msg, this ); 3144 Unlock(); 3145 3146 queue->RemoveMessage( msg ); 3147 } 3148 queue->Unlock(); 3149 3150 // we'll send a message to app_server, tell him that we want all our views updated 3151 Lock(); 3152 session->WriteInt32( AS_UPDATE_IF_NEEDED ); 3153 session->Sync(); 3154 Unlock(); 3155 3156 // TODO: update!!!!!!!!!!!!!!!!!!! 3157 // process all update messages from receive port queue 3158 bool over = false; 3159 while (!over) 3160 { 3161 msg = MessageFromPort(0); 3162 if (msg){ 3163 switch (msg->what){ 3164 3165 case _ALL_UPDATED_:{ 3166 over = true; 3167 }break; 3168 3169 case _UPDATE_:{ 3170 Lock(); 3171 DispatchMessage( msg, this ); 3172 Unlock(); 3173 }break; 3174 3175 default:{ 3176 queue->Lock(); 3177 queue->AddMessage(msg); 3178 queue->Unlock(); 3179 }break; 3180 } 3181 } 3182 } 3183 } 3184 3185 //------------------------------------------------------------------------------ 3186 3187 void BWindow::drawView(BView* aView, BRect area){ 3188 3189 /* TODO: Drawing during an Update 3190 These settings are temporary. When the update is over, all graphics 3191 parameters are reset to their initial values 3192 */ 3193 aView->Draw( area ); 3194 3195 BView *child; 3196 if ( (child = aView->first_child) ){ 3197 while ( child ) { 3198 if ( area.Intersects( child->Frame() ) ){ 3199 BRect newArea; 3200 3201 newArea = area & child->Frame(); 3202 child->ConvertFromParent( &newArea ); 3203 child->Invalidate( newArea ); 3204 } 3205 child = child->next_sibling; 3206 } 3207 } 3208 } 3209 3210 //------------------------------------------------------------------------------ 3211 3212 void BWindow::SetIsFilePanel(bool yes){ 3213 3214 // TODO: is this not enough? 3215 fIsFilePanel = yes; 3216 } 3217 3218 //------------------------------------------------------------------------------ 3219 3220 bool BWindow::IsFilePanel() const{ 3221 return fIsFilePanel; 3222 } 3223 3224 3225 //------------------------------------------------------------------------------ 3226 // Virtual reserved Functions 3227 3228 void BWindow::_ReservedWindow1() { } 3229 //------------------------------------------------------------------------------ 3230 void BWindow::_ReservedWindow2() { } 3231 //------------------------------------------------------------------------------ 3232 void BWindow::_ReservedWindow3() { } 3233 //------------------------------------------------------------------------------ 3234 void BWindow::_ReservedWindow4() { } 3235 //------------------------------------------------------------------------------ 3236 void BWindow::_ReservedWindow5() { } 3237 //------------------------------------------------------------------------------ 3238 void BWindow::_ReservedWindow6() { } 3239 //------------------------------------------------------------------------------ 3240 void BWindow::_ReservedWindow7() { } 3241 //------------------------------------------------------------------------------ 3242 void BWindow::_ReservedWindow8() { } 3243 3244 void BWindow::PrintToStream() const{ 3245 printf("BWindow '%s' data:\ 3246 Title = %s\ 3247 Token = %ld\ 3248 InTransaction = %s\ 3249 Active = %s\ 3250 fShowLevel = %d\ 3251 Flags = %lx\ 3252 send_port = %ld\ 3253 receive_port = %ld\ 3254 top_view name = %s\ 3255 focus view name = %s\ 3256 lastMouseMoved = %s\ 3257 session = %s\ 3258 KeyMenuBar name = %s\ 3259 DefaultButton = %s\ 3260 # of shortcuts = %ld", 3261 Name(), 3262 fTitle!=NULL? fTitle:"NULL", 3263 _get_object_token_(this), 3264 fInTransaction==true? "yes":"no", 3265 fActive==true? "yes":"no", 3266 fShowLevel, 3267 fFlags, 3268 send_port, 3269 receive_port, 3270 top_view!=NULL? top_view->Name():"NULL", 3271 fFocus!=NULL? fFocus->Name():"NULL", 3272 fLastMouseMovedView!=NULL? fLastMouseMovedView->Name():"NULL", 3273 session!=NULL? "In place":"NULL", 3274 fKeyMenuBar!=NULL? fKeyMenuBar->Name():"NULL", 3275 fDefaultButton!=NULL? fDefaultButton->Name():"NULL", 3276 accelList.CountItems()); 3277 /* 3278 for( int32 i=0; i<accelList.CountItems(); i++){ 3279 _BCmdKey *key = (_BCmdKey*)accelList.ItemAt(i); 3280 printf("\tShortCut %ld: char %s\n\t\t message: \n", i, (key->key > 127)?"ASCII":"UNICODE"); 3281 key->message->PrintToStream(); 3282 } 3283 */ 3284 printf("\ 3285 topViewToken = %ld\ 3286 pluseEnabled = %s\ 3287 isFilePanel = %s\ 3288 MaskActivated = %s\ 3289 pulseRate = %lld\ 3290 waitingForMenu = %s\ 3291 minimized = %s\ 3292 Menu semaphore = %ld\ 3293 maxZoomHeight = %f\ 3294 maxZoomWidth = %f\ 3295 minWindHeight = %f\ 3296 minWindWidth = %f\ 3297 maxWindHeight = %f\ 3298 maxWindWidth = %f\ 3299 frame = ( %f, %f, %f, %f )\ 3300 look = %d\ 3301 feel = %d\ 3302 lastViewToken = %ld\ 3303 pulseRUNNER = %s\n", 3304 fTopViewToken, 3305 fPulseEnabled==true?"Yes":"No", 3306 fIsFilePanel==true?"Yes":"No", 3307 fMaskActivated==true?"Yes":"No", 3308 fPulseRate, 3309 fWaitingForMenu==true?"Yes":"No", 3310 fMinimized==true?"Yes":"No", 3311 fMenuSem, 3312 fMaxZoomHeight, 3313 fMaxZoomWidth, 3314 fMinWindHeight, 3315 fMinWindWidth, 3316 fMaxWindHeight, 3317 fMaxWindWidth, 3318 fFrame.left, fFrame.top, fFrame.right, fFrame.bottom, 3319 (int16)fLook, 3320 (int16)fFeel, 3321 fLastViewToken, 3322 fPulseRunner!=NULL?"In place":"NULL"); 3323 } 3324 3325 /* 3326 TODO list: 3327 3328 *) take care of temporarely events mask!!! 3329 *) what's with this flag B_ASYNCHRONOUS_CONTROLS ? 3330 *) test arguments for SetWindowAligment 3331 *) call hook functions: MenusBeginning, MenusEnded. Add menu activation code. 3332 3333 * add handlers for B_VIEW_MOVED/RESIZED in DispatchMessage() 3334 * modify _UPDATE_ handler in DispatchMessage() 3335 */ 3336 3337 /* 3338 @log 3339 *modified ReadRawFromPort() and ConvertToMessage() methods to use BSession class. 3340 *modified/added B_VIEW_(MOVED/RESIZED) handlers in ConvertToMessage()/DispatchMessage() 3341 */ 3342