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