1 /*
2 * Copyright 2001-2016, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * Adrian Oanca <adioanca@cotty.iren.ro>
8 * Stephan Aßmus <superstippi@gmx.de>
9 * Stefano Ceccherini (burton666@libero.it)
10 * Axel Dörfler, axeld@pinc-software.de
11 * Jérôme Duval, jerome.duval@free.fr
12 * Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
13 * Philippe Saint-Pierre, stpere@gmail.com
14 * Wim van der Meer, <WPJvanderMeer@gmail.com>
15 * Joseph Groover <looncraz@looncraz.net>
16 */
17
18
19 /*! \class ServerApp ServerApp.h
20 \brief Counterpart to BApplication within the app_server
21 */
22
23
24 #include "ServerApp.h"
25
26 #include <new>
27 #include <stdio.h>
28 #include <string.h>
29 #include <syslog.h>
30
31 #include <AppDefs.h>
32 #include <Autolock.h>
33 #include <AutoLocker.h>
34 #include <Debug.h>
35 #include <List.h>
36 #include <ScrollBar.h>
37 #include <Shape.h>
38 #include <String.h>
39 #include <StackOrHeapArray.h>
40
41 #include <FontPrivate.h>
42 #include <MessengerPrivate.h>
43 #include <PrivateScreen.h>
44 #include <RosterPrivate.h>
45 #include <ServerProtocol.h>
46 #include <WindowPrivate.h>
47
48 #include "AppFontManager.h"
49 #include "AppServer.h"
50 #include "BitmapManager.h"
51 #include "CursorManager.h"
52 #include "CursorSet.h"
53 #include "Desktop.h"
54 #include "DecorManager.h"
55 #include "DrawingEngine.h"
56 #include "EventStream.h"
57 #include "GlobalFontManager.h"
58 #include "HWInterface.h"
59 #include "InputManager.h"
60 #include "OffscreenServerWindow.h"
61 #include "Screen.h"
62 #include "ServerBitmap.h"
63 #include "ServerConfig.h"
64 #include "ServerCursor.h"
65 #include "ServerPicture.h"
66 #include "ServerTokenSpace.h"
67 #include "ServerWindow.h"
68 #include "SystemPalette.h"
69 #include "Window.h"
70
71
72 //#define DEBUG_SERVERAPP
73 #ifdef DEBUG_SERVERAPP
74 # define STRACE(x) debug_printf x
75 #else
76 # define STRACE(x) ;
77 #endif
78
79 //#define DEBUG_SERVERAPP_FONT
80 #ifdef DEBUG_SERVERAPP_FONT
81 # define FTRACE(x) debug_printf x
82 #else
83 # define FTRACE(x) ;
84 #endif
85
86 using std::nothrow;
87
88 static const uint32 kMsgUpdateShowAllDraggers = '_adg';
89 static const uint32 kMsgAppQuit = 'appQ';
90
91
ServerApp(Desktop * desktop,port_id clientReplyPort,port_id clientLooperPort,team_id clientTeam,int32 clientToken,const char * signature)92 ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort,
93 port_id clientLooperPort, team_id clientTeam,
94 int32 clientToken, const char* signature)
95 :
96 MessageLooper("application"),
97
98 fMessagePort(-1),
99 fClientReplyPort(clientReplyPort),
100 fDesktop(desktop),
101 fSignature(signature),
102 fClientTeam(clientTeam),
103 fWindowListLock("window list"),
104 fInitialWorkspace(desktop->CurrentWorkspace()),
105 // TODO: this should probably be retrieved when the app is loaded!
106 fTemporaryDisplayModeChange(0),
107 fMapLocker("server app maps"),
108 fAppCursor(NULL),
109 fViewCursor(NULL),
110 fCursorHideLevel(0),
111 fIsActive(false),
112 fMemoryAllocator(new (std::nothrow) ClientMemoryAllocator(this), true),
113 fAppFontManager(NULL)
114 {
115 if (fSignature.IsEmpty())
116 fSignature = "application/no-signature";
117
118 char name[B_OS_NAME_LENGTH];
119 snprintf(name, sizeof(name), "a<%" B_PRId32 ":%s", fClientTeam,
120 SignatureLeaf());
121
122 fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name);
123 if (fMessagePort < B_OK)
124 return;
125
126 fLink.SetSenderPort(fClientReplyPort);
127 fLink.SetReceiverPort(fMessagePort);
128 fLink.SetTargetTeam(fClientTeam);
129
130 // we let the application own the port, so that we get aware when it's gone
131 if (set_port_owner(fMessagePort, fClientTeam) < B_OK) {
132 delete_port(fMessagePort);
133 fMessagePort = -1;
134 return;
135 }
136
137 BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
138 clientLooperPort, clientToken);
139
140 // record the current system wide fonts..
141 desktop->LockSingleWindow();
142 DesktopSettings settings(desktop);
143 settings.GetDefaultPlainFont(fPlainFont);
144 settings.GetDefaultBoldFont(fBoldFont);
145 settings.GetDefaultFixedFont(fFixedFont);
146 desktop->UnlockSingleWindow();
147
148 fAppFontManager = new AppFontManager();
149
150 STRACE(("ServerApp %s:\n", Signature()));
151 STRACE(("\tBApp port: %" B_PRId32 "\n", fClientReplyPort));
152 STRACE(("\tReceiver port: %" B_PRId32 "\n", fMessagePort));
153 }
154
155
~ServerApp()156 ServerApp::~ServerApp()
157 {
158 STRACE(("*ServerApp %s:~ServerApp()\n", Signature()));
159 ASSERT(fQuitting);
160
161 // quit all server windows
162
163 fWindowListLock.Lock();
164 for (int32 i = fWindowList.CountItems(); i-- > 0;) {
165 ServerWindow* window = fWindowList.ItemAt(i);
166 window->Quit();
167 }
168 fWindowListLock.Unlock();
169
170 // wait for the windows to quit
171 snooze(20000);
172
173 fDesktop->RevertScreenModes(fTemporaryDisplayModeChange);
174
175 fWindowListLock.Lock();
176 for (int32 i = fWindowList.CountItems(); i-- > 0;) {
177 ServerWindow* window = fWindowList.ItemAt(i);
178
179 // A window could have been removed in the mean time
180 // (if those 20 milli seconds from above weren't enough)
181 if (window == NULL)
182 continue;
183
184 sem_id deathSemaphore = window->DeathSemaphore();
185 fWindowListLock.Unlock();
186
187 // wait 3 seconds for our window to quit - that's quite a long
188 // time, but killing it might have desastrous effects
189 if (MessageLooper::WaitForQuit(deathSemaphore, 3000000) != B_OK) {
190 // This really shouldn't happen, as it shows we're buggy
191 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
192 syslog(LOG_ERR, "ServerApp %s: ServerWindow doesn't respond!\n",
193 Signature());
194 #else
195 debugger("ServerWindow doesn't respond!\n");
196 #endif
197 }
198 fWindowListLock.Lock();
199 }
200
201 if (fMemoryAllocator != NULL)
202 fMemoryAllocator->Detach();
203 fMapLocker.Lock();
204
205 while (!fBitmapMap.empty())
206 _DeleteBitmap(fBitmapMap.begin()->second);
207
208 while (!fPictureMap.empty())
209 fPictureMap.begin()->second->SetOwner(NULL);
210
211 fDesktop->GetCursorManager().DeleteCursors(fClientTeam);
212
213 delete fAppFontManager;
214
215 STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature()));
216 }
217
218
219 /*! \brief Checks if the application was initialized correctly
220 */
221 status_t
InitCheck()222 ServerApp::InitCheck()
223 {
224 if (fMessagePort < B_OK)
225 return fMessagePort;
226
227 if (fClientReplyPort < B_OK)
228 return fClientReplyPort;
229
230 if (fWindowListLock.InitCheck() < B_OK)
231 return fWindowListLock.InitCheck();
232
233 if (fMemoryAllocator == NULL)
234 return B_NO_MEMORY;
235
236 return B_OK;
237 }
238
239
240 void
Quit()241 ServerApp::Quit()
242 {
243 Quit(-1);
244 }
245
246
247 /*! \brief This quits the application and deletes it. You're not supposed
248 to call its destructor directly.
249
250 At the point you're calling this method, the application should already
251 be removed from the application list.
252 */
253 void
Quit(sem_id shutdownSemaphore)254 ServerApp::Quit(sem_id shutdownSemaphore)
255 {
256 if (fThread < B_OK) {
257 delete this;
258 return;
259 }
260
261 // execute application deletion in the message looper thread
262
263 fQuitting = true;
264 PostMessage(kMsgAppQuit);
265
266 send_data(fThread, 'QUIT', &shutdownSemaphore, sizeof(sem_id));
267 }
268
269
270 /*! \brief Sets the ServerApp's active status
271 \param value The new status of the ServerApp.
272
273 This changes an internal flag and also sets the current cursor to the one
274 specified by the application
275 */
276 void
Activate(bool value)277 ServerApp::Activate(bool value)
278 {
279 if (fIsActive == value)
280 return;
281
282 fIsActive = value;
283
284 if (fIsActive) {
285 // notify registrar about the active app
286 BRoster::Private roster;
287 roster.UpdateActiveApp(ClientTeam());
288
289 if (_HasWindowUnderMouse()) {
290 // Set the cursor to the application cursor, if any
291 fDesktop->SetCursor(CurrentCursor());
292 }
293 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
294 }
295 }
296
297
298 void
SetCurrentCursor(ServerCursor * cursor)299 ServerApp::SetCurrentCursor(ServerCursor* cursor)
300 {
301 fViewCursor.SetTo(cursor, false);
302
303 fDesktop->SetCursor(CurrentCursor());
304 }
305
306
307 ServerCursor*
CurrentCursor() const308 ServerApp::CurrentCursor() const
309 {
310 if (fViewCursor != NULL)
311 return fViewCursor;
312
313 return fAppCursor;
314 }
315
316
317 bool
AddWindow(ServerWindow * window)318 ServerApp::AddWindow(ServerWindow* window)
319 {
320 BAutolock locker(fWindowListLock);
321
322 return fWindowList.AddItem(window);
323 }
324
325
326 void
RemoveWindow(ServerWindow * window)327 ServerApp::RemoveWindow(ServerWindow* window)
328 {
329 BAutolock locker(fWindowListLock);
330
331 fWindowList.RemoveItem(window);
332 }
333
334
335 bool
InWorkspace(int32 index) const336 ServerApp::InWorkspace(int32 index) const
337 {
338 BAutolock locker(fWindowListLock);
339
340 // we could cache this, but then we'd have to recompute the cached
341 // value everytime a window has closed or changed workspaces
342
343 // TODO: support initial application workspace!
344
345 for (int32 i = fWindowList.CountItems(); i-- > 0;) {
346 ServerWindow* serverWindow = fWindowList.ItemAt(i);
347
348 const Window* window = serverWindow->Window();
349 if (window == NULL || window->IsOffscreenWindow())
350 continue;
351
352 // only normal and unhidden windows count
353
354 if (window->IsNormal() && !window->IsHidden()
355 && window->InWorkspace(index))
356 return true;
357 }
358
359 return false;
360 }
361
362
363 uint32
Workspaces() const364 ServerApp::Workspaces() const
365 {
366 uint32 workspaces = 0;
367
368 BAutolock locker(fWindowListLock);
369
370 // we could cache this, but then we'd have to recompute the cached
371 // value everytime a window has closed or changed workspaces
372
373 for (int32 i = fWindowList.CountItems(); i-- > 0;) {
374 ServerWindow* serverWindow = fWindowList.ItemAt(i);
375
376 const Window* window = serverWindow->Window();
377 if (window == NULL || window->IsOffscreenWindow())
378 continue;
379
380 // only normal and unhidden windows count
381
382 if (window->IsNormal() && !window->IsHidden())
383 workspaces |= window->Workspaces();
384 }
385
386 // TODO: add initial application workspace!
387 return workspaces;
388 }
389
390
391 /*! \brief Acquires a reference of the desired bitmap, if available.
392 \param token ID token of the bitmap to find
393 \return The bitmap having that ID or NULL if not found
394 */
395 ServerBitmap*
GetBitmap(int32 token) const396 ServerApp::GetBitmap(int32 token) const
397 {
398 if (token < 1)
399 return NULL;
400
401 BAutolock _(fMapLocker);
402
403 ServerBitmap* bitmap = _FindBitmap(token);
404 if (bitmap == NULL)
405 return NULL;
406
407 bitmap->AcquireReference();
408
409 return bitmap;
410 }
411
412
413 ServerPicture*
CreatePicture(const ServerPicture * original)414 ServerApp::CreatePicture(const ServerPicture* original)
415 {
416 BReference<ServerPicture> picture;
417 if (original != NULL)
418 picture.SetTo(new(std::nothrow) ServerPicture(*original), true);
419 else
420 picture.SetTo(new(std::nothrow) ServerPicture(), true);
421
422 if (picture != NULL && !picture->SetOwner(this))
423 return NULL;
424
425 return picture.Detach();
426 }
427
428
429 ServerPicture*
GetPicture(int32 token) const430 ServerApp::GetPicture(int32 token) const
431 {
432 if (token < 1)
433 return NULL;
434
435 BAutolock _(fMapLocker);
436
437 ServerPicture* picture = _FindPicture(token);
438 if (picture == NULL)
439 return NULL;
440
441 picture->AcquireReference();
442
443 return picture;
444 }
445
446
447 /*! To be called only by ServerPicture itself.*/
448 bool
AddPicture(ServerPicture * picture)449 ServerApp::AddPicture(ServerPicture* picture)
450 {
451 BAutolock _(fMapLocker);
452
453 ASSERT(picture->Owner() == NULL);
454
455 try {
456 fPictureMap.insert(std::make_pair(picture->Token(), BReference<ServerPicture>(picture, false)));
457 } catch (std::bad_alloc& exception) {
458 return false;
459 }
460
461 return true;
462 }
463
464
465 /*! To be called only by ServerPicture itself.*/
466 void
RemovePicture(ServerPicture * picture)467 ServerApp::RemovePicture(ServerPicture* picture)
468 {
469 BAutolock _(fMapLocker);
470
471 ASSERT(picture->Owner() == this);
472
473 fPictureMap.erase(picture->Token());
474 }
475
476
477 /*! Called from the ClientMemoryAllocator whenever a server area could be
478 deleted.
479 A message is then sent to the client telling it that it can delete its
480 client area, too.
481 */
482 void
NotifyDeleteClientArea(area_id serverArea)483 ServerApp::NotifyDeleteClientArea(area_id serverArea)
484 {
485 BMessage notify(kMsgDeleteServerMemoryArea);
486 notify.AddInt32("server area", serverArea);
487
488 SendMessageToClient(¬ify);
489 }
490
491
492 /*! \brief Send a message to the ServerApp's BApplication
493 \param message The message to send
494 */
495 void
SendMessageToClient(BMessage * message) const496 ServerApp::SendMessageToClient(BMessage* message) const
497 {
498 status_t status = fHandlerMessenger.SendMessage(message, (BHandler*)NULL,
499 100000);
500 if (status != B_OK) {
501 syslog(LOG_ERR, "app %s send to client failed: %s\n", Signature(),
502 strerror(status));
503 }
504 }
505
506
507 // #pragma mark - private methods
508
509
510 void
_GetLooperName(char * name,size_t length)511 ServerApp::_GetLooperName(char* name, size_t length)
512 {
513 snprintf(name, length, "a:%" B_PRId32 ":%s", ClientTeam(), SignatureLeaf());
514 }
515
516
517 /*! \brief Handler function for BApplication API messages
518 \param code Identifier code for the message. Equivalent to BMessage::what
519 \param buffer Any attachments
520
521 Note that the buffer's exact format is determined by the particular message.
522 All attachments are placed in the buffer via a PortLink, so it will be a
523 matter of casting and incrementing an index variable to access them.
524 */
525 void
_DispatchMessage(int32 code,BPrivate::LinkReceiver & link)526 ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
527 {
528 switch (code) {
529 case AS_REGISTER_INPUT_SERVER:
530 {
531 EventStream* stream
532 = new(std::nothrow) InputServerStream(fHandlerMessenger);
533 if (stream != NULL
534 && (!stream->IsValid() || !gInputManager->AddStream(stream))) {
535 delete stream;
536 break;
537 }
538
539 // TODO: this should be done using notifications (so that an
540 // abandoned stream will get noticed directly)
541 if (fDesktop->EventDispatcher().InitCheck() != B_OK)
542 fDesktop->EventDispatcher().SetTo(gInputManager->GetStream());
543 break;
544 }
545
546 case AS_APP_CRASHED:
547 // Allow the debugger to show its window: if needed, remove any
548 // kWindowScreenFeels from the windows of this application
549 if (fDesktop->LockAllWindows()) {
550 if (fWindowListLock.Lock()) {
551 for (int32 i = fWindowList.CountItems(); i-- > 0;) {
552 ServerWindow* serverWindow = fWindowList.ItemAt(i);
553
554 Window* window = serverWindow->Window();
555 if (window == NULL || window->IsOffscreenWindow())
556 continue;
557
558 if (window->Feel() == kWindowScreenFeel)
559 fDesktop->SetWindowFeel(window, B_NORMAL_WINDOW_FEEL);
560 }
561
562 fWindowListLock.Unlock();
563 }
564 fDesktop->UnlockAllWindows();
565 }
566 break;
567
568 case AS_DUMP_ALLOCATOR:
569 fMemoryAllocator->Dump();
570 break;
571 case AS_DUMP_BITMAPS:
572 {
573 fMapLocker.Lock();
574
575 debug_printf("Application %" B_PRId32 ", %s: %d bitmaps:\n",
576 ClientTeam(), Signature(), (int)fBitmapMap.size());
577
578 BitmapMap::const_iterator iterator = fBitmapMap.begin();
579 for (; iterator != fBitmapMap.end(); iterator++) {
580 ServerBitmap* bitmap = iterator->second;
581 debug_printf(" [%" B_PRId32 "] %" B_PRId32 "x%" B_PRId32 ", "
582 "area %" B_PRId32 ", size %" B_PRId32 "\n",
583 bitmap->Token(), bitmap->Width(), bitmap->Height(),
584 bitmap->Area(), bitmap->BitsLength());
585 }
586 fMapLocker.Unlock();
587 break;
588 }
589
590 case AS_CREATE_WINDOW:
591 case AS_CREATE_OFFSCREEN_WINDOW:
592 {
593 port_id clientReplyPort = -1;
594 status_t status = _CreateWindow(code, link, clientReplyPort);
595
596 // if sucessful, ServerWindow::Run() will already have replied
597 if (status < B_OK) {
598 // window creation failed, we need to notify the client
599 BPrivate::LinkSender reply(clientReplyPort);
600 reply.StartMessage(status);
601 reply.Flush();
602 }
603 break;
604 }
605
606 case AS_GET_WINDOW_LIST:
607 {
608 team_id team;
609 if (link.Read<team_id>(&team) == B_OK)
610 fDesktop->WriteWindowList(team, fLink.Sender());
611 break;
612 }
613
614 case AS_GET_WINDOW_INFO:
615 {
616 int32 serverToken;
617 if (link.Read<int32>(&serverToken) == B_OK)
618 fDesktop->WriteWindowInfo(serverToken, fLink.Sender());
619 break;
620 }
621
622 case AS_GET_WINDOW_ORDER:
623 {
624 int32 workspace;
625 if (link.Read<int32>(&workspace) == B_OK)
626 fDesktop->WriteWindowOrder(workspace, fLink.Sender());
627 break;
628 }
629
630 case AS_GET_APPLICATION_ORDER:
631 {
632 int32 workspace;
633 if (link.Read<int32>(&workspace) == B_OK)
634 fDesktop->WriteApplicationOrder(workspace, fLink.Sender());
635 break;
636 }
637
638 case AS_MINIMIZE_TEAM:
639 {
640 team_id team;
641 if (link.Read<team_id>(&team) == B_OK)
642 fDesktop->MinimizeApplication(team);
643 break;
644 }
645
646 case AS_BRING_TEAM_TO_FRONT:
647 {
648 team_id team;
649 if (link.Read<team_id>(&team) == B_OK)
650 fDesktop->BringApplicationToFront(team);
651 break;
652 }
653
654 case AS_WINDOW_ACTION:
655 {
656 int32 token;
657 int32 action;
658
659 link.Read<int32>(&token);
660 if (link.Read<int32>(&action) != B_OK)
661 break;
662
663 fDesktop->WindowAction(token, action);
664 break;
665 }
666
667 // Decorator commands
668
669 case AS_SET_DECORATOR:
670 {
671 // Attached Data:
672 // path to decorator add-on
673
674 BString path;
675 link.ReadString(path);
676
677 status_t error = gDecorManager.SetDecorator(path, fDesktop);
678
679 fLink.Attach<status_t>(error);
680 fLink.Flush();
681
682 if (error == B_OK)
683 fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR);
684 break;
685 }
686
687 case AS_GET_DECORATOR:
688 {
689 fLink.StartMessage(B_OK);
690 fLink.AttachString(gDecorManager.GetCurrentDecorator().String());
691 fLink.Flush();
692 break;
693 }
694
695 case AS_SET_CONTROL_LOOK:
696 {
697 STRACE(("ServerApp %s: Set ControlLook\n", Signature()));
698
699 BString path;
700 status_t error = B_ERROR;
701 if (link.ReadString(path) == B_OK) {
702 LockedDesktopSettings settings(fDesktop);
703 error = settings.SetControlLook(path.String());
704 }
705
706 fLink.StartMessage(error);
707 fLink.Flush();
708 break;
709 }
710
711 case AS_GET_CONTROL_LOOK:
712 {
713 STRACE(("ServerApp %s: Get ControlLook\n", Signature()));
714
715 if (fDesktop->LockSingleWindow()) {
716 DesktopSettings settings(fDesktop);
717
718 fLink.StartMessage(B_OK);
719 fLink.AttachString(settings.ControlLook().String());
720 fDesktop->UnlockSingleWindow();
721 } else
722 fLink.StartMessage(B_ERROR);
723
724 fLink.Flush();
725 break;
726 }
727
728 case AS_CREATE_BITMAP:
729 {
730 STRACE(("ServerApp %s: Received BBitmap creation request\n",
731 Signature()));
732
733 // Allocate a bitmap for an application
734
735 // Attached Data:
736 // 1) BRect bounds
737 // 2) color_space space
738 // 3) int32 bitmap_flags
739 // 4) int32 bytes_per_row
740 // 5) int32 screen_id
741
742 // Reply Data:
743 // 1) int32 server token
744 // 2) area_id id of the area in which the bitmap data resides
745 // 3) int32 area pointer offset used to calculate fBasePtr
746
747 // First, let's attempt to allocate the bitmap
748 BReference<ServerBitmap> bitmap;
749 uint8 allocationFlags = kAllocator;
750
751 BRect frame;
752 color_space colorSpace;
753 uint32 flags;
754 int32 bytesPerRow;
755 int32 screenID;
756
757 link.Read<BRect>(&frame);
758 link.Read<color_space>(&colorSpace);
759 link.Read<uint32>(&flags);
760 link.Read<int32>(&bytesPerRow);
761 if (link.Read<int32>(&screenID) == B_OK) {
762 // TODO: choose the right HWInterface with regards to the
763 // screenID
764 bitmap.SetTo(gBitmapManager->CreateBitmap(fMemoryAllocator,
765 *fDesktop->HWInterface(), frame, colorSpace, flags,
766 bytesPerRow, screenID, &allocationFlags), true);
767 }
768
769 STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n",
770 Signature(), frame.Width() + 1, frame.Height() + 1));
771
772 if (bitmap != NULL && _AddBitmap(bitmap)) {
773 fLink.StartMessage(B_OK);
774 fLink.Attach<int32>(bitmap->Token());
775 fLink.Attach<uint8>(allocationFlags);
776
777 fLink.Attach<area_id>(bitmap->Area());
778 fLink.Attach<int32>(bitmap->AreaOffset());
779
780 if ((allocationFlags & kFramebuffer) != 0)
781 fLink.Attach<int32>(bitmap->BytesPerRow());
782 } else {
783 fLink.StartMessage(B_NO_MEMORY);
784 }
785
786 fLink.Flush();
787 break;
788 }
789
790 case AS_DELETE_BITMAP:
791 {
792 STRACE(("ServerApp %s: received BBitmap delete request\n",
793 Signature()));
794
795 // Attached Data:
796 // 1) int32 token
797 int32 token;
798 link.Read<int32>(&token);
799
800 fMapLocker.Lock();
801
802 ServerBitmap* bitmap = _FindBitmap(token);
803 if (bitmap != NULL) {
804 STRACE(("ServerApp %s: Deleting Bitmap %" B_PRId32 "\n",
805 Signature(), token));
806
807 _DeleteBitmap(bitmap);
808 }
809
810 fMapLocker.Unlock();
811 break;
812 }
813
814 case AS_GET_BITMAP_OVERLAY_RESTRICTIONS:
815 {
816 overlay_restrictions restrictions;
817 status_t status = B_ERROR;
818
819 int32 token;
820 if (link.Read<int32>(&token) != B_OK)
821 break;
822
823 BReference<ServerBitmap> bitmap(GetBitmap(token), true);
824 if (bitmap != NULL) {
825 STRACE(("ServerApp %s: Get overlay restrictions for bitmap "
826 "%" B_PRId32 "\n", Signature(), token));
827
828 status = fDesktop->HWInterface()->GetOverlayRestrictions(
829 bitmap->Overlay(), &restrictions);
830 }
831
832 fLink.StartMessage(status);
833 if (status == B_OK)
834 fLink.Attach(&restrictions, sizeof(overlay_restrictions));
835
836 fLink.Flush();
837 break;
838 }
839
840 case AS_GET_BITMAP_SUPPORT_FLAGS:
841 {
842 uint32 colorSpace;
843 if (link.Read<uint32>(&colorSpace) != B_OK)
844 break;
845
846 bool overlay = fDesktop->HWInterface()->CheckOverlayRestrictions(
847 64, 64, (color_space)colorSpace);
848 uint32 flags = overlay ? B_BITMAPS_SUPPORT_OVERLAY : 0;
849
850 fLink.StartMessage(B_OK);
851 fLink.Attach<int32>(flags);
852 fLink.Flush();
853 break;
854 }
855
856 case AS_RECONNECT_BITMAP:
857 {
858 // First, let's attempt to allocate the bitmap
859 BReference<ServerBitmap> bitmap;
860
861 BRect frame;
862 color_space colorSpace;
863 uint32 flags;
864 int32 bytesPerRow;
865 int32 screenID;
866 area_id clientArea;
867 int32 areaOffset;
868
869 link.Read<BRect>(&frame);
870 link.Read<color_space>(&colorSpace);
871 link.Read<uint32>(&flags);
872 link.Read<int32>(&bytesPerRow);
873 link.Read<int32>(&screenID);
874 link.Read<int32>(&clientArea);
875 if (link.Read<int32>(&areaOffset) == B_OK) {
876 // TODO: choose the right HWInterface with regards to the
877 // screenID
878 bitmap.SetTo(gBitmapManager->CloneFromClient(clientArea, areaOffset,
879 frame, colorSpace, flags, bytesPerRow), true);
880 }
881
882 if (bitmap != NULL && _AddBitmap(bitmap)) {
883 fLink.StartMessage(B_OK);
884 fLink.Attach<int32>(bitmap->Token());
885
886 fLink.Attach<area_id>(bitmap->Area());
887
888 } else {
889 fLink.StartMessage(B_NO_MEMORY);
890 }
891
892 fLink.Flush();
893 break;
894 }
895
896 // Picture ops
897
898 case AS_CREATE_PICTURE:
899 {
900 // TODO: Maybe rename this to AS_UPLOAD_PICTURE ?
901 STRACE(("ServerApp %s: Create Picture\n", Signature()));
902 status_t status = B_NO_MEMORY;
903
904 BReference<ServerPicture> picture(CreatePicture());
905 if (picture != NULL) {
906 int32 subPicturesCount = 0;
907 link.Read<int32>(&subPicturesCount);
908 for (int32 i = 0; i < subPicturesCount; i++) {
909 int32 token = -1;
910 link.Read<int32>(&token);
911
912 BAutolock _(fMapLocker);
913 if (ServerPicture* subPicture = _FindPicture(token))
914 picture->NestPicture(subPicture);
915 }
916 status = picture->ImportData(link);
917 }
918 if (status == B_OK) {
919 fLink.StartMessage(B_OK);
920 fLink.Attach<int32>(picture->Token());
921 } else
922 fLink.StartMessage(status);
923
924 fLink.Flush();
925 break;
926 }
927
928 case AS_DELETE_PICTURE:
929 {
930 STRACE(("ServerApp %s: Delete Picture\n", Signature()));
931 int32 token;
932 if (link.Read<int32>(&token) == B_OK) {
933 BAutolock _(fMapLocker);
934
935 ServerPicture* picture = _FindPicture(token);
936 if (picture != NULL)
937 picture->SetOwner(NULL);
938 }
939 break;
940 }
941
942 case AS_CLONE_PICTURE:
943 {
944 STRACE(("ServerApp %s: Clone Picture\n", Signature()));
945 int32 token;
946 BReference<ServerPicture> original;
947 if (link.Read<int32>(&token) == B_OK)
948 original.SetTo(GetPicture(token), true);
949
950 if (original != NULL) {
951 BReference<ServerPicture> cloned(CreatePicture(original), true);
952 if (cloned != NULL) {
953 fLink.StartMessage(B_OK);
954 fLink.Attach<int32>(cloned->Token());
955 } else
956 fLink.StartMessage(B_NO_MEMORY);
957 } else
958 fLink.StartMessage(B_BAD_VALUE);
959
960 fLink.Flush();
961 break;
962 }
963
964 case AS_DOWNLOAD_PICTURE:
965 {
966 STRACE(("ServerApp %s: Download Picture\n", Signature()));
967 int32 token;
968 link.Read<int32>(&token);
969 BReference<ServerPicture> picture(GetPicture(token), true);
970 if (picture != NULL) {
971 picture->ExportData(fLink);
972 // ExportData() calls StartMessage() already
973 } else
974 fLink.StartMessage(B_ERROR);
975
976 fLink.Flush();
977 break;
978 }
979
980 case AS_CURRENT_WORKSPACE:
981 STRACE(("ServerApp %s: get current workspace\n", Signature()));
982
983 if (fDesktop->LockSingleWindow()) {
984 fLink.StartMessage(B_OK);
985 fLink.Attach<int32>(fDesktop->CurrentWorkspace());
986 fDesktop->UnlockSingleWindow();
987 } else
988 fLink.StartMessage(B_ERROR);
989
990 fLink.Flush();
991 break;
992
993 case AS_ACTIVATE_WORKSPACE:
994 {
995 STRACE(("ServerApp %s: activate workspace\n", Signature()));
996
997 // TODO: See above
998 int32 index;
999 link.Read<int32>(&index);
1000
1001 bool takeFocusWindowThere;
1002 link.Read<bool>(&takeFocusWindowThere);
1003
1004 fDesktop->SetWorkspace(index, takeFocusWindowThere);
1005 break;
1006 }
1007
1008 case AS_SET_WORKSPACE_LAYOUT:
1009 {
1010 int32 newColumns;
1011 int32 newRows;
1012 if (link.Read<int32>(&newColumns) == B_OK
1013 && link.Read<int32>(&newRows) == B_OK)
1014 fDesktop->SetWorkspacesLayout(newColumns, newRows);
1015 break;
1016 }
1017
1018 case AS_GET_WORKSPACE_LAYOUT:
1019 {
1020 if (fDesktop->LockSingleWindow()) {
1021 DesktopSettings settings(fDesktop);
1022
1023 fLink.StartMessage(B_OK);
1024 fLink.Attach<int32>(settings.WorkspacesColumns());
1025 fLink.Attach<int32>(settings.WorkspacesRows());
1026
1027 fDesktop->UnlockSingleWindow();
1028 } else
1029 fLink.StartMessage(B_ERROR);
1030
1031 fLink.Flush();
1032 break;
1033 }
1034
1035 case AS_IDLE_TIME:
1036 STRACE(("ServerApp %s: idle time\n", Signature()));
1037
1038 fLink.StartMessage(B_OK);
1039 fLink.Attach<bigtime_t>(fDesktop->EventDispatcher().IdleTime());
1040 fLink.Flush();
1041 break;
1042
1043 case AS_SHOW_CURSOR:
1044 {
1045 STRACE(("ServerApp %s: Show Cursor\n", Signature()));
1046 fCursorHideLevel--;
1047 if (fCursorHideLevel < 0)
1048 fCursorHideLevel = 0;
1049 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
1050 break;
1051 }
1052
1053 case AS_HIDE_CURSOR:
1054 {
1055 STRACE(("ServerApp %s: Hide Cursor\n", Signature()));
1056 fCursorHideLevel++;
1057 fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
1058 break;
1059 }
1060
1061 case AS_OBSCURE_CURSOR:
1062 {
1063 STRACE(("ServerApp %s: Obscure Cursor\n", Signature()));
1064 fDesktop->HWInterface()->ObscureCursor();
1065 break;
1066 }
1067
1068 case AS_QUERY_CURSOR_HIDDEN:
1069 {
1070 STRACE(("ServerApp %s: Received IsCursorHidden request\n",
1071 Signature()));
1072
1073 fLink.StartMessage(fCursorHideLevel > 0 ? B_OK : B_ERROR);
1074 fLink.Flush();
1075 break;
1076 }
1077
1078 case AS_SET_CURSOR:
1079 {
1080 STRACE(("ServerApp %s: SetCursor\n", Signature()));
1081
1082 // Attached data:
1083 // 1) bool flag to send a reply
1084 // 2) int32 token ID of the cursor to set
1085 // 3) port_id port to receive a reply. Only exists if the sync flag
1086 // is true.
1087 bool sync;
1088 int32 token;
1089
1090 link.Read<bool>(&sync);
1091 if (link.Read<int32>(&token) != B_OK)
1092 break;
1093
1094 if (!fDesktop->GetCursorManager().Lock())
1095 break;
1096
1097 fAppCursor.SetTo(fDesktop->GetCursorManager().FindCursor(token), false);
1098
1099 if (_HasWindowUnderMouse())
1100 fDesktop->SetCursor(CurrentCursor());
1101
1102 fDesktop->GetCursorManager().Unlock();
1103
1104 if (sync) {
1105 // The application is expecting a reply
1106 fLink.StartMessage(B_OK);
1107 fLink.Flush();
1108 }
1109 break;
1110 }
1111
1112 case AS_SET_VIEW_CURSOR:
1113 {
1114 STRACE(("ServerApp %s: AS_SET_VIEW_CURSOR:\n", Signature()));
1115
1116 ViewSetViewCursorInfo info;
1117 if (link.Read<ViewSetViewCursorInfo>(&info) != B_OK)
1118 break;
1119
1120 if (fDesktop->GetCursorManager().Lock()) {
1121 BReference<ServerCursor> cursor(fDesktop->GetCursorManager().FindCursor(
1122 info.cursorToken), false);
1123
1124 fDesktop->GetCursorManager().Unlock();
1125
1126 // We need to acquire the write lock here, since we cannot
1127 // afford that the window thread to which the view belongs
1128 // is running and messing with that same view.
1129 fDesktop->LockAllWindows();
1130
1131 // Find the corresponding view by the given token. It's ok
1132 // if this view does not exist anymore, since it may have
1133 // already be deleted in the window thread before this
1134 // message got here.
1135 View* view;
1136 if (fViewTokens.GetToken(info.viewToken, B_HANDLER_TOKEN,
1137 (void**)&view) == B_OK) {
1138 // Set the cursor on the view.
1139 view->SetCursor(cursor);
1140
1141 // The cursor might need to be updated now.
1142 Window* window = view->Window();
1143 if (window != NULL && window->IsFocus()) {
1144 if (fDesktop->ViewUnderMouse(window) == view->Token())
1145 SetCurrentCursor(cursor);
1146 }
1147 }
1148
1149 fDesktop->UnlockAllWindows();
1150 }
1151
1152 if (info.sync) {
1153 // sync the client (it can now delete the cursor)
1154 fLink.StartMessage(B_OK);
1155 fLink.Flush();
1156 }
1157 break;
1158 }
1159
1160 case AS_CREATE_CURSOR:
1161 {
1162 STRACE(("ServerApp %s: Create Cursor\n", Signature()));
1163
1164 // Attached data:
1165 // 1) 68 bytes of fAppCursor data
1166 // 2) port_id reply port
1167
1168 status_t status = B_ERROR;
1169 uint8 cursorData[68];
1170 ServerCursor* cursor = NULL;
1171
1172 // if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
1173 // cursor = new (nothrow) ServerCursor(cursorData);
1174 // if (cursor == NULL)
1175 // status = B_NO_MEMORY;
1176 // }
1177 //
1178 // if (cursor != NULL) {
1179 // cursor->SetOwningTeam(fClientTeam);
1180 // fDesktop->GetCursorManager().AddCursor(cursor);
1181 //
1182 // // Synchronous message - BApplication is waiting on the cursor's ID
1183 // fLink.StartMessage(B_OK);
1184 // fLink.Attach<int32>(cursor->Token());
1185 // } else
1186 // fLink.StartMessage(status);
1187
1188 if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
1189 cursor = fDesktop->GetCursorManager().CreateCursor(fClientTeam,
1190 cursorData);
1191 if (cursor == NULL)
1192 status = B_NO_MEMORY;
1193 }
1194
1195 if (cursor != NULL) {
1196 // Synchronous message - BApplication is waiting on the
1197 // cursor's ID
1198 fLink.StartMessage(B_OK);
1199 fLink.Attach<int32>(cursor->Token());
1200 } else
1201 fLink.StartMessage(status);
1202
1203 fLink.Flush();
1204 break;
1205 }
1206
1207 case AS_CREATE_CURSOR_BITMAP:
1208 {
1209 STRACE(("ServerApp %s: Create Cursor bitmap\n", Signature()));
1210
1211 status_t status = B_ERROR;
1212
1213 int32 size = 0, bytesPerRow = 0;
1214 BRect cursorRect;
1215 color_space colorspace = B_RGBA32;
1216 BPoint hotspot;
1217 ServerCursor* cursor = NULL;
1218
1219 if (link.Read<BRect>(&cursorRect) == B_OK
1220 && link.Read<BPoint>(&hotspot) == B_OK
1221 && link.Read<color_space>(&colorspace) == B_OK
1222 && link.Read<int32>(&bytesPerRow) == B_OK
1223 && link.Read<int32>(&size) == B_OK
1224 && size > 0) {
1225
1226 BStackOrHeapArray<uint8, 256> byteArray(size);
1227 if (!byteArray.IsValid()) {
1228 status = B_NO_MEMORY;
1229 } else if (link.Read(byteArray, size) == B_OK) {
1230 cursor = fDesktop->GetCursorManager().CreateCursor(
1231 fClientTeam, cursorRect, colorspace, 0, hotspot);
1232 if (cursor == NULL)
1233 status = B_NO_MEMORY;
1234 else
1235 cursor->ImportBits(byteArray, size, bytesPerRow, colorspace);
1236 }
1237 }
1238
1239 if (cursor != NULL) {
1240 // Synchronous message - BApplication is waiting on the
1241 // cursor's ID
1242 fLink.StartMessage(B_OK);
1243 fLink.Attach<int32>(cursor->Token());
1244 } else
1245 fLink.StartMessage(status);
1246
1247 fLink.Flush();
1248 break;
1249 }
1250
1251 case AS_CLONE_CURSOR:
1252 {
1253 STRACE(("ServerApp %s: Reference BCursor\n", Signature()));
1254
1255 // Attached data:
1256 // 1) int32 token ID of the cursor to clone
1257
1258 int32 token;
1259 if (link.Read<int32>(&token) != B_OK)
1260 break;
1261
1262 status_t status = B_ERROR;
1263 ServerCursor* cursor = NULL;
1264
1265 if (fDesktop->GetCursorManager().Lock()) {
1266 ServerCursor* existingCursor
1267 = fDesktop->GetCursorManager().FindCursor(token);
1268 if (existingCursor != NULL)
1269 cursor = new(std::nothrow) ServerCursor(existingCursor);
1270 if (cursor != NULL) {
1271 cursor->SetOwningTeam(fClientTeam);
1272 token = fDesktop->GetCursorManager().AddCursor(cursor);
1273 if (token < 0) {
1274 delete cursor;
1275 cursor = NULL;
1276 }
1277 }
1278
1279 fDesktop->GetCursorManager().Unlock();
1280 }
1281
1282 if (cursor != NULL) {
1283 // Synchronous message - BApplication is waiting on the
1284 // cursor's ID
1285 fLink.StartMessage(B_OK);
1286 fLink.Attach<int32>(cursor->Token());
1287 } else
1288 fLink.StartMessage(status);
1289
1290 fLink.Flush();
1291 break;
1292 }
1293
1294 case AS_DELETE_CURSOR:
1295 {
1296 STRACE(("ServerApp %s: Delete BCursor\n", Signature()));
1297
1298 // Attached data:
1299 // 1) int32 token ID of the cursor to delete
1300
1301 int32 token;
1302 if (link.Read<int32>(&token) != B_OK)
1303 break;
1304
1305 if (!fDesktop->GetCursorManager().Lock())
1306 break;
1307
1308 ServerCursor* cursor
1309 = fDesktop->GetCursorManager().FindCursor(token);
1310 if (cursor != NULL && cursor->OwningTeam() == fClientTeam)
1311 fDesktop->GetCursorManager().RemoveCursor(cursor);
1312
1313 fDesktop->GetCursorManager().Unlock();
1314
1315 break;
1316 }
1317
1318 case AS_GET_CURSOR_POSITION:
1319 {
1320 STRACE(("ServerApp %s: Get Cursor position\n", Signature()));
1321
1322 // Returns
1323 // 1) BPoint mouse location
1324 // 2) int32 button state
1325
1326 BPoint where;
1327 int32 buttons;
1328 fDesktop->GetLastMouseState(&where, &buttons);
1329 fLink.StartMessage(B_OK);
1330 fLink.Attach<BPoint>(where);
1331 fLink.Attach<int32>(buttons);
1332 fLink.Flush();
1333 break;
1334 }
1335
1336 case AS_GET_CURSOR_BITMAP:
1337 {
1338 STRACE(("ServerApp %s: Get Cursor bitmap\n", Signature()));
1339
1340 // Returns
1341 // 1) uint32 number of data bytes of the bitmap
1342 // 2) uint32 cursor width in number of pixels
1343 // 3) uint32 cursor height in number of pixels
1344 // 4) BPoint cursor hot spot
1345 // 5) cursor bitmap data
1346
1347 ServerCursorReference cursorRef = fDesktop->Cursor();
1348 ServerCursor* cursor = cursorRef.Get();
1349 if (cursor != NULL) {
1350 uint32 size = cursor->BitsLength();
1351 fLink.StartMessage(B_OK);
1352 fLink.Attach<uint32>(size);
1353 fLink.Attach<uint32>(cursor->Width());
1354 fLink.Attach<uint32>(cursor->Height());
1355 fLink.Attach<color_space>(cursor->ColorSpace());
1356 fLink.Attach<BPoint>(cursor->GetHotSpot());
1357 fLink.Attach(cursor->Bits(), size);
1358 } else
1359 fLink.StartMessage(B_ERROR);
1360
1361 fLink.Flush();
1362
1363 break;
1364 }
1365
1366 case AS_GET_SCROLLBAR_INFO:
1367 {
1368 STRACE(("ServerApp %s: Get ScrollBar info\n", Signature()));
1369
1370 if (fDesktop->LockSingleWindow()) {
1371 scroll_bar_info info;
1372 DesktopSettings settings(fDesktop);
1373 settings.GetScrollBarInfo(info);
1374
1375 fLink.StartMessage(B_OK);
1376 fLink.Attach<scroll_bar_info>(info);
1377 fDesktop->UnlockSingleWindow();
1378 } else
1379 fLink.StartMessage(B_ERROR);
1380
1381 fLink.Flush();
1382 break;
1383 }
1384
1385 case AS_SET_SCROLLBAR_INFO:
1386 {
1387 STRACE(("ServerApp %s: Set ScrollBar info\n", Signature()));
1388
1389 // Attached Data:
1390 // 1) scroll_bar_info scroll bar info structure
1391
1392 scroll_bar_info info;
1393 if (link.Read<scroll_bar_info>(&info) == B_OK) {
1394 LockedDesktopSettings settings(fDesktop);
1395 settings.SetScrollBarInfo(info);
1396 }
1397
1398 fLink.StartMessage(B_OK);
1399 fLink.Flush();
1400 break;
1401 }
1402
1403 case AS_GET_MENU_INFO:
1404 {
1405 STRACE(("ServerApp %s: Get menu info\n", Signature()));
1406 if (fDesktop->LockSingleWindow()) {
1407 menu_info info;
1408 DesktopSettings settings(fDesktop);
1409 settings.GetMenuInfo(info);
1410
1411 fLink.StartMessage(B_OK);
1412 fLink.Attach<menu_info>(info);
1413
1414 fDesktop->UnlockSingleWindow();
1415 } else
1416 fLink.StartMessage(B_ERROR);
1417
1418 fLink.Flush();
1419 break;
1420 }
1421
1422 case AS_SET_MENU_INFO:
1423 {
1424 STRACE(("ServerApp %s: Set menu info\n", Signature()));
1425 menu_info info;
1426 if (link.Read<menu_info>(&info) == B_OK) {
1427 LockedDesktopSettings settings(fDesktop);
1428 settings.SetMenuInfo(info);
1429 // TODO: SetMenuInfo() should do some validity check, so
1430 // that the answer we're giving can actually be useful
1431 }
1432
1433 fLink.StartMessage(B_OK);
1434 fLink.Flush();
1435 break;
1436 }
1437
1438 case AS_SET_MOUSE_MODE:
1439 {
1440 STRACE(("ServerApp %s: Set Mouse Focus mode\n",
1441 Signature()));
1442
1443 // Attached Data:
1444 // 1) enum mode_mouse mouse focus mode
1445
1446 mode_mouse mouseMode;
1447 if (link.Read<mode_mouse>(&mouseMode) == B_OK) {
1448 LockedDesktopSettings settings(fDesktop);
1449 settings.SetMouseMode(mouseMode);
1450 }
1451 break;
1452 }
1453
1454 case AS_GET_MOUSE_MODE:
1455 {
1456 STRACE(("ServerApp %s: Get Mouse Focus mode\n",
1457 Signature()));
1458
1459 if (fDesktop->LockSingleWindow()) {
1460 DesktopSettings settings(fDesktop);
1461
1462 fLink.StartMessage(B_OK);
1463 fLink.Attach<mode_mouse>(settings.MouseMode());
1464
1465 fDesktop->UnlockSingleWindow();
1466 } else
1467 fLink.StartMessage(B_ERROR);
1468
1469 fLink.Flush();
1470 break;
1471 }
1472
1473 case AS_SET_FOCUS_FOLLOWS_MOUSE_MODE:
1474 {
1475 STRACE(("ServerApp %s: Set Focus Follows Mouse mode\n", Signature()));
1476
1477 // Attached Data:
1478 // 1) enum mode_focus_follows_mouse FFM mouse mode
1479
1480 mode_focus_follows_mouse focusFollowsMousMode;
1481 if (link.Read<mode_focus_follows_mouse>(&focusFollowsMousMode) == B_OK) {
1482 LockedDesktopSettings settings(fDesktop);
1483 settings.SetFocusFollowsMouseMode(focusFollowsMousMode);
1484 }
1485 break;
1486 }
1487
1488 case AS_GET_FOCUS_FOLLOWS_MOUSE_MODE:
1489 {
1490 STRACE(("ServerApp %s: Get Focus Follows Mouse mode\n", Signature()));
1491
1492 if (fDesktop->LockSingleWindow()) {
1493 DesktopSettings settings(fDesktop);
1494
1495 fLink.StartMessage(B_OK);
1496 fLink.Attach<mode_focus_follows_mouse>(
1497 settings.FocusFollowsMouseMode());
1498
1499 fDesktop->UnlockSingleWindow();
1500 } else
1501 fLink.StartMessage(B_ERROR);
1502
1503 fLink.Flush();
1504 break;
1505 }
1506
1507 case AS_SET_ACCEPT_FIRST_CLICK:
1508 {
1509 STRACE(("ServerApp %s: Set Accept First Click\n", Signature()));
1510
1511 // Attached Data:
1512 // 1) bool accept_first_click
1513
1514 bool acceptFirstClick;
1515 if (link.Read<bool>(&acceptFirstClick) == B_OK) {
1516 LockedDesktopSettings settings(fDesktop);
1517 settings.SetAcceptFirstClick(acceptFirstClick);
1518 }
1519 break;
1520 }
1521
1522 case AS_GET_ACCEPT_FIRST_CLICK:
1523 {
1524 STRACE(("ServerApp %s: Get Accept First Click\n", Signature()));
1525
1526 if (fDesktop->LockSingleWindow()) {
1527 DesktopSettings settings(fDesktop);
1528
1529 fLink.StartMessage(B_OK);
1530 fLink.Attach<bool>(settings.AcceptFirstClick());
1531
1532 fDesktop->UnlockSingleWindow();
1533 } else
1534 fLink.StartMessage(B_ERROR);
1535
1536 fLink.Flush();
1537 break;
1538 }
1539
1540 case AS_GET_SHOW_ALL_DRAGGERS:
1541 {
1542 STRACE(("ServerApp %s: Get Show All Draggers\n", Signature()));
1543
1544 if (fDesktop->LockSingleWindow()) {
1545 DesktopSettings settings(fDesktop);
1546
1547 fLink.StartMessage(B_OK);
1548 fLink.Attach<bool>(settings.ShowAllDraggers());
1549
1550 fDesktop->UnlockSingleWindow();
1551 } else
1552 fLink.StartMessage(B_ERROR);
1553
1554 fLink.Flush();
1555 break;
1556 }
1557
1558 case AS_SET_SHOW_ALL_DRAGGERS:
1559 {
1560 STRACE(("ServerApp %s: Set Show All Draggers\n", Signature()));
1561
1562 bool changed = false;
1563 bool show;
1564 if (link.Read<bool>(&show) == B_OK) {
1565 LockedDesktopSettings settings(fDesktop);
1566 if (show != settings.ShowAllDraggers()) {
1567 settings.SetShowAllDraggers(show);
1568 changed = true;
1569 }
1570 }
1571
1572 if (changed)
1573 fDesktop->BroadcastToAllApps(kMsgUpdateShowAllDraggers);
1574 break;
1575 }
1576
1577 case kMsgUpdateShowAllDraggers:
1578 {
1579 bool show = false;
1580 if (fDesktop->LockSingleWindow()) {
1581 DesktopSettings settings(fDesktop);
1582 show = settings.ShowAllDraggers();
1583 fDesktop->UnlockSingleWindow();
1584 }
1585 BMessage update(_SHOW_DRAG_HANDLES_);
1586 update.AddBool("show", show);
1587
1588 SendMessageToClient(&update);
1589 break;
1590 }
1591
1592 /* font messages */
1593
1594 case AS_ADD_FONT_FILE:
1595 {
1596 FTRACE(("ServerApp %s: Received BFont creation request\n",
1597 Signature()));
1598
1599 // Add a font for an application from a file
1600
1601 // Attached Data:
1602 // 1) char* - path to font on disk
1603 // 2) uint16 - index in font file
1604 // 3) uint16 - instance
1605
1606 // Returns:
1607 // 1) uint16 - family ID of added font
1608 // 2) uint16 - style ID of added font
1609 // 3) uint16 - face of added font
1610
1611 AutoLocker< ::FontManager> fontLock(fAppFontManager);
1612
1613 if (fAppFontManager->CountFamilies() > MAX_USER_FONTS) {
1614 fLink.StartMessage(B_NOT_ALLOWED);
1615 fLink.Flush();
1616 break;
1617 }
1618
1619 uint16 familyID, styleID;
1620 char* fontPath;
1621 uint16 index, instance;
1622 link.ReadString(&fontPath);
1623 link.Read<uint16>(&index);
1624 link.Read<uint16>(&instance);
1625
1626 status_t status = fAppFontManager->AddUserFontFromFile(fontPath, index, instance,
1627 familyID, styleID);
1628
1629 if (status != B_OK) {
1630 fLink.StartMessage(status);
1631 } else {
1632 ServerFont font;
1633 status = font.SetFamilyAndStyle(familyID, styleID,
1634 fAppFontManager);
1635
1636 fLink.StartMessage(status);
1637 if (status == B_OK) {
1638 fLink.Attach<uint16>(font.FamilyID());
1639 fLink.Attach<uint16>(font.StyleID());
1640 fLink.Attach<uint16>(font.Face());
1641 }
1642 }
1643
1644 fLink.Flush();
1645 break;
1646 }
1647
1648 case AS_ADD_FONT_MEMORY:
1649 {
1650 FTRACE(("ServerApp %s: Received BFont memory creation request\n",
1651 Signature()));
1652
1653 // Add a font for an application from a memory area
1654
1655 // Attached Data:
1656 // 1) area_id - id of memory area where font resides
1657 // 2) size_t - size of memory area for font
1658 // 3) size_t - offset to start of font memory
1659 // 4) uint16 - index in font buffer
1660 // 5) uint16 - instance
1661
1662 // Returns:
1663 // 1) uint16 - family ID of added font
1664 // 2) uint16 - style ID of added font
1665 // 3) uint16 - face of added font
1666
1667 AutoLocker< ::FontManager> fontLock(fAppFontManager);
1668
1669 if (fAppFontManager->CountFamilies() > MAX_USER_FONTS) {
1670 fLink.StartMessage(B_NOT_ALLOWED);
1671 fLink.Flush();
1672 break;
1673 }
1674
1675 area_id fontAreaID, fontAreaCloneID;
1676 area_info fontAreaInfo;
1677 char* area_addr;
1678 size_t size, offset;
1679 uint16 index, instance;
1680
1681 link.Read<int32>(&fontAreaID);
1682 link.Read<size_t>(&size);
1683 link.Read<size_t>(&offset);
1684 link.Read<uint16>(&index);
1685 link.Read<uint16>(&instance);
1686 fontAreaCloneID = clone_area("user font",
1687 (void **)&area_addr,
1688 B_ANY_ADDRESS,
1689 B_READ_AREA,
1690 fontAreaID);
1691
1692 if (fontAreaCloneID < B_OK) {
1693 fLink.StartMessage(fontAreaCloneID);
1694 fLink.Flush();
1695 break;
1696 }
1697
1698 status_t status = get_area_info(fontAreaCloneID, &fontAreaInfo);
1699 if (status != B_OK) {
1700 fLink.StartMessage(status);
1701 fLink.Flush();
1702 delete_area(fontAreaCloneID);
1703 break;
1704 }
1705
1706 size_t fontMemorySize = fontAreaInfo.size - offset;
1707
1708 if (size == 0)
1709 size = fontMemorySize;
1710
1711 // Check size of font area and reject if it's too large
1712 if (size > MAX_FONT_DATA_SIZE_BYTES
1713 || size > fontMemorySize) {
1714 fLink.StartMessage(B_BAD_DATA);
1715 fLink.Flush();
1716 delete_area(fontAreaCloneID);
1717 break;
1718 }
1719
1720 FT_Byte* fontData = (FT_Byte*)(malloc (sizeof(FT_Byte) * size));
1721 if (fontData == NULL) {
1722 delete_area(fontAreaCloneID);
1723 fLink.StartMessage(B_BAD_DATA);
1724 fLink.Flush();
1725 break;
1726 }
1727
1728 memcpy(fontData, (FT_Byte*)fontAreaInfo.address + offset, size);
1729
1730 delete_area(fontAreaCloneID);
1731
1732 uint16 familyID, styleID;
1733
1734 status = fAppFontManager->AddUserFontFromMemory(fontData, size, index, instance,
1735 familyID, styleID);
1736
1737 if (status != B_OK) {
1738 fLink.StartMessage(status);
1739 free(fontData);
1740 } else {
1741 ServerFont font;
1742 status = font.SetFamilyAndStyle(familyID, styleID,
1743 fAppFontManager);
1744
1745 if (status == B_OK) {
1746 font.SetFontData(fontData, size);
1747 fLink.StartMessage(B_OK);
1748 fLink.Attach<uint16>(font.FamilyID());
1749 fLink.Attach<uint16>(font.StyleID());
1750 fLink.Attach<uint16>(font.Face());
1751 } else {
1752 fLink.StartMessage(status);
1753 free(fontData);
1754 }
1755 }
1756
1757 fLink.Flush();
1758 break;
1759 }
1760
1761 case AS_REMOVE_FONT:
1762 {
1763 STRACE(("ServerApp %s: Received BFont removal request\n",
1764 Signature()));
1765
1766 // Remove an application-added font
1767
1768 // Attached Data:
1769 // 1) uint16 - familyID of font to remove
1770 // 2) uint16 - styleID of font to remove
1771
1772 uint16 familyID, styleID;
1773 link.Read<uint16>(&familyID);
1774 link.Read<uint16>(&styleID);
1775
1776 status_t status = B_OK;
1777
1778 AutoLocker< ::FontManager> fontLock(fAppFontManager);
1779 status = fAppFontManager->RemoveUserFont(familyID, styleID);
1780
1781 fLink.StartMessage(status);
1782 fLink.Flush();
1783 break;
1784 }
1785
1786 case AS_SET_SYSTEM_FONT:
1787 {
1788 FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature()));
1789 // gets:
1790 // 1) string - font type ("plain", ...)
1791 // 2) string - family
1792 // 3) string - style
1793 // 4) float - size
1794
1795 char type[B_OS_NAME_LENGTH];
1796 font_family familyName;
1797 font_style styleName;
1798 float size;
1799
1800 if (link.ReadString(type, sizeof(type)) == B_OK
1801 && link.ReadString(familyName, sizeof(familyName)) == B_OK
1802 && link.ReadString(styleName, sizeof(styleName)) == B_OK
1803 && link.Read<float>(&size) == B_OK) {
1804 gFontManager->Lock();
1805
1806 FontStyle* style
1807 = gFontManager->GetStyle(familyName, styleName);
1808 if (style != NULL) {
1809 ServerFont font(*style, size);
1810 gFontManager->Unlock();
1811 // We must not have locked the font manager when
1812 // locking the desktop (through LockedDesktopSettings
1813 // below)
1814
1815 LockedDesktopSettings settings(fDesktop);
1816
1817 // TODO: Should we also update our internal copies now?
1818 if (strcmp(type, "plain") == 0)
1819 settings.SetDefaultPlainFont(font);
1820 else if (strcmp(type, "bold") == 0)
1821 settings.SetDefaultBoldFont(font);
1822 else if (strcmp(type, "fixed") == 0)
1823 settings.SetDefaultFixedFont(font);
1824 } else
1825 gFontManager->Unlock();
1826 }
1827 break;
1828 }
1829
1830 case AS_GET_SYSTEM_DEFAULT_FONT:
1831 {
1832 // input:
1833 // 1) string - font type ("plain", ...)
1834
1835 ServerFont font;
1836
1837 char type[B_OS_NAME_LENGTH];
1838 status_t status = link.ReadString(type, sizeof(type));
1839 if (status == B_OK) {
1840 if (strcmp(type, "plain") == 0)
1841 font = *gFontManager->DefaultPlainFont();
1842 else if (strcmp(type, "bold") == 0)
1843 font = *gFontManager->DefaultBoldFont();
1844 else if (strcmp(type, "fixed") == 0)
1845 font = *gFontManager->DefaultFixedFont();
1846 else
1847 status = B_BAD_VALUE;
1848 }
1849
1850 if (status == B_OK) {
1851 // returns:
1852 // 1) string - family
1853 // 2) string - style
1854 // 3) float - size
1855
1856 fLink.StartMessage(B_OK);
1857 fLink.AttachString(font.Family());
1858 fLink.AttachString(font.Style());
1859 fLink.Attach<float>(font.Size());
1860 } else
1861 fLink.StartMessage(status);
1862
1863 fLink.Flush();
1864 break;
1865 }
1866
1867 case AS_GET_SYSTEM_FONTS:
1868 {
1869 FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature()));
1870 // Returns:
1871 // 1) uint16 - family ID
1872 // 2) uint16 - style ID
1873 // 3) float - size in points
1874 // 4) uint16 - face flags
1875 // 5) uint32 - font flags
1876
1877 if (!fDesktop->LockSingleWindow()) {
1878 fLink.StartMessage(B_OK);
1879 fLink.Flush();
1880 break;
1881 }
1882
1883 // The client is requesting the system fonts, this
1884 // could have happened either at application start up,
1885 // or because the client is resyncing with the global
1886 // fonts. So we record the current system wide fonts
1887 // into our own copies at this point.
1888 DesktopSettings settings(fDesktop);
1889
1890 settings.GetDefaultPlainFont(fPlainFont);
1891 settings.GetDefaultBoldFont(fBoldFont);
1892 settings.GetDefaultFixedFont(fFixedFont);
1893
1894 fLink.StartMessage(B_OK);
1895
1896 for (int32 i = 0; i < 3; i++) {
1897 ServerFont* font = NULL;
1898 switch (i) {
1899 case 0:
1900 font = &fPlainFont;
1901 fLink.AttachString("plain");
1902 break;
1903
1904 case 1:
1905 font = &fBoldFont;
1906 fLink.AttachString("bold");
1907 break;
1908
1909 case 2:
1910 font = &fFixedFont;
1911 fLink.AttachString("fixed");
1912 break;
1913 }
1914
1915 fLink.Attach<uint16>(font->FamilyID());
1916 fLink.Attach<uint16>(font->StyleID());
1917 fLink.Attach<float>(font->Size());
1918 fLink.Attach<uint16>(font->Face());
1919 fLink.Attach<uint32>(font->Flags());
1920 }
1921
1922 fDesktop->UnlockSingleWindow();
1923 fLink.Flush();
1924 break;
1925 }
1926
1927 case AS_GET_FONT_LIST_REVISION:
1928 {
1929 FTRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature()));
1930
1931 fLink.StartMessage(B_OK);
1932 gFontManager->Lock();
1933 fLink.Attach<uint32>(gFontManager->Revision());
1934 // TODO: get value per fDesktop->UserID()
1935 gFontManager->Unlock();
1936 fLink.Flush();
1937 break;
1938 }
1939
1940 case AS_GET_FAMILY_AND_STYLES:
1941 {
1942 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature()));
1943
1944 // Attached Data:
1945 // 1) int32 the index of the font family to get
1946
1947 // Returns:
1948 // 1) string - name of family
1949 // 2) uint32 - flags of font family (B_IS_FIXED || B_HAS_TUNED_FONT)
1950 // 3) count of styles in that family
1951 // For each style:
1952 // 1) string - name of style
1953 // 2) uint16 - face of style
1954 // 3) uint32 - flags of style
1955
1956 int32 index;
1957 link.Read<int32>(&index);
1958
1959 AutoLocker< ::FontManager> fontLock(gFontManager);
1960
1961 FontFamily* family = gFontManager->FamilyAt(index);
1962 if (family == NULL) {
1963 fontLock.SetTo(fAppFontManager, false);
1964
1965 family = fAppFontManager->FamilyAt(index);
1966 }
1967
1968 if (family) {
1969 fLink.StartMessage(B_OK);
1970 fLink.AttachString(family->Name());
1971 fLink.Attach<uint32>(family->Flags());
1972
1973 int32 count = family->CountStyles();
1974
1975 fLink.Attach<int32>(count);
1976
1977 for (int32 i = 0; i < count; i++) {
1978 FontStyle* style = family->StyleAt(i);
1979
1980 fLink.AttachString(style->Name());
1981 fLink.Attach<uint16>(style->Face());
1982 fLink.Attach<uint32>(style->Flags());
1983 }
1984 } else
1985 fLink.StartMessage(B_BAD_VALUE);
1986
1987
1988 fLink.Flush();
1989 break;
1990 }
1991
1992 case AS_GET_FAMILY_AND_STYLE:
1993 {
1994 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE\n", Signature()));
1995
1996 // Attached Data:
1997 // 1) uint16 - family ID
1998 // 2) uint16 - style ID
1999
2000 // Returns:
2001 // 1) font_family The name of the font family
2002 // 2) font_style - name of the style
2003
2004 uint16 familyID, styleID;
2005 link.Read<uint16>(&familyID);
2006 link.Read<uint16>(&styleID);
2007
2008 AutoLocker< ::FontManager> fontLock(gFontManager);
2009
2010 FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
2011 if (fontStyle == NULL) {
2012 fontLock.SetTo(fAppFontManager, false);
2013
2014 fontStyle = fAppFontManager->GetStyle(familyID, styleID);
2015 }
2016
2017 if (fontStyle != NULL) {
2018 fLink.StartMessage(B_OK);
2019 fLink.AttachString(fontStyle->Family()->Name());
2020 fLink.AttachString(fontStyle->Name());
2021 } else
2022 fLink.StartMessage(B_BAD_VALUE);
2023
2024 fLink.Flush();
2025
2026 break;
2027 }
2028
2029 case AS_GET_FAMILY_AND_STYLE_IDS:
2030 {
2031 FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE_IDS\n",
2032 Signature()));
2033
2034 // Attached Data:
2035 // 1) font_family - name of font family to use
2036 // 2) font_style - name of style in family
2037 // 3) family ID - only used if 1) is empty
2038 // 4) style ID - only used if 1) and 2) are empty
2039 // 5) face - the font's current face
2040
2041 // Returns:
2042 // 1) uint16 - family ID
2043 // 2) uint16 - style ID
2044 // 3) uint16 - face
2045
2046 font_family family;
2047 font_style style;
2048 uint16 familyID, styleID;
2049 uint16 face;
2050 if (link.ReadString(family, sizeof(font_family)) == B_OK
2051 && link.ReadString(style, sizeof(font_style)) == B_OK
2052 && link.Read<uint16>(&familyID) == B_OK
2053 && link.Read<uint16>(&styleID) == B_OK
2054 && link.Read<uint16>(&face) == B_OK) {
2055 // get the font and return IDs and face
2056 AutoLocker< ::FontManager> fontLock(gFontManager);
2057
2058 FontStyle* fontStyle = gFontManager->GetStyle(family, style,
2059 familyID, styleID, face);
2060 if (fontStyle == NULL) {
2061 fontLock.SetTo(fAppFontManager, false);
2062
2063 fontStyle = fAppFontManager->GetStyle(family, style,
2064 familyID, styleID, face);
2065 }
2066
2067 if (fontStyle != NULL) {
2068 fLink.StartMessage(B_OK);
2069 fLink.Attach<uint16>(fontStyle->Family()->ID());
2070 fLink.Attach<uint16>(fontStyle->ID());
2071
2072 // we try to keep the font face close to what we got
2073 face = fontStyle->PreservedFace(face);
2074
2075 fLink.Attach<uint16>(face);
2076 } else
2077 fLink.StartMessage(B_NAME_NOT_FOUND);
2078 } else
2079 fLink.StartMessage(B_BAD_VALUE);
2080
2081 fLink.Flush();
2082 break;
2083 }
2084
2085 case AS_GET_FONT_FILE_FORMAT:
2086 {
2087 FTRACE(("ServerApp %s: AS_GET_FONT_FILE_FORMAT\n", Signature()));
2088
2089 // Attached Data:
2090 // 1) uint16 - family ID
2091 // 2) uint16 - style ID
2092
2093 // Returns:
2094 // 1) uint16 font_file_format of font
2095
2096 int32 familyID, styleID;
2097 link.Read<int32>(&familyID);
2098 link.Read<int32>(&styleID);
2099
2100 AutoLocker< ::FontManager> fontLock(gFontManager);
2101
2102 FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
2103 if (fontStyle == NULL) {
2104 fontLock.SetTo(fAppFontManager, false);
2105
2106 fontStyle = fAppFontManager->GetStyle(familyID, styleID);
2107 }
2108
2109 if (fontStyle != NULL) {
2110 fLink.StartMessage(B_OK);
2111 fLink.Attach<uint16>((uint16)fontStyle->FileFormat());
2112 } else
2113 fLink.StartMessage(B_BAD_VALUE);
2114
2115 fLink.Flush();
2116 break;
2117 }
2118
2119 case AS_GET_STRING_WIDTHS:
2120 {
2121 FTRACE(("ServerApp %s: AS_GET_STRING_WIDTHS\n", Signature()));
2122
2123 // Attached Data:
2124 // 1) uint16 ID of family
2125 // 2) uint16 ID of style
2126 // 3) float point size of font
2127 // 4) uint8 spacing to use
2128 // 5) int32 numStrings
2129 // 6) int32 string length to measure (numStrings times)
2130 // 7) string String to measure (numStrings times)
2131
2132 // Returns:
2133 // 1) float - width of the string in pixels (numStrings times)
2134
2135 uint16 familyID, styleID;
2136 float size;
2137 uint8 spacing;
2138
2139 link.Read<uint16>(&familyID);
2140 link.Read<uint16>(&styleID);
2141 link.Read<float>(&size);
2142 link.Read<uint8>(&spacing);
2143 int32 numStrings;
2144 if (link.Read<int32>(&numStrings) != B_OK) {
2145 // this results in a B_BAD_VALUE return
2146 numStrings = 0;
2147 size = 0.0f;
2148 }
2149
2150 BStackOrHeapArray<float, 64> widthArray(numStrings);
2151 BStackOrHeapArray<int32, 64> lengthArray(numStrings);
2152 BStackOrHeapArray<char*, 64> stringArray(numStrings);
2153 if (!widthArray.IsValid() || !lengthArray.IsValid()
2154 || !stringArray.IsValid()) {
2155 fLink.StartMessage(B_NO_MEMORY);
2156 fLink.Flush();
2157 break;
2158 }
2159
2160 for (int32 i = 0; i < numStrings; i++) {
2161 // This version of ReadString allocates the strings, we free
2162 // them below
2163 link.ReadString(&stringArray[i], (size_t *)&lengthArray[i]);
2164 }
2165
2166 ServerFont font;
2167
2168 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2169 fAppFontManager);
2170
2171 if (status == B_OK && size > 0) {
2172 font.SetSize(size);
2173 font.SetSpacing(spacing);
2174
2175 for (int32 i = 0; i < numStrings; i++) {
2176 if (!stringArray[i] || lengthArray[i] <= 0)
2177 widthArray[i] = 0.0;
2178 else {
2179 widthArray[i] = font.StringWidth(stringArray[i],
2180 lengthArray[i]);
2181 }
2182 }
2183
2184 fLink.StartMessage(B_OK);
2185 fLink.Attach(widthArray, numStrings * sizeof(float));
2186 } else
2187 fLink.StartMessage(B_BAD_VALUE);
2188
2189 fLink.Flush();
2190
2191 for (int32 i = 0; i < numStrings; i++)
2192 free(stringArray[i]);
2193 break;
2194 }
2195
2196 case AS_GET_FONT_BOUNDING_BOX:
2197 {
2198 FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX\n",
2199 Signature()));
2200
2201 // Attached Data:
2202 // 1) uint16 - family ID
2203 // 2) uint16 - style ID
2204 // 3) float - font size
2205
2206 // Returns:
2207 // 1) BRect - box holding entire font
2208
2209 uint16 familyID, styleID;
2210 float size;
2211
2212 link.Read<uint16>(&familyID);
2213 link.Read<uint16>(&styleID);
2214 link.Read<float>(&size);
2215
2216 ServerFont font;
2217
2218 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2219 fAppFontManager);
2220
2221 if (status == B_OK && size > 0) {
2222 font.SetSize(size);
2223
2224 fLink.StartMessage(B_OK);
2225 fLink.Attach<BRect>(font.BoundingBox());
2226 } else
2227 fLink.StartMessage(B_BAD_VALUE);
2228
2229 fLink.Flush();
2230 break;
2231 }
2232
2233 case AS_GET_TUNED_COUNT:
2234 {
2235 FTRACE(("ServerApp %s: AS_GET_TUNED_COUNT\n", Signature()));
2236
2237 // Attached Data:
2238 // 1) uint16 - family ID
2239 // 2) uint16 - style ID
2240
2241 // Returns:
2242 // 1) int32 - number of font strikes available
2243
2244 uint16 familyID, styleID;
2245 link.Read<uint16>(&familyID);
2246 link.Read<uint16>(&styleID);
2247
2248 AutoLocker< ::FontManager> fontLock(gFontManager);
2249
2250 FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
2251 if (fontStyle == NULL) {
2252 fontLock.SetTo(fAppFontManager, false);
2253
2254 fontStyle = fAppFontManager->GetStyle(familyID, styleID);
2255 }
2256
2257 if (fontStyle != NULL) {
2258 fLink.StartMessage(B_OK);
2259 fLink.Attach<int32>(fontStyle->TunedCount());
2260 } else
2261 fLink.StartMessage(B_BAD_VALUE);
2262
2263 fLink.Flush();
2264 break;
2265 }
2266
2267 case AS_GET_TUNED_INFO:
2268 {
2269 FTRACE(("ServerApp %s: AS_GET_TUNED_INFO unimplmemented\n",
2270 Signature()));
2271
2272 // Attached Data:
2273 // 1) uint16 - family ID
2274 // 2) uint16 - style ID
2275 // 3) uint32 - index of the particular font strike
2276
2277 // Returns:
2278 // 1) tuned_font_info - info on the strike specified
2279 // ToDo: implement me!
2280
2281 fLink.StartMessage(B_ERROR);
2282 fLink.Flush();
2283 break;
2284 }
2285
2286 case AS_GET_EXTRA_FONT_FLAGS:
2287 {
2288 FTRACE(("ServerApp %s: AS_GET_EXTRA_FONT_FLAGS\n",
2289 Signature()));
2290
2291 // Attached Data:
2292 // 1) uint16 - family ID
2293 // 2) uint16 - style ID
2294
2295 // Returns:
2296 // 1) uint32 - extra font flags
2297
2298 uint16 familyID, styleID;
2299 link.Read<uint16>(&familyID);
2300 link.Read<uint16>(&styleID);
2301
2302 AutoLocker< ::FontManager> fontLock(gFontManager);
2303
2304 FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
2305 if (fontStyle == NULL) {
2306 fontLock.SetTo(fAppFontManager, false);
2307
2308 fontStyle = fAppFontManager->GetStyle(familyID, styleID);
2309 }
2310
2311 if (fontStyle != NULL) {
2312 fLink.StartMessage(B_OK);
2313 fLink.Attach<uint32>(fontStyle->Flags());
2314 } else
2315 fLink.StartMessage(B_BAD_VALUE);
2316
2317 fLink.Flush();
2318 break;
2319 }
2320
2321 case AS_GET_FONT_HEIGHT:
2322 {
2323 FTRACE(("ServerApp %s: AS_GET_FONT_HEIGHT\n", Signature()));
2324
2325 // Attached Data:
2326 // 1) uint16 family ID
2327 // 2) uint16 style ID
2328 // 3) float size
2329
2330 uint16 familyID, styleID;
2331 float size;
2332 link.Read<uint16>(&familyID);
2333 link.Read<uint16>(&styleID);
2334 link.Read<float>(&size);
2335
2336 AutoLocker< ::FontManager> fontLock(gFontManager);
2337
2338 FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
2339 if (fontStyle == NULL) {
2340 fontLock.SetTo(fAppFontManager, false);
2341
2342 fontStyle = fAppFontManager->GetStyle(familyID, styleID);
2343 }
2344
2345 if (fontStyle != NULL) {
2346 font_height height;
2347 fontStyle->GetHeight(size, height);
2348
2349 fLink.StartMessage(B_OK);
2350 fLink.Attach<font_height>(height);
2351 } else
2352 fLink.StartMessage(B_BAD_VALUE);
2353
2354 fLink.Flush();
2355 break;
2356 }
2357
2358 case AS_GET_UNICODE_BLOCKS:
2359 {
2360 FTRACE(("ServerApp %s: AS_GET_UNICODE_BLOCKS\n", Signature()));
2361
2362 // Attached Data:
2363 // 1) uint16 family ID
2364 // 2) uint16 style ID
2365
2366 // Returns:
2367 // 1) unicode_block - bitfield of Unicode blocks in font
2368
2369 uint16 familyID, styleID;
2370 link.Read<uint16>(&familyID);
2371 link.Read<uint16>(&styleID);
2372
2373 ServerFont font;
2374 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2375 fAppFontManager);
2376
2377 if (status == B_OK) {
2378 unicode_block blocksForFont;
2379 font.GetUnicodeBlocks(blocksForFont);
2380
2381 fLink.StartMessage(B_OK);
2382 fLink.Attach<unicode_block>(blocksForFont);
2383 } else
2384 fLink.StartMessage(status);
2385
2386 fLink.Flush();
2387 break;
2388 }
2389
2390 case AS_GET_HAS_UNICODE_BLOCK:
2391 {
2392 FTRACE(("ServerApp %s: AS_INCLUDES_UNICODE_BLOCK\n", Signature()));
2393
2394 // Attached Data:
2395 // 1) uint16 family ID
2396 // 2) uint16 style ID
2397 // 3) uint32 start of unicode block
2398 // 4) uint32 end of unicode block
2399
2400 // Returns:
2401 // 1) bool - whether or not font includes specified block range
2402
2403 uint16 familyID, styleID;
2404 uint32 start, end;
2405 link.Read<uint16>(&familyID);
2406 link.Read<uint16>(&styleID);
2407 link.Read<uint32>(&start);
2408 link.Read<uint32>(&end);
2409
2410 ServerFont font;
2411 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2412 fAppFontManager);
2413
2414 if (status == B_OK) {
2415 bool hasBlock;
2416
2417 status = font.IncludesUnicodeBlock(start, end, hasBlock);
2418 fLink.StartMessage(status);
2419 fLink.Attach<bool>(hasBlock);
2420 } else
2421 fLink.StartMessage(status);
2422
2423 fLink.Flush();
2424 break;
2425 }
2426
2427 case AS_GET_GLYPH_SHAPES:
2428 {
2429 FTRACE(("ServerApp %s: AS_GET_GLYPH_SHAPES\n", Signature()));
2430
2431 // Attached Data:
2432 // 1) uint16 - family ID
2433 // 2) uint16 - style ID
2434 // 3) float - point size
2435 // 4) float - shear
2436 // 5) float - rotation
2437 // 6) float - false bold width
2438 // 6) uint32 - flags
2439 // 7) int32 - numChars
2440 // 8) int32 - numBytes
2441 // 8) char - chars (numBytes times)
2442
2443 // Returns:
2444 // 1) BShape - glyph shape
2445 // numChars times
2446
2447 uint16 familyID, styleID;
2448 uint32 flags;
2449 float size, shear, rotation, falseBoldWidth;
2450
2451 link.Read<uint16>(&familyID);
2452 link.Read<uint16>(&styleID);
2453 link.Read<float>(&size);
2454 link.Read<float>(&shear);
2455 link.Read<float>(&rotation);
2456 link.Read<float>(&falseBoldWidth);
2457 link.Read<uint32>(&flags);
2458
2459 int32 numChars, numBytes;
2460 link.Read<int32>(&numChars);
2461 link.Read<int32>(&numBytes);
2462
2463 BStackOrHeapArray<char, 256> charArray(numBytes);
2464 BStackOrHeapArray<BShape*, 64> shapes(numChars);
2465 if (!charArray.IsValid() || !shapes.IsValid()) {
2466 fLink.StartMessage(B_NO_MEMORY);
2467 fLink.Flush();
2468 break;
2469 }
2470
2471 link.Read(charArray, numBytes);
2472
2473 ServerFont font;
2474 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2475 fAppFontManager);
2476
2477 if (status == B_OK) {
2478 font.SetSize(size);
2479 font.SetShear(shear);
2480 font.SetRotation(rotation);
2481 font.SetFalseBoldWidth(falseBoldWidth);
2482 font.SetFlags(flags);
2483
2484 status = font.GetGlyphShapes(charArray, numChars, shapes);
2485 if (status == B_OK) {
2486 fLink.StartMessage(B_OK);
2487 for (int32 i = 0; i < numChars; i++) {
2488 fLink.AttachShape(*shapes[i]);
2489 delete shapes[i];
2490 }
2491 }
2492 }
2493
2494 if (status != B_OK)
2495 fLink.StartMessage(status);
2496
2497 fLink.Flush();
2498 break;
2499 }
2500
2501 case AS_GET_HAS_GLYPHS:
2502 {
2503 FTRACE(("ServerApp %s: AS_GET_HAS_GLYPHS\n", Signature()));
2504
2505 // Attached Data:
2506 // 1) uint16 - family ID
2507 // 2) uint16 - style ID
2508 // 3) int32 - numChars
2509 // 4) int32 - numBytes
2510 // 5) char - the char buffer with size numBytes
2511 // 6) bool - whether to try fallback fonts
2512
2513 uint16 familyID, styleID;
2514 link.Read<uint16>(&familyID);
2515 link.Read<uint16>(&styleID);
2516
2517 int32 numChars, numBytes;
2518 link.Read<int32>(&numChars);
2519 link.Read<int32>(&numBytes);
2520
2521 BStackOrHeapArray<char, 256> charArray(numBytes);
2522 BStackOrHeapArray<bool, 256> hasArray(numChars);
2523 if (!charArray.IsValid() || !hasArray.IsValid()) {
2524 fLink.StartMessage(B_NO_MEMORY);
2525 fLink.Flush();
2526 break;
2527 }
2528
2529 link.Read(charArray, numBytes);
2530
2531 bool useFallbacks;
2532 link.Read<bool>(&useFallbacks);
2533
2534 ServerFont font;
2535 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2536 fAppFontManager);
2537
2538 if (status == B_OK) {
2539 status = font.GetHasGlyphs(charArray, numBytes, numChars, hasArray, useFallbacks);
2540 if (status == B_OK) {
2541 fLink.StartMessage(B_OK);
2542 fLink.Attach(hasArray, numChars * sizeof(bool));
2543 }
2544 }
2545
2546 if (status != B_OK)
2547 fLink.StartMessage(status);
2548
2549 fLink.Flush();
2550 break;
2551 }
2552
2553 case AS_GET_EDGES:
2554 {
2555 FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature()));
2556
2557 // Attached Data:
2558 // 1) uint16 - family ID
2559 // 2) uint16 - style ID
2560 // 3) int32 - numChars
2561 // 4) int32 - numBytes
2562 // 5) char - the char buffer with size numBytes
2563
2564 uint16 familyID, styleID;
2565 link.Read<uint16>(&familyID);
2566 link.Read<uint16>(&styleID);
2567
2568 int32 numChars;
2569 link.Read<int32>(&numChars);
2570
2571 uint32 numBytes;
2572 link.Read<uint32>(&numBytes);
2573
2574 BStackOrHeapArray<char, 256> charArray(numBytes);
2575 BStackOrHeapArray<edge_info, 64> edgeArray(numChars);
2576 if (!charArray.IsValid() || !edgeArray.IsValid()) {
2577 fLink.StartMessage(B_NO_MEMORY);
2578 fLink.Flush();
2579 break;
2580 }
2581
2582 link.Read(charArray, numBytes);
2583
2584 ServerFont font;
2585 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2586 fAppFontManager);
2587
2588 if (status == B_OK) {
2589 status = font.GetEdges(charArray, numBytes, numChars,
2590 edgeArray);
2591 if (status == B_OK) {
2592 fLink.StartMessage(B_OK);
2593 fLink.Attach(edgeArray, numChars * sizeof(edge_info));
2594 }
2595 }
2596
2597 if (status != B_OK)
2598 fLink.StartMessage(status);
2599
2600 fLink.Flush();
2601 break;
2602 }
2603
2604 case AS_GET_ESCAPEMENTS:
2605 {
2606 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature()));
2607
2608 // Attached Data:
2609 // 1) uint16 - family ID
2610 // 2) uint16 - style ID
2611 // 3) float - point size
2612 // 4) uint8 - spacing
2613 // 5) float - rotation
2614 // 6) uint32 - flags
2615 // 7) int32 - numChars
2616 // 8) char - char -\ both
2617 // 9) BPoint - offset -/ (numChars times)
2618
2619 // Returns:
2620 // 1) BPoint - escapement
2621 // numChars times
2622
2623 uint16 familyID, styleID;
2624 uint32 flags;
2625 float size, rotation;
2626 uint8 spacing;
2627
2628 link.Read<uint16>(&familyID);
2629 link.Read<uint16>(&styleID);
2630 link.Read<float>(&size);
2631 link.Read<uint8>(&spacing);
2632 link.Read<float>(&rotation);
2633 link.Read<uint32>(&flags);
2634
2635 escapement_delta delta;
2636 link.Read<float>(&delta.nonspace);
2637 link.Read<float>(&delta.space);
2638
2639 bool wantsOffsets;
2640 link.Read<bool>(&wantsOffsets);
2641
2642 int32 numChars;
2643 link.Read<int32>(&numChars);
2644
2645 uint32 numBytes;
2646 link.Read<uint32>(&numBytes);
2647
2648 BStackOrHeapArray<char, 256> charArray(numBytes);
2649 BStackOrHeapArray<BPoint, 64> escapements(numChars);
2650 BPoint* offsets = NULL;
2651 if (wantsOffsets)
2652 offsets = new(std::nothrow) BPoint[numChars];
2653
2654 if (!charArray.IsValid() || !escapements.IsValid()
2655 || (offsets == NULL && wantsOffsets)) {
2656 delete[] offsets;
2657 fLink.StartMessage(B_NO_MEMORY);
2658 fLink.Flush();
2659 break;
2660 }
2661
2662 link.Read(charArray, numBytes);
2663
2664 ServerFont font;
2665 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2666 fAppFontManager);
2667
2668 if (status == B_OK) {
2669 font.SetSize(size);
2670 font.SetSpacing(spacing);
2671 font.SetRotation(rotation);
2672 font.SetFlags(flags);
2673
2674 status = font.GetEscapements(charArray, numBytes, numChars,
2675 delta, escapements, offsets);
2676
2677 if (status == B_OK) {
2678 fLink.StartMessage(B_OK);
2679 for (int32 i = 0; i < numChars; i++)
2680 fLink.Attach<BPoint>(escapements[i]);
2681
2682 if (wantsOffsets) {
2683 for (int32 i = 0; i < numChars; i++)
2684 fLink.Attach<BPoint>(offsets[i]);
2685 }
2686 }
2687 }
2688
2689 if (status != B_OK)
2690 fLink.StartMessage(status);
2691
2692 delete[] offsets;
2693 fLink.Flush();
2694 break;
2695 }
2696
2697 case AS_GET_ESCAPEMENTS_AS_FLOATS:
2698 {
2699 FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature()));
2700
2701 // Attached Data:
2702 // 1) uint16 - family ID
2703 // 2) uint16 - style ID
2704 // 3) float - point size
2705 // 4) uint8 - spacing
2706 // 5) float - rotation
2707 // 6) uint32 - flags
2708 // 7) float - additional "nonspace" delta
2709 // 8) float - additional "space" delta
2710 // 9) int32 - numChars
2711 // 10) int32 - numBytes
2712 // 11) char - the char buffer with size numBytes
2713
2714 // Returns:
2715 // 1) float - escapement buffer with numChar entries
2716
2717 uint16 familyID, styleID;
2718 uint32 flags;
2719 float size, rotation;
2720 uint8 spacing;
2721
2722 link.Read<uint16>(&familyID);
2723 link.Read<uint16>(&styleID);
2724 link.Read<float>(&size);
2725 link.Read<uint8>(&spacing);
2726 link.Read<float>(&rotation);
2727 link.Read<uint32>(&flags);
2728
2729 escapement_delta delta;
2730 link.Read<float>(&delta.nonspace);
2731 link.Read<float>(&delta.space);
2732
2733 int32 numChars;
2734 link.Read<int32>(&numChars);
2735
2736 uint32 numBytes;
2737 link.Read<uint32>(&numBytes);
2738
2739 BStackOrHeapArray<char, 256> charArray(numBytes);
2740 BStackOrHeapArray<float, 64> escapements(numChars);
2741 if (!charArray.IsValid() || !escapements.IsValid()) {
2742 fLink.StartMessage(B_NO_MEMORY);
2743 fLink.Flush();
2744 break;
2745 }
2746
2747 link.Read(charArray, numBytes);
2748
2749 // figure out escapements
2750
2751 ServerFont font;
2752 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2753 fAppFontManager);
2754
2755 if (status == B_OK) {
2756 font.SetSize(size);
2757 font.SetSpacing(spacing);
2758 font.SetRotation(rotation);
2759 font.SetFlags(flags);
2760
2761 status = font.GetEscapements(charArray, numBytes, numChars,
2762 delta, escapements);
2763
2764 if (status == B_OK) {
2765 fLink.StartMessage(B_OK);
2766 fLink.Attach(escapements, numChars * sizeof(float));
2767 }
2768 }
2769
2770 if (status != B_OK)
2771 fLink.StartMessage(status);
2772
2773 fLink.Flush();
2774 break;
2775 }
2776
2777 case AS_GET_BOUNDINGBOXES_CHARS:
2778 case AS_GET_BOUNDINGBOXES_STRING:
2779 {
2780 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature()));
2781
2782 // Attached Data:
2783 // 1) uint16 - family ID
2784 // 2) uint16 - style ID
2785 // 3) float - point size
2786 // 4) float - rotation
2787 // 5) float - shear
2788 // 6) float - false bold width
2789 // 7) uint8 - spacing
2790 // 8) uint32 - flags
2791 // 9) font_metric_mode - mode
2792 // 10) bool - string escapement
2793 // 11) escapement_delta - additional delta
2794 // 12) int32 - numChars
2795 // 13) int32 - numBytes
2796 // 14) char - the char buffer with size numBytes
2797
2798 // Returns:
2799 // 1) BRect - rects with numChar entries
2800
2801 uint16 familyID, styleID;
2802 uint32 flags;
2803 float size, rotation, shear, falseBoldWidth;
2804 uint8 spacing;
2805 font_metric_mode mode;
2806 bool stringEscapement;
2807
2808 link.Read<uint16>(&familyID);
2809 link.Read<uint16>(&styleID);
2810 link.Read<float>(&size);
2811 link.Read<float>(&rotation);
2812 link.Read<float>(&shear);
2813 link.Read<float>(&falseBoldWidth);
2814 link.Read<uint8>(&spacing);
2815 link.Read<uint32>(&flags);
2816 link.Read<font_metric_mode>(&mode);
2817 link.Read<bool>(&stringEscapement);
2818
2819 escapement_delta delta;
2820 link.Read<escapement_delta>(&delta);
2821
2822 int32 numChars;
2823 link.Read<int32>(&numChars);
2824
2825 uint32 numBytes;
2826 link.Read<uint32>(&numBytes);
2827
2828 BStackOrHeapArray<char, 256> charArray(numBytes);
2829 BStackOrHeapArray<BRect, 64> rectArray(numChars);
2830 if (!charArray.IsValid() || !rectArray.IsValid()) {
2831 fLink.StartMessage(B_NO_MEMORY);
2832 fLink.Flush();
2833 break;
2834 }
2835
2836 link.Read(charArray, numBytes);
2837
2838 // figure out escapements
2839
2840 ServerFont font;
2841 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2842 fAppFontManager);
2843
2844 if (status == B_OK) {
2845 font.SetSize(size);
2846 font.SetRotation(rotation);
2847 font.SetShear(shear);
2848 font.SetFalseBoldWidth(falseBoldWidth);
2849 font.SetSpacing(spacing);
2850 font.SetFlags(flags);
2851
2852 // TODO: implement for real
2853 status = font.GetBoundingBoxes(charArray, numBytes,
2854 numChars, rectArray, stringEscapement, mode, delta,
2855 code == AS_GET_BOUNDINGBOXES_STRING);
2856 if (status == B_OK) {
2857 fLink.StartMessage(B_OK);
2858 for (int32 i = 0; i < numChars; i++)
2859 fLink.Attach<BRect>(rectArray[i]);
2860 }
2861 }
2862
2863 if (status != B_OK)
2864 fLink.StartMessage(status);
2865
2866 fLink.Flush();
2867 break;
2868 }
2869
2870 case AS_GET_BOUNDINGBOXES_STRINGS:
2871 {
2872 FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n",
2873 Signature()));
2874
2875 // Attached Data:
2876 // 1) uint16 - family ID
2877 // 2) uint16 - style ID
2878 // 3) float - point size
2879 // 4) float - rotation
2880 // 5) float - shear
2881 // 6) float - false bold width
2882 // 7) uint8 - spacing
2883 // 8) uint32 - flags
2884 // 9) font_metric_mode - mode
2885 // 10) int32 numStrings
2886 // 11) escapement_delta - additional delta (numStrings times)
2887 // 12) int32 string length to measure (numStrings times)
2888 // 13) string - string (numStrings times)
2889
2890 // Returns:
2891 // 1) BRect - rects with numStrings entries
2892
2893 uint16 familyID, styleID;
2894 uint32 flags;
2895 float ptsize, rotation, shear, falseBoldWidth;
2896 uint8 spacing;
2897 font_metric_mode mode;
2898
2899 link.Read<uint16>(&familyID);
2900 link.Read<uint16>(&styleID);
2901 link.Read<float>(&ptsize);
2902 link.Read<float>(&rotation);
2903 link.Read<float>(&shear);
2904 link.Read<float>(&falseBoldWidth);
2905 link.Read<uint8>(&spacing);
2906 link.Read<uint32>(&flags);
2907 link.Read<font_metric_mode>(&mode);
2908
2909 int32 numStrings;
2910 link.Read<int32>(&numStrings);
2911
2912 BStackOrHeapArray<escapement_delta, 64> deltaArray(numStrings);
2913 BStackOrHeapArray<char*, 64> stringArray(numStrings);
2914 BStackOrHeapArray<size_t, 64> lengthArray(numStrings);
2915 BStackOrHeapArray<BRect, 64> rectArray(numStrings);
2916 if (!deltaArray.IsValid() || !stringArray.IsValid()
2917 || !lengthArray.IsValid() || !rectArray.IsValid()) {
2918 fLink.StartMessage(B_NO_MEMORY);
2919 fLink.Flush();
2920 break;
2921 }
2922
2923 for (int32 i = 0; i < numStrings; i++) {
2924 // This version of ReadString allocates the strings, we free
2925 // them below
2926 link.ReadString(&stringArray[i], &lengthArray[i]);
2927 link.Read<escapement_delta>(&deltaArray[i]);
2928 }
2929
2930 ServerFont font;
2931 status_t status = font.SetFamilyAndStyle(familyID, styleID,
2932 fAppFontManager);
2933
2934 if (status == B_OK) {
2935 font.SetSize(ptsize);
2936 font.SetRotation(rotation);
2937 font.SetShear(shear);
2938 font.SetFalseBoldWidth(falseBoldWidth);
2939 font.SetSpacing(spacing);
2940 font.SetFlags(flags);
2941
2942 status = font.GetBoundingBoxesForStrings(stringArray,
2943 lengthArray, numStrings, rectArray, mode, deltaArray);
2944 if (status == B_OK) {
2945 fLink.StartMessage(B_OK);
2946 fLink.Attach(rectArray, numStrings * sizeof(BRect));
2947 }
2948 }
2949
2950 for (int32 i = 0; i < numStrings; i++)
2951 free(stringArray[i]);
2952
2953 if (status != B_OK)
2954 fLink.StartMessage(status);
2955
2956 fLink.Flush();
2957 break;
2958 }
2959
2960 // Screen commands
2961
2962 case AS_VALID_SCREEN_ID:
2963 {
2964 // Attached data
2965 // 1) int32 screen
2966
2967 int32 id;
2968 if (link.Read<int32>(&id) == B_OK
2969 && id == B_MAIN_SCREEN_ID.id)
2970 fLink.StartMessage(B_OK);
2971 else
2972 fLink.StartMessage(B_ERROR);
2973
2974 fLink.Flush();
2975 break;
2976 }
2977
2978 case AS_GET_NEXT_SCREEN_ID:
2979 {
2980 // Attached data
2981 // 1) int32 screen
2982
2983 int32 id;
2984 link.Read<int32>(&id);
2985
2986 // TODO: for now, just say we're the last one
2987 fLink.StartMessage(B_ENTRY_NOT_FOUND);
2988 fLink.Flush();
2989 break;
2990 }
2991
2992 case AS_GET_SCREEN_ID_FROM_WINDOW:
2993 {
2994 status_t status = B_BAD_VALUE;
2995
2996 // Attached data
2997 // 1) int32 - window client token
2998
2999 int32 clientToken;
3000 if (link.Read<int32>(&clientToken) != B_OK)
3001 status = B_BAD_DATA;
3002 else {
3003 BAutolock locker(fWindowListLock);
3004
3005 for (int32 i = fWindowList.CountItems(); i-- > 0;) {
3006 ServerWindow* serverWindow = fWindowList.ItemAt(i);
3007
3008 if (serverWindow->ClientToken() == clientToken) {
3009 AutoReadLocker _(fDesktop->ScreenLocker());
3010
3011 // found it!
3012 Window* window = serverWindow->Window();
3013 const Screen* screen = NULL;
3014 if (window != NULL)
3015 screen = window->Screen();
3016
3017 if (screen == NULL) {
3018 // The window hasn't been added to the desktop yet,
3019 // or it's an offscreen window
3020 break;
3021 }
3022
3023 fLink.StartMessage(B_OK);
3024 fLink.Attach<int32>(screen->ID());
3025 status = B_OK;
3026 break;
3027 }
3028 }
3029 }
3030
3031 if (status != B_OK)
3032 fLink.StartMessage(status);
3033 fLink.Flush();
3034 break;
3035 }
3036
3037 case AS_SCREEN_GET_MODE:
3038 {
3039 STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature()));
3040
3041 // Attached data
3042 // 1) int32 screen
3043 // 2) uint32 workspace index
3044
3045 int32 id;
3046 link.Read<int32>(&id);
3047 uint32 workspace;
3048 link.Read<uint32>(&workspace);
3049
3050 display_mode mode;
3051 status_t status = fDesktop->GetScreenMode(workspace, id, mode);
3052
3053 fLink.StartMessage(status);
3054 if (status == B_OK)
3055 fLink.Attach<display_mode>(mode);
3056 fLink.Flush();
3057 break;
3058 }
3059
3060 case AS_SCREEN_SET_MODE:
3061 {
3062 STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature()));
3063
3064 // Attached data
3065 // 1) int32 screen
3066 // 2) workspace index
3067 // 3) display_mode to set
3068 // 4) 'makeDefault' boolean
3069
3070 int32 id;
3071 link.Read<int32>(&id);
3072 uint32 workspace;
3073 link.Read<uint32>(&workspace);
3074
3075 display_mode mode;
3076 link.Read<display_mode>(&mode);
3077
3078 bool makeDefault = false;
3079 status_t status = link.Read<bool>(&makeDefault);
3080
3081 if (status == B_OK) {
3082 status = fDesktop->SetScreenMode(workspace, id, mode,
3083 makeDefault);
3084 }
3085 if (status == B_OK) {
3086 if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX
3087 && fDesktop->LockSingleWindow()) {
3088 workspace = fDesktop->CurrentWorkspace();
3089 fDesktop->UnlockSingleWindow();
3090 }
3091
3092 if (!makeDefault) {
3093 // Memorize the screen change, so that it can be reverted
3094 // later
3095 fTemporaryDisplayModeChange |= 1 << workspace;
3096 } else
3097 fTemporaryDisplayModeChange &= ~(1 << workspace);
3098 }
3099
3100 fLink.StartMessage(status);
3101 fLink.Flush();
3102 break;
3103 }
3104
3105 case AS_PROPOSE_MODE:
3106 {
3107 STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature()));
3108 int32 id;
3109 link.Read<int32>(&id);
3110
3111 display_mode target, low, high;
3112 link.Read<display_mode>(&target);
3113 link.Read<display_mode>(&low);
3114 link.Read<display_mode>(&high);
3115 status_t status = fDesktop->HWInterface()->ProposeMode(&target,
3116 &low, &high);
3117
3118 // ProposeMode() returns B_BAD_VALUE to hint that the candidate is
3119 // not within the given limits (but is supported)
3120 if (status == B_OK || status == B_BAD_VALUE) {
3121 fLink.StartMessage(B_OK);
3122 fLink.Attach<display_mode>(target);
3123 fLink.Attach<bool>(status == B_OK);
3124 } else
3125 fLink.StartMessage(status);
3126
3127 fLink.Flush();
3128 break;
3129 }
3130
3131 case AS_GET_MODE_LIST:
3132 {
3133 int32 id;
3134 link.Read<int32>(&id);
3135 // TODO: use this screen id
3136
3137 display_mode* modeList;
3138 uint32 count;
3139 status_t status = fDesktop->HWInterface()->GetModeList(&modeList,
3140 &count);
3141 if (status == B_OK) {
3142 fLink.StartMessage(B_OK);
3143 fLink.Attach<uint32>(count);
3144 fLink.Attach(modeList, sizeof(display_mode) * count);
3145
3146 delete[] modeList;
3147 } else
3148 fLink.StartMessage(status);
3149
3150 fLink.Flush();
3151 break;
3152 }
3153
3154 case AS_GET_SCREEN_FRAME:
3155 {
3156 STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature()));
3157
3158 // Attached data
3159 // 1) int32 screen
3160 // 2) uint32 workspace index
3161
3162 int32 id;
3163 link.Read<int32>(&id);
3164 uint32 workspace;
3165 link.Read<uint32>(&workspace);
3166
3167 BRect frame;
3168 status_t status = fDesktop->GetScreenFrame(workspace, id, frame);
3169
3170 fLink.StartMessage(status);
3171 if (status == B_OK)
3172 fLink.Attach<BRect>(frame);
3173
3174 fLink.Flush();
3175 break;
3176 }
3177
3178 case AS_SCREEN_GET_COLORMAP:
3179 {
3180 STRACE(("ServerApp %s: AS_SCREEN_GET_COLORMAP\n", Signature()));
3181
3182 int32 id;
3183 link.Read<int32>(&id);
3184
3185 const color_map* colorMap = SystemColorMap();
3186 if (colorMap != NULL) {
3187 fLink.StartMessage(B_OK);
3188 fLink.Attach<color_map>(*colorMap);
3189 } else
3190 fLink.StartMessage(B_ERROR);
3191
3192 fLink.Flush();
3193 break;
3194 }
3195
3196 case AS_GET_DESKTOP_COLOR:
3197 {
3198 STRACE(("ServerApp %s: get desktop color\n", Signature()));
3199
3200 uint32 index;
3201 link.Read<uint32>(&index);
3202
3203 fLink.StartMessage(B_OK);
3204 fDesktop->LockSingleWindow();
3205
3206 // we're nice to our children (and also take the default case
3207 // into account which asks for the current workspace)
3208 if (index >= (uint32)kMaxWorkspaces)
3209 index = fDesktop->CurrentWorkspace();
3210
3211 Workspace workspace(*fDesktop, index, true);
3212 fLink.Attach<rgb_color>(workspace.Color());
3213
3214 fDesktop->UnlockSingleWindow();
3215 fLink.Flush();
3216 break;
3217 }
3218
3219 case AS_SET_DESKTOP_COLOR:
3220 {
3221 STRACE(("ServerApp %s: set desktop color\n", Signature()));
3222
3223 rgb_color color;
3224 uint32 index;
3225 bool makeDefault;
3226
3227 link.Read<rgb_color>(&color);
3228 link.Read<uint32>(&index);
3229 if (link.Read<bool>(&makeDefault) != B_OK)
3230 break;
3231
3232 fDesktop->LockAllWindows();
3233
3234 // we're nice to our children (and also take the default case
3235 // into account which asks for the current workspace)
3236 if (index >= (uint32)kMaxWorkspaces)
3237 index = fDesktop->CurrentWorkspace();
3238
3239 Workspace workspace(*fDesktop, index);
3240 workspace.SetColor(color, makeDefault);
3241
3242 fDesktop->UnlockAllWindows();
3243 break;
3244 }
3245
3246 case AS_GET_ACCELERANT_INFO:
3247 {
3248 STRACE(("ServerApp %s: get accelerant info\n", Signature()));
3249
3250 // We aren't using the screen_id for now...
3251 int32 id;
3252 link.Read<int32>(&id);
3253
3254 accelerant_device_info accelerantInfo;
3255 // TODO: I wonder if there should be a "desktop" lock...
3256 status_t status
3257 = fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo);
3258 if (status == B_OK) {
3259 fLink.StartMessage(B_OK);
3260 fLink.Attach<accelerant_device_info>(accelerantInfo);
3261 } else
3262 fLink.StartMessage(status);
3263
3264 fLink.Flush();
3265 break;
3266 }
3267
3268 case AS_GET_MONITOR_INFO:
3269 {
3270 STRACE(("ServerApp %s: get monitor info\n", Signature()));
3271
3272 // We aren't using the screen_id for now...
3273 int32 id;
3274 link.Read<int32>(&id);
3275
3276 monitor_info info;
3277 // TODO: I wonder if there should be a "desktop" lock...
3278 status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info);
3279 if (status == B_OK) {
3280 fLink.StartMessage(B_OK);
3281 fLink.Attach<monitor_info>(info);
3282 } else
3283 fLink.StartMessage(status);
3284
3285 fLink.Flush();
3286 break;
3287 }
3288
3289 case AS_GET_FRAME_BUFFER_CONFIG:
3290 {
3291 STRACE(("ServerApp %s: get frame buffer config\n", Signature()));
3292
3293 // We aren't using the screen_id for now...
3294 int32 id;
3295 link.Read<int32>(&id);
3296
3297 frame_buffer_config config;
3298 // TODO: I wonder if there should be a "desktop" lock...
3299 status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config);
3300 if (status == B_OK) {
3301 fLink.StartMessage(B_OK);
3302 fLink.Attach<frame_buffer_config>(config);
3303 } else
3304 fLink.StartMessage(status);
3305
3306 fLink.Flush();
3307 break;
3308 }
3309
3310 case AS_GET_RETRACE_SEMAPHORE:
3311 {
3312 STRACE(("ServerApp %s: get retrace semaphore\n", Signature()));
3313
3314 // We aren't using the screen_id for now...
3315 int32 id;
3316 link.Read<int32>(&id);
3317
3318 fLink.StartMessage(B_OK);
3319 fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore());
3320 fLink.Flush();
3321 break;
3322 }
3323
3324 case AS_GET_TIMING_CONSTRAINTS:
3325 {
3326 STRACE(("ServerApp %s: get timing constraints\n", Signature()));
3327
3328 // We aren't using the screen_id for now...
3329 int32 id;
3330 link.Read<int32>(&id);
3331
3332 display_timing_constraints constraints;
3333 status_t status = fDesktop->HWInterface()->GetTimingConstraints(
3334 &constraints);
3335 if (status == B_OK) {
3336 fLink.StartMessage(B_OK);
3337 fLink.Attach<display_timing_constraints>(constraints);
3338 } else
3339 fLink.StartMessage(status);
3340
3341 fLink.Flush();
3342 break;
3343 }
3344
3345 case AS_GET_PIXEL_CLOCK_LIMITS:
3346 {
3347 STRACE(("ServerApp %s: get pixel clock limits\n", Signature()));
3348 // We aren't using the screen_id for now...
3349 int32 id;
3350 link.Read<int32>(&id);
3351 display_mode mode;
3352 link.Read<display_mode>(&mode);
3353
3354 uint32 low, high;
3355 status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode,
3356 &low, &high);
3357 if (status == B_OK) {
3358 fLink.StartMessage(B_OK);
3359 fLink.Attach<uint32>(low);
3360 fLink.Attach<uint32>(high);
3361 } else
3362 fLink.StartMessage(status);
3363
3364 fLink.Flush();
3365 break;
3366 }
3367
3368 case AS_SET_DPMS:
3369 {
3370 STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature()));
3371 int32 id;
3372 link.Read<int32>(&id);
3373
3374 uint32 mode;
3375 link.Read<uint32>(&mode);
3376
3377 status_t status = fDesktop->HWInterface()->SetDPMSMode(mode);
3378 fLink.StartMessage(status);
3379
3380 fLink.Flush();
3381 break;
3382 }
3383
3384 case AS_GET_DPMS_STATE:
3385 {
3386 STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature()));
3387
3388 int32 id;
3389 link.Read<int32>(&id);
3390
3391 uint32 state = fDesktop->HWInterface()->DPMSMode();
3392 fLink.StartMessage(B_OK);
3393 fLink.Attach<uint32>(state);
3394 fLink.Flush();
3395 break;
3396 }
3397
3398 case AS_GET_DPMS_CAPABILITIES:
3399 {
3400 STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature()));
3401 int32 id;
3402 link.Read<int32>(&id);
3403
3404 uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities();
3405 fLink.StartMessage(B_OK);
3406 fLink.Attach<uint32>(capabilities);
3407 fLink.Flush();
3408 break;
3409 }
3410
3411 case AS_SCREEN_SET_BRIGHTNESS:
3412 {
3413 STRACE(("ServerApp %s: AS_SCREEN_SET_BRIGHTNESS\n", Signature()));
3414 int32 id;
3415 link.Read<int32>(&id);
3416
3417 float brightness;
3418 link.Read<float>(&brightness);
3419
3420 status_t status = fDesktop->SetBrightness(id, brightness);
3421 fLink.StartMessage(status);
3422
3423 fLink.Flush();
3424 break;
3425 }
3426
3427 case AS_SCREEN_GET_BRIGHTNESS:
3428 {
3429 STRACE(("ServerApp %s: AS_SCREEN_GET_BRIGHTNESS\n", Signature()));
3430 int32 id;
3431 link.Read<int32>(&id);
3432
3433 float brightness;
3434 status_t result = fDesktop->HWInterface()->GetBrightness(&brightness);
3435 fLink.StartMessage(result);
3436 if (result == B_OK)
3437 fLink.Attach<float>(brightness);
3438 fLink.Flush();
3439 break;
3440 }
3441
3442 case AS_READ_BITMAP:
3443 {
3444 STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature()));
3445 int32 token;
3446 link.Read<int32>(&token);
3447
3448 bool drawCursor = true;
3449 link.Read<bool>(&drawCursor);
3450
3451 BRect bounds;
3452 link.Read<BRect>(&bounds);
3453
3454 bool success = false;
3455
3456 BReference<ServerBitmap> bitmap(GetBitmap(token), true);
3457 if (bitmap != NULL) {
3458 if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) {
3459 success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap,
3460 drawCursor, bounds) == B_OK;
3461 fDesktop->GetDrawingEngine()->UnlockExclusiveAccess();
3462 }
3463 }
3464
3465 if (success)
3466 fLink.StartMessage(B_OK);
3467 else
3468 fLink.StartMessage(B_BAD_VALUE);
3469
3470 fLink.Flush();
3471 break;
3472 }
3473
3474 case AS_GET_ACCELERANT_PATH:
3475 {
3476 int32 id;
3477 fLink.Read<int32>(&id);
3478
3479 BString path;
3480 status_t status = fDesktop->HWInterface()->GetAccelerantPath(path);
3481 fLink.StartMessage(status);
3482 if (status == B_OK)
3483 fLink.AttachString(path.String());
3484
3485 fLink.Flush();
3486 break;
3487 }
3488
3489 case AS_GET_DRIVER_PATH:
3490 {
3491 int32 id;
3492 fLink.Read<int32>(&id);
3493
3494 BString path;
3495 status_t status = fDesktop->HWInterface()->GetDriverPath(path);
3496 fLink.StartMessage(status);
3497 if (status == B_OK)
3498 fLink.AttachString(path.String());
3499
3500 fLink.Flush();
3501 break;
3502 }
3503
3504 // BWindowScreen communication
3505
3506 case AS_DIRECT_SCREEN_LOCK:
3507 {
3508 bool lock;
3509 link.Read<bool>(&lock);
3510
3511 status_t status;
3512 if (lock)
3513 status = fDesktop->LockDirectScreen(ClientTeam());
3514 else
3515 status = fDesktop->UnlockDirectScreen(ClientTeam());
3516
3517 fLink.StartMessage(status);
3518 fLink.Flush();
3519 break;
3520 }
3521
3522 // Hinting and aliasing
3523
3524 case AS_SET_SUBPIXEL_ANTIALIASING:
3525 {
3526 bool subpix;
3527 if (link.Read<bool>(&subpix) == B_OK) {
3528 LockedDesktopSettings settings(fDesktop);
3529 settings.SetSubpixelAntialiasing(subpix);
3530 }
3531 fDesktop->Redraw();
3532 break;
3533 }
3534
3535 case AS_GET_SUBPIXEL_ANTIALIASING:
3536 {
3537 DesktopSettings settings(fDesktop);
3538 fLink.StartMessage(B_OK);
3539 fLink.Attach<bool>(settings.SubpixelAntialiasing());
3540 fLink.Flush();
3541 break;
3542 }
3543
3544 case AS_SET_HINTING:
3545 {
3546 uint8 hinting;
3547 if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) {
3548 LockedDesktopSettings settings(fDesktop);
3549 if (hinting != settings.Hinting()) {
3550 settings.SetHinting(hinting);
3551 fDesktop->Redraw();
3552 }
3553 }
3554 break;
3555 }
3556
3557 case AS_GET_HINTING:
3558 {
3559 DesktopSettings settings(fDesktop);
3560 fLink.StartMessage(B_OK);
3561 fLink.Attach<uint8>(settings.Hinting());
3562 fLink.Flush();
3563 break;
3564 }
3565
3566 case AS_SET_SUBPIXEL_AVERAGE_WEIGHT:
3567 {
3568 uint8 averageWeight;
3569 if (link.Read<uint8>(&averageWeight) == B_OK) {
3570 LockedDesktopSettings settings(fDesktop);
3571 settings.SetSubpixelAverageWeight(averageWeight);
3572 }
3573 fDesktop->Redraw();
3574 break;
3575 }
3576
3577 case AS_GET_SUBPIXEL_AVERAGE_WEIGHT:
3578 {
3579 DesktopSettings settings(fDesktop);
3580 fLink.StartMessage(B_OK);
3581 fLink.Attach<uint8>(settings.SubpixelAverageWeight());
3582 fLink.Flush();
3583 break;
3584 }
3585
3586 case AS_SET_SUBPIXEL_ORDERING:
3587 {
3588 bool subpixelOrdering;
3589 if (link.Read<bool>(&subpixelOrdering) == B_OK) {
3590 LockedDesktopSettings settings(fDesktop);
3591 settings.SetSubpixelOrderingRegular(subpixelOrdering);
3592 }
3593 fDesktop->Redraw();
3594 break;
3595 }
3596
3597 case AS_GET_SUBPIXEL_ORDERING:
3598 {
3599 DesktopSettings settings(fDesktop);
3600 fLink.StartMessage(B_OK);
3601 fLink.Attach<bool>(settings.IsSubpixelOrderingRegular());
3602 fLink.Flush();
3603 break;
3604 }
3605
3606 default:
3607 printf("ServerApp %s received unhandled message code %" B_PRId32
3608 "\n", Signature(), code);
3609
3610 if (link.NeedsReply()) {
3611 // the client is now blocking and waiting for a reply!
3612 fLink.StartMessage(B_ERROR);
3613 fLink.Flush();
3614 } else
3615 puts("message doesn't need a reply!");
3616 break;
3617 }
3618 }
3619
3620
3621 /*! \brief The thread function ServerApps use to monitor messages
3622 */
3623 void
_MessageLooper()3624 ServerApp::_MessageLooper()
3625 {
3626 // Message-dispatching loop for the ServerApp
3627
3628 // get our own team ID
3629 thread_info threadInfo;
3630 get_thread_info(fThread, &threadInfo);
3631
3632 // First let's tell the client how to talk with us.
3633 fLink.StartMessage(B_OK);
3634 fLink.Attach<port_id>(fMessagePort);
3635 fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea());
3636 fLink.Attach<team_id>(threadInfo.team);
3637 fLink.Flush();
3638
3639 BPrivate::LinkReceiver &receiver = fLink.Receiver();
3640
3641 int32 code;
3642 status_t err = B_OK;
3643
3644 while (!fQuitting) {
3645 STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32
3646 ".\n", fMessagePort));
3647
3648 err = receiver.GetNextMessage(code);
3649 if (err != B_OK || code == B_QUIT_REQUESTED) {
3650 STRACE(("ServerApp: application seems to be gone...\n"));
3651
3652 // Tell desktop to quit us
3653 BPrivate::LinkSender link(fDesktop->MessagePort());
3654 link.StartMessage(AS_DELETE_APP);
3655 link.Attach<thread_id>(Thread());
3656 link.Flush();
3657 break;
3658 }
3659
3660 switch (code) {
3661 case kMsgAppQuit:
3662 // we receive this from our destructor on quit
3663 fQuitting = true;
3664 break;
3665
3666 case AS_QUIT_APP:
3667 {
3668 // This message is received only when the app_server is asked
3669 // to shut down in test/debug mode. Of course, if we are testing
3670 // while using AccelerantDriver, we do NOT want to shut down
3671 // client applications. The server can be quit in this fashion
3672 // through the driver's interface, such as closing the
3673 // ViewDriver's window.
3674
3675 STRACE(("ServerApp %s:Server shutdown notification received\n",
3676 Signature()));
3677
3678 // If we are using the real, accelerated version of the
3679 // DrawingEngine, we do NOT want the user to be able shut down
3680 // the server. The results would NOT be pretty
3681 #if TEST_MODE
3682 BMessage pleaseQuit(B_QUIT_REQUESTED);
3683 SendMessageToClient(&pleaseQuit);
3684 #endif
3685 break;
3686 }
3687
3688 default:
3689 STRACE(("ServerApp %s: Got a Message to dispatch\n",
3690 Signature()));
3691 _DispatchMessage(code, receiver);
3692 break;
3693 }
3694 }
3695
3696 // Quit() will send us a message; we're handling the exiting procedure
3697 thread_id sender;
3698 sem_id shutdownSemaphore;
3699 receive_data(&sender, &shutdownSemaphore, sizeof(sem_id));
3700
3701 delete this;
3702
3703 if (shutdownSemaphore >= B_OK)
3704 release_sem(shutdownSemaphore);
3705 }
3706
3707
3708 status_t
_CreateWindow(int32 code,BPrivate::LinkReceiver & link,port_id & clientReplyPort)3709 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link,
3710 port_id& clientReplyPort)
3711 {
3712 // Attached data:
3713 // 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW)
3714 // 2) BRect window frame
3715 // 3) uint32 window look
3716 // 4) uint32 window feel
3717 // 5) uint32 window flags
3718 // 6) uint32 workspace index
3719 // 7) int32 BHandler token of the window
3720 // 8) port_id window's reply port
3721 // 9) port_id window's looper port
3722 // 10) const char * title
3723
3724 BRect frame;
3725 int32 bitmapToken;
3726 uint32 look;
3727 uint32 feel;
3728 uint32 flags;
3729 uint32 workspaces;
3730 int32 token;
3731 port_id looperPort;
3732 char* title;
3733
3734 if (code == AS_CREATE_OFFSCREEN_WINDOW)
3735 link.Read<int32>(&bitmapToken);
3736
3737 link.Read<BRect>(&frame);
3738 link.Read<uint32>(&look);
3739 link.Read<uint32>(&feel);
3740 link.Read<uint32>(&flags);
3741 link.Read<uint32>(&workspaces);
3742 link.Read<int32>(&token);
3743 link.Read<port_id>(&clientReplyPort);
3744 link.Read<port_id>(&looperPort);
3745 if (link.ReadString(&title) != B_OK)
3746 return B_ERROR;
3747
3748 if (!frame.IsValid()) {
3749 // make sure we pass a valid rectangle to ServerWindow
3750 frame.right = frame.left + 1;
3751 frame.bottom = frame.top + 1;
3752 }
3753
3754 status_t status = B_NO_MEMORY;
3755 ServerWindow *window = NULL;
3756
3757 if (code == AS_CREATE_OFFSCREEN_WINDOW) {
3758 ServerBitmap* bitmap = GetBitmap(bitmapToken);
3759
3760 if (bitmap != NULL) {
3761 window = new (nothrow) OffscreenServerWindow(title, this,
3762 clientReplyPort, looperPort, token, bitmap);
3763 } else
3764 status = B_ERROR;
3765 } else {
3766 window = new (nothrow) ServerWindow(title, this, clientReplyPort,
3767 looperPort, token);
3768 STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n",
3769 Signature(), title, frame.left, frame.top,
3770 frame.right, frame.bottom));
3771 }
3772
3773 free(title);
3774
3775 // NOTE: the reply to the client is handled in ServerWindow::Run()
3776 if (window != NULL) {
3777 status = window->Init(frame, (window_look)look, (window_feel)feel,
3778 flags, workspaces);
3779 if (status == B_OK) {
3780 status = window->Run();
3781 if (status != B_OK) {
3782 syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run "
3783 "the window thread\n");
3784 }
3785 }
3786
3787 if (status != B_OK)
3788 delete window;
3789 }
3790
3791 return status;
3792 }
3793
3794
3795 bool
_HasWindowUnderMouse()3796 ServerApp::_HasWindowUnderMouse()
3797 {
3798 BAutolock locker(fWindowListLock);
3799
3800 for (int32 i = fWindowList.CountItems(); i-- > 0;) {
3801 ServerWindow* serverWindow = fWindowList.ItemAt(i);
3802
3803 if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN)
3804 return true;
3805 }
3806
3807 return false;
3808 }
3809
3810
3811 bool
_AddBitmap(ServerBitmap * bitmap)3812 ServerApp::_AddBitmap(ServerBitmap* bitmap)
3813 {
3814 BAutolock _(fMapLocker);
3815
3816 try {
3817 fBitmapMap.insert(std::make_pair(bitmap->Token(), BReference<ServerBitmap>(bitmap, false)));
3818 } catch (std::bad_alloc& exception) {
3819 return false;
3820 }
3821
3822 bitmap->SetOwner(this);
3823 return true;
3824 }
3825
3826
3827 void
_DeleteBitmap(ServerBitmap * bitmap)3828 ServerApp::_DeleteBitmap(ServerBitmap* bitmap)
3829 {
3830 ASSERT(fMapLocker.IsLocked());
3831
3832 gBitmapManager->BitmapRemoved(bitmap);
3833 fBitmapMap.erase(bitmap->Token());
3834 }
3835
3836
3837 ServerBitmap*
_FindBitmap(int32 token) const3838 ServerApp::_FindBitmap(int32 token) const
3839 {
3840 ASSERT(fMapLocker.IsLocked());
3841
3842 BitmapMap::const_iterator iterator = fBitmapMap.find(token);
3843 if (iterator == fBitmapMap.end())
3844 return NULL;
3845
3846 return iterator->second;
3847 }
3848
3849
3850 ServerPicture*
_FindPicture(int32 token) const3851 ServerApp::_FindPicture(int32 token) const
3852 {
3853 ASSERT(fMapLocker.IsLocked());
3854
3855 PictureMap::const_iterator iterator = fPictureMap.find(token);
3856 if (iterator == fPictureMap.end())
3857 return NULL;
3858
3859 return iterator->second;
3860 }
3861