* Moved workspace keyboard switch and dump screen capability from RootLayer
into a Desktop keyboard filter. * Removed keyboard handling code from RootLayer and Layer. * Renamed Desktop::ActiveRootLayer() to RootLayer() as there is only one root layer per desktop. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15018 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
f68598780e
commit
fa26723bb2
@ -30,6 +30,7 @@
|
||||
#include <WindowInfo.h>
|
||||
#include <ServerProtocol.h>
|
||||
|
||||
#include <Entry.h>
|
||||
#include <Message.h>
|
||||
#include <MessageFilter.h>
|
||||
#include <Region.h>
|
||||
@ -48,6 +49,98 @@
|
||||
#endif
|
||||
|
||||
|
||||
class KeyboardFilter : public BMessageFilter {
|
||||
public:
|
||||
KeyboardFilter(Desktop* desktop);
|
||||
|
||||
virtual filter_result Filter(BMessage* message, BHandler** _target);
|
||||
|
||||
private:
|
||||
Desktop* fDesktop;
|
||||
};
|
||||
|
||||
|
||||
KeyboardFilter::KeyboardFilter(Desktop* desktop)
|
||||
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
|
||||
fDesktop(desktop)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
filter_result
|
||||
KeyboardFilter::Filter(BMessage* message, BHandler** /*_target*/)
|
||||
{
|
||||
int32 key;
|
||||
int32 modifiers;
|
||||
|
||||
if (message->what != B_KEY_DOWN
|
||||
|| message->FindInt32("key", &key) != B_OK
|
||||
|| message->FindInt32("modifiers", &modifiers) != B_OK)
|
||||
return B_DISPATCH_MESSAGE;
|
||||
|
||||
// Check for safe video mode (F12 + l-cmd + l-ctrl + l-shift)
|
||||
if (key == 0x0d
|
||||
&& (modifiers & (B_LEFT_COMMAND_KEY
|
||||
| B_LEFT_CONTROL_KEY | B_LEFT_SHIFT_KEY)) != 0)
|
||||
{
|
||||
// TODO: Set to Safe Mode in KeyboardEventHandler:B_KEY_DOWN.
|
||||
STRACE(("Safe Video Mode invoked - code unimplemented\n"));
|
||||
return B_SKIP_MESSAGE;
|
||||
}
|
||||
|
||||
if (key > 0x01 && key < 0x0e) {
|
||||
// workspace change, F1-F12
|
||||
|
||||
#if !TEST_MODE
|
||||
if (modifiers & B_COMMAND_KEY)
|
||||
#else
|
||||
if (modifiers & B_CONTROL_KEY)
|
||||
#endif
|
||||
{
|
||||
STRACE(("Set Workspace %ld\n", key - 1));
|
||||
RootLayer* root = fDesktop->RootLayer();
|
||||
|
||||
root->Lock();
|
||||
root->SetActiveWorkspace(key - 2);
|
||||
|
||||
#ifdef APPSERVER_ROOTLAYER_SHOW_WORKSPACE_NUMBER
|
||||
// to draw the current Workspace index on screen.
|
||||
BRegion region(VisibleRegion());
|
||||
fDesktop->GetDrawingEngine()->ConstrainClippingRegion(®ion);
|
||||
root->Draw(region.Frame());
|
||||
fDesktop->GetDrawingEngine()->ConstrainClippingRegion(NULL);
|
||||
#endif
|
||||
root->Unlock();
|
||||
return B_SKIP_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this should be moved client side!
|
||||
// (that's how it is done in BeOS, clients could need this key for
|
||||
// different purposes - also, it's preferrable to let the client
|
||||
// write the dump within his own environment)
|
||||
if (key == 0xe) {
|
||||
// screen dump, PrintScreen
|
||||
char filename[128];
|
||||
BEntry entry;
|
||||
|
||||
int32 index = 1;
|
||||
do {
|
||||
sprintf(filename, "/boot/home/screen%ld.png", index++);
|
||||
entry.SetTo(filename);
|
||||
} while(entry.Exists());
|
||||
|
||||
fDesktop->GetDrawingEngine()->DumpToFile(filename);
|
||||
return B_SKIP_MESSAGE;
|
||||
}
|
||||
|
||||
return B_DISPATCH_MESSAGE;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
Desktop::Desktop(uid_t userID)
|
||||
: MessageLooper("desktop"),
|
||||
fUserID(userID),
|
||||
@ -94,7 +187,7 @@ Desktop::Init()
|
||||
// TODO: add user identity to the name
|
||||
char name[32];
|
||||
sprintf(name, "RootLayer %d", 1);
|
||||
fRootLayer = new RootLayer(name, 4, this, GetDrawingEngine());
|
||||
fRootLayer = new ::RootLayer(name, 4, this, GetDrawingEngine());
|
||||
|
||||
#if TEST_MODE
|
||||
gInputManager->AddStream(new InputServerStream);
|
||||
@ -105,7 +198,7 @@ Desktop::Init()
|
||||
// temporary hack to get things started
|
||||
class MouseFilter : public BMessageFilter {
|
||||
public:
|
||||
MouseFilter(RootLayer* layer)
|
||||
MouseFilter(::RootLayer* layer)
|
||||
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
|
||||
fRootLayer(layer)
|
||||
{
|
||||
@ -121,9 +214,10 @@ Desktop::Init()
|
||||
}
|
||||
|
||||
private:
|
||||
RootLayer* fRootLayer;
|
||||
::RootLayer* fRootLayer;
|
||||
};
|
||||
fEventDispatcher.SetMouseFilter(new MouseFilter(fRootLayer));
|
||||
fEventDispatcher.SetKeyboardFilter(new KeyboardFilter(this));
|
||||
|
||||
// take care of setting the default cursor
|
||||
ServerCursor *cursor = fCursorManager.GetCursor(B_CURSOR_DEFAULT);
|
||||
@ -394,20 +488,17 @@ Desktop::AddWinBorder(WinBorder *winBorder)
|
||||
if (!winBorder)
|
||||
return;
|
||||
|
||||
// R2: how to determine the RootLayer to which this window should be added???
|
||||
// for now, use ActiveRootLayer() because we only have one instance.
|
||||
|
||||
int32 feel = winBorder->Feel();
|
||||
|
||||
// we are ServerApp thread, we need to lock RootLayer here.
|
||||
ActiveRootLayer()->Lock();
|
||||
RootLayer()->Lock();
|
||||
|
||||
// we're playing with window list. lock first.
|
||||
Lock();
|
||||
|
||||
if (fWinBorderList.HasItem(winBorder)) {
|
||||
Unlock();
|
||||
ActiveRootLayer()->Unlock();
|
||||
RootLayer()->Unlock();
|
||||
debugger("AddWinBorder: WinBorder already in Desktop list\n");
|
||||
return;
|
||||
}
|
||||
@ -443,12 +534,12 @@ Desktop::AddWinBorder(WinBorder *winBorder)
|
||||
}
|
||||
|
||||
// send WinBorder to be added to workspaces
|
||||
ActiveRootLayer()->AddWinBorder(winBorder);
|
||||
RootLayer()->AddWinBorder(winBorder);
|
||||
|
||||
// hey, unlock!
|
||||
Unlock();
|
||||
|
||||
ActiveRootLayer()->Unlock();
|
||||
RootLayer()->Unlock();
|
||||
}
|
||||
|
||||
|
||||
@ -459,7 +550,7 @@ Desktop::RemoveWinBorder(WinBorder *winBorder)
|
||||
return;
|
||||
|
||||
// we are ServerApp thread, we need to lock RootLayer here.
|
||||
ActiveRootLayer()->Lock();
|
||||
RootLayer()->Lock();
|
||||
|
||||
// we're playing with window list. lock first.
|
||||
Lock();
|
||||
@ -494,16 +585,16 @@ Desktop::RemoveWinBorder(WinBorder *winBorder)
|
||||
}
|
||||
} else {
|
||||
Unlock();
|
||||
ActiveRootLayer()->Unlock();
|
||||
RootLayer()->Unlock();
|
||||
debugger("RemoveWinBorder: WinBorder not found in Desktop list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell to winBorder's RootLayer about this.
|
||||
ActiveRootLayer()->RemoveWinBorder(winBorder);
|
||||
RootLayer()->RemoveWinBorder(winBorder);
|
||||
|
||||
Unlock();
|
||||
ActiveRootLayer()->Unlock();
|
||||
RootLayer()->Unlock();
|
||||
}
|
||||
|
||||
|
||||
@ -538,7 +629,7 @@ Desktop::AddWinBorderToSubset(WinBorder *winBorder, WinBorder *toWinBorder)
|
||||
}
|
||||
|
||||
// send WinBorder to be added to workspaces, if not already in there.
|
||||
ActiveRootLayer()->AddSubsetWinBorder(winBorder, toWinBorder);
|
||||
RootLayer()->AddSubsetWinBorder(winBorder, toWinBorder);
|
||||
|
||||
Unlock();
|
||||
}
|
||||
@ -562,7 +653,7 @@ Desktop::RemoveWinBorderFromSubset(WinBorder *winBorder, WinBorder *fromWinBorde
|
||||
}
|
||||
|
||||
// remove WinBorder from workspace, if needed - some other windows may still have it in their subset
|
||||
ActiveRootLayer()->RemoveSubsetWinBorder(winBorder, fromWinBorder);
|
||||
RootLayer()->RemoveSubsetWinBorder(winBorder, fromWinBorder);
|
||||
|
||||
if (fromWinBorder->Feel() == B_NORMAL_WINDOW_FEEL) {
|
||||
//remove from this normal_window's subset.
|
||||
|
@ -60,7 +60,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
|
||||
{ return fActiveScreen; }
|
||||
inline Screen* ActiveScreen() const
|
||||
{ return fActiveScreen; }
|
||||
inline RootLayer* ActiveRootLayer() const { return fRootLayer; }
|
||||
inline ::RootLayer* RootLayer() const { return fRootLayer; }
|
||||
inline CursorManager& GetCursorManager() { return fCursorManager; }
|
||||
|
||||
virtual void ScreenRemoved(Screen* screen) {}
|
||||
@ -116,7 +116,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
|
||||
|
||||
BObjectList<WinBorder> fWinBorderList;
|
||||
|
||||
RootLayer* fRootLayer;
|
||||
::RootLayer* fRootLayer;
|
||||
Screen* fActiveScreen;
|
||||
|
||||
CursorManager fCursorManager;
|
||||
|
@ -61,7 +61,7 @@ EventDispatcher::EventDispatcher()
|
||||
fTransit(false),
|
||||
fSuspendFocus(false),
|
||||
fMouseFilter(NULL),
|
||||
fKeyFilter(NULL),
|
||||
fKeyboardFilter(NULL),
|
||||
fListeners(10, true),
|
||||
// the list owns its items
|
||||
fCursorLock("cursor loop lock"),
|
||||
@ -322,15 +322,15 @@ EventDispatcher::SetMouseFilter(BMessageFilter* filter)
|
||||
|
||||
|
||||
void
|
||||
EventDispatcher::SetKeyFilter(BMessageFilter* filter)
|
||||
EventDispatcher::SetKeyboardFilter(BMessageFilter* filter)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
if (fKeyFilter == filter)
|
||||
if (fKeyboardFilter == filter)
|
||||
return;
|
||||
|
||||
delete fKeyFilter;
|
||||
fKeyFilter = filter;
|
||||
delete fKeyboardFilter;
|
||||
fKeyboardFilter = filter;
|
||||
}
|
||||
|
||||
|
||||
@ -501,8 +501,8 @@ EventDispatcher::_EventLoop()
|
||||
case B_UNMAPPED_KEY_DOWN:
|
||||
case B_UNMAPPED_KEY_UP:
|
||||
case B_MODIFIERS_CHANGED:
|
||||
if (fKeyFilter != NULL
|
||||
&& fKeyFilter->Filter(event, NULL) == B_SKIP_MESSAGE)
|
||||
if (fKeyboardFilter != NULL
|
||||
&& fKeyboardFilter->Filter(event, NULL) == B_SKIP_MESSAGE)
|
||||
break;
|
||||
|
||||
keyboardEvent = true;
|
||||
|
@ -36,7 +36,7 @@ class EventDispatcher : public BLocker {
|
||||
void RemoveListener(BMessenger& messenger, int32 token);
|
||||
|
||||
void SetMouseFilter(BMessageFilter* filter);
|
||||
void SetKeyFilter(BMessageFilter* filter);
|
||||
void SetKeyboardFilter(BMessageFilter* filter);
|
||||
|
||||
bool HasCursorThread();
|
||||
void SetHWInterface(HWInterface* interface);
|
||||
@ -81,7 +81,7 @@ class EventDispatcher : public BLocker {
|
||||
bool fSuspendFocus;
|
||||
|
||||
BMessageFilter* fMouseFilter;
|
||||
BMessageFilter* fKeyFilter;
|
||||
BMessageFilter* fKeyboardFilter;
|
||||
|
||||
BObjectList<event_target> fListeners;
|
||||
|
||||
|
@ -806,45 +806,6 @@ Layer::MouseWheelChanged(const BMessage *msg)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layer::KeyDown(const BMessage *msg)
|
||||
{
|
||||
if (Window() && !IsTopLayer()) {
|
||||
Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layer::KeyUp(const BMessage *msg)
|
||||
{
|
||||
if (Window() && !IsTopLayer()) {
|
||||
Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layer::UnmappedKeyDown(const BMessage *msg)
|
||||
{
|
||||
if (Window() && !IsTopLayer()) {
|
||||
Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layer::UnmappedKeyUp(const BMessage *msg)
|
||||
{
|
||||
if (Window() && !IsTopLayer()) {
|
||||
Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layer::ModifiersChanged(const BMessage *msg)
|
||||
{
|
||||
if (Window() && !IsTopLayer()) {
|
||||
Window()->SendMessageToClient(msg, B_NULL_TOKEN, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layer::WorkspaceActivated(int32 index, bool active)
|
||||
|
@ -146,12 +146,6 @@ class Layer {
|
||||
virtual void MouseMoved(const BMessage *msg);
|
||||
virtual void MouseWheelChanged(const BMessage *msg);
|
||||
|
||||
virtual void KeyDown(const BMessage *msg);
|
||||
virtual void KeyUp(const BMessage *msg);
|
||||
virtual void UnmappedKeyDown(const BMessage *msg);
|
||||
virtual void UnmappedKeyUp(const BMessage *msg);
|
||||
virtual void ModifiersChanged(const BMessage *msg);
|
||||
|
||||
virtual void WorkspaceActivated(int32 index, bool active);
|
||||
virtual void WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces);
|
||||
virtual void Activated(bool active);
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <Window.h>
|
||||
#include <List.h>
|
||||
#include <Message.h>
|
||||
#include <Entry.h>
|
||||
//#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <PortLink.h>
|
||||
|
||||
@ -1056,134 +1056,6 @@ RootLayer::MouseEventHandler(BMessage *msg)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RootLayer::KeyboardEventHandler(BMessage *msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case B_KEY_DOWN:
|
||||
{
|
||||
int32 scancode = 0;
|
||||
int32 modifiers = 0;
|
||||
|
||||
msg->FindInt32("key", &scancode);
|
||||
msg->FindInt32("modifiers", &modifiers);
|
||||
|
||||
// F1-F12
|
||||
if (scancode > 0x01 && scancode < 0x0e) {
|
||||
// Check for workspace change or safe video mode
|
||||
if (scancode == 0x0d && (modifiers & (B_LEFT_COMMAND_KEY
|
||||
| B_LEFT_CONTROL_KEY | B_LEFT_SHIFT_KEY)) != 0)
|
||||
{
|
||||
// TODO: Set to Safe Mode in KeyboardEventHandler:B_KEY_DOWN. (DrawingEngine API change)
|
||||
STRACE(("Safe Video Mode invoked - code unimplemented\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
#if !TEST_MODE
|
||||
if (modifiers & B_COMMAND_KEY)
|
||||
#else
|
||||
if (modifiers & B_CONTROL_KEY)
|
||||
#endif
|
||||
{
|
||||
STRACE(("Set Workspace %ld\n",scancode-1));
|
||||
SetActiveWorkspace(scancode - 2);
|
||||
#ifdef APPSERVER_ROOTLAYER_SHOW_WORKSPACE_NUMBER
|
||||
// to draw the current Workspace index on screen.
|
||||
BRegion reg(VisibleRegion());
|
||||
fDriver->ConstrainClippingRegion(®);
|
||||
Draw(reg.Frame());
|
||||
fDriver->ConstrainClippingRegion(NULL);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Tab key
|
||||
if (scancode == 0x26 && (modifiers & B_CONTROL_KEY)) {
|
||||
STRACE(("Twitcher\n"));
|
||||
//ServerApp *deskbar = app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
//if(deskbar)
|
||||
//{
|
||||
// TODO: implement;
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
//}
|
||||
}
|
||||
|
||||
// PrintScreen
|
||||
if (scancode == 0xe) {
|
||||
if (GetDrawingEngine()) {
|
||||
char filename[128];
|
||||
BEntry entry;
|
||||
|
||||
int32 index = 1;
|
||||
do {
|
||||
sprintf(filename, "/boot/home/screen%ld.png", index++);
|
||||
entry.SetTo(filename);
|
||||
} while(entry.Exists());
|
||||
|
||||
GetDrawingEngine()->DumpToFile(filename);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We got this far, so apparently it's safe to pass to the active
|
||||
// window.
|
||||
|
||||
if (Focus())
|
||||
Focus()->KeyDown(msg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case B_KEY_UP:
|
||||
{
|
||||
int32 scancode = 0;
|
||||
int32 modifiers = 0;
|
||||
|
||||
msg->FindInt32("key", &scancode);
|
||||
msg->FindInt32("modifiers", &modifiers);
|
||||
|
||||
// Tab key
|
||||
if (scancode == 0x26 && (modifiers & B_CONTROL_KEY)) {
|
||||
//ServerApp *deskbar=app_server->FindApp("application/x-vnd.Be-TSKB");
|
||||
//if(deskbar)
|
||||
//{
|
||||
printf("Send Twitcher message key to Deskbar - unimplmemented\n");
|
||||
break;
|
||||
//}
|
||||
}
|
||||
|
||||
// We got this far, so apparently it's safe to pass to the active
|
||||
// window.
|
||||
|
||||
if (Focus())
|
||||
Focus()->KeyUp(msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case B_UNMAPPED_KEY_DOWN:
|
||||
if (Focus())
|
||||
Focus()->UnmappedKeyDown(msg);
|
||||
break;
|
||||
|
||||
case B_UNMAPPED_KEY_UP:
|
||||
if (Focus())
|
||||
Focus()->UnmappedKeyUp(msg);
|
||||
break;
|
||||
|
||||
case B_MODIFIERS_CHANGED:
|
||||
if (Focus())
|
||||
Focus()->ModifiersChanged(msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
RootLayer::AddToInputNotificationLists(Layer *lay, uint32 mask, uint32 options)
|
||||
{
|
||||
|
@ -123,10 +123,6 @@ public:
|
||||
|
||||
thread_id LockingThread() { return fAllRegionsLock.LockingThread(); }
|
||||
|
||||
// BRegion fRedrawReg;
|
||||
// BList fCopyRegList;
|
||||
// BList fCopyList;
|
||||
|
||||
private:
|
||||
friend class Desktop;
|
||||
|
||||
@ -143,8 +139,6 @@ friend class Desktop;
|
||||
|
||||
// Input related methods
|
||||
void MouseEventHandler(BMessage *msg);
|
||||
void KeyboardEventHandler(BMessage *msg);
|
||||
|
||||
void _ProcessMouseMovedEvent(BMessage *msg);
|
||||
|
||||
Desktop* fDesktop;
|
||||
|
@ -847,7 +847,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
STRACE(("ServerApp %s: get current workspace\n", Signature()));
|
||||
|
||||
// TODO: Locking this way is not nice
|
||||
RootLayer *root = fDesktop->ActiveRootLayer();
|
||||
RootLayer *root = fDesktop->RootLayer();
|
||||
root->Lock();
|
||||
|
||||
fLink.StartMessage(SERVER_TRUE);
|
||||
@ -865,7 +865,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
// TODO: See above
|
||||
int32 index;
|
||||
link.Read<int32>(&index);
|
||||
RootLayer *root = fDesktop->ActiveRootLayer();
|
||||
RootLayer *root = fDesktop->RootLayer();
|
||||
root->Lock();
|
||||
root->SetActiveWorkspace(index);
|
||||
root->Unlock();
|
||||
@ -2098,9 +2098,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
bool makedefault = false;
|
||||
link.Read<bool>(&makedefault);
|
||||
|
||||
// TODO: lock RootLayer, set mode and tell it to update it's frame and all clipping
|
||||
// optionally put this into a message and let the root layer thread handle it.
|
||||
RootLayer* rootLayer = fDesktop->ActiveRootLayer();
|
||||
RootLayer* rootLayer = fDesktop->RootLayer();
|
||||
rootLayer->Lock();
|
||||
status_t status = fDesktop->ScreenAt(0)->SetMode(mode);
|
||||
if (status == B_OK) {
|
||||
@ -2189,7 +2187,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
|
||||
// ToDo: locking is probably wrong - why the hell is there no (safe)
|
||||
// way to get to the workspace object directly?
|
||||
RootLayer *root = fDesktop->ActiveRootLayer();
|
||||
RootLayer *root = fDesktop->RootLayer();
|
||||
root->Lock();
|
||||
|
||||
Workspace *workspace;
|
||||
|
@ -1587,7 +1587,7 @@ if (myRootLayer)
|
||||
// 2) int32 button state
|
||||
|
||||
fLink.Attach<BPoint>(fDesktop->HWInterface()->GetCursorPosition());
|
||||
fLink.Attach<int32>(fDesktop->ActiveRootLayer()->Buttons());
|
||||
fLink.Attach<int32>(fDesktop->RootLayer()->Buttons());
|
||||
|
||||
fLink.Flush();
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user