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 float dxNew; 1759 float dyNew; 1760 1761 // stay in minimum & maximum frame limits 1762 dxNew = (fFrame.Width() + dx) < fMinWindWidth ? fFrame.Width() - fMinWindWidth : dx; 1763 if (dxNew == dx) 1764 dxNew = (fFrame.Width() + dx) > fMaxWindWidth ? fMaxWindWidth - fFrame.Width() : dx; 1765 1766 dyNew = (fFrame.Height() + dy) < fMinWindHeight ? fFrame.Height() - fMinWindHeight : dy; 1767 if (dyNew == dy) 1768 dyNew = (fFrame.Height() + dy) > fMaxWindHeight ? fMaxWindHeight - fFrame.Height() : dy; 1769 1770 Lock(); 1771 session->WriteInt32( AS_WINDOW_RESIZE ); 1772 session->WriteFloat( dxNew ); 1773 session->WriteFloat( dyNew ); 1774 session->Sync( ); 1775 Unlock(); 1776 } 1777 1778 //------------------------------------------------------------------------------ 1779 1780 void BWindow::ResizeTo(float width, float height){ 1781 ResizeBy(width - fFrame.Width(), height - fFrame.Height()); 1782 } 1783 1784 //------------------------------------------------------------------------------ 1785 1786 void BWindow::Show(){ 1787 bool isLocked = this->IsLocked(); 1788 1789 fShowLevel--; 1790 1791 if (fShowLevel == 0){ 1792 STRACE(("BWindow(%s): sending AS_SHOW_WINDOW message...\n", Name() )); 1793 if ( !isLocked ) Lock(); 1794 top_view->Show(); 1795 session->WriteInt32( AS_SHOW_WINDOW ); 1796 session->Sync(); 1797 if ( !isLocked ) Unlock(); 1798 } 1799 1800 // if it's the fist time Show() is called... start the Looper thread. 1801 if ( Thread() == B_ERROR ) 1802 { 1803 // normaly this won't happen, but I want to be sure! 1804 if ( !isLocked ) Lock(); 1805 Run(); 1806 } 1807 1808 } 1809 1810 //------------------------------------------------------------------------------ 1811 1812 void BWindow::Hide(){ 1813 if (fShowLevel == 0){ 1814 Lock(); 1815 top_view->Hide(); 1816 session->WriteInt32( AS_HIDE_WINDOW ); 1817 session->Sync(); 1818 Unlock(); 1819 } 1820 fShowLevel++; 1821 } 1822 1823 //------------------------------------------------------------------------------ 1824 1825 bool BWindow::IsHidden() const{ 1826 return fShowLevel > 0; 1827 } 1828 1829 //------------------------------------------------------------------------------ 1830 1831 bool BWindow::QuitRequested(){ 1832 return BLooper::QuitRequested(); 1833 } 1834 1835 //------------------------------------------------------------------------------ 1836 1837 thread_id BWindow::Run(){ 1838 return BLooper::Run(); 1839 } 1840 1841 //------------------------------------------------------------------------------ 1842 1843 status_t BWindow::GetSupportedSuites(BMessage* data){ 1844 status_t err = B_OK; 1845 if (!data) 1846 err = B_BAD_VALUE; 1847 1848 if (!err){ 1849 err = data->AddString("Suites", "suite/vnd.Be-window"); 1850 if (!err){ 1851 BPropertyInfo propertyInfo(windowPropInfo); 1852 err = data->AddFlat("message", &propertyInfo); 1853 if (!err){ 1854 err = BLooper::GetSupportedSuites(data); 1855 } 1856 } 1857 } 1858 return err; 1859 } 1860 1861 //------------------------------------------------------------------------------ 1862 1863 BHandler* BWindow::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, 1864 int32 what, const char* property) 1865 { 1866 if (msg->what == B_WINDOW_MOVE_BY) 1867 return this; 1868 if (msg->what == B_WINDOW_MOVE_TO) 1869 return this; 1870 1871 BPropertyInfo propertyInfo(windowPropInfo); 1872 switch (propertyInfo.FindMatch(msg, index, specifier, what, property)) 1873 { 1874 case B_ERROR: 1875 break; 1876 case 0: 1877 case 1: 1878 case 2: 1879 case 3: 1880 case 4: 1881 case 5: 1882 case 6: 1883 case 7: 1884 case 8: 1885 case 9: 1886 case 10: 1887 case 11: 1888 case 12: 1889 case 13: 1890 return this; 1891 1892 case 14: 1893 if (fKeyMenuBar){ 1894 msg->PopSpecifier(); 1895 return fKeyMenuBar; 1896 } 1897 else{ 1898 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 1899 replyMsg.AddInt32( "error", B_NAME_NOT_FOUND ); 1900 replyMsg.AddString( "message", "This window doesn't have a main MenuBar"); 1901 msg->SendReply( &replyMsg ); 1902 return NULL; 1903 } 1904 case 15: 1905 // we will NOT pop the current specifier 1906 return top_view; 1907 1908 case 16: 1909 return this; 1910 } 1911 1912 return BLooper::ResolveSpecifier(msg, index, specifier, what, property); 1913 } 1914 1915 // PRIVATE 1916 //--------------------Private Methods------------------------------------------- 1917 // PRIVATE 1918 1919 void BWindow::InitData( BRect frame, 1920 const char* title, 1921 window_look look, 1922 window_feel feel, 1923 uint32 flags, 1924 uint32 workspace){ 1925 1926 STRACE(("BWindow::InitData(...)\n")); 1927 1928 fTitle=NULL; 1929 if ( be_app == NULL ){ 1930 debugger("You need a valid BApplication object before interacting with the app_server"); 1931 return; 1932 } 1933 1934 fFrame = frame; 1935 1936 if (title) 1937 SetTitle( title ); 1938 1939 fFeel = feel; 1940 fLook = look; 1941 fFlags = flags; 1942 1943 1944 fInTransaction = false; 1945 fActive = false; 1946 fShowLevel = 1; 1947 1948 top_view = NULL; 1949 fFocus = NULL; 1950 fLastMouseMovedView = NULL; 1951 fKeyMenuBar = NULL; 1952 fDefaultButton = NULL; 1953 1954 // accelList = new BList( 10 ); 1955 AddShortcut('X', B_COMMAND_KEY, new BMessage(B_CUT), NULL); 1956 AddShortcut('C', B_COMMAND_KEY, new BMessage(B_COPY), NULL); 1957 AddShortcut('V', B_COMMAND_KEY, new BMessage(B_PASTE), NULL); 1958 AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), NULL); 1959 AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); 1960 1961 fPulseEnabled = false; 1962 fPulseRate = 0; 1963 fPulseRunner = NULL; 1964 1965 // TODO: is this correct??? should the thread loop be started??? 1966 //SetPulseRate( 500000 ); 1967 1968 // TODO: see if you can use 'fViewsNeedPulse' 1969 1970 fIsFilePanel = false; 1971 1972 // TODO: see WHEN is this used! 1973 fMaskActivated = false; 1974 1975 // TODO: see WHEN is this used! 1976 fWaitingForMenu = false; 1977 1978 fMinimized = false; 1979 1980 // TODO: see WHERE you can use 'fMenuSem' 1981 1982 fMaxZoomHeight = 32768.0; 1983 fMaxZoomWidth = 32768.0; 1984 fMinWindHeight = 0.0; 1985 fMinWindWidth = 0.0; 1986 fMaxWindHeight = 32768.0; 1987 fMaxWindWidth = 32768.0; 1988 1989 fLastViewToken = B_NULL_TOKEN; 1990 // TODO: other initializations! 1991 1992 /* 1993 Here, we will contact app_server and let him know that a window has 1994 been created 1995 */ 1996 receive_port = create_port( B_LOOPER_PORT_DEFAULT_CAPACITY , 1997 "w_rcv_port"); 1998 if (receive_port==B_BAD_VALUE || receive_port==B_NO_MORE_PORTS){ 1999 debugger("Could not create BWindow's receive port, used for interacting with the app_server!"); 2000 delete this; 2001 } 2002 2003 STRACE(("BWindow::InitData(): contacting app_server...\n")); 2004 // let app_server to know that a window has been created. 2005 2006 session = new BSession( receive_port, be_app->fServerFrom ); 2007 2008 // HERE we are in BApplication's thread, so for locking we use be_app variable 2009 // we'll lock the be_app to be sure we're the only one writing at BApplication's server port 2010 bool locked = false; 2011 if ( !(be_app->IsLocked()) ) 2012 { be_app->Lock(); locked = true; } 2013 2014 PortMessage pmsg; 2015 PortLink link(be_app->fServerFrom); 2016 link.SetOpCode(AS_CREATE_WINDOW); 2017 2018 link.Attach<BRect>( fFrame ); 2019 link.Attach<int32>( (int32)fLook ); 2020 link.Attach<int32>( (int32)fFeel ); 2021 link.Attach<uint32>( fFlags ); 2022 link.Attach<uint32>( workspace ); 2023 link.Attach<int32>( _get_object_token_(this) ); 2024 link.Attach<port_id>( receive_port ); 2025 link.Attach<port_id>( fMsgPort ); 2026 link.AttachString( title ); 2027 link.FlushWithReply(&pmsg); 2028 2029 pmsg.Read<port_id>(&send_port); 2030 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, "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 this window. 2281 top_view->setOwner( this ); 2282 2283 // send top_view's information to app_server 2284 session->WriteInt32( AS_LAYER_CREATE_ROOT ); 2285 fLastViewToken = _get_object_token_( top_view ); 2286 2287 top_view->attachView(top_view); 2288 2289 STRACE(("BuildTopView ended\n")); 2290 } 2291 2292 //------------------------------------------------------------------------------ 2293 2294 void BWindow::stopConnection(){ 2295 Lock(); 2296 session->WriteInt32( B_QUIT_REQUESTED ); 2297 session->Sync(); 2298 Unlock(); 2299 } 2300 2301 //------------------------------------------------------------------------------ 2302 2303 void BWindow::prepareView(BView *aView){ 2304 2305 // TODO: implement 2306 2307 } 2308 2309 //------------------------------------------------------------------------------ 2310 2311 void BWindow::attachView(BView *aView){ 2312 2313 // TODO: implement 2314 2315 } 2316 2317 //------------------------------------------------------------------------------ 2318 2319 void BWindow::detachView(BView *aView){ 2320 2321 // TODO: implement 2322 2323 } 2324 //------------------------------------------------------------------------------ 2325 2326 void BWindow::setFocus(BView *focusView, bool notifyInputServer){ 2327 BView* previousFocus = fFocus; 2328 2329 if (previousFocus == focusView) 2330 return; 2331 2332 fFocus = NULL; 2333 2334 if (previousFocus != NULL) 2335 previousFocus->Invalidate(); 2336 2337 fFocus = focusView; 2338 2339 if (focusView != NULL) 2340 focusView->Invalidate(); 2341 2342 // TODO: find out why do we have to notify input server. 2343 if (notifyInputServer){ 2344 // what am I suppose to do here?? 2345 } 2346 } 2347 2348 //------------------------------------------------------------------------------ 2349 2350 void BWindow::handleActivation( bool active ){ 2351 2352 if (active){ 2353 // TODO: talk to Ingo to make BWindow a friend for BRoster 2354 // be_roster->UpdateActiveApp( be_app->Team() ); 2355 } 2356 2357 WindowActivated( active ); 2358 2359 // recursively call hook function 'WindowActivated(bool)' 2360 // for all views attached to this window. 2361 activateView( top_view, active ); 2362 } 2363 2364 //------------------------------------------------------------------------------ 2365 2366 void BWindow::activateView( BView *aView, bool active ){ 2367 2368 aView->WindowActivated( active ); 2369 2370 BView *child; 2371 if ( (child = aView->first_child) ){ 2372 while ( child ) { 2373 activateView( child, active ); 2374 child = child->next_sibling; 2375 } 2376 } 2377 } 2378 2379 //------------------------------------------------------------------------------ 2380 2381 bool BWindow::handleKeyDown( int32 raw_char, uint32 modifiers){ 2382 2383 // TODO: ask people if using 'raw_char' is OK ? 2384 2385 // handle BMenuBar key 2386 if ( (raw_char == B_ESCAPE) && (modifiers & B_COMMAND_KEY) 2387 && fKeyMenuBar) 2388 { 2389 2390 // TODO: ask Marc about 'fWaitingForMenu' member! 2391 2392 // fWaitingForMenu = true; 2393 fKeyMenuBar->StartMenuBar(0, true, false, NULL); 2394 return true; 2395 } 2396 2397 // Command+q has been pressed, so, we will quit 2398 if ( (raw_char == 'Q' || raw_char == 'q') && modifiers & B_COMMAND_KEY){ 2399 be_app->PostMessage(B_QUIT_REQUESTED); 2400 return true; 2401 } 2402 2403 // Keyboard navigation through views!!!! 2404 if ( raw_char == B_TAB){ 2405 2406 // even if we have no focus view, we'll say that we will handle TAB key 2407 if (!fFocus) 2408 return true; 2409 2410 BView *nextFocus; 2411 2412 if (modifiers & B_CONTROL_KEY & B_SHIFT_KEY){ 2413 nextFocus = findPrevView( fFocus, B_NAVIGABLE_JUMP ); 2414 } 2415 else 2416 if (modifiers & B_CONTROL_KEY){ 2417 nextFocus = findNextView( fFocus, B_NAVIGABLE_JUMP ); 2418 } 2419 else 2420 if (modifiers & B_SHIFT_KEY){ 2421 nextFocus = findPrevView( fFocus, B_NAVIGABLE ); 2422 } 2423 else 2424 nextFocus = findNextView( fFocus, B_NAVIGABLE ); 2425 2426 if ( nextFocus ) 2427 setFocus( nextFocus, false ); 2428 2429 return true; 2430 } 2431 2432 // Handle shortcuts 2433 int index; 2434 if ( (index = findShortcut(raw_char, modifiers)) >=0){ 2435 _BCmdKey *cmdKey; 2436 2437 cmdKey = (_BCmdKey*)accelList.ItemAt( index ); 2438 2439 // we'll give the message to the focus view 2440 if (cmdKey->targetToken == B_ANY_TOKEN){ 2441 fFocus->MessageReceived( cmdKey->message ); 2442 return true; 2443 } 2444 else{ 2445 BHandler *handler; 2446 BHandler *aHandler; 2447 int noOfHandlers; 2448 2449 // search for a match through BLooper's list of eligible handlers 2450 handler = NULL; 2451 noOfHandlers = CountHandlers(); 2452 for( int i=0; i < noOfHandlers; i++ ) 2453 // do we have a match? 2454 if ( _get_object_token_( aHandler = HandlerAt(i) ) 2455 == cmdKey->targetToken) 2456 { 2457 // yes, we do. 2458 handler = aHandler; 2459 break; 2460 } 2461 2462 if ( handler ) 2463 handler->MessageReceived( cmdKey->message ); 2464 else 2465 // if no handler was found, BWindow will handle the message 2466 MessageReceived( cmdKey->message ); 2467 } 2468 return true; 2469 } 2470 2471 // if <ENTER> is pressed and we have a default button 2472 if (DefaultButton() && (raw_char == B_ENTER)){ 2473 const char *chars; // just to be sure 2474 CurrentMessage()->FindString("bytes", &chars); 2475 2476 DefaultButton()->KeyDown( chars, strlen(chars)-1 ); 2477 return true; 2478 } 2479 2480 2481 return false; 2482 } 2483 2484 //------------------------------------------------------------------------------ 2485 2486 BView* BWindow::sendMessageUsingEventMask2( BView* aView, int32 message, BPoint where ){ 2487 2488 BView *destView; 2489 destView = NULL; 2490 2491 if ( aView->fBounds.Contains( aView->ConvertFromScreen(where) ) && 2492 !aView->first_child ){ 2493 return aView; 2494 } 2495 2496 // Code for Event Masks 2497 BView *child; 2498 if ( (child = aView->first_child) ){ 2499 while ( child ) { 2500 // see if a BView registered for mouse events and it's not the current focus view 2501 if ( child->fEventMask & B_POINTER_EVENTS && 2502 aView != fFocus ){ 2503 switch (message){ 2504 case B_MOUSE_DOWN:{ 2505 child->MouseDown( child->ConvertFromScreen( where ) ); 2506 } 2507 break; 2508 2509 case B_MOUSE_UP:{ 2510 child->MouseUp( child->ConvertFromScreen( where ) ); 2511 } 2512 break; 2513 2514 case B_MOUSE_MOVED:{ 2515 BMessage *dragMessage; 2516 2517 // TODO: get the dragMessage if any 2518 // for now... 2519 dragMessage = NULL; 2520 2521 /* TODO: after you have an example working, see if a view that registered for such events, 2522 does reveive B_MOUSE_MOVED with other options than B_OUTDIDE_VIEW !!! 2523 like: B_INSIDE_VIEW, B_ENTERED_VIEW, B_EXITED_VIEW 2524 */ 2525 child->MouseMoved( ConvertFromScreen(where), B_OUTSIDE_VIEW , dragMessage); 2526 } 2527 break; 2528 } 2529 } 2530 if (destView == NULL) 2531 destView = sendMessageUsingEventMask2( child, message, where ); 2532 else 2533 sendMessageUsingEventMask2( child, message, where ); 2534 child = child->next_sibling; 2535 } 2536 } 2537 2538 return destView; 2539 } 2540 2541 //------------------------------------------------------------------------------ 2542 2543 void BWindow::sendMessageUsingEventMask( int32 message, BPoint where ){ 2544 BView* destView; 2545 2546 destView = sendMessageUsingEventMask2(top_view, message, where); 2547 2548 // I'm SURE this is NEVER going to happen, but, durring development of BWindow, it may slip a NULL value 2549 if (!destView){ 2550 // debugger("There is no BView under the mouse;"); 2551 return; 2552 } 2553 2554 switch( message ){ 2555 case B_MOUSE_DOWN:{ 2556 setFocus( destView ); 2557 destView->MouseDown( destView->ConvertFromScreen( where ) ); 2558 break;} 2559 2560 case B_MOUSE_UP:{ 2561 destView->MouseUp( destView->ConvertFromScreen( where ) ); 2562 break;} 2563 2564 case B_MOUSE_MOVED:{ 2565 BMessage *dragMessage; 2566 2567 // TODO: add code for drag and drop 2568 // for now... 2569 dragMessage = NULL; 2570 2571 if (destView != fLastMouseMovedView){ 2572 fLastMouseMovedView->MouseMoved( destView->ConvertFromScreen( where ), B_EXITED_VIEW , dragMessage); 2573 destView->MouseMoved( ConvertFromScreen( where ), B_ENTERED_VIEW, dragMessage); 2574 fLastMouseMovedView = destView; 2575 } 2576 else{ 2577 destView->MouseMoved( ConvertFromScreen( where ), B_INSIDE_VIEW , dragMessage); 2578 } 2579 2580 // I'm guessing that B_OUTSIDE_VIEW is given to the view that has focus, I'll have to check 2581 // TODO: Do a research on mouse capturing, maybe it has something to do with this 2582 if (fFocus != destView) 2583 fFocus->MouseMoved( ConvertFromScreen( where ), B_OUTSIDE_VIEW , dragMessage); 2584 break;} 2585 } 2586 } 2587 2588 //------------------------------------------------------------------------------ 2589 2590 BMessage* BWindow::ConvertToMessage(void* raw1, int32 code){ 2591 2592 BMessage *msg; 2593 msg = new BMessage(); 2594 // time since 01/01/70 2595 int64 when; 2596 2597 switch(code){ 2598 case B_WINDOW_ACTIVATED:{ 2599 bool active; 2600 2601 session->ReadInt64( &when ); 2602 session->ReadBool( &active ); 2603 2604 msg->what = B_WINDOW_ACTIVATED; 2605 msg->AddInt64("when", when); 2606 msg->AddBool("active", active); 2607 2608 break;} 2609 2610 case B_QUIT_REQUESTED:{ 2611 2612 msg->what = B_QUIT_REQUESTED; 2613 msg->AddBool("shortcut", false); 2614 2615 break;} 2616 2617 case B_KEY_DOWN:{ 2618 int32 physicalKeyCode, 2619 repeat, 2620 modifiers, 2621 ASCIIcode; 2622 char *bytes = NULL; 2623 uint8 states; 2624 int8 UTF8_1, UTF8_2, UTF8_3; 2625 2626 session->ReadInt64( &when ); 2627 session->ReadInt32( &physicalKeyCode ); 2628 session->ReadInt32( &repeat ); 2629 session->ReadInt32( &modifiers ); 2630 session->ReadUInt8( &states ); 2631 session->ReadInt8( &UTF8_1 ); 2632 session->ReadInt8( &UTF8_2 ); 2633 session->ReadInt8( &UTF8_3 ); 2634 session->ReadInt32( &ASCIIcode ); 2635 bytes = session->ReadString(); 2636 2637 msg->what = B_KEY_DOWN; 2638 msg->AddInt64("when", when); 2639 msg->AddInt32("key", physicalKeyCode); 2640 msg->AddInt32("be:key_repeat", repeat); 2641 msg->AddInt32("modifiers", modifiers); 2642 msg->AddInt8("states", states); 2643 msg->AddInt8("byte", UTF8_1); 2644 msg->AddInt8("byte", UTF8_2); 2645 msg->AddInt8("byte", UTF8_3); 2646 msg->AddInt32("raw_char", ASCIIcode); 2647 msg->AddString("bytes", bytes); 2648 2649 if (bytes) 2650 delete bytes; 2651 2652 break;} 2653 2654 case B_KEY_UP:{ 2655 int32 physicalKeyCode, 2656 modifiers, 2657 ASCIIcode; 2658 char *bytes; 2659 uint8 states; 2660 int8 UTF8_1, UTF8_2, UTF8_3; 2661 2662 session->ReadInt64( &when ); 2663 session->ReadInt32( &physicalKeyCode ); 2664 session->ReadInt32( &modifiers ); 2665 session->ReadUInt8( &states ); 2666 session->ReadInt8( &UTF8_1 ); 2667 session->ReadInt8( &UTF8_2 ); 2668 session->ReadInt8( &UTF8_3 ); 2669 session->ReadInt32( &ASCIIcode ); 2670 bytes = session->ReadString(); 2671 2672 msg->what = B_KEY_UP; 2673 msg->AddInt64("when", when); 2674 msg->AddInt32("key", physicalKeyCode); 2675 msg->AddInt32("modifiers", modifiers); 2676 msg->AddInt8("states", states); 2677 msg->AddInt8("byte", UTF8_1); 2678 msg->AddInt8("byte", UTF8_2); 2679 msg->AddInt8("byte", UTF8_3); 2680 msg->AddInt32("raw_char", ASCIIcode); 2681 msg->AddString("bytes", bytes); 2682 2683 if (bytes) 2684 delete bytes; 2685 2686 break;} 2687 2688 case B_UNMAPPED_KEY_DOWN:{ 2689 int32 physicalKeyCode, 2690 modifiers; 2691 uint8 states; 2692 2693 session->ReadInt64( &when ); 2694 session->ReadInt32( &physicalKeyCode ); 2695 session->ReadInt32( &modifiers ); 2696 session->ReadUInt8( &states ); 2697 2698 msg->what = B_UNMAPPED_KEY_DOWN; 2699 msg->AddInt64("when", when); 2700 msg->AddInt32("key", physicalKeyCode); 2701 msg->AddInt32("modifiers", modifiers); 2702 msg->AddInt8("states", states); 2703 2704 break;} 2705 2706 case B_UNMAPPED_KEY_UP:{ 2707 int32 physicalKeyCode, 2708 modifiers; 2709 uint8 states; 2710 2711 session->ReadInt64( &when ); 2712 session->ReadInt32( &physicalKeyCode ); 2713 session->ReadInt32( &modifiers ); 2714 session->ReadUInt8( &states ); 2715 2716 msg->what = B_UNMAPPED_KEY_UP; 2717 msg->AddInt64("when", when); 2718 msg->AddInt32("key", physicalKeyCode); 2719 msg->AddInt32("modifiers", modifiers); 2720 msg->AddInt8("states", states); 2721 2722 break;} 2723 2724 case B_MODIFIERS_CHANGED:{ 2725 int32 modifiers, 2726 modifiersOld; 2727 uint8 states; 2728 2729 session->ReadInt64( &when ); 2730 session->ReadInt32( &modifiers ); 2731 session->ReadInt32( &modifiersOld ); 2732 session->ReadUInt8( &states ); 2733 2734 msg->what = B_MODIFIERS_CHANGED; 2735 msg->AddInt64("when", when); 2736 msg->AddInt32("modifiers", modifiers); 2737 msg->AddInt32("be:old_modifiers", modifiersOld); 2738 msg->AddInt8("states", states); 2739 2740 break;} 2741 2742 case B_MINIMIZE:{ 2743 bool minimize; 2744 2745 session->ReadInt64( &when ); 2746 session->ReadBool( &minimize ); 2747 2748 msg->what = B_MINIMIZE; 2749 msg->AddInt64("when", when); 2750 msg->AddBool("minimize", minimize); 2751 2752 break;} 2753 2754 case B_MOUSE_DOWN:{ 2755 int32 modifiers, 2756 buttons, 2757 noOfClicks; 2758 BPoint where; 2759 2760 session->ReadInt64( &when ); 2761 session->ReadPoint( &where ); 2762 session->ReadInt32( &modifiers ); 2763 session->ReadInt32( &buttons ); 2764 session->ReadInt32( &noOfClicks ); 2765 2766 msg->what = B_MOUSE_DOWN; 2767 msg->AddInt64("when", when); 2768 msg->AddPoint("where", where); 2769 msg->AddInt32("modifiers", modifiers); 2770 msg->AddInt32("buttons", buttons); 2771 msg->AddInt32("clicks", noOfClicks); 2772 2773 break;} 2774 2775 case B_MOUSE_MOVED:{ 2776 int32 buttons; 2777 int32 modifiers; // added by OBOS Team 2778 BPoint where; 2779 2780 session->ReadInt64( &when ); 2781 session->ReadPoint( &where ); 2782 session->ReadInt32( &buttons ); 2783 session->ReadInt32( &modifiers ); 2784 2785 msg->what = B_MOUSE_MOVED; 2786 msg->AddInt64("when", when); 2787 msg->AddPoint("where", where); 2788 msg->AddInt32("buttons", buttons); 2789 msg->AddInt32("modifiers", modifiers); 2790 2791 break;} 2792 2793 case B_MOUSE_UP:{ 2794 int32 modifiers, 2795 buttons; 2796 BPoint where; 2797 2798 session->ReadInt64( &when ); 2799 session->ReadPoint( &where ); 2800 session->ReadInt32( &buttons ); 2801 session->ReadInt32( &modifiers ); 2802 2803 msg->what = B_MOUSE_UP; 2804 msg->AddInt64("when", when); 2805 msg->AddPoint("where", where); 2806 msg->AddInt32("modifiers", modifiers); 2807 msg->AddInt32("buttons", buttons); 2808 2809 break;} 2810 2811 case B_MOUSE_WHEEL_CHANGED:{ 2812 float whellChangeX, 2813 whellChangeY; 2814 2815 session->ReadInt64( &when ); 2816 session->ReadFloat( &whellChangeX ); 2817 session->ReadFloat( &whellChangeY ); 2818 2819 msg->what = B_MOUSE_WHEEL_CHANGED; 2820 msg->AddInt64("when", when); 2821 msg->AddFloat("be:wheel_delta_x", whellChangeX); 2822 msg->AddFloat("be:wheel_delta_y", whellChangeY); 2823 2824 break;} 2825 2826 case B_SCREEN_CHANGED:{ 2827 int32 colorSpace; 2828 BRect frame; 2829 2830 session->ReadInt64( &when ); 2831 session->ReadRect( &frame ); 2832 session->ReadInt32( &colorSpace ); 2833 2834 msg->what = B_SCREEN_CHANGED; 2835 msg->AddInt64("when", when); 2836 msg->AddRect("frame", frame); 2837 msg->AddInt32("mode", colorSpace); 2838 2839 break;} 2840 2841 case B_WINDOW_MOVED:{ 2842 BPoint where; 2843 2844 session->ReadInt64( &when ); 2845 session->ReadPoint( &where ); 2846 2847 msg->what = B_WINDOW_MOVED; 2848 msg->AddInt64("when", when); 2849 msg->AddPoint("where", where); 2850 2851 break;} 2852 2853 case B_WINDOW_RESIZED:{ 2854 int32 newWidth, 2855 newHeight; 2856 2857 session->ReadInt64( &when ); 2858 session->ReadInt32( &newWidth ); 2859 session->ReadInt32( &newHeight ); 2860 2861 msg->what = B_WINDOW_RESIZED; 2862 msg->AddInt64("when", when); 2863 msg->AddInt32("width", newWidth); 2864 msg->AddInt32("height", newHeight); 2865 2866 break;} 2867 2868 case B_WORKSPACES_CHANGED:{ 2869 int32 newWorkSpace, 2870 oldWorkSpace; 2871 2872 session->ReadInt64( &when ); 2873 session->ReadInt32( &newWorkSpace ); 2874 session->ReadInt32( &oldWorkSpace ); 2875 2876 msg->what = B_WORKSPACES_CHANGED; 2877 msg->AddInt64("when", when); 2878 msg->AddInt32("old", oldWorkSpace); 2879 msg->AddInt32("new", newWorkSpace); 2880 2881 break;} 2882 2883 case B_WORKSPACE_ACTIVATED:{ 2884 int32 workSpace; 2885 bool active; 2886 2887 session->ReadInt64( &when ); 2888 session->ReadInt32( &workSpace ); 2889 session->ReadBool( &active ); 2890 2891 msg->what = B_WORKSPACE_ACTIVATED; 2892 msg->AddInt64("when", when); 2893 msg->AddInt32("workspace", workSpace); 2894 msg->AddBool("active", active); 2895 2896 break;} 2897 2898 case B_ZOOM:{ 2899 2900 session->ReadInt64( &when ); 2901 2902 msg->what = B_ZOOM; 2903 msg->AddInt64("when", when); 2904 2905 break;} 2906 2907 default:{ 2908 delete msg; 2909 2910 msg = BLooper::ConvertToMessage( raw1, code ); 2911 if (!msg) 2912 printf("***PANIC: app_server message NOT understood: '%c%c%c%c'***\n", 2913 (char)((code & 0xFF000000) >> 24), (char)((code & 0x00FF0000) >> 16), 2914 (char)((code & 0x0000FF00) >> 8), (char)(code & 0x000000FF) ); 2915 } 2916 } 2917 2918 return msg; 2919 } 2920 2921 //------------------------------------------------------------------------------ 2922 2923 void BWindow::sendPulse( BView* aView ){ 2924 BView *child; 2925 if ( (child = aView->first_child) ){ 2926 while ( child ) { 2927 if ( child->Flags() & B_PULSE_NEEDED ) child->Pulse(); 2928 sendPulse( child ); 2929 child = child->next_sibling; 2930 } 2931 } 2932 } 2933 2934 //------------------------------------------------------------------------------ 2935 2936 int32 BWindow::findShortcut( uint32 key, uint32 modifiers ){ 2937 int32 index, 2938 noOfItems; 2939 2940 index = -1; 2941 noOfItems = accelList.CountItems(); 2942 2943 for ( int32 i = 0; i < noOfItems; i++ ) { 2944 _BCmdKey* tempCmdKey; 2945 2946 tempCmdKey = (_BCmdKey*)accelList.ItemAt(i); 2947 if (tempCmdKey->key == key && tempCmdKey->modifiers == modifiers){ 2948 index = i; 2949 break; 2950 } 2951 } 2952 2953 return index; 2954 } 2955 2956 //------------------------------------------------------------------------------ 2957 2958 BView* BWindow::findView(BView* aView, int32 token){ 2959 2960 if ( _get_object_token_(aView) == token ) 2961 return aView; 2962 2963 BView *child; 2964 if ( (child = aView->first_child) ){ 2965 while ( child ) { 2966 BView* view; 2967 if ( (view = findView( child, token )) ) 2968 return view; 2969 child = child->next_sibling; 2970 } 2971 } 2972 2973 return NULL; 2974 } 2975 2976 //------------------------------------------------------------------------------ 2977 2978 BView* BWindow::findView(BView* aView, const char* viewName) const{ 2979 2980 if ( strcmp( viewName, aView->Name() ) == 0) 2981 return aView; 2982 2983 BView *child; 2984 if ( (child = aView->first_child) ){ 2985 while ( child ) { 2986 BView* view; 2987 if ( (view = findView( child, viewName )) ) 2988 return view; 2989 child = child->next_sibling; 2990 } 2991 } 2992 2993 return NULL; 2994 } 2995 2996 //------------------------------------------------------------------------------ 2997 2998 BView* BWindow::findView(BView* aView, BPoint point) const{ 2999 3000 if ( aView->Bounds().Contains(point) && 3001 !aView->first_child ) 3002 return aView; 3003 3004 BView *child; 3005 if ( (child = aView->first_child) ){ 3006 while ( child ) { 3007 BView* view; 3008 if ( (view = findView( child, point )) ) 3009 return view; 3010 child = child->next_sibling; 3011 } 3012 } 3013 3014 return NULL; 3015 } 3016 3017 //------------------------------------------------------------------------------ 3018 3019 BView* BWindow::findNextView( BView *focus, uint32 flags){ 3020 bool found; 3021 found = false; 3022 3023 BView *nextFocus; 3024 nextFocus = focus; 3025 3026 /* Ufff... this toked me some time... this is the best form I've reached. 3027 This algorithm searches the tree for BViews that accept focus. 3028 */ 3029 while (!found){ 3030 if (nextFocus->first_child) 3031 nextFocus = nextFocus->first_child; 3032 else 3033 if (nextFocus->next_sibling) 3034 nextFocus = nextFocus->next_sibling; 3035 else{ 3036 while( !nextFocus->next_sibling && nextFocus->parent ){ 3037 nextFocus = nextFocus->parent; 3038 } 3039 3040 if (nextFocus == top_view) 3041 nextFocus = nextFocus->first_child; 3042 else 3043 nextFocus = nextFocus->next_sibling; 3044 } 3045 3046 if (nextFocus->Flags() & flags) 3047 found = true; 3048 3049 /* It means that the hole tree has been searched and there is no 3050 view with B_NAVIGABLE_JUMP flag set! 3051 */ 3052 if (nextFocus == focus) 3053 return NULL; 3054 } 3055 3056 return nextFocus; 3057 } 3058 3059 //------------------------------------------------------------------------------ 3060 3061 BView* BWindow::findPrevView( BView *focus, uint32 flags){ 3062 bool found; 3063 found = false; 3064 3065 BView *prevFocus; 3066 prevFocus = focus; 3067 3068 BView *aView; 3069 3070 while (!found){ 3071 if ( (aView = findLastChild(prevFocus)) ) 3072 prevFocus = aView; 3073 else 3074 if (prevFocus->prev_sibling) 3075 prevFocus = prevFocus->prev_sibling; 3076 else{ 3077 while( !prevFocus->prev_sibling && prevFocus->parent ){ 3078 prevFocus = prevFocus->parent; 3079 } 3080 3081 if (prevFocus == top_view) 3082 prevFocus = findLastChild( prevFocus ); 3083 else 3084 prevFocus = prevFocus->prev_sibling; 3085 } 3086 3087 if (prevFocus->Flags() & flags) 3088 found = true; 3089 3090 3091 /* It means that the hole tree has been searched and there is no 3092 view with B_NAVIGABLE_JUMP flag set! 3093 */ 3094 if (prevFocus == focus) 3095 return NULL; 3096 } 3097 3098 return prevFocus; 3099 } 3100 3101 //------------------------------------------------------------------------------ 3102 3103 BView* BWindow::findLastChild(BView *parent){ 3104 BView *aView; 3105 if ( (aView = parent->first_child) ){ 3106 while (aView->next_sibling) 3107 aView = aView->next_sibling; 3108 3109 return aView; 3110 } 3111 else 3112 return NULL; 3113 } 3114 3115 //------------------------------------------------------------------------------ 3116 3117 void BWindow::drawAllViews(BView* aView){ 3118 3119 BMessageQueue *queue; 3120 BMessage *msg; 3121 3122 queue = MessageQueue(); 3123 3124 // process all update BMessages from message queue 3125 queue->Lock(); 3126 while ( (msg = queue->FindMessage( (uint32)_UPDATE_ )) ) 3127 { 3128 Lock(); 3129 DispatchMessage( msg, this ); 3130 Unlock(); 3131 3132 queue->RemoveMessage( msg ); 3133 } 3134 queue->Unlock(); 3135 3136 // we'll send a message to app_server, tell him that we want all our views updated 3137 Lock(); 3138 session->WriteInt32( AS_UPDATE_IF_NEEDED ); 3139 session->Sync(); 3140 Unlock(); 3141 3142 // TODO: update!!!!!!!!!!!!!!!!!!! 3143 // process all update messages from receive port queue 3144 bool over = false; 3145 while (!over) 3146 { 3147 msg = MessageFromPort(0); 3148 if (msg){ 3149 switch (msg->what){ 3150 3151 case _ALL_UPDATED_:{ 3152 over = true; 3153 }break; 3154 3155 case _UPDATE_:{ 3156 Lock(); 3157 DispatchMessage( msg, this ); 3158 Unlock(); 3159 }break; 3160 3161 default:{ 3162 queue->Lock(); 3163 queue->AddMessage(msg); 3164 queue->Unlock(); 3165 }break; 3166 } 3167 } 3168 } 3169 } 3170 3171 //------------------------------------------------------------------------------ 3172 3173 void BWindow::drawView(BView* aView, BRect area){ 3174 3175 /* TODO: Drawing during an Update 3176 These settings are temporary. When the update is over, all graphics 3177 parameters are reset to their initial values 3178 */ 3179 aView->Draw( area ); 3180 3181 BView *child; 3182 if ( (child = aView->first_child) ){ 3183 while ( child ) { 3184 if ( area.Intersects( child->Frame() ) ){ 3185 BRect newArea; 3186 3187 newArea = area & child->Frame(); 3188 child->ConvertFromParent( &newArea ); 3189 child->Invalidate( newArea ); 3190 } 3191 child = child->next_sibling; 3192 } 3193 } 3194 } 3195 3196 //------------------------------------------------------------------------------ 3197 3198 void BWindow::SetIsFilePanel(bool yes){ 3199 3200 // TODO: is this not enough? 3201 fIsFilePanel = yes; 3202 } 3203 3204 //------------------------------------------------------------------------------ 3205 3206 bool BWindow::IsFilePanel() const{ 3207 return fIsFilePanel; 3208 } 3209 3210 3211 //------------------------------------------------------------------------------ 3212 // Virtual reserved Functions 3213 3214 void BWindow::_ReservedWindow1() { } 3215 //------------------------------------------------------------------------------ 3216 void BWindow::_ReservedWindow2() { } 3217 //------------------------------------------------------------------------------ 3218 void BWindow::_ReservedWindow3() { } 3219 //------------------------------------------------------------------------------ 3220 void BWindow::_ReservedWindow4() { } 3221 //------------------------------------------------------------------------------ 3222 void BWindow::_ReservedWindow5() { } 3223 //------------------------------------------------------------------------------ 3224 void BWindow::_ReservedWindow6() { } 3225 //------------------------------------------------------------------------------ 3226 void BWindow::_ReservedWindow7() { } 3227 //------------------------------------------------------------------------------ 3228 void BWindow::_ReservedWindow8() { } 3229 3230 void BWindow::PrintToStream() const{ 3231 printf("BWindow '%s' data:\ 3232 Title = %s\ 3233 Token = %ld\ 3234 InTransaction = %s\ 3235 Active = %s\ 3236 fShowLevel = %d\ 3237 Flags = %lx\ 3238 send_port = %ld\ 3239 receive_port = %ld\ 3240 top_view name = %s\ 3241 focus view name = %s\ 3242 lastMouseMoved = %s\ 3243 session = %s\ 3244 KeyMenuBar name = %s\ 3245 DefaultButton = %s\ 3246 # of shortcuts = %ld", 3247 Name(), 3248 fTitle!=NULL? fTitle:"NULL", 3249 _get_object_token_(this), 3250 fInTransaction==true? "yes":"no", 3251 fActive==true? "yes":"no", 3252 fShowLevel, 3253 fFlags, 3254 send_port, 3255 receive_port, 3256 top_view!=NULL? top_view->Name():"NULL", 3257 fFocus!=NULL? fFocus->Name():"NULL", 3258 fLastMouseMovedView!=NULL? fLastMouseMovedView->Name():"NULL", 3259 session!=NULL? "In place":"NULL", 3260 fKeyMenuBar!=NULL? fKeyMenuBar->Name():"NULL", 3261 fDefaultButton!=NULL? fDefaultButton->Name():"NULL", 3262 accelList.CountItems()); 3263 /* 3264 for( int32 i=0; i<accelList.CountItems(); i++){ 3265 _BCmdKey *key = (_BCmdKey*)accelList.ItemAt(i); 3266 printf("\tShortCut %ld: char %s\n\t\t message: \n", i, (key->key > 127)?"ASCII":"UNICODE"); 3267 key->message->PrintToStream(); 3268 } 3269 */ 3270 printf("\ 3271 topViewToken = %ld\ 3272 pluseEnabled = %s\ 3273 isFilePanel = %s\ 3274 MaskActivated = %s\ 3275 pulseRate = %lld\ 3276 waitingForMenu = %s\ 3277 minimized = %s\ 3278 Menu semaphore = %ld\ 3279 maxZoomHeight = %f\ 3280 maxZoomWidth = %f\ 3281 minWindHeight = %f\ 3282 minWindWidth = %f\ 3283 maxWindHeight = %f\ 3284 maxWindWidth = %f\ 3285 frame = ( %f, %f, %f, %f )\ 3286 look = %d\ 3287 feel = %d\ 3288 lastViewToken = %ld\ 3289 pulseRUNNER = %s\n", 3290 fTopViewToken, 3291 fPulseEnabled==true?"Yes":"No", 3292 fIsFilePanel==true?"Yes":"No", 3293 fMaskActivated==true?"Yes":"No", 3294 fPulseRate, 3295 fWaitingForMenu==true?"Yes":"No", 3296 fMinimized==true?"Yes":"No", 3297 fMenuSem, 3298 fMaxZoomHeight, 3299 fMaxZoomWidth, 3300 fMinWindHeight, 3301 fMinWindWidth, 3302 fMaxWindHeight, 3303 fMaxWindWidth, 3304 fFrame.left, fFrame.top, fFrame.right, fFrame.bottom, 3305 (int16)fLook, 3306 (int16)fFeel, 3307 fLastViewToken, 3308 fPulseRunner!=NULL?"In place":"NULL"); 3309 } 3310 3311 /* 3312 TODO list: 3313 3314 *) take care of temporarely events mask!!! 3315 *) what's with this flag B_ASYNCHRONOUS_CONTROLS ? 3316 *) test arguments for SetWindowAligment 3317 *) call hook functions: MenusBeginning, MenusEnded. Add menu activation code. 3318 3319 * add handlers for B_VIEW_MOVED/RESIZED in DispatchMessage() 3320 * modify _UPDATE_ handler in DispatchMessage() 3321 */ 3322 3323 /* 3324 @log 3325 *modified ReadRawFromPort() and ConvertToMessage() methods to use BSession class. 3326 *modified/added B_VIEW_(MOVED/RESIZED) handlers in ConvertToMessage()/DispatchMessage() 3327 */ 3328