Apertura del repositorio

This commit is contained in:
2025-05-24 18:09:39 -03:00
parent 76e6359dad
commit d883ddd0d0
35253 changed files with 2891973 additions and 2 deletions
+198
View File
@@ -0,0 +1,198 @@
# -*- cmake -*-
#
# Compared to other libraries, compiling this one is a mess. The
# reason is that we have several source files that have two different
# sets of behaviour, depending on whether they're intended to be part
# of the viewer or the map server.
#
# Unfortunately, the affected code is a rat's nest of #ifdefs, so it's
# easier to play compilation tricks than to actually fix the problem.
project(llwindow)
include(00-Common)
include(DragDrop)
include(LLCommon)
include(LLImage)
include(LLWindow)
include(UI)
include(ViewerMiscLibs)
include(GLM)
set(llwindow_SOURCE_FILES
llcursortypes.cpp
llkeyboard.cpp
llkeyboardheadless.cpp
llwindowheadless.cpp
llwindowcallbacks.cpp
llwindow.cpp
)
set(llwindow_HEADER_FILES
CMakeLists.txt
llcursortypes.h
llkeyboard.h
llkeyboardheadless.h
llwindowheadless.h
llwindowcallbacks.h
)
set(viewer_SOURCE_FILES
llmousehandler.cpp
)
set(viewer_HEADER_FILES
llwindow.h
llpreeditor.h
llmousehandler.h
)
set(llwindow_LINK_LIBRARIES
llcommon
llimage
llmath
llrender
llfilesystem
llxml
ll::glm
ll::glext
ll::uilibraries
ll::SDL
)
if(LINUX)
set(llwindow_LINK_LIBRARIES ${llwindow_LINK_LIBRARIES} ll::fontconfig)
endif()
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
if (LINUX)
if( USE_SDL1 )
list(APPEND viewer_SOURCE_FILES
llkeyboardsdl.cpp
llwindowsdl.cpp
)
list(APPEND viewer_HEADER_FILES
llkeyboardsdl.h
llwindowsdl.h
)
else()
list(APPEND viewer_SOURCE_FILES
llkeyboardsdl2.cpp
llwindowsdl2.cpp
)
list(APPEND viewer_HEADER_FILES
llkeyboardsdl2.h
llwindowsdl2.h
)
endif()
if (BUILD_HEADLESS)
set(llwindowheadless_LINK_LIBRARIES
${LLCOMMON_LIBRARIES}
${LLIMAGE_LIBRARIES}
${LLMATH_LIBRARIES}
${LLRENDER_HEADLESS_LIBRARIES}
${LLFILESYSTEM_LIBRARIES}
${LLWINDOW_HEADLESS_LIBRARIES}
${LLXML_LIBRARIES}
fontconfig # For FCInit and other FC* functions.
)
endif (BUILD_HEADLESS)
endif (LINUX)
if (DARWIN)
list(APPEND llwindow_SOURCE_FILES
llkeyboardmacosx.cpp
llwindowmacosx.cpp
llwindowmacosx-objc.mm
llopenglview-objc.mm
)
list(APPEND llwindow_HEADER_FILES
llkeyboardmacosx.h
llwindowmacosx.h
llwindowmacosx-objc.h
llopenglview-objc.h
llappdelegate-objc.h
)
# We use a bunch of deprecated system APIs.
set_source_files_properties(
llkeyboardmacosx.cpp
llwindowmacosx.cpp
PROPERTIES
COMPILE_FLAGS "-Wno-deprecated-declarations -fpascal-strings"
)
endif (DARWIN)
if (WINDOWS)
list(APPEND llwindow_SOURCE_FILES
llwindowwin32.cpp
lldxhardware.cpp
llkeyboardwin32.cpp
lldragdropwin32.cpp
)
list(APPEND llwindow_HEADER_FILES
llwindowwin32.h
lldxhardware.h
llkeyboardwin32.h
lldragdropwin32.h
)
list(APPEND llwindow_LINK_LIBRARIES
comdlg32 # Common Dialogs for ChooseColor
ole32
dxgi
d3d9
)
endif (WINDOWS)
if (SOLARIS)
list(APPEND llwindow_SOURCE_FILES
llwindowsolaris.cpp
)
list(APPEND llwindow_HEADER_FILES
llwindowsolaris.h
)
endif (SOLARIS)
if (BUILD_HEADLESS)
set(llwindowheadless_SOURCE_FILES
llwindowmesaheadless.cpp
llmousehandler.cpp
)
set(llwindowheadless_HEADER_FILES
llwindowmesaheadless.h
llmousehandler.h
)
add_library (llwindowheadless
${llwindow_SOURCE_FILES}
${llwindowheadless_SOURCE_FILES}
)
set_property(TARGET llwindowheadless
PROPERTY COMPILE_DEFINITIONS LL_MESA=1 LL_MESA_HEADLESS=1
)
target_link_libraries (llwindowheadless ${llwindowheadless_LINK_LIBRARIES} dl)
endif (BUILD_HEADLESS)
if (llwindow_HEADER_FILES)
list(APPEND llwindow_SOURCE_FILES ${llwindow_HEADER_FILES})
endif (llwindow_HEADER_FILES)
list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES})
add_library (llwindow
${llwindow_SOURCE_FILES}
${viewer_SOURCE_FILES}
)
target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES})
target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
if (DARWIN)
include(CMakeFindFrameworks)
find_library(CARBON_LIBRARY Carbon)
target_link_libraries(llwindow ${CARBON_LIBRARY})
endif (DARWIN)
+52
View File
@@ -0,0 +1,52 @@
/**
* @file llappdelegate-objc.h
* @brief Class interface for the Mac version's application delegate.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#import <Cocoa/Cocoa.h>
#import "llopenglview-objc.h"
@interface LLAppDelegate : NSObject <NSApplicationDelegate> {
LLNSWindow *window;
NSWindow *inputWindow;
LLNonInlineTextView *inputView;
NSTimer *frameTimer;
NSString *currentInputLanguage;
std::string secondLogPath;
}
@property (assign) IBOutlet LLNSWindow *window;
@property (assign) IBOutlet NSWindow *inputWindow;
@property (assign) IBOutlet LLNonInlineTextView *inputView;
@property (retain) NSString *currentInputLanguage;
- (void) oneFrame;
- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;
- (void) languageUpdated;
- (bool) romanScript;
@end
@interface LLApplication : NSApplication
@end
+94
View File
@@ -0,0 +1,94 @@
/**
* @file llcursortypes.cpp
* @brief Cursor types and lookup of types from a string
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llcursortypes.h"
ECursorType getCursorFromString(const std::string& cursor_string)
{
static std::map<std::string,U32> cursor_string_table;
if (cursor_string_table.empty())
{
cursor_string_table["UI_CURSOR_ARROW"] = UI_CURSOR_ARROW;
cursor_string_table["UI_CURSOR_WAIT"] = UI_CURSOR_WAIT;
cursor_string_table["UI_CURSOR_HAND"] = UI_CURSOR_HAND;
cursor_string_table["UI_CURSOR_IBEAM"] = UI_CURSOR_IBEAM;
cursor_string_table["UI_CURSOR_CROSS"] = UI_CURSOR_CROSS;
cursor_string_table["UI_CURSOR_SIZENWSE"] = UI_CURSOR_SIZENWSE;
cursor_string_table["UI_CURSOR_SIZENESW"] = UI_CURSOR_SIZENESW;
cursor_string_table["UI_CURSOR_SIZEWE"] = UI_CURSOR_SIZEWE;
cursor_string_table["UI_CURSOR_SIZENS"] = UI_CURSOR_SIZENS;
cursor_string_table["UI_CURSOR_SIZEALL"] = UI_CURSOR_SIZEALL;
cursor_string_table["UI_CURSOR_NO"] = UI_CURSOR_NO;
cursor_string_table["UI_CURSOR_WORKING"] = UI_CURSOR_WORKING;
cursor_string_table["UI_CURSOR_TOOLGRAB"] = UI_CURSOR_TOOLGRAB;
cursor_string_table["UI_CURSOR_TOOLLAND"] = UI_CURSOR_TOOLLAND;
cursor_string_table["UI_CURSOR_TOOLFOCUS"] = UI_CURSOR_TOOLFOCUS;
cursor_string_table["UI_CURSOR_TOOLCREATE"] = UI_CURSOR_TOOLCREATE;
cursor_string_table["UI_CURSOR_ARROWDRAG"] = UI_CURSOR_ARROWDRAG;
cursor_string_table["UI_CURSOR_ARROWCOPY"] = UI_CURSOR_ARROWCOPY;
cursor_string_table["UI_CURSOR_ARROWDRAGMULTI"] = UI_CURSOR_ARROWDRAGMULTI;
cursor_string_table["UI_CURSOR_ARROWCOPYMULTI"] = UI_CURSOR_ARROWCOPYMULTI;
cursor_string_table["UI_CURSOR_NOLOCKED"] = UI_CURSOR_NOLOCKED;
cursor_string_table["UI_CURSOR_ARROWLOCKED"] = UI_CURSOR_ARROWLOCKED;
cursor_string_table["UI_CURSOR_GRABLOCKED"] = UI_CURSOR_GRABLOCKED;
cursor_string_table["UI_CURSOR_TOOLTRANSLATE"] = UI_CURSOR_TOOLTRANSLATE;
cursor_string_table["UI_CURSOR_TOOLROTATE"] = UI_CURSOR_TOOLROTATE;
cursor_string_table["UI_CURSOR_TOOLSCALE"] = UI_CURSOR_TOOLSCALE;
cursor_string_table["UI_CURSOR_TOOLCAMERA"] = UI_CURSOR_TOOLCAMERA;
cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN;
cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN;
cursor_string_table["UI_CURSOR_TOOLZOOMOUT"] = UI_CURSOR_TOOLZOOMOUT;
cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3;
cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY;
cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE;
cursor_string_table["UI_CURSOR_TOOLMEDIAOPEN"] = UI_CURSOR_TOOLMEDIAOPEN;
cursor_string_table["UI_CURSOR_PIPETTE"] = UI_CURSOR_PIPETTE;
cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT;
cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY;
cursor_string_table["UI_CURSOR_TOOLPAY"] = UI_CURSOR_TOOLPAY; // <FS:LO> Legacy cursor setting from main program
cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN;
cursor_string_table["UI_CURSOR_TOOLPATHFINDING"] = UI_CURSOR_TOOLPATHFINDING;
cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHSTART"] = UI_CURSOR_TOOLPATHFINDING_PATH_START;
cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHSTARTADD"] = UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD;
cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHEND"] = UI_CURSOR_TOOLPATHFINDING_PATH_END;
cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHENDADD"] = UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD;
cursor_string_table["UI_CURSOR_TOOLNO"] = UI_CURSOR_TOOLNO;
}
std::map<std::string,U32>::const_iterator iter = cursor_string_table.find(cursor_string);
if (iter != cursor_string_table.end())
{
return (ECursorType)iter->second;
}
return UI_CURSOR_ARROW;
}
+82
View File
@@ -0,0 +1,82 @@
/**
* @file llcursortypes.h
* @brief Cursor types
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLCURSORTYPES_H
#define LL_LLCURSORTYPES_H
// If you add types here, add them in LLCursor::getCursorFromString
enum ECursorType {
UI_CURSOR_ARROW,
UI_CURSOR_WAIT,
UI_CURSOR_HAND,
UI_CURSOR_IBEAM,
UI_CURSOR_CROSS,
UI_CURSOR_SIZENWSE,
UI_CURSOR_SIZENESW,
UI_CURSOR_SIZEWE,
UI_CURSOR_SIZENS,
UI_CURSOR_SIZEALL,
UI_CURSOR_NO,
UI_CURSOR_WORKING,
UI_CURSOR_TOOLGRAB,
UI_CURSOR_TOOLLAND,
UI_CURSOR_TOOLFOCUS,
UI_CURSOR_TOOLCREATE,
UI_CURSOR_ARROWDRAG,
UI_CURSOR_ARROWCOPY, // drag with copy
UI_CURSOR_ARROWDRAGMULTI,
UI_CURSOR_ARROWCOPYMULTI, // drag with copy
UI_CURSOR_NOLOCKED,
UI_CURSOR_ARROWLOCKED,
UI_CURSOR_GRABLOCKED,
UI_CURSOR_TOOLTRANSLATE,
UI_CURSOR_TOOLROTATE,
UI_CURSOR_TOOLSCALE,
UI_CURSOR_TOOLCAMERA,
UI_CURSOR_TOOLPAN,
UI_CURSOR_TOOLZOOMIN,
UI_CURSOR_TOOLZOOMOUT,
UI_CURSOR_TOOLPICKOBJECT3,
UI_CURSOR_TOOLPLAY,
UI_CURSOR_TOOLPAUSE,
UI_CURSOR_TOOLMEDIAOPEN,
UI_CURSOR_PIPETTE,
UI_CURSOR_TOOLSIT,
UI_CURSOR_TOOLBUY,
UI_CURSOR_TOOLPAY, // <FS:LO> Legacy cursor setting from main program
UI_CURSOR_TOOLOPEN,
UI_CURSOR_TOOLPATHFINDING,
UI_CURSOR_TOOLPATHFINDING_PATH_START,
UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD,
UI_CURSOR_TOOLPATHFINDING_PATH_END,
UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD,
UI_CURSOR_TOOLNO,
UI_CURSOR_COUNT // Number of elements in this enum (NOT a cursor)
};
LL_COMMON_API ECursorType getCursorFromString(const std::string& cursor_string);
#endif // LL_LLCURSORTYPES_H
+361
View File
@@ -0,0 +1,361 @@
/**
* @file lldragdrop32.cpp
* @brief Handler for Windows specific drag and drop (OS to client) code
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#if LL_WINDOWS
#if LL_OS_DRAGDROP_ENABLED
#include "linden_common.h"
#include "llwindowwin32.h"
#include "llkeyboardwin32.h"
#include "llwindowcallbacks.h"
#include "lldragdropwin32.h"
class LLDragDropWin32Target:
public IDropTarget
{
public:
////////////////////////////////////////////////////////////////////////////////
//
LLDragDropWin32Target( HWND hWnd ) :
mRefCount( 1 ),
mAppWindowHandle( hWnd ),
mAllowDrop(false),
mIsSlurl(false)
{
};
virtual ~LLDragDropWin32Target()
{
};
////////////////////////////////////////////////////////////////////////////////
//
ULONG __stdcall AddRef( void )
{
return InterlockedIncrement( &mRefCount );
};
////////////////////////////////////////////////////////////////////////////////
//
ULONG __stdcall Release( void )
{
LONG count = InterlockedDecrement( &mRefCount );
if ( count == 0 )
{
delete this;
return 0;
}
else
{
return count;
};
};
////////////////////////////////////////////////////////////////////////////////
//
HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject )
{
if ( iid == IID_IUnknown || iid == IID_IDropTarget )
{
AddRef();
*ppvObject = this;
return S_OK;
}
else
{
*ppvObject = 0;
return E_NOINTERFACE;
};
};
////////////////////////////////////////////////////////////////////////////////
//
HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
{
FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
// support CF_TEXT using a HGLOBAL?
if ( S_OK == pDataObject->QueryGetData( &fmtetc ) )
{
mAllowDrop = true;
mDropUrl = std::string();
mIsSlurl = false;
STGMEDIUM stgmed;
if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) )
{
PVOID data = GlobalLock( stgmed.hGlobal );
mDropUrl = std::string( (char*)data );
// XXX MAJOR MAJOR HACK!
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( mAppWindowHandle, GWLP_USERDATA );
if (NULL != window_imp)
{
LLCoordGL gl_coord( 0, 0 );
POINT pt2;
pt2.x = pt.x;
pt2.y = pt.y;
ScreenToClient( mAppWindowHandle, &pt2 );
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
MASK mask = gKeyboard->currentMask(true);
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
switch (result)
{
case LLWindowCallbacks::DND_COPY:
*pdwEffect = DROPEFFECT_COPY;
break;
case LLWindowCallbacks::DND_LINK:
*pdwEffect = DROPEFFECT_LINK;
break;
case LLWindowCallbacks::DND_MOVE:
*pdwEffect = DROPEFFECT_MOVE;
break;
case LLWindowCallbacks::DND_NONE:
default:
*pdwEffect = DROPEFFECT_NONE;
break;
}
};
GlobalUnlock( stgmed.hGlobal );
ReleaseStgMedium( &stgmed );
};
SetFocus( mAppWindowHandle );
}
else
{
mAllowDrop = false;
*pdwEffect = DROPEFFECT_NONE;
};
return S_OK;
};
////////////////////////////////////////////////////////////////////////////////
//
HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
{
if ( mAllowDrop )
{
// XXX MAJOR MAJOR HACK!
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( mAppWindowHandle, GWLP_USERDATA );
if (NULL != window_imp)
{
LLCoordGL gl_coord( 0, 0 );
POINT pt2;
pt2.x = pt.x;
pt2.y = pt.y;
ScreenToClient( mAppWindowHandle, &pt2 );
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
MASK mask = gKeyboard->currentMask(true);
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
LLWindowCallbacks::DNDA_TRACK, mDropUrl );
switch (result)
{
case LLWindowCallbacks::DND_COPY:
*pdwEffect = DROPEFFECT_COPY;
break;
case LLWindowCallbacks::DND_LINK:
*pdwEffect = DROPEFFECT_LINK;
break;
case LLWindowCallbacks::DND_MOVE:
*pdwEffect = DROPEFFECT_MOVE;
break;
case LLWindowCallbacks::DND_NONE:
default:
*pdwEffect = DROPEFFECT_NONE;
break;
}
};
}
else
{
*pdwEffect = DROPEFFECT_NONE;
};
return S_OK;
};
////////////////////////////////////////////////////////////////////////////////
//
HRESULT __stdcall DragLeave( void )
{
// XXX MAJOR MAJOR HACK!
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( mAppWindowHandle, GWLP_USERDATA );
if (NULL != window_imp)
{
LLCoordGL gl_coord( 0, 0 );
MASK mask = gKeyboard->currentMask(true);
window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl );
};
return S_OK;
};
////////////////////////////////////////////////////////////////////////////////
//
HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
{
if ( mAllowDrop )
{
// window impl stored in Window data (neat!)
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( mAppWindowHandle, GWLP_USERDATA );
if ( NULL != window_imp )
{
POINT pt_client;
pt_client.x = pt.x;
pt_client.y = pt.y;
ScreenToClient( mAppWindowHandle, &pt_client );
LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y );
LLCoordGL gl_coord(cursor_coord_window.convert());
LL_INFOS() << "### (Drop) URL is: " << mDropUrl << LL_ENDL;
LL_INFOS() << "### raw coords are: " << pt.x << " x " << pt.y << LL_ENDL;
LL_INFOS() << "### client coords are: " << pt_client.x << " x " << pt_client.y << LL_ENDL;
LL_INFOS() << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << LL_ENDL;
LL_INFOS() << LL_ENDL;
// no keyboard modifier option yet but we could one day
MASK mask = gKeyboard->currentMask( true );
// actually do the drop
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
LLWindowCallbacks::DNDA_DROPPED, mDropUrl );
switch (result)
{
case LLWindowCallbacks::DND_COPY:
*pdwEffect = DROPEFFECT_COPY;
break;
case LLWindowCallbacks::DND_LINK:
*pdwEffect = DROPEFFECT_LINK;
break;
case LLWindowCallbacks::DND_MOVE:
*pdwEffect = DROPEFFECT_MOVE;
break;
case LLWindowCallbacks::DND_NONE:
default:
*pdwEffect = DROPEFFECT_NONE;
break;
}
};
}
else
{
*pdwEffect = DROPEFFECT_NONE;
};
return S_OK;
};
////////////////////////////////////////////////////////////////////////////////
//
private:
LONG mRefCount;
HWND mAppWindowHandle;
bool mAllowDrop;
std::string mDropUrl;
bool mIsSlurl;
friend class LLWindowWin32;
};
////////////////////////////////////////////////////////////////////////////////
//
LLDragDropWin32::LLDragDropWin32() :
mDropTarget( NULL ),
mDropWindowHandle( NULL )
{
}
////////////////////////////////////////////////////////////////////////////////
//
LLDragDropWin32::~LLDragDropWin32()
{
}
////////////////////////////////////////////////////////////////////////////////
//
bool LLDragDropWin32::init( HWND hWnd )
{
if ( NOERROR != OleInitialize( NULL ) )
return false;
mDropTarget = new LLDragDropWin32Target( hWnd );
if ( mDropTarget )
{
HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE );
if ( S_OK == result )
{
result = RegisterDragDrop( hWnd, mDropTarget );
if ( S_OK != result )
{
// RegisterDragDrop failed
return false;
};
// all ok
mDropWindowHandle = hWnd;
}
else
{
// Unable to lock OLE object
return false;
};
};
// success
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
void LLDragDropWin32::reset()
{
if ( mDropTarget )
{
RevokeDragDrop( mDropWindowHandle );
CoLockObjectExternal( mDropTarget, FALSE, TRUE );
mDropTarget->Release();
};
OleUninitialize();
}
#endif // LL_OS_DRAGDROP_ENABLED
#endif // LL_WINDOWS
+74
View File
@@ -0,0 +1,74 @@
/**
* @file lldragdrop32.cpp
* @brief Handler for Windows specific drag and drop (OS to client) code
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#if LL_WINDOWS
#if LL_OS_DRAGDROP_ENABLED
#ifndef LL_LLDRAGDROP32_H
#define LL_LLDRAGDROP32_H
#include "llwin32headers.h"
#include <ole2.h>
class LLDragDropWin32
{
public:
LLDragDropWin32();
~LLDragDropWin32();
bool init( HWND hWnd );
void reset();
private:
IDropTarget* mDropTarget;
HWND mDropWindowHandle;
};
#endif // LL_LLDRAGDROP32_H
#else // LL_OS_DRAGDROP_ENABLED
#ifndef LL_LLDRAGDROP32_H
#define LL_LLDRAGDROP32_H
#include "llwin32headers.h"
#include <ole2.h>
// impostor class that does nothing
class LLDragDropWin32
{
public:
LLDragDropWin32() {};
~LLDragDropWin32() {};
bool init( HWND hWnd ) { return false; };
void reset() { };
};
#endif // LL_LLDRAGDROP32_H
#endif // LL_OS_DRAGDROP_ENABLED
#endif // LL_WINDOWS
File diff suppressed because it is too large Load Diff
+129
View File
@@ -0,0 +1,129 @@
/**
* @file lldxhardware.h
* @brief LLDXHardware definition
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLDXHARDWARE_H
#define LL_LLDXHARDWARE_H
#include <map>
#include "stdtypes.h"
#include "llstring.h"
#include "llsd.h"
class LLVersion
{
public:
LLVersion();
bool set(const std::string &version_string);
S32 getField(const S32 field_num);
protected:
std::string mVersionString;
S32 mFields[4];
bool mValid;
};
class LLDXDriverFile
{
public:
std::string dump();
public:
std::string mFilepath;
std::string mName;
std::string mVersionString;
LLVersion mVersion;
std::string mDateString;
};
class LLDXDevice
{
public:
~LLDXDevice();
std::string dump();
LLDXDriverFile *findDriver(const std::string &driver);
public:
std::string mName;
std::string mPCIString;
std::string mVendorID;
std::string mDeviceID;
typedef std::map<std::string, LLDXDriverFile *> driver_file_map_t;
driver_file_map_t mDriverFiles;
};
class LLDXHardware
{
public:
LLDXHardware();
void setWriteDebugFunc(void (*func)(const char*));
void cleanup();
// Returns true on success.
// vram_only true does a "light" probe.
// <FS:Ansariel> FIRE-15891: Add option to disable WMI check in case of problems
//bool getInfo(bool vram_only);
bool getInfo(bool vram_only, bool disable_wmi);
// </FS:Ansariel>
// WMI can return multiple GPU drivers
// specify which one to output
typedef enum {
GPU_INTEL,
GPU_NVIDIA,
GPU_AMD,
GPU_ANY
} EGPUVendor;
std::string getDriverVersionWMI(EGPUVendor vendor);
S32 getVRAM() const { return mVRAM; }
LLSD getDisplayInfo();
// Will get memory of best GPU in MB, return memory on sucsess, 0 on failure
// Note: WMI is not accurate in some cases
static U32 getMBVideoMemoryViaWMI();
// Find a particular device that matches the following specs.
// Empty strings indicate that you don't care.
// You can separate multiple devices with '|' chars to indicate you want
// ANY of them to match and return.
// LLDXDevice *findDevice(const std::string &vendor, const std::string &devices);
// std::string dumpDevices();
public:
typedef std::map<std::string, LLDXDevice *> device_map_t;
// device_map_t mDevices;
protected:
S32 mVRAM;
};
extern void (*gWriteDebug)(const char* msg);
extern LLDXHardware gDXHardware;
#endif // LL_LLDXHARDWARE_H
+544
View File
@@ -0,0 +1,544 @@
/**
* @file llkeyboard.cpp
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "indra_constants.h"
#include "llkeyboard.h"
#include "llwindowcallbacks.h"
//
// Globals
//
LLKeyboard *gKeyboard = NULL;
//static
std::map<KEY,std::string> LLKeyboard::sKeysToNames;
std::map<std::string,KEY> LLKeyboard::sNamesToKeys;
LLKeyStringTranslatorFunc* LLKeyboard::mStringTranslator = NULL; // Used for l10n + PC/Mac/Linux accelerator labeling
//
// Class Implementation
//
LLKeyboard::LLKeyboard() : mCallbacks(NULL)
{
S32 i;
// Constructor for LLTimer inits each timer. We want them to
// be constructed without being initialized, so we shut them down here.
for (i = 0; i < KEY_COUNT; i++)
{
mKeyLevelFrameCount[i] = 0;
mKeyLevel[i] = false;
mKeyUp[i] = false;
mKeyDown[i] = false;
mKeyRepeated[i] = false;
}
mInsertMode = LL_KIM_INSERT;
mCurTranslatedKey = KEY_NONE;
mCurScanKey = KEY_NONE;
addKeyName(' ', "Space" );
addKeyName(KEY_RETURN, "Enter" );
addKeyName(KEY_LEFT, "Left" );
addKeyName(KEY_RIGHT, "Right" );
addKeyName(KEY_UP, "Up" );
addKeyName(KEY_DOWN, "Down" );
addKeyName(KEY_ESCAPE, "Esc" );
addKeyName(KEY_HOME, "Home" );
addKeyName(KEY_END, "End" );
addKeyName(KEY_PAGE_UP, "PgUp" );
addKeyName(KEY_PAGE_DOWN, "PgDn" );
addKeyName(KEY_F1, "F1" );
addKeyName(KEY_F2, "F2" );
addKeyName(KEY_F3, "F3" );
addKeyName(KEY_F4, "F4" );
addKeyName(KEY_F5, "F5" );
addKeyName(KEY_F6, "F6" );
addKeyName(KEY_F7, "F7" );
addKeyName(KEY_F8, "F8" );
addKeyName(KEY_F9, "F9" );
addKeyName(KEY_F10, "F10" );
addKeyName(KEY_F11, "F11" );
addKeyName(KEY_F12, "F12" );
addKeyName(KEY_TAB, "Tab" );
addKeyName(KEY_ADD, "Add" );
addKeyName(KEY_SUBTRACT, "Subtract" );
addKeyName(KEY_MULTIPLY, "Multiply" );
addKeyName(KEY_DIVIDE, "Divide" );
addKeyName(KEY_PAD_DIVIDE, "PAD_DIVIDE" );
addKeyName(KEY_PAD_LEFT, "PAD_LEFT" );
addKeyName(KEY_PAD_RIGHT, "PAD_RIGHT" );
addKeyName(KEY_PAD_DOWN, "PAD_DOWN" );
addKeyName(KEY_PAD_UP, "PAD_UP" );
addKeyName(KEY_PAD_HOME, "PAD_HOME" );
addKeyName(KEY_PAD_END, "PAD_END" );
addKeyName(KEY_PAD_PGUP, "PAD_PGUP" );
addKeyName(KEY_PAD_PGDN, "PAD_PGDN" );
addKeyName(KEY_PAD_CENTER, "PAD_CENTER" );
addKeyName(KEY_PAD_INS, "PAD_INS" );
addKeyName(KEY_PAD_DEL, "PAD_DEL" );
addKeyName(KEY_PAD_RETURN, "PAD_Enter" );
addKeyName(KEY_BUTTON0, "PAD_BUTTON0" );
addKeyName(KEY_BUTTON1, "PAD_BUTTON1" );
addKeyName(KEY_BUTTON2, "PAD_BUTTON2" );
addKeyName(KEY_BUTTON3, "PAD_BUTTON3" );
addKeyName(KEY_BUTTON4, "PAD_BUTTON4" );
addKeyName(KEY_BUTTON5, "PAD_BUTTON5" );
addKeyName(KEY_BUTTON6, "PAD_BUTTON6" );
addKeyName(KEY_BUTTON7, "PAD_BUTTON7" );
addKeyName(KEY_BUTTON8, "PAD_BUTTON8" );
addKeyName(KEY_BUTTON9, "PAD_BUTTON9" );
addKeyName(KEY_BUTTON10, "PAD_BUTTON10" );
addKeyName(KEY_BUTTON11, "PAD_BUTTON11" );
addKeyName(KEY_BUTTON12, "PAD_BUTTON12" );
addKeyName(KEY_BUTTON13, "PAD_BUTTON13" );
addKeyName(KEY_BUTTON14, "PAD_BUTTON14" );
addKeyName(KEY_BUTTON15, "PAD_BUTTON15" );
addKeyName(KEY_BACKSPACE, "Backsp" );
addKeyName(KEY_DELETE, "Del" );
addKeyName(KEY_SHIFT, "Shift" );
addKeyName(KEY_CONTROL, "Ctrl" );
addKeyName(KEY_ALT, "Alt" );
addKeyName(KEY_HYPHEN, "-" );
addKeyName(KEY_EQUALS, "=" );
addKeyName(KEY_INSERT, "Ins" );
addKeyName(KEY_CAPSLOCK, "CapsLock" );
}
LLKeyboard::~LLKeyboard()
{
// nothing
}
void LLKeyboard::addKeyName(KEY key, const std::string& name)
{
sKeysToNames[key] = name;
std::string nameuc = name;
LLStringUtil::toUpper(nameuc);
sNamesToKeys[nameuc] = key;
}
void LLKeyboard::resetKeyDownAndHandle()
{
MASK mask = currentMask(false);
for (S32 i = 0; i < KEY_COUNT; i++)
{
if (mKeyLevel[i])
{
mKeyDown[i] = false;
mKeyLevel[i] = false;
mKeyUp[i] = true;
mCurTranslatedKey = (KEY)i;
mCallbacks->handleTranslatedKeyUp(i, mask);
}
}
}
// BUG this has to be called when an OS dialog is shown, otherwise modifier key state
// is wrong because the keyup event is never received by the main window. JC
void LLKeyboard::resetKeys()
{
S32 i;
for (i = 0; i < KEY_COUNT; i++)
{
if( mKeyLevel[i] )
{
mKeyLevel[i] = false;
}
}
for (i = 0; i < KEY_COUNT; i++)
{
mKeyUp[i] = false;
}
for (i = 0; i < KEY_COUNT; i++)
{
mKeyDown[i] = false;
}
for (i = 0; i < KEY_COUNT; i++)
{
mKeyRepeated[i] = false;
}
}
// <FS:ND/> SDL2 compat
//bool LLKeyboard::translateKey(const U16 os_key, KEY *out_key)
bool LLKeyboard::translateKey(const NATIVE_KEY_TYPE os_key, KEY *out_key)
{
// Only translate keys in the map, ignore all other keys for now
auto iter = mTranslateKeyMap.find(os_key);
if (iter == mTranslateKeyMap.end())
{
//LL_WARNS() << "Unknown virtual key " << os_key << LL_ENDL;
*out_key = 0;
return false;
}
else
{
*out_key = iter->second;
return true;
}
}
// <FS:ND/> SDL2 compat
//U16 LLKeyboard::inverseTranslateKey(const KEY translated_key)
LLKeyboard::NATIVE_KEY_TYPE LLKeyboard::inverseTranslateKey(const KEY translated_key)
{
auto iter = mInvTranslateKeyMap.find(translated_key);
if (iter == mInvTranslateKeyMap.end())
{
return 0;
}
else
{
return iter->second;
}
}
bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask)
{
bool handled = false;
bool repeated = false;
// is this the first time the key went down?
// if so, generate "character" message
if( !mKeyLevel[translated_key] )
{
mKeyLevel[translated_key] = true;
mKeyLevelTimer[translated_key].reset();
mKeyLevelFrameCount[translated_key] = 0;
mKeyRepeated[translated_key] = false;
}
else
{
// Level is already down, assume it's repeated.
repeated = true;
mKeyRepeated[translated_key] = true;
}
mKeyDown[translated_key] = true;
mCurTranslatedKey = (KEY)translated_key;
handled = mCallbacks->handleTranslatedKeyDown(translated_key, translated_mask, repeated);
return handled;
}
bool LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask)
{
bool handled = false;
if( mKeyLevel[translated_key] )
{
mKeyLevel[translated_key] = false;
// Only generate key up events if the key is thought to
// be down. This allows you to call resetKeys() in the
// middle of a frame and ignore subsequent KEY_UP
// messages in the same frame. This was causing the
// sequence W<return> in chat to move agents forward. JC
mKeyUp[translated_key] = true;
handled = mCallbacks->handleTranslatedKeyUp(translated_key, translated_mask);
}
LL_DEBUGS("UserInput") << "keyup -" << translated_key << "-" << LL_ENDL;
return handled;
}
void LLKeyboard::toggleInsertMode()
{
if (LL_KIM_INSERT == mInsertMode)
{
mInsertMode = LL_KIM_OVERWRITE;
}
else
{
mInsertMode = LL_KIM_INSERT;
}
}
// Returns time in seconds since key was pressed.
F32 LLKeyboard::getKeyElapsedTime(KEY key)
{
return mKeyLevelTimer[key].getElapsedTimeF32();
}
// Returns time in frames since key was pressed.
S32 LLKeyboard::getKeyElapsedFrameCount(KEY key)
{
return mKeyLevelFrameCount[key];
}
// static
bool LLKeyboard::keyFromString(const std::string& str, KEY *key)
{
std::string instring(str);
size_t length = instring.size();
if (length < 1)
{
return false;
}
if (length == 1)
{
char ch = toupper(instring[0]);
if (('0' <= ch && ch <= '9') ||
('A' <= ch && ch <= 'Z') ||
('!' <= ch && ch <= '/') || // !"#$%&'()*+,-./
(':' <= ch && ch <= '@') || // :;<=>?@
('[' <= ch && ch <= '`') || // [\]^_`
('{' <= ch && ch <= '~')) // {|}~
{
*key = ch;
return true;
}
}
LLStringUtil::toUpper(instring);
KEY res = get_if_there(sNamesToKeys, instring, (KEY)0);
if (res != 0)
{
*key = res;
return true;
}
LL_WARNS() << "keyFromString failed: " << str << LL_ENDL;
return false;
}
// static
std::string LLKeyboard::stringFromKey(KEY key, bool translate)
{
std::string res = get_if_there(sKeysToNames, key, std::string());
if (res.empty())
{
char buffer[2]; /* Flawfinder: ignore */
buffer[0] = key;
buffer[1] = '\0';
res = std::string(buffer);
}
if (translate)
{
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans != NULL)
{
res = trans(res);
}
}
return res;
}
//static
std::string LLKeyboard::stringFromMouse(EMouseClickType click, bool translate)
{
std::string res;
switch (click)
{
case CLICK_LEFT:
res = "LMB";
break;
case CLICK_MIDDLE:
res = "MMB";
break;
case CLICK_RIGHT:
res = "RMB";
break;
case CLICK_BUTTON4:
res = "MB4";
break;
case CLICK_BUTTON5:
res = "MB5";
break;
case CLICK_DOUBLELEFT:
res = "Double LMB";
break;
default:
break;
}
if (translate && !res.empty())
{
LLKeyStringTranslatorFunc* trans = gKeyboard->mStringTranslator;
if (trans != NULL)
{
res = trans(res);
}
}
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator(MASK accel_mask)
{
std::string res;
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans == NULL)
{
LL_ERRS() << "No mKeyStringTranslator" << LL_ENDL;
return res;
}
// Append any masks
#ifdef LL_DARWIN
// Standard Mac names for modifier keys in menu equivalents
// We could use the symbol characters, but they only exist in certain fonts.
if (accel_mask & MASK_CONTROL)
{
if (accel_mask & MASK_MAC_CONTROL)
{
res.append(trans("accel-mac-control"));
}
else
{
res.append(trans("accel-mac-command")); // Symbol would be "\xE2\x8C\x98"
}
}
if (accel_mask & MASK_ALT)
res.append(trans("accel-mac-option")); // Symbol would be "\xE2\x8C\xA5"
if (accel_mask & MASK_SHIFT)
res.append(trans("accel-mac-shift")); // Symbol would be "\xE2\x8C\xA7"
#else
if (accel_mask & MASK_CONTROL)
res.append(trans("accel-win-control"));
if (accel_mask & MASK_ALT)
res.append(trans("accel-win-alt"));
if (accel_mask & MASK_SHIFT)
res.append(trans("accel-win-shift"));
#endif
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
{
std::string res;
// break early if this is a silly thing to do.
if( KEY_NONE == key )
{
return res;
}
res.append(stringFromAccelerator(accel_mask));
std::string key_string = LLKeyboard::stringFromKey(key);
if ((accel_mask & MASK_NORMALKEYS) &&
(key_string[0] == '-' || key_string[0] == '=' || key_string[0] == '+'))
{
res.append( " " );
}
std::string keystr = stringFromKey( key );
res.append( keystr );
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator(MASK accel_mask, EMouseClickType click)
{
std::string res;
if (CLICK_NONE == click)
{
return res;
}
res.append(stringFromAccelerator(accel_mask));
res.append(stringFromMouse(click));
return res;
}
//static
bool LLKeyboard::maskFromString(const std::string& str, MASK *mask)
{
std::string instring(str);
if (instring == "NONE")
{
*mask = MASK_NONE;
return true;
}
else if (instring == "SHIFT")
{
*mask = MASK_SHIFT;
return true;
}
else if (instring == "CTL")
{
*mask = MASK_CONTROL;
return true;
}
else if (instring == "ALT")
{
*mask = MASK_ALT;
return true;
}
else if (instring == "CTL_SHIFT")
{
*mask = MASK_CONTROL | MASK_SHIFT;
return true;
}
else if (instring == "ALT_SHIFT")
{
*mask = MASK_ALT | MASK_SHIFT;
return true;
}
else if (instring == "CTL_ALT")
{
*mask = MASK_CONTROL | MASK_ALT;
return true;
}
else if (instring == "CTL_ALT_SHIFT")
{
*mask = MASK_CONTROL | MASK_ALT | MASK_SHIFT;
return true;
}
else
{
return false;
}
}
//static
void LLKeyboard::setStringTranslatorFunc( LLKeyStringTranslatorFunc *trans_func )
{
mStringTranslator = trans_func;
}
+164
View File
@@ -0,0 +1,164 @@
/**
* @file llkeyboard.h
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLKEYBOARD_H
#define LL_LLKEYBOARD_H
#include <map>
#include <boost/function.hpp>
#include "llstringtable.h"
#include "lltimer.h"
#include "indra_constants.h"
enum EKeystate
{
KEYSTATE_DOWN,
KEYSTATE_LEVEL,
KEYSTATE_UP
};
typedef boost::function<bool(EKeystate keystate)> LLKeyFunc;
typedef std::string (LLKeyStringTranslatorFunc)(std::string_view);
enum EKeyboardInsertMode
{
LL_KIM_INSERT,
LL_KIM_OVERWRITE
};
class LLWindowCallbacks;
class LLKeyboard
{
public:
// <FS:ND> For SDL2 input is widened to U32 symbols
#ifndef LL_SDL2
typedef U16 NATIVE_KEY_TYPE;
#else
typedef U32 NATIVE_KEY_TYPE;
#endif
// </FS:MD>
LLKeyboard();
virtual ~LLKeyboard();
void resetKeyDownAndHandle();
void resetKeys();
F32 getCurKeyElapsedTime() { return getKeyDown(mCurScanKey) ? getKeyElapsedTime( mCurScanKey ) : 0.f; }
F32 getCurKeyElapsedFrameCount() { return getKeyDown(mCurScanKey) ? (F32)getKeyElapsedFrameCount( mCurScanKey ) : 0.f; }
bool getKeyDown(const KEY key) { return mKeyLevel[key]; }
bool getKeyRepeated(const KEY key) { return mKeyRepeated[key]; }
// <FS:ND> SDL2 compat
//bool translateKey(const U16 os_key, KEY *translated_key);
//U16 inverseTranslateKey(const KEY translated_key);
bool translateKey(const NATIVE_KEY_TYPE os_key, KEY *translated_key);
NATIVE_KEY_TYPE inverseTranslateKey(const KEY translated_key);
// </FS:ND>
bool handleTranslatedKeyUp(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes
bool handleTranslatedKeyDown(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes
// <FS:ND> SDL2 compat
//virtual bool handleKeyUp(const U16 key, MASK mask) = 0;
//virtual bool handleKeyDown(const U16 key, MASK mask) = 0;
virtual bool handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) = 0;
virtual bool handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0;
// </FS:ND>
#ifdef LL_DARWIN
// We only actually use this for macOS.
virtual void handleModifier(MASK mask) = 0;
#endif // LL_DARWIN
// Asynchronously poll the control, alt, and shift keys and set the
// appropriate internal key masks.
virtual void resetMaskKeys() = 0;
virtual void scanKeyboard() = 0; // scans keyboard, calls functions as necessary
// Mac must differentiate between Command = Control for keyboard events
// and Command != Control for mouse events.
virtual MASK currentMask(bool for_mouse_event) = 0;
virtual KEY currentKey() { return mCurTranslatedKey; }
EKeyboardInsertMode getInsertMode() { return mInsertMode; }
void toggleInsertMode();
static bool maskFromString(const std::string& str, MASK *mask); // False on failure
static bool keyFromString(const std::string& str, KEY *key); // False on failure
static std::string stringFromKey(KEY key, bool translate = true);
static std::string stringFromMouse(EMouseClickType click, bool translate = true);
static std::string stringFromAccelerator( MASK accel_mask ); // separated for convinience, returns with "+": "Shift+" or "Shift+Alt+"...
static std::string stringFromAccelerator( MASK accel_mask, KEY key );
static std::string stringFromAccelerator(MASK accel_mask, EMouseClickType click);
void setCallbacks(LLWindowCallbacks *cbs) { mCallbacks = cbs; }
F32 getKeyElapsedTime( KEY key ); // Returns time in seconds since key was pressed.
S32 getKeyElapsedFrameCount( KEY key ); // Returns time in frames since key was pressed.
static void setStringTranslatorFunc( LLKeyStringTranslatorFunc *trans_func );
protected:
void addKeyName(KEY key, const std::string& name);
protected:
// <FS:ND> SDL2 compat
//std::map<U16, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs
//std::map<KEY, U16> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys
std::map<NATIVE_KEY_TYPE, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs
std::map<KEY, NATIVE_KEY_TYPE> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys
//</FS:ND>
LLWindowCallbacks *mCallbacks;
LLTimer mKeyLevelTimer[KEY_COUNT]; // Time since level was set
S32 mKeyLevelFrameCount[KEY_COUNT]; // Frames since level was set
bool mKeyLevel[KEY_COUNT]; // Levels
bool mKeyRepeated[KEY_COUNT]; // Key was repeated
bool mKeyUp[KEY_COUNT]; // Up edge
bool mKeyDown[KEY_COUNT]; // Down edge
KEY mCurTranslatedKey;
KEY mCurScanKey; // Used during the scanKeyboard()
static LLKeyStringTranslatorFunc* mStringTranslator; // Used for l10n + PC/Mac/Linux accelerator labeling
EKeyboardInsertMode mInsertMode;
static std::map<KEY,std::string> sKeysToNames;
static std::map<std::string,KEY> sNamesToKeys;
};
// Interface to get key from assigned command
class LLKeyBindingToStringHandler
{
public:
virtual std::string getKeyBindingAsString(const std::string& mode, const std::string& control) const = 0;
};
extern LLKeyboard *gKeyboard;
#endif
+72
View File
@@ -0,0 +1,72 @@
/**
* @file llkeyboardheadless.cpp
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llkeyboardheadless.h"
#include "llwindowcallbacks.h"
LLKeyboardHeadless::LLKeyboardHeadless()
{ }
void LLKeyboardHeadless::resetMaskKeys()
{ }
MASK LLKeyboardHeadless::currentMask(bool for_mouse_event)
{ return MASK_NONE; }
#ifdef LL_DARWIN
void LLKeyboardHeadless::handleModifier(MASK mask)
{
}
#endif
void LLKeyboardHeadless::scanKeyboard()
{
for (S32 key = 0; key < KEY_COUNT; key++)
{
// Generate callback if any event has occurred on this key this frame.
// Can't just test mKeyLevel, because this could be a slow frame and
// key might have gone down then up. JC
if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
{
mCurScanKey = key;
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
}
}
// Reset edges for next frame
for (S32 key = 0; key < KEY_COUNT; key++)
{
mKeyUp[key] = false;
mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
}
}
}
+53
View File
@@ -0,0 +1,53 @@
/**
* @file llkeyboardheadless.h
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLKEYBOARDHEADLESS_H
#define LL_LLKEYBOARDHEADLESS_H
#include "llkeyboard.h"
class LLKeyboardHeadless : public LLKeyboard
{
public:
LLKeyboardHeadless();
/*virtual*/ ~LLKeyboardHeadless() {};
#ifndef LL_SDL2
/*virtual*/ bool handleKeyUp(const U16 key, MASK mask) { return false; }
/*virtual*/ bool handleKeyDown(const U16 key, MASK mask) { return false; }
#else
/*virtual*/ bool handleKeyUp(const U32 key, MASK mask) { return false; }
/*virtual*/ bool handleKeyDown(const U32 key, MASK mask) { return false; }
#endif
/*virtual*/ void resetMaskKeys();
/*virtual*/ MASK currentMask(bool for_mouse_event);
/*virtual*/ void scanKeyboard();
#ifdef LL_DARWIN
/*virtual*/ void handleModifier(MASK mask);
#endif
};
#endif
+321
View File
@@ -0,0 +1,321 @@
/**
* @file llkeyboardmacosx.cpp
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#if LL_DARWIN
#include "linden_common.h"
#include "llkeyboardmacosx.h"
#include "llwindowcallbacks.h"
#include "llwindowmacosx-objc.h"
LLKeyboardMacOSX::LLKeyboardMacOSX()
{
// Virtual keycode mapping table. Yes, this was as annoying to generate as it looks.
mTranslateKeyMap[0x00] = 'A';
mTranslateKeyMap[0x01] = 'S';
mTranslateKeyMap[0x02] = 'D';
mTranslateKeyMap[0x03] = 'F';
mTranslateKeyMap[0x04] = 'H';
mTranslateKeyMap[0x05] = 'G';
mTranslateKeyMap[0x06] = 'Z';
mTranslateKeyMap[0x07] = 'X';
mTranslateKeyMap[0x08] = 'C';
mTranslateKeyMap[0x09] = 'V';
mTranslateKeyMap[0x0b] = 'B';
mTranslateKeyMap[0x0c] = 'Q';
mTranslateKeyMap[0x0d] = 'W';
mTranslateKeyMap[0x0e] = 'E';
mTranslateKeyMap[0x0f] = 'R';
mTranslateKeyMap[0x10] = 'Y';
mTranslateKeyMap[0x11] = 'T';
mTranslateKeyMap[0x12] = '1';
mTranslateKeyMap[0x13] = '2';
mTranslateKeyMap[0x14] = '3';
mTranslateKeyMap[0x15] = '4';
mTranslateKeyMap[0x16] = '6';
mTranslateKeyMap[0x17] = '5';
mTranslateKeyMap[0x18] = '='; // KEY_EQUALS
mTranslateKeyMap[0x19] = '9';
mTranslateKeyMap[0x1a] = '7';
mTranslateKeyMap[0x1b] = '-'; // KEY_HYPHEN
mTranslateKeyMap[0x1c] = '8';
mTranslateKeyMap[0x1d] = '0';
mTranslateKeyMap[0x1e] = ']';
mTranslateKeyMap[0x1f] = 'O';
mTranslateKeyMap[0x20] = 'U';
mTranslateKeyMap[0x21] = '[';
mTranslateKeyMap[0x22] = 'I';
mTranslateKeyMap[0x23] = 'P';
mTranslateKeyMap[0x24] = KEY_RETURN;
mTranslateKeyMap[0x25] = 'L';
mTranslateKeyMap[0x26] = 'J';
mTranslateKeyMap[0x27] = '\'';
mTranslateKeyMap[0x28] = 'K';
mTranslateKeyMap[0x29] = ';';
mTranslateKeyMap[0x2a] = '\\';
mTranslateKeyMap[0x2b] = ',';
mTranslateKeyMap[0x2c] = KEY_DIVIDE;
mTranslateKeyMap[0x2d] = 'N';
mTranslateKeyMap[0x2e] = 'M';
mTranslateKeyMap[0x2f] = '.';
mTranslateKeyMap[0x30] = KEY_TAB;
mTranslateKeyMap[0x31] = ' '; // space!
mTranslateKeyMap[0x32] = '`';
mTranslateKeyMap[0x33] = KEY_BACKSPACE;
mTranslateKeyMap[0x35] = KEY_ESCAPE;
//mTranslateKeyMap[0x37] = 0; // Command key. (not used yet)
mTranslateKeyMap[0x38] = KEY_SHIFT;
mTranslateKeyMap[0x39] = KEY_CAPSLOCK;
mTranslateKeyMap[0x3a] = KEY_ALT;
mTranslateKeyMap[0x3b] = KEY_CONTROL;
mTranslateKeyMap[0x41] = '.'; // keypad
mTranslateKeyMap[0x43] = '*'; // keypad
mTranslateKeyMap[0x45] = '+'; // keypad
mTranslateKeyMap[0x4b] = KEY_PAD_DIVIDE; // keypad
mTranslateKeyMap[0x4c] = KEY_RETURN; // keypad enter
mTranslateKeyMap[0x4e] = '-'; // keypad
mTranslateKeyMap[0x51] = '='; // keypad
mTranslateKeyMap[0x52] = '0'; // keypad
mTranslateKeyMap[0x53] = '1'; // keypad
mTranslateKeyMap[0x54] = '2'; // keypad
mTranslateKeyMap[0x55] = '3'; // keypad
mTranslateKeyMap[0x56] = '4'; // keypad
mTranslateKeyMap[0x57] = '5'; // keypad
mTranslateKeyMap[0x58] = '6'; // keypad
mTranslateKeyMap[0x59] = '7'; // keypad
mTranslateKeyMap[0x5b] = '8'; // keypad
mTranslateKeyMap[0x5c] = '9'; // keypad
mTranslateKeyMap[0x60] = KEY_F5;
mTranslateKeyMap[0x61] = KEY_F6;
mTranslateKeyMap[0x62] = KEY_F7;
mTranslateKeyMap[0x63] = KEY_F3;
mTranslateKeyMap[0x64] = KEY_F8;
mTranslateKeyMap[0x65] = KEY_F9;
mTranslateKeyMap[0x67] = KEY_F11;
mTranslateKeyMap[0x6d] = KEY_F10;
mTranslateKeyMap[0x6f] = KEY_F12;
mTranslateKeyMap[0x72] = KEY_INSERT;
mTranslateKeyMap[0x73] = KEY_HOME;
mTranslateKeyMap[0x74] = KEY_PAGE_UP;
mTranslateKeyMap[0x75] = KEY_DELETE;
mTranslateKeyMap[0x76] = KEY_F4;
mTranslateKeyMap[0x77] = KEY_END;
mTranslateKeyMap[0x78] = KEY_F2;
mTranslateKeyMap[0x79] = KEY_PAGE_DOWN;
mTranslateKeyMap[0x7a] = KEY_F1;
mTranslateKeyMap[0x7b] = KEY_LEFT;
mTranslateKeyMap[0x7c] = KEY_RIGHT;
mTranslateKeyMap[0x7d] = KEY_DOWN;
mTranslateKeyMap[0x7e] = KEY_UP;
// Build inverse map
// <FS:ND> <FS:LO> Change to U32 for SDL2
//std::map<U16, KEY>::iterator iter;
//for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
for (auto iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
{
mInvTranslateKeyMap[iter->second] = iter->first;
}
// build numpad maps
mTranslateNumpadMap[0x52] = KEY_PAD_INS; // keypad 0
mTranslateNumpadMap[0x53] = KEY_PAD_END; // keypad 1
mTranslateNumpadMap[0x54] = KEY_PAD_DOWN; // keypad 2
mTranslateNumpadMap[0x55] = KEY_PAD_PGDN; // keypad 3
mTranslateNumpadMap[0x56] = KEY_PAD_LEFT; // keypad 4
mTranslateNumpadMap[0x57] = KEY_PAD_CENTER; // keypad 5
mTranslateNumpadMap[0x58] = KEY_PAD_RIGHT; // keypad 6
mTranslateNumpadMap[0x59] = KEY_PAD_HOME; // keypad 7
mTranslateNumpadMap[0x5b] = KEY_PAD_UP; // keypad 8
mTranslateNumpadMap[0x5c] = KEY_PAD_PGUP; // keypad 9
mTranslateNumpadMap[0x41] = KEY_PAD_DEL; // keypad .
mTranslateNumpadMap[0x4c] = KEY_PAD_RETURN; // keypad enter
// Build inverse numpad map
// <FS:ND> <FS:LO> Change to U32 for SDL2
//for (iter = mTranslateNumpadMap.begin(); iter != mTranslateNumpadMap.end(); iter++)
for (auto iter = mTranslateNumpadMap.begin(); iter != mTranslateNumpadMap.end(); iter++)
{
mInvTranslateNumpadMap[iter->second] = iter->first;
}
}
void LLKeyboardMacOSX::resetMaskKeys()
{
U32 mask = getModifiers();
// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
// It looks a bit suspicious, as it won't correct for keys that have been released.
// Is this the way it's supposed to work?
// We apply the modifier masks directly within getModifiers. So check to see which masks we've applied.
if(mask & MAC_SHIFT_KEY)
{
mKeyLevel[KEY_SHIFT] = true;
}
if(mask & (MAC_CTRL_KEY | MAC_CMD_KEY))
{
mKeyLevel[KEY_CONTROL] = true;
}
if(mask & MAC_ALT_KEY)
{
mKeyLevel[KEY_ALT] = true;
}
}
/*
static bool translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &outMask)
{
// Translate the virtual keycode into the keycodes the keyboard system expects.
U16 virtualKey = (mask >> 24) & 0x0000007F;
outKey = macKeyTransArray[virtualKey];
return(outKey != 0);
}
*/
void LLKeyboardMacOSX::handleModifier(MASK mask)
{
updateModifiers(mask);
}
MASK LLKeyboardMacOSX::updateModifiers(const U32 mask)
{
// translate the mask
MASK out_mask = 0;
if(mask & MAC_SHIFT_KEY)
{
out_mask |= MASK_SHIFT;
}
if(mask & (MAC_CTRL_KEY | MAC_CMD_KEY))
{
out_mask |= MASK_CONTROL;
}
if(mask & MAC_ALT_KEY)
{
out_mask |= MASK_ALT;
}
return out_mask;
}
bool LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask)
{
KEY translated_key = 0;
U32 translated_mask = 0;
bool handled = false;
translated_mask = updateModifiers(mask);
if(translateNumpadKey(key, &translated_key))
{
handled = handleTranslatedKeyDown(translated_key, translated_mask);
}
return handled;
}
bool LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask)
{
KEY translated_key = 0;
U32 translated_mask = 0;
bool handled = false;
translated_mask = updateModifiers(mask);
if(translateNumpadKey(key, &translated_key))
{
handled = handleTranslatedKeyUp(translated_key, translated_mask);
}
return handled;
}
MASK LLKeyboardMacOSX::currentMask(bool for_mouse_event)
{
MASK result = MASK_NONE;
U32 mask = getModifiers();
if (mask & MAC_SHIFT_KEY) result |= MASK_SHIFT;
if (mask & MAC_CTRL_KEY) result |= MASK_CONTROL;
if (mask & MAC_ALT_KEY) result |= MASK_ALT;
// For keyboard events, consider Command equivalent to Control
if (!for_mouse_event)
{
if (mask & MAC_CMD_KEY) result |= MASK_CONTROL;
}
return result;
}
void LLKeyboardMacOSX::scanKeyboard()
{
S32 key;
for (key = 0; key < KEY_COUNT; key++)
{
// Generate callback if any event has occurred on this key this frame.
// Can't just test mKeyLevel, because this could be a slow frame and
// key might have gone down then up. JC
if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
{
mCurScanKey = key;
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
}
}
// Reset edges for next frame
for (key = 0; key < KEY_COUNT; key++)
{
mKeyUp[key] = false;
mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
}
}
}
bool LLKeyboardMacOSX::translateNumpadKey( const U16 os_key, KEY *translated_key )
{
return translateKey(os_key, translated_key);
}
U16 LLKeyboardMacOSX::inverseTranslateNumpadKey(const KEY translated_key)
{
return inverseTranslateKey(translated_key);
}
#endif // LL_DARWIN
+64
View File
@@ -0,0 +1,64 @@
/**
* @file llkeyboardmacosx.h
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLKEYBOARDMACOSX_H
#define LL_LLKEYBOARDMACOSX_H
#include "llkeyboard.h"
// These more or less mirror their equivalents in NSEvent.h.
enum EMacEventKeys {
MAC_SHIFT_KEY = 1 << 17,
MAC_CTRL_KEY = 1 << 18,
MAC_ALT_KEY = 1 << 19,
MAC_CMD_KEY = 1 << 20,
MAC_FN_KEY = 1 << 23
};
class LLKeyboardMacOSX : public LLKeyboard
{
public:
LLKeyboardMacOSX();
/*virtual*/ ~LLKeyboardMacOSX() {};
/*virtual*/ bool handleKeyUp(const U16 key, MASK mask);
/*virtual*/ bool handleKeyDown(const U16 key, MASK mask);
/*virtual*/ void resetMaskKeys();
/*virtual*/ MASK currentMask(bool for_mouse_event);
/*virtual*/ void scanKeyboard();
/*virtual*/ void handleModifier(MASK mask);
protected:
MASK updateModifiers(const U32 mask);
void setModifierKeyLevel( KEY key, bool new_state );
bool translateNumpadKey( const U16 os_key, KEY *translated_key );
U16 inverseTranslateNumpadKey(const KEY translated_key);
private:
std::map<U16, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys
std::map<KEY, U16> mInvTranslateNumpadMap; // inverse of the above
};
#endif
+323
View File
@@ -0,0 +1,323 @@
/**
* @file llkeyboardsdl.cpp
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#if LL_SDL
#include "linden_common.h"
#include "llkeyboardsdl.h"
#include "llwindowcallbacks.h"
#include "SDL/SDL.h"
LLKeyboardSDL::LLKeyboardSDL()
{
// Set up key mapping for SDL - eventually can read this from a file?
// Anything not in the key map gets dropped
// Add default A-Z
// Virtual key mappings from SDL_keysym.h ...
// SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
U16 cur_char;
for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
{
mTranslateKeyMap[cur_char] = cur_char;
}
for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
{
mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
}
for (cur_char = '0'; cur_char <= '9'; cur_char++)
{
mTranslateKeyMap[cur_char] = cur_char;
}
// These ones are translated manually upon keydown/keyup because
// SDL doesn't handle their numlock transition.
//mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT;
//mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT;
//mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP;
//mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN;
//mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE;
//mTranslateKeyMap[SDLK_KP7] = KEY_HOME;
//mTranslateKeyMap[SDLK_KP1] = KEY_END;
//mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP;
//mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
//mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
mTranslateKeyMap[SDLK_SPACE] = ' ';
mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
mTranslateKeyMap[SDLK_UP] = KEY_UP;
mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
mTranslateKeyMap[SDLK_END] = KEY_END;
mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
mTranslateKeyMap[SDLK_MINUS] = KEY_HYPHEN;
mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
mTranslateKeyMap[SDLK_F1] = KEY_F1;
mTranslateKeyMap[SDLK_F2] = KEY_F2;
mTranslateKeyMap[SDLK_F3] = KEY_F3;
mTranslateKeyMap[SDLK_F4] = KEY_F4;
mTranslateKeyMap[SDLK_F5] = KEY_F5;
mTranslateKeyMap[SDLK_F6] = KEY_F6;
mTranslateKeyMap[SDLK_F7] = KEY_F7;
mTranslateKeyMap[SDLK_F8] = KEY_F8;
mTranslateKeyMap[SDLK_F9] = KEY_F9;
mTranslateKeyMap[SDLK_F10] = KEY_F10;
mTranslateKeyMap[SDLK_F11] = KEY_F11;
mTranslateKeyMap[SDLK_F12] = KEY_F12;
mTranslateKeyMap[SDLK_PLUS] = '=';
mTranslateKeyMap[SDLK_COMMA] = ',';
mTranslateKeyMap[SDLK_MINUS] = '-';
mTranslateKeyMap[SDLK_PERIOD] = '.';
mTranslateKeyMap[SDLK_BACKQUOTE] = '`';
mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
mTranslateKeyMap[SDLK_SEMICOLON] = ';';
mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
mTranslateKeyMap[SDLK_QUOTE] = '\'';
// Build inverse map
std::map<U16, KEY>::iterator iter;
for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
{
mInvTranslateKeyMap[iter->second] = iter->first;
}
// numpad map
mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS;
mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END;
mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN;
mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN;
mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT;
mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER;
mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT;
mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME;
mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP;
mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP;
mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
// build inverse numpad map
for (iter = mTranslateNumpadMap.begin();
iter != mTranslateNumpadMap.end();
iter++)
{
mInvTranslateNumpadMap[iter->second] = iter->first;
}
}
void LLKeyboardSDL::resetMaskKeys()
{
SDLMod mask = SDL_GetModState();
// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
// It looks a bit suspicious, as it won't correct for keys that have been released.
// Is this the way it's supposed to work?
if(mask & KMOD_SHIFT)
{
mKeyLevel[KEY_SHIFT] = true;
}
if(mask & KMOD_CTRL)
{
mKeyLevel[KEY_CONTROL] = true;
}
if(mask & KMOD_ALT)
{
mKeyLevel[KEY_ALT] = true;
}
}
MASK LLKeyboardSDL::updateModifiers(const U32 mask)
{
// translate the mask
MASK out_mask = MASK_NONE;
if(mask & KMOD_SHIFT)
{
out_mask |= MASK_SHIFT;
}
if(mask & KMOD_CTRL)
{
out_mask |= MASK_CONTROL;
}
if(mask & KMOD_ALT)
{
out_mask |= MASK_ALT;
}
return out_mask;
}
static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask)
{
// SDL doesn't automatically adjust the keysym according to
// whether NUMLOCK is engaged, so we massage the keysym manually.
U16 rtn = key;
if (!(mask & KMOD_NUM))
{
switch (key)
{
case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
case SDLK_KP0: rtn = SDLK_INSERT; break;
case SDLK_KP1: rtn = SDLK_END; break;
case SDLK_KP2: rtn = SDLK_DOWN; break;
case SDLK_KP3: rtn = SDLK_PAGEDOWN; break;
case SDLK_KP4: rtn = SDLK_LEFT; break;
case SDLK_KP6: rtn = SDLK_RIGHT; break;
case SDLK_KP7: rtn = SDLK_HOME; break;
case SDLK_KP8: rtn = SDLK_UP; break;
case SDLK_KP9: rtn = SDLK_PAGEUP; break;
}
}
return rtn;
}
bool LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
{
U16 adjusted_nativekey;
KEY translated_key = 0;
U32 translated_mask = MASK_NONE;
bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
translated_mask = updateModifiers(mask);
if(translateNumpadKey(adjusted_nativekey, &translated_key))
{
handled = handleTranslatedKeyDown(translated_key, translated_mask);
}
return handled;
}
bool LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
{
U16 adjusted_nativekey;
KEY translated_key = 0;
U32 translated_mask = MASK_NONE;
bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
translated_mask = updateModifiers(mask);
if(translateNumpadKey(adjusted_nativekey, &translated_key))
{
handled = handleTranslatedKeyUp(translated_key, translated_mask);
}
return handled;
}
MASK LLKeyboardSDL::currentMask(bool for_mouse_event)
{
MASK result = MASK_NONE;
SDLMod mask = SDL_GetModState();
if (mask & KMOD_SHIFT) result |= MASK_SHIFT;
if (mask & KMOD_CTRL) result |= MASK_CONTROL;
if (mask & KMOD_ALT) result |= MASK_ALT;
// For keyboard events, consider Meta keys equivalent to Control
if (!for_mouse_event)
{
if (mask & KMOD_META) result |= MASK_CONTROL;
}
return result;
}
void LLKeyboardSDL::scanKeyboard()
{
for (S32 key = 0; key < KEY_COUNT; key++)
{
// Generate callback if any event has occurred on this key this frame.
// Can't just test mKeyLevel, because this could be a slow frame and
// key might have gone down then up. JC
if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
{
mCurScanKey = key;
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
}
}
// Reset edges for next frame
for (S32 key = 0; key < KEY_COUNT; key++)
{
mKeyUp[key] = false;
mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
}
}
}
bool LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key)
{
return translateKey(os_key, translated_key);
}
U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
{
return inverseTranslateKey(translated_key);
}
#endif
+60
View File
@@ -0,0 +1,60 @@
/**
* @file llkeyboardsdl.h
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifdef LL_SDL2
#include "llkeyboardsdl2.h"
#else
#ifndef LL_LLKEYBOARDSDL_H
#define LL_LLKEYBOARDSDL_H
#include "llkeyboard.h"
#include "SDL/SDL.h"
class LLKeyboardSDL : public LLKeyboard
{
public:
LLKeyboardSDL();
/*virtual*/ ~LLKeyboardSDL() {};
/*virtual*/ bool handleKeyUp(const U16 key, MASK mask);
/*virtual*/ bool handleKeyDown(const U16 key, MASK mask);
/*virtual*/ void resetMaskKeys();
/*virtual*/ MASK currentMask(bool for_mouse_event);
/*virtual*/ void scanKeyboard();
protected:
MASK updateModifiers(const U32 mask);
void setModifierKeyLevel( KEY key, bool new_state );
bool translateNumpadKey( const U16 os_key, KEY *translated_key );
U16 inverseTranslateNumpadKey(const KEY translated_key);
private:
std::map<U16, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys
std::map<KEY, U16> mInvTranslateNumpadMap; // inverse of the above
};
#endif
#endif
+646
View File
@@ -0,0 +1,646 @@
#if LL_SDL2
#include "linden_common.h"
#include "llkeyboardsdl2.h"
#include "llwindowcallbacks.h"
#include "SDL2/SDL.h"
#include "SDL2/SDL_keycode.h"
LLKeyboardSDL::LLKeyboardSDL()
{
// Set up key mapping for SDL - eventually can read this from a file?
// Anything not in the key map gets dropped
// Add default A-Z
// Virtual key mappings from SDL_keysym.h ...
// SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
// <FS:ND> Looks like we need to map those despite of SDL_TEXTINPUT handling most of this, but without
// the translation lower->upper here accelerators will not work.
U16 cur_char;
for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
{
mTranslateKeyMap[cur_char] = cur_char;
}
for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
{
mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
}
for (cur_char = '0'; cur_char <= '9'; cur_char++)
{
mTranslateKeyMap[cur_char] = cur_char;
}
// These ones are translated manually upon keydown/keyup because
// SDL doesn't handle their numlock transition.
//mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT;
//mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT;
//mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP;
//mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN;
//mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE;
//mTranslateKeyMap[SDLK_KP7] = KEY_HOME;
//mTranslateKeyMap[SDLK_KP1] = KEY_END;
//mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP;
//mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
//mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
mTranslateKeyMap[SDLK_SPACE] = ' '; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
mTranslateKeyMap[SDLK_UP] = KEY_UP;
mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
// mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
mTranslateKeyMap[SDLK_END] = KEY_END;
mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
mTranslateKeyMap[SDLK_MINUS] = KEY_HYPHEN;
mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
mTranslateKeyMap[SDLK_F1] = KEY_F1;
mTranslateKeyMap[SDLK_F2] = KEY_F2;
mTranslateKeyMap[SDLK_F3] = KEY_F3;
mTranslateKeyMap[SDLK_F4] = KEY_F4;
mTranslateKeyMap[SDLK_F5] = KEY_F5;
mTranslateKeyMap[SDLK_F6] = KEY_F6;
mTranslateKeyMap[SDLK_F7] = KEY_F7;
mTranslateKeyMap[SDLK_F8] = KEY_F8;
mTranslateKeyMap[SDLK_F9] = KEY_F9;
mTranslateKeyMap[SDLK_F10] = KEY_F10;
mTranslateKeyMap[SDLK_F11] = KEY_F11;
mTranslateKeyMap[SDLK_F12] = KEY_F12;
mTranslateKeyMap[SDLK_PLUS] = '='; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_COMMA] = ','; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_MINUS] = '-'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_PERIOD] = '.'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_BACKQUOTE] = '`'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_SEMICOLON] = ';'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
mTranslateKeyMap[SDLK_QUOTE] = '\''; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
// Build inverse map
for (auto iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
{
mInvTranslateKeyMap[iter->second] = iter->first;
}
// numpad map
mTranslateNumpadMap[SDLK_KP_0] = KEY_PAD_INS;
mTranslateNumpadMap[SDLK_KP_1] = KEY_PAD_END;
mTranslateNumpadMap[SDLK_KP_2] = KEY_PAD_DOWN;
mTranslateNumpadMap[SDLK_KP_3] = KEY_PAD_PGDN;
mTranslateNumpadMap[SDLK_KP_4] = KEY_PAD_LEFT;
mTranslateNumpadMap[SDLK_KP_5] = KEY_PAD_CENTER;
mTranslateNumpadMap[SDLK_KP_6] = KEY_PAD_RIGHT;
mTranslateNumpadMap[SDLK_KP_7] = KEY_PAD_HOME;
mTranslateNumpadMap[SDLK_KP_8] = KEY_PAD_UP;
mTranslateNumpadMap[SDLK_KP_9] = KEY_PAD_PGUP;
mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
// build inverse numpad map
for (auto iter = mTranslateNumpadMap.begin();
iter != mTranslateNumpadMap.end();
iter++)
{
mInvTranslateNumpadMap[iter->second] = iter->first;
}
}
void LLKeyboardSDL::resetMaskKeys()
{
SDL_Keymod mask = SDL_GetModState();
// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
// It looks a bit suspicious, as it won't correct for keys that have been released.
// Is this the way it's supposed to work?
if(mask & KMOD_SHIFT)
{
mKeyLevel[KEY_SHIFT] = true;
}
if(mask & KMOD_CTRL)
{
mKeyLevel[KEY_CONTROL] = true;
}
if(mask & KMOD_ALT)
{
mKeyLevel[KEY_ALT] = true;
}
}
MASK LLKeyboardSDL::updateModifiers(const U32 mask)
{
// translate the mask
MASK out_mask = MASK_NONE;
if(mask & KMOD_SHIFT)
{
out_mask |= MASK_SHIFT;
}
if(mask & KMOD_CTRL)
{
out_mask |= MASK_CONTROL;
}
if(mask & KMOD_ALT)
{
out_mask |= MASK_ALT;
}
return out_mask;
}
static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask)
{
// SDL doesn't automatically adjust the keysym according to
// whether NUMLOCK is engaged, so we massage the keysym manually.
U32 rtn = key;
if (!(mask & KMOD_NUM))
{
switch (key)
{
case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
case SDLK_KP_0: rtn = SDLK_INSERT; break;
case SDLK_KP_1: rtn = SDLK_END; break;
case SDLK_KP_2: rtn = SDLK_DOWN; break;
case SDLK_KP_3: rtn = SDLK_PAGEDOWN; break;
case SDLK_KP_4: rtn = SDLK_LEFT; break;
case SDLK_KP_6: rtn = SDLK_RIGHT; break;
case SDLK_KP_7: rtn = SDLK_HOME; break;
case SDLK_KP_8: rtn = SDLK_UP; break;
case SDLK_KP_9: rtn = SDLK_PAGEUP; break;
}
}
return rtn;
}
bool LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask)
{
U32 adjusted_nativekey;
KEY translated_key = 0;
U32 translated_mask = MASK_NONE;
bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
translated_mask = updateModifiers(mask);
if(translateNumpadKey(adjusted_nativekey, &translated_key))
{
handled = handleTranslatedKeyDown(translated_key, translated_mask);
}
return handled;
}
bool LLKeyboardSDL::handleKeyUp(const U32 key, const U32 mask)
{
U32 adjusted_nativekey;
KEY translated_key = 0;
U32 translated_mask = MASK_NONE;
bool handled = false;
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
translated_mask = updateModifiers(mask);
if(translateNumpadKey(adjusted_nativekey, &translated_key))
{
handled = handleTranslatedKeyUp(translated_key, translated_mask);
}
return handled;
}
MASK LLKeyboardSDL::currentMask(bool for_mouse_event)
{
MASK result = MASK_NONE;
SDL_Keymod mask = SDL_GetModState();
if (mask & KMOD_SHIFT)
result |= MASK_SHIFT;
if (mask & KMOD_CTRL)
result |= MASK_CONTROL;
if (mask & KMOD_ALT)
result |= MASK_ALT;
// For keyboard events, consider Meta keys equivalent to Control
if (!for_mouse_event)
{
if (mask & KMOD_GUI)
result |= MASK_CONTROL;
}
return result;
}
void LLKeyboardSDL::scanKeyboard()
{
for (S32 key = 0; key < KEY_COUNT; key++)
{
// Generate callback if any event has occurred on this key this frame.
// Can't just test mKeyLevel, because this could be a slow frame and
// key might have gone down then up. JC
if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
{
mCurScanKey = key;
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
}
}
// Reset edges for next frame
for (S32 key = 0; key < KEY_COUNT; key++)
{
mKeyUp[key] = false;
mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
}
}
}
bool LLKeyboardSDL::translateNumpadKey( const U32 os_key, KEY *translated_key)
{
return translateKey(os_key, translated_key);
}
U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
{
return inverseTranslateKey(translated_key);
}
enum class WindowsVK : U32
{
VK_UNKNOWN = 0,
VK_CANCEL = 0x03,
VK_BACK = 0x08,
VK_TAB = 0x09,
VK_CLEAR = 0x0C,
VK_RETURN = 0x0D,
VK_SHIFT = 0x10,
VK_CONTROL = 0x11,
VK_MENU = 0x12,
VK_PAUSE = 0x13,
VK_CAPITAL = 0x14,
VK_KANA = 0x15,
VK_HANGUL = 0x15,
VK_JUNJA = 0x17,
VK_FINAL = 0x18,
VK_HANJA = 0x19,
VK_KANJI = 0x19,
VK_ESCAPE = 0x1B,
VK_CONVERT = 0x1C,
VK_NONCONVERT = 0x1D,
VK_ACCEPT = 0x1E,
VK_MODECHANGE = 0x1F,
VK_SPACE = 0x20,
VK_PRIOR = 0x21,
VK_NEXT = 0x22,
VK_END = 0x23,
VK_HOME = 0x24,
VK_LEFT = 0x25,
VK_UP = 0x26,
VK_RIGHT = 0x27,
VK_DOWN = 0x28,
VK_SELECT = 0x29,
VK_PRINT = 0x2A,
VK_EXECUTE = 0x2B,
VK_SNAPSHOT = 0x2C,
VK_INSERT = 0x2D,
VK_DELETE = 0x2E,
VK_HELP = 0x2F,
VK_0 = 0x30,
VK_1 = 0x31,
VK_2 = 0x32,
VK_3 = 0x33,
VK_4 = 0x34,
VK_5 = 0x35,
VK_6 = 0x36,
VK_7 = 0x37,
VK_8 = 0x38,
VK_9 = 0x39,
VK_A = 0x41,
VK_B = 0x42,
VK_C = 0x43,
VK_D = 0x44,
VK_E = 0x45,
VK_F = 0x46,
VK_G = 0x47,
VK_H = 0x48,
VK_I = 0x49,
VK_J = 0x4A,
VK_K = 0x4B,
VK_L = 0x4C,
VK_M = 0x4D,
VK_N = 0x4E,
VK_O = 0x4F,
VK_P = 0x50,
VK_Q = 0x51,
VK_R = 0x52,
VK_S = 0x53,
VK_T = 0x54,
VK_U = 0x55,
VK_V = 0x56,
VK_W = 0x57,
VK_X = 0x58,
VK_Y = 0x59,
VK_Z = 0x5A,
VK_LWIN = 0x5B,
VK_RWIN = 0x5C,
VK_APPS = 0x5D,
VK_SLEEP = 0x5F,
VK_NUMPAD0 = 0x60,
VK_NUMPAD1 = 0x61,
VK_NUMPAD2 = 0x62,
VK_NUMPAD3 = 0x63,
VK_NUMPAD4 = 0x64,
VK_NUMPAD5 = 0x65,
VK_NUMPAD6 = 0x66,
VK_NUMPAD7 = 0x67,
VK_NUMPAD8 = 0x68,
VK_NUMPAD9 = 0x69,
VK_MULTIPLY = 0x6A,
VK_ADD = 0x6B,
VK_SEPARATOR = 0x6C,
VK_SUBTRACT = 0x6D,
VK_DECIMAL = 0x6E,
VK_DIVIDE = 0x6F,
VK_F1 = 0x70,
VK_F2 = 0x71,
VK_F3 = 0x72,
VK_F4 = 0x73,
VK_F5 = 0x74,
VK_F6 = 0x75,
VK_F7 = 0x76,
VK_F8 = 0x77,
VK_F9 = 0x78,
VK_F10 = 0x79,
VK_F11 = 0x7A,
VK_F12 = 0x7B,
VK_F13 = 0x7C,
VK_F14 = 0x7D,
VK_F15 = 0x7E,
VK_F16 = 0x7F,
VK_F17 = 0x80,
VK_F18 = 0x81,
VK_F19 = 0x82,
VK_F20 = 0x83,
VK_F21 = 0x84,
VK_F22 = 0x85,
VK_F23 = 0x86,
VK_F24 = 0x87,
VK_NUMLOCK = 0x90,
VK_SCROLL = 0x91,
VK_LSHIFT = 0xA0,
VK_RSHIFT = 0xA1,
VK_LCONTROL = 0xA2,
VK_RCONTROL = 0xA3,
VK_LMENU = 0xA4,
VK_RMENU = 0xA5,
VK_BROWSER_BACK = 0xA6,
VK_BROWSER_FORWARD = 0xA7,
VK_BROWSER_REFRESH = 0xA8,
VK_BROWSER_STOP = 0xA9,
VK_BROWSER_SEARCH = 0xAA,
VK_BROWSER_FAVORITES = 0xAB,
VK_BROWSER_HOME = 0xAC,
VK_VOLUME_MUTE = 0xAD,
VK_VOLUME_DOWN = 0xAE,
VK_VOLUME_UP = 0xAF,
VK_MEDIA_NEXT_TRACK = 0xB0,
VK_MEDIA_PREV_TRACK = 0xB1,
VK_MEDIA_STOP = 0xB2,
VK_MEDIA_PLAY_PAUSE = 0xB3,
VK_MEDIA_LAUNCH_MAIL = 0xB4,
VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
VK_MEDIA_LAUNCH_APP1 = 0xB6,
VK_MEDIA_LAUNCH_APP2 = 0xB7,
VK_OEM_1 = 0xBA,
VK_OEM_PLUS = 0xBB,
VK_OEM_COMMA = 0xBC,
VK_OEM_MINUS = 0xBD,
VK_OEM_PERIOD = 0xBE,
VK_OEM_2 = 0xBF,
VK_OEM_3 = 0xC0,
VK_OEM_4 = 0xDB,
VK_OEM_5 = 0xDC,
VK_OEM_6 = 0xDD,
VK_OEM_7 = 0xDE,
VK_OEM_8 = 0xDF,
VK_OEM_102 = 0xE2,
VK_PROCESSKEY = 0xE5,
VK_PACKET = 0xE7,
VK_ATTN = 0xF6,
VK_CRSEL = 0xF7,
VK_EXSEL = 0xF8,
VK_EREOF = 0xF9,
VK_PLAY = 0xFA,
VK_ZOOM = 0xFB,
VK_NONAME = 0xFC,
VK_PA1 = 0xFD,
VK_OEM_CLEAR = 0xFE,
};
std::map< U32, U32 > mSDL2_to_Win;
std::set< U32 > mIgnoreSDL2Keys;
U32 LLKeyboardSDL::mapSDL2toWin( U32 aSymbol )
{
// <FS:ND> Map SDLK_ virtual keys to Windows VK_ virtual keys.
// Text is handled via unicode input (SDL_TEXTINPUT event) and does not need to be translated into VK_ values as those match already.
if( mSDL2_to_Win.empty() )
{
mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK;
mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB;
mSDL2_to_Win[ 12 ] = (U32)WindowsVK::VK_CLEAR;
mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN;
mSDL2_to_Win[ 19 ] = (U32)WindowsVK::VK_PAUSE;
mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE;
mSDL2_to_Win[ SDLK_SPACE ] = (U32)WindowsVK::VK_SPACE;
mSDL2_to_Win[ SDLK_QUOTE ] = (U32)WindowsVK::VK_OEM_7;
mSDL2_to_Win[ SDLK_COMMA ] = (U32)WindowsVK::VK_OEM_COMMA;
mSDL2_to_Win[ SDLK_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS;
mSDL2_to_Win[ SDLK_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD;
mSDL2_to_Win[ SDLK_SLASH ] = (U32)WindowsVK::VK_OEM_2;
mSDL2_to_Win[ SDLK_0 ] = (U32)WindowsVK::VK_0;
mSDL2_to_Win[ SDLK_1 ] = (U32)WindowsVK::VK_1;
mSDL2_to_Win[ SDLK_2 ] = (U32)WindowsVK::VK_2;
mSDL2_to_Win[ SDLK_3 ] = (U32)WindowsVK::VK_3;
mSDL2_to_Win[ SDLK_4 ] = (U32)WindowsVK::VK_4;
mSDL2_to_Win[ SDLK_5 ] = (U32)WindowsVK::VK_5;
mSDL2_to_Win[ SDLK_6 ] = (U32)WindowsVK::VK_6;
mSDL2_to_Win[ SDLK_7 ] = (U32)WindowsVK::VK_7;
mSDL2_to_Win[ SDLK_8 ] = (U32)WindowsVK::VK_8;
mSDL2_to_Win[ SDLK_9 ] = (U32)WindowsVK::VK_9;
mSDL2_to_Win[ SDLK_SEMICOLON ] = (U32)WindowsVK::VK_OEM_1;
mSDL2_to_Win[ SDLK_LESS ] = (U32)WindowsVK::VK_OEM_102;
mSDL2_to_Win[ SDLK_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS;
mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS;
mSDL2_to_Win[ SDLK_LEFTBRACKET ] = (U32)WindowsVK::VK_OEM_4;
mSDL2_to_Win[ SDLK_BACKSLASH ] = (U32)WindowsVK::VK_OEM_5;
mSDL2_to_Win[ SDLK_RIGHTBRACKET ] = (U32)WindowsVK::VK_OEM_6;
mSDL2_to_Win[ SDLK_BACKQUOTE ] = (U32)WindowsVK::VK_OEM_8;
mSDL2_to_Win[ SDLK_a ] = (U32)WindowsVK::VK_A;
mSDL2_to_Win[ SDLK_b ] = (U32)WindowsVK::VK_B;
mSDL2_to_Win[ SDLK_c ] = (U32)WindowsVK::VK_C;
mSDL2_to_Win[ SDLK_d ] = (U32)WindowsVK::VK_D;
mSDL2_to_Win[ SDLK_e ] = (U32)WindowsVK::VK_E;
mSDL2_to_Win[ SDLK_f ] = (U32)WindowsVK::VK_F;
mSDL2_to_Win[ SDLK_g ] = (U32)WindowsVK::VK_G;
mSDL2_to_Win[ SDLK_h ] = (U32)WindowsVK::VK_H;
mSDL2_to_Win[ SDLK_i ] = (U32)WindowsVK::VK_I;
mSDL2_to_Win[ SDLK_j ] = (U32)WindowsVK::VK_J;
mSDL2_to_Win[ SDLK_k ] = (U32)WindowsVK::VK_K;
mSDL2_to_Win[ SDLK_l ] = (U32)WindowsVK::VK_L;
mSDL2_to_Win[ SDLK_m ] = (U32)WindowsVK::VK_M;
mSDL2_to_Win[ SDLK_n ] = (U32)WindowsVK::VK_N;
mSDL2_to_Win[ SDLK_o ] = (U32)WindowsVK::VK_O;
mSDL2_to_Win[ SDLK_p ] = (U32)WindowsVK::VK_P;
mSDL2_to_Win[ SDLK_q ] = (U32)WindowsVK::VK_Q;
mSDL2_to_Win[ SDLK_r ] = (U32)WindowsVK::VK_R;
mSDL2_to_Win[ SDLK_s ] = (U32)WindowsVK::VK_S;
mSDL2_to_Win[ SDLK_t ] = (U32)WindowsVK::VK_T;
mSDL2_to_Win[ SDLK_u ] = (U32)WindowsVK::VK_U;
mSDL2_to_Win[ SDLK_v ] = (U32)WindowsVK::VK_V;
mSDL2_to_Win[ SDLK_w ] = (U32)WindowsVK::VK_W;
mSDL2_to_Win[ SDLK_x ] = (U32)WindowsVK::VK_X;
mSDL2_to_Win[ SDLK_y ] = (U32)WindowsVK::VK_Y;
mSDL2_to_Win[ SDLK_z ] = (U32)WindowsVK::VK_Z;
mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE;
mSDL2_to_Win[ SDLK_NUMLOCKCLEAR ] = (U32)WindowsVK::VK_NUMLOCK;
mSDL2_to_Win[ SDLK_SCROLLLOCK ] = (U32)WindowsVK::VK_SCROLL;
mSDL2_to_Win[ SDLK_HELP ] = (U32)WindowsVK::VK_HELP;
mSDL2_to_Win[ SDLK_PRINTSCREEN ] = (U32)WindowsVK::VK_SNAPSHOT;
mSDL2_to_Win[ SDLK_CANCEL ] = (U32)WindowsVK::VK_CANCEL;
mSDL2_to_Win[ SDLK_APPLICATION ] = (U32)WindowsVK::VK_APPS;
mSDL2_to_Win[ SDLK_UNKNOWN ] = (U32)WindowsVK::VK_UNKNOWN;
mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK;
mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB;
mSDL2_to_Win[ SDLK_CLEAR ] = (U32)WindowsVK::VK_CLEAR;
mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN;
mSDL2_to_Win[ SDLK_PAUSE ] = (U32)WindowsVK::VK_PAUSE;
mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE;
mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE;
mSDL2_to_Win[ SDLK_KP_DIVIDE ] = (U32)WindowsVK::VK_DIVIDE;
mSDL2_to_Win[ SDLK_KP_MULTIPLY] = (U32)WindowsVK::VK_MULTIPLY;
mSDL2_to_Win[ SDLK_KP_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS; // VK_SUBSTRACT?
mSDL2_to_Win[ SDLK_KP_PLUS ] = (U32)WindowsVK::VK_OEM_PLUS; // VK_ADD?
mSDL2_to_Win[ SDLK_KP_ENTER ] = (U32)WindowsVK::VK_RETURN;
// map numpad keys as best we can, mapping to VK_NUMPADx will break things
// for SDL2, so we use the actual functions
mSDL2_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::VK_INSERT; // VK_NUMPAD0
mSDL2_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::VK_END; // VK_NUMPAD1
mSDL2_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::VK_DOWN; // VK_NUMPAD2
mSDL2_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::VK_NEXT; // VK_NUMPAD3
mSDL2_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::VK_LEFT; // VK_NUMPAD4
mSDL2_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::VK_NUMPAD5; // has no function
mSDL2_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::VK_RIGHT; // VK_NUMPAD6
mSDL2_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::VK_HOME; // VK_NUMPAD7
mSDL2_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::VK_UP; // VK_NUMPAD8
mSDL2_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::VK_PRIOR; // VK_NUMPAD9
mSDL2_to_Win[ SDLK_KP_PERIOD ] = (U32)WindowsVK::VK_DELETE; // VK_OEM_PERIOD;
// ?
mSDL2_to_Win[ SDLK_UP ] = (U32)WindowsVK::VK_UP;
mSDL2_to_Win[ SDLK_DOWN ] = (U32)WindowsVK::VK_DOWN;
mSDL2_to_Win[ SDLK_RIGHT ] = (U32)WindowsVK::VK_RIGHT;
mSDL2_to_Win[ SDLK_LEFT ] = (U32)WindowsVK::VK_LEFT;
mSDL2_to_Win[ SDLK_INSERT ] = (U32)WindowsVK::VK_INSERT;
mSDL2_to_Win[ SDLK_HOME ] = (U32)WindowsVK::VK_HOME;
mSDL2_to_Win[ SDLK_END ] = (U32)WindowsVK::VK_END;
mSDL2_to_Win[ SDLK_PAGEUP ] = (U32)WindowsVK::VK_PRIOR;
mSDL2_to_Win[ SDLK_PAGEDOWN ] = (U32)WindowsVK::VK_NEXT;
mSDL2_to_Win[ SDLK_F1 ] = (U32)WindowsVK::VK_F1;
mSDL2_to_Win[ SDLK_F2 ] = (U32)WindowsVK::VK_F2;
mSDL2_to_Win[ SDLK_F3 ] = (U32)WindowsVK::VK_F3;
mSDL2_to_Win[ SDLK_F4 ] = (U32)WindowsVK::VK_F4;
mSDL2_to_Win[ SDLK_F5 ] = (U32)WindowsVK::VK_F5;
mSDL2_to_Win[ SDLK_F6 ] = (U32)WindowsVK::VK_F6;
mSDL2_to_Win[ SDLK_F7 ] = (U32)WindowsVK::VK_F7;
mSDL2_to_Win[ SDLK_F8 ] = (U32)WindowsVK::VK_F8;
mSDL2_to_Win[ SDLK_F9 ] = (U32)WindowsVK::VK_F9;
mSDL2_to_Win[ SDLK_F10 ] = (U32)WindowsVK::VK_F10;
mSDL2_to_Win[ SDLK_F11 ] = (U32)WindowsVK::VK_F11;
mSDL2_to_Win[ SDLK_F12 ] = (U32)WindowsVK::VK_F12;
mSDL2_to_Win[ SDLK_F13 ] = (U32)WindowsVK::VK_F13;
mSDL2_to_Win[ SDLK_F14 ] = (U32)WindowsVK::VK_F14;
mSDL2_to_Win[ SDLK_F15 ] = (U32)WindowsVK::VK_F15;
mSDL2_to_Win[ SDLK_CAPSLOCK ] = (U32)WindowsVK::VK_CAPITAL;
mSDL2_to_Win[ SDLK_RSHIFT ] = (U32)WindowsVK::VK_SHIFT;
mSDL2_to_Win[ SDLK_LSHIFT ] = (U32)WindowsVK::VK_SHIFT;
mSDL2_to_Win[ SDLK_RCTRL ] = (U32)WindowsVK::VK_CONTROL;
mSDL2_to_Win[ SDLK_LCTRL ] = (U32)WindowsVK::VK_CONTROL;
mSDL2_to_Win[ SDLK_RALT ] = (U32)WindowsVK::VK_MENU;
mSDL2_to_Win[ SDLK_LALT ] = (U32)WindowsVK::VK_MENU;
mSDL2_to_Win[ SDLK_MENU ] = (U32)WindowsVK::VK_MENU;
// VK_MODECHANGE ?
// mSDL2_to_Win[ SDLK_MODE ] = (U32)WindowsVK::VK_MODE;
// ?
// mSDL2_to_Win[ SDLK_SYSREQ ] = (U32)WindowsVK::VK_SYSREQ;
// mSDL2_to_Win[ SDLK_POWER ] = (U32)WindowsVK::VK_POWER;
// mSDL2_to_Win[ SDLK_UNDO ] = (U32)WindowsVK::VK_UNDO;
// mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_EQUALS;
// mSDL2_to_Win[ 311 ] = (U32)WindowsVK::VK_LWIN;
// mSDL2_to_Win[ 312 ] = (U32)WindowsVK::VK_RWIN;
// mSDL2_to_Win[ SDLK_COLON ] = ?
}
auto itr = mSDL2_to_Win.find( aSymbol );
if( itr != mSDL2_to_Win.end() )
return itr->second;
return aSymbol;
}
#endif
+33
View File
@@ -0,0 +1,33 @@
#ifndef LL_LLKEYBOARDSDL2_H
#define LL_LLKEYBOARDSDL2_H
#include "llkeyboard.h"
#include "SDL2/SDL.h"
class LLKeyboardSDL : public LLKeyboard
{
public:
LLKeyboardSDL();
/*virtual*/ ~LLKeyboardSDL() {};
/*virtual*/ bool handleKeyUp(const U32 key, MASK mask);
/*virtual*/ bool handleKeyDown(const U32 key, MASK mask);
/*virtual*/ void resetMaskKeys();
/*virtual*/ MASK currentMask(bool for_mouse_event);
/*virtual*/ void scanKeyboard();
protected:
MASK updateModifiers(const U32 mask);
void setModifierKeyLevel( KEY key, bool new_state );
bool translateNumpadKey( const U32 os_key, KEY *translated_key );
U16 inverseTranslateNumpadKey(const KEY translated_key);
private:
std::map<U32, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys
std::map<KEY, U32> mInvTranslateNumpadMap; // inverse of the above
public:
static U32 mapSDL2toWin( U32 );
};
#endif
+329
View File
@@ -0,0 +1,329 @@
/**
* @file llkeyboardwin32.cpp
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#if LL_WINDOWS
#include "linden_common.h"
#include "llwin32headers.h"
#include "llkeyboardwin32.h"
#include "llwindowcallbacks.h"
LLKeyboardWin32::LLKeyboardWin32()
{
// Set up key mapping for windows - eventually can read this from a file?
// Anything not in the key map gets dropped
// Add default A-Z
// Virtual key mappings from WinUser.h
KEY cur_char;
for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
{
mTranslateKeyMap[cur_char] = (KEY)cur_char;
}
for (cur_char = '0'; cur_char <= '9'; cur_char++)
{
mTranslateKeyMap[cur_char] = (KEY)cur_char;
}
// numpad number keys
for (cur_char = 0x60; cur_char <= 0x69; cur_char++)
{
mTranslateKeyMap[cur_char] = (KEY)('0' + (cur_char - 0x60));
}
mTranslateKeyMap[VK_SPACE] = ' ';
mTranslateKeyMap[VK_OEM_1] = ';';
// When the user hits, for example, Ctrl-= as a keyboard shortcut,
// Windows generates VK_OEM_PLUS. This is true on both QWERTY and DVORAK
// keyboards in the US. Numeric keypad '+' generates VK_ADD below.
// Thus we translate it as '='.
// Potential bug: This may not be true on international keyboards. JC
mTranslateKeyMap[VK_OEM_PLUS] = '=';
mTranslateKeyMap[VK_OEM_COMMA] = ',';
mTranslateKeyMap[VK_OEM_MINUS] = '-';
mTranslateKeyMap[VK_OEM_PERIOD] = '.';
// <FS:Ansariel> Reverted back and changed to KEY_DIVIDE. This allows easy starting
// gestures in chat.
// Shared Media prims borkage is worked around in llviewerkeyboard.cpp,
// start_gesture( EKeystate s )
mTranslateKeyMap[VK_OEM_2] = KEY_DIVIDE; //'/';//This used to be KEY_PAD_DIVIDE, but that breaks typing into text fields in media prims
mTranslateKeyMap[VK_OEM_3] = '`';
mTranslateKeyMap[VK_OEM_4] = '[';
mTranslateKeyMap[VK_OEM_5] = '\\';
mTranslateKeyMap[VK_OEM_6] = ']';
mTranslateKeyMap[VK_OEM_7] = '\'';
mTranslateKeyMap[VK_ESCAPE] = KEY_ESCAPE;
mTranslateKeyMap[VK_RETURN] = KEY_RETURN;
mTranslateKeyMap[VK_LEFT] = KEY_LEFT;
mTranslateKeyMap[VK_RIGHT] = KEY_RIGHT;
mTranslateKeyMap[VK_UP] = KEY_UP;
mTranslateKeyMap[VK_DOWN] = KEY_DOWN;
mTranslateKeyMap[VK_BACK] = KEY_BACKSPACE;
mTranslateKeyMap[VK_INSERT] = KEY_INSERT;
mTranslateKeyMap[VK_DELETE] = KEY_DELETE;
mTranslateKeyMap[VK_SHIFT] = KEY_SHIFT;
mTranslateKeyMap[VK_CONTROL] = KEY_CONTROL;
mTranslateKeyMap[VK_MENU] = KEY_ALT;
mTranslateKeyMap[VK_CAPITAL] = KEY_CAPSLOCK;
mTranslateKeyMap[VK_HOME] = KEY_HOME;
mTranslateKeyMap[VK_END] = KEY_END;
mTranslateKeyMap[VK_PRIOR] = KEY_PAGE_UP;
mTranslateKeyMap[VK_NEXT] = KEY_PAGE_DOWN;
mTranslateKeyMap[VK_TAB] = KEY_TAB;
mTranslateKeyMap[VK_ADD] = KEY_ADD;
mTranslateKeyMap[VK_SUBTRACT] = KEY_SUBTRACT;
mTranslateKeyMap[VK_MULTIPLY] = KEY_MULTIPLY;
mTranslateKeyMap[VK_DIVIDE] = KEY_DIVIDE;
mTranslateKeyMap[VK_F1] = KEY_F1;
mTranslateKeyMap[VK_F2] = KEY_F2;
mTranslateKeyMap[VK_F3] = KEY_F3;
mTranslateKeyMap[VK_F4] = KEY_F4;
mTranslateKeyMap[VK_F5] = KEY_F5;
mTranslateKeyMap[VK_F6] = KEY_F6;
mTranslateKeyMap[VK_F7] = KEY_F7;
mTranslateKeyMap[VK_F8] = KEY_F8;
mTranslateKeyMap[VK_F9] = KEY_F9;
mTranslateKeyMap[VK_F10] = KEY_F10;
mTranslateKeyMap[VK_F11] = KEY_F11;
mTranslateKeyMap[VK_F12] = KEY_F12;
mTranslateKeyMap[VK_CLEAR] = KEY_PAD_CENTER;
mTranslateKeyMap[VK_APPS] = KEY_CONTEXT_MENU; // <FS:Ansariel> FIRE-19933: Open context menu on context menu key press
// Build inverse map
std::map<U16, KEY>::iterator iter;
for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
{
mInvTranslateKeyMap[iter->second] = iter->first;
}
// numpad map
mTranslateNumpadMap[0x60] = KEY_PAD_INS; // keypad 0
mTranslateNumpadMap[0x61] = KEY_PAD_END; // keypad 1
mTranslateNumpadMap[0x62] = KEY_PAD_DOWN; // keypad 2
mTranslateNumpadMap[0x63] = KEY_PAD_PGDN; // keypad 3
mTranslateNumpadMap[0x64] = KEY_PAD_LEFT; // keypad 4
mTranslateNumpadMap[0x65] = KEY_PAD_CENTER; // keypad 5
mTranslateNumpadMap[0x66] = KEY_PAD_RIGHT; // keypad 6
mTranslateNumpadMap[0x67] = KEY_PAD_HOME; // keypad 7
mTranslateNumpadMap[0x68] = KEY_PAD_UP; // keypad 8
mTranslateNumpadMap[0x69] = KEY_PAD_PGUP; // keypad 9
mTranslateNumpadMap[0x6A] = KEY_PAD_MULTIPLY; // keypad *
mTranslateNumpadMap[0x6B] = KEY_PAD_ADD; // keypad +
mTranslateNumpadMap[0x6D] = KEY_PAD_SUBTRACT; // keypad -
mTranslateNumpadMap[0x6E] = KEY_PAD_DEL; // keypad .
mTranslateNumpadMap[0x6F] = KEY_PAD_DIVIDE; // keypad /
for (iter = mTranslateNumpadMap.begin(); iter != mTranslateNumpadMap.end(); iter++)
{
mInvTranslateNumpadMap[iter->second] = iter->first;
}
}
// Asynchronously poll the control, alt and shift keys and set the
// appropriate states.
// Note: this does not generate edges.
void LLKeyboardWin32::resetMaskKeys()
{
// GetAsyncKeyState returns a short and uses the most significant
// bit to indicate that the key is down.
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
{
mKeyLevel[KEY_SHIFT] = true;
}
if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
{
mKeyLevel[KEY_CONTROL] = true;
}
if (GetAsyncKeyState(VK_MENU) & 0x8000)
{
mKeyLevel[KEY_ALT] = true;
}
}
//void LLKeyboardWin32::setModifierKeyLevel( KEY key, bool new_state )
//{
// if( mKeyLevel[key] != new_state )
// {
// mKeyLevelFrameCount[key] = 0;
//
// if( new_state )
// {
// mKeyLevelTimer[key].reset();
// }
// mKeyLevel[key] = new_state;
// }
//}
MASK LLKeyboardWin32::updateModifiers()
{
//RN: this seems redundant, as we should have already received the appropriate
// messages for the modifier keys
// Scan the modifier keys as of the last Windows key message
// (keydown encoded in high order bit of short)
mKeyLevel[KEY_CAPSLOCK] = (GetKeyState(VK_CAPITAL) & 0x0001) != 0; // Low order bit carries the toggle state.
// Get mask for keyboard events
MASK mask = currentMask(false);
return mask;
}
// mask is ignored, except for extended flag -- we poll the modifier keys for the other flags
bool LLKeyboardWin32::handleKeyDown(const U16 key, MASK mask)
{
KEY translated_key;
U32 translated_mask;
bool handled = false;
translated_mask = updateModifiers();
if (translateExtendedKey(key, mask, &translated_key))
{
handled = handleTranslatedKeyDown(translated_key, translated_mask);
}
return handled;
}
// mask is ignored, except for extended flag -- we poll the modifier keys for the other flags
bool LLKeyboardWin32::handleKeyUp(const U16 key, MASK mask)
{
KEY translated_key;
U32 translated_mask;
bool handled = false;
translated_mask = updateModifiers();
if (translateExtendedKey(key, mask, &translated_key))
{
handled = handleTranslatedKeyUp(translated_key, translated_mask);
}
return handled;
}
MASK LLKeyboardWin32::currentMask(bool)
{
MASK mask = MASK_NONE;
if (mKeyLevel[KEY_SHIFT]) mask |= MASK_SHIFT;
if (mKeyLevel[KEY_CONTROL]) mask |= MASK_CONTROL;
if (mKeyLevel[KEY_ALT]) mask |= MASK_ALT;
return mask;
}
void LLKeyboardWin32::scanKeyboard()
{
S32 key;
MSG msg;
PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
for (key = 0; key < KEY_COUNT; key++)
{
// Generate callback if any event has occurred on this key this frame.
// Can't just test mKeyLevel, because this could be a slow frame and
// key might have gone down then up. JC
if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
{
mCurScanKey = key;
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
}
}
// Reset edges for next frame
for (key = 0; key < KEY_COUNT; key++)
{
mKeyUp[key] = false;
mKeyDown[key] = false;
if (mKeyLevel[key])
{
mKeyLevelFrameCount[key]++;
}
}
}
bool LLKeyboardWin32::translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key)
{
return translateKey(os_key, translated_key);
}
U16 LLKeyboardWin32::inverseTranslateExtendedKey(const KEY translated_key)
{
// if numlock is on, then we need to translate KEY_PAD_FOO to the corresponding number pad number
if(GetKeyState(VK_NUMLOCK) & 1)
{
std::map<KEY, U16>::iterator iter = mInvTranslateNumpadMap.find(translated_key);
if (iter != mInvTranslateNumpadMap.end())
{
return iter->second;
}
}
// if numlock is off or we're not converting numbers to arrows, we map our keypad arrows
// to regular arrows since Windows doesn't distinguish between them
KEY converted_key = translated_key;
switch (converted_key)
{
case KEY_PAD_LEFT:
converted_key = KEY_LEFT; break;
case KEY_PAD_RIGHT:
converted_key = KEY_RIGHT; break;
case KEY_PAD_UP:
converted_key = KEY_UP; break;
case KEY_PAD_DOWN:
converted_key = KEY_DOWN; break;
case KEY_PAD_HOME:
converted_key = KEY_HOME; break;
case KEY_PAD_END:
converted_key = KEY_END; break;
case KEY_PAD_PGUP:
converted_key = KEY_PAGE_UP; break;
case KEY_PAD_PGDN:
converted_key = KEY_PAGE_DOWN; break;
case KEY_PAD_INS:
converted_key = KEY_INSERT; break;
case KEY_PAD_DEL:
converted_key = KEY_DELETE; break;
case KEY_PAD_RETURN:
converted_key = KEY_RETURN; break;
}
// convert our virtual keys to OS keys
return inverseTranslateKey(converted_key);
}
#endif
+58
View File
@@ -0,0 +1,58 @@
/**
* @file llkeyboardwin32.h
* @brief Handler for assignable key bindings
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLKEYBOARDWIN32_H
#define LL_LLKEYBOARDWIN32_H
#include "llkeyboard.h"
// this mask distinguishes extended keys, which include non-numpad arrow keys
// (and, curiously, the num lock and numpad '/')
const MASK MASK_EXTENDED = 0x0100;
class LLKeyboardWin32 : public LLKeyboard
{
public:
LLKeyboardWin32();
/*virtual*/ ~LLKeyboardWin32() {};
/*virtual*/ bool handleKeyUp(const U16 key, MASK mask);
/*virtual*/ bool handleKeyDown(const U16 key, MASK mask);
/*virtual*/ void resetMaskKeys();
/*virtual*/ MASK currentMask(bool for_mouse_event);
/*virtual*/ void scanKeyboard();
bool translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key);
U16 inverseTranslateExtendedKey(const KEY translated_key);
protected:
MASK updateModifiers();
//void setModifierKeyLevel( KEY key, bool new_state );
private:
std::map<U16, KEY> mTranslateNumpadMap;
std::map<KEY, U16> mInvTranslateNumpadMap;
};
#endif
+66
View File
@@ -0,0 +1,66 @@
/**
* @file llmousehandler.cpp
* @brief LLMouseHandler class implementation
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llmousehandler.h"
//virtual
bool LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, bool down)
{
bool handled = false;
if (down)
{
switch (clicktype)
{
case CLICK_LEFT: handled = handleMouseDown(x, y, mask); break;
case CLICK_RIGHT: handled = handleRightMouseDown(x, y, mask); break;
case CLICK_MIDDLE: handled = handleMiddleMouseDown(x, y, mask); break;
case CLICK_DOUBLELEFT: handled = handleDoubleClick(x, y, mask); break;
case CLICK_BUTTON4:
case CLICK_BUTTON5:
LL_INFOS() << "Handle mouse button " << clicktype + 1 << " down." << LL_ENDL;
break;
default:
LL_WARNS() << "Unhandled enum." << LL_ENDL;
}
}
else
{
switch (clicktype)
{
case CLICK_LEFT: handled = handleMouseUp(x, y, mask); break;
case CLICK_RIGHT: handled = handleRightMouseUp(x, y, mask); break;
case CLICK_MIDDLE: handled = handleMiddleMouseUp(x, y, mask); break;
case CLICK_DOUBLELEFT: handled = handleDoubleClick(x, y, mask); break;
case CLICK_BUTTON4:
case CLICK_BUTTON5:
LL_INFOS() << "Handle mouse button " << clicktype + 1 << " up." << LL_ENDL;
break;
default:
LL_WARNS() << "Unhandled enum." << LL_ENDL;
}
}
return handled;
}
+73
View File
@@ -0,0 +1,73 @@
/**
* @file llmousehandler.h
* @brief LLMouseHandler class definition
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_MOUSEHANDLER_H
#define LL_MOUSEHANDLER_H
#include "linden_common.h"
#include "llrect.h"
#include "indra_constants.h"
// Mostly-abstract interface.
// Intended for use via multiple inheritance.
// A class may have as many interfaces as it likes, but never needs to inherit one more than once.
class LLMouseHandler
{
public:
LLMouseHandler() {}
virtual ~LLMouseHandler() {}
typedef enum {
SHOW_NEVER,
SHOW_IF_NOT_BLOCKED,
SHOW_ALWAYS,
} EShowToolTip;
virtual bool handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, bool down);
virtual bool handleMouseDown(S32 x, S32 y, MASK mask) = 0;
virtual bool handleMouseUp(S32 x, S32 y, MASK mask) = 0;
virtual bool handleMiddleMouseDown(S32 x, S32 y, MASK mask) = 0;
virtual bool handleMiddleMouseUp(S32 x, S32 y, MASK mask) = 0;
virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask) = 0;
virtual bool handleRightMouseUp(S32 x, S32 y, MASK mask) = 0;
virtual bool handleDoubleClick(S32 x, S32 y, MASK mask) = 0;
virtual bool handleHover(S32 x, S32 y, MASK mask) = 0;
virtual bool handleScrollWheel(S32 x, S32 y, S32 clicks) = 0;
virtual bool handleScrollHWheel(S32 x, S32 y, S32 clicks) = 0;
virtual bool handleToolTip(S32 x, S32 y, MASK mask) = 0;
virtual const std::string& getName() const = 0;
virtual void onMouseCaptureLost() = 0;
virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const = 0;
virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const = 0;
virtual bool hasMouseCapture() = 0;
};
#endif
+115
View File
@@ -0,0 +1,115 @@
/**
* @file llopenglview-objc.h
* @brief Class interfaces for most of the Mac facing window functionality.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLOpenGLView_H
#define LLOpenGLView_H
#import <Cocoa/Cocoa.h>
#import <IOKit/IOKitLib.h>
#import <CoreFoundation/CFBase.h>
#import <CoreFoundation/CFNumber.h>
#include <string>
@interface LLOpenGLView : NSOpenGLView <NSTextInputClient>
{
std::string mLastDraggedUrl;
unsigned int mModifiers;
float mMousePos[2];
bool mHasMarkedText;
unsigned int mMarkedTextLength;
bool mMarkedTextAllowed;
bool mSimulatedRightClick;
bool mOldResize;
}
- (id) initWithSamples:(NSUInteger)samples;
- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync;
- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync;
- (void)commitCurrentPreedit;
- (void) setOldResize:(bool)oldresize;
// rebuildContext
// Destroys and recreates a context with the view's internal format set via setPixelFormat;
// Use this in event of needing to rebuild a context for whatever reason, without needing to assign a new pixel format.
- (BOOL) rebuildContext;
// rebuildContextWithFormat
// Destroys and recreates a context with the specified pixel format.
- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format;
// These are mostly just for C++ <-> Obj-C interop. We can manipulate the CGLContext from C++ without reprecussions.
- (CGLContextObj) getCGLContextObj;
- (CGLPixelFormatObj*)getCGLPixelFormatObj;
- (unsigned long) getVramSize;
- (void) allowMarkedTextInput:(bool)allowed;
- (void) viewDidEndLiveResize;
@end
@interface LLUserInputWindow : NSPanel
@end
@interface LLNonInlineTextView : NSTextView
{
LLOpenGLView *glview;
unichar mKeyPressed;
}
- (void) setGLView:(LLOpenGLView*)view;
@end
@interface LLNSWindow : NSWindow
- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view;
- (NSPoint)flipPoint:(NSPoint)aPoint;
@end
@interface NSScreen (PointConversion)
/*
Returns the screen where the mouse resides
*/
+ (NSScreen *)currentScreenForMouseLocation;
/*
Allows you to convert a point from global coordinates to the current screen coordinates.
*/
- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint;
/*
Allows to flip the point coordinates, so y is 0 at the top instead of the bottom. x remains the same
*/
- (NSPoint)flipPoint:(NSPoint)aPoint;
@end
#endif
+955
View File
@@ -0,0 +1,955 @@
/**
* @file llopenglview-objc.mm
* @brief Class implementation for most of the Mac facing window functionality.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#import "llopenglview-objc.h"
#import "llwindowmacosx-objc.h"
#import "llappdelegate-objc.h"
extern BOOL gHiDPISupport;
#pragma mark local functions
NativeKeyEventData extractKeyDataFromKeyEvent(NSEvent* theEvent)
{
NativeKeyEventData eventData;
eventData.mKeyEvent = NativeKeyEventData::KEYUNKNOWN;
eventData.mEventType = [theEvent type];
eventData.mEventModifiers = [theEvent modifierFlags];
eventData.mEventKeyCode = [theEvent keyCode];
NSString *strEventChars = [theEvent characters];
eventData.mEventChars = (strEventChars.length) ? [strEventChars characterAtIndex:0] : 0;
NSString *strEventUChars = [theEvent charactersIgnoringModifiers];
eventData.mEventUnmodChars = (strEventUChars.length) ? [strEventUChars characterAtIndex:0] : 0;
eventData.mEventRepeat = [theEvent isARepeat];
return eventData;
}
NativeKeyEventData extractKeyDataFromModifierEvent(NSEvent* theEvent)
{
NativeKeyEventData eventData;
eventData.mKeyEvent = NativeKeyEventData::KEYUNKNOWN;
eventData.mEventType = [theEvent type];
eventData.mEventModifiers = [theEvent modifierFlags];
eventData.mEventKeyCode = [theEvent keyCode];
return eventData;
}
attributedStringInfo getSegments(NSAttributedString *str)
{
attributedStringInfo segments;
segment_lengths seg_lengths;
segment_standouts seg_standouts;
NSRange effectiveRange;
NSRange limitRange = NSMakeRange(0, [str length]);
while (limitRange.length > 0) {
NSNumber *attr = [str attribute:NSUnderlineStyleAttributeName atIndex:limitRange.location longestEffectiveRange:&effectiveRange inRange:limitRange];
limitRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(limitRange) - NSMaxRange(effectiveRange));
if (effectiveRange.length <= 0)
{
effectiveRange.length = 1;
}
if ([attr integerValue] == 2)
{
seg_lengths.push_back(effectiveRange.length);
seg_standouts.push_back(true);
} else
{
seg_lengths.push_back(effectiveRange.length);
seg_standouts.push_back(false);
}
}
segments.seg_lengths = seg_lengths;
segments.seg_standouts = seg_standouts;
return segments;
}
#pragma mark class implementations
@implementation NSScreen (PointConversion)
+ (NSScreen *)currentScreenForMouseLocation
{
NSPoint mouseLocation = [NSEvent mouseLocation];
NSEnumerator *screenEnumerator = [[NSScreen screens] objectEnumerator];
NSScreen *screen;
while ((screen = [screenEnumerator nextObject]) && !NSMouseInRect(mouseLocation, screen.frame, NO))
;
return screen;
}
- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint
{
float normalizedX = fabs(fabs(self.frame.origin.x) - fabs(aPoint.x));
float normalizedY = aPoint.y - self.frame.origin.y;
return NSMakePoint(normalizedX, normalizedY);
}
- (NSPoint)flipPoint:(NSPoint)aPoint
{
return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y);
}
@end
@implementation LLOpenGLView
// Force a high quality update after live resizing
- (void) viewDidEndLiveResize
{
if (mOldResize) //Maint-3135
{
NSSize size = [self frame].size;
callResize(size.width, size.height);
}
}
- (unsigned long)getVramSize
{
CGLRendererInfoObj info = 0;
GLint vram_megabytes = 0;
int num_renderers = 0;
CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers);
if(0 == the_err)
{
// The name, uses, and other platform definitions of gGLManager.mVRAM suggest that this is supposed to be total vram in MB,
// rather than, say, just the texture memory. The two exceptions are:
// 1. LLAppViewer::getViewerInfo() puts the value in a field labeled "TEXTURE_MEMORY"
// 2. For years, this present function used kCGLRPTextureMemoryMegabytes
// Now we use kCGLRPVideoMemoryMegabytes to bring it in line with everything else (except thatone label).
CGLDescribeRenderer (info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes);
CGLDestroyRendererInfo (info);
}
else
{
vram_megabytes = 256;
}
return (unsigned long)vram_megabytes; // return value is in megabytes.
}
- (void)viewDidMoveToWindow
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowResized:) name:NSWindowDidResizeNotification
object:[self window]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowWillMiniaturize:) name:NSWindowWillMiniaturizeNotification
object:[self window]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification
object:[self window]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification
object:[self window]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(windowDidChangeScreen:) name:NSWindowDidChangeScreenNotification
object:[self window]];
NSRect wnd_rect = [[self window] frame];
NSRect dev_rect = [self convertRectToBacking:wnd_rect];
if (!NSEqualSizes(wnd_rect.size,dev_rect.size))
{
callResize(dev_rect.size.width, dev_rect.size.height);
}
}
- (void)setOldResize:(bool)oldresize
{
mOldResize = oldresize;
}
- (void)windowResized:(NSNotification *)notification;
{
if (!mOldResize) //Maint-3288
{
NSSize dev_sz = gHiDPISupport ? [self convertSizeToBacking:[self frame].size] : [self frame].size;
callResize(dev_sz.width, dev_sz.height);
}
}
- (void)windowWillMiniaturize:(NSNotification *)notification;
{
callWindowHide();
}
- (void)windowDidDeminiaturize:(NSNotification *)notification;
{
callWindowUnhide();
}
- (void)windowDidBecomeKey:(NSNotification *)notification;
{
mModifiers = [NSEvent modifierFlags];
}
-(void)windowDidChangeScreen:(NSNotification *)notification;
{
callWindowDidChangeScreen();
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id) init
{
return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE];
}
- (id) initWithSamples:(NSUInteger)samples
{
return [self initWithFrame:[self bounds] withSamples:samples andVsync:TRUE];
}
- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync
{
return [self initWithFrame:[self bounds] withSamples:samples andVsync:vsync];
}
- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync
{
// <FS> Fix some bad refcount code and squash some potential leakiness; by Cinder Roxley
self = [super initWithFrame:frame];
if (!self) { return self; } // Despite what this may look like, returning nil self is a-ok.
// <F/S>
[self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]];
//[self initWithFrame:frame]; <FS> Fix some bad refcount code and squash some potential leakiness; by Cinder Roxley
// Initialize with a default "safe" pixel format that will work with versions dating back to OS X 10.6.
// Any specialized pixel formats, i.e. a core profile pixel format, should be initialized through rebuildContextWithFormat.
// 10.7 and 10.8 don't really care if we're defining a profile or not. If we don't explicitly request a core or legacy profile, it'll always assume a legacy profile (for compatibility reasons).
NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFANoRecovery,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAClosestPolicy,
NSOpenGLPFAAccelerated,
NSOpenGLPFASampleBuffers, static_cast<NSOpenGLPixelFormatAttribute>(samples > 0 ? 1 : 0),
NSOpenGLPFASamples, static_cast<NSOpenGLPixelFormatAttribute>(samples),
NSOpenGLPFAStencilSize, 8,
NSOpenGLPFADepthSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
0
};
NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease];
if (pixelFormat == nil)
{
NSLog(@"Failed to create pixel format!", nil);
return nil;
}
// <FS> Fix some bad refcount code and squash some potential leakiness; by Cinder Roxley
//NSOpenGLContext *glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
NSOpenGLContext *glContext = [[[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil] autorelease];
// </FS>
if (glContext == nil)
{
NSLog(@"Failed to create OpenGL context!", nil);
return nil;
}
[self setPixelFormat:pixelFormat];
//for retina support
[self setWantsBestResolutionOpenGLSurface:gHiDPISupport];
[self setOpenGLContext:glContext];
[glContext setView:self];
[glContext makeCurrentContext];
if (vsync)
{
GLint value = 1;
[glContext setValues:&value forParameter:NSOpenGLCPSwapInterval];
} else {
// supress this error after move to Xcode 7:
// error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull]
// Tried using ObjC 'nonnull' keyword as per SO article but didn't build
GLint swapInterval=0;
[glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
}
mOldResize = false;
return self;
}
- (BOOL) rebuildContext
{
return [self rebuildContextWithFormat:[self pixelFormat]];
}
- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format
{
NSOpenGLContext *ctx = [self openGLContext];
[ctx clearDrawable];
// <FS> Fix some bad refcount code and squash some potential leakiness; by Cinder Roxley
//[ctx initWithFormat:format shareContext:nil];
ctx = [[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease];
// </FS>
if (ctx == nil)
{
NSLog(@"Failed to create OpenGL context!", nil);
return false;
}
[self setOpenGLContext:ctx];
[ctx setView:self];
[ctx makeCurrentContext];
return true;
}
- (CGLContextObj)getCGLContextObj
{
NSOpenGLContext *ctx = [self openGLContext];
return (CGLContextObj)[ctx CGLContextObj];
}
- (CGLPixelFormatObj*)getCGLPixelFormatObj
{
NSOpenGLPixelFormat *fmt = [self pixelFormat];
return (CGLPixelFormatObj*)[fmt CGLPixelFormatObj];
}
// Various events can be intercepted by our view, thus not reaching our window.
// Intercept these events, and pass them to the window as needed. - Geenz
- (void) mouseDown:(NSEvent *)theEvent
{
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
// Apparently people still use this?
if ([theEvent modifierFlags] & NSCommandKeyMask &&
!([theEvent modifierFlags] & NSControlKeyMask) &&
!([theEvent modifierFlags] & NSShiftKeyMask) &&
!([theEvent modifierFlags] & NSAlternateKeyMask) &&
!([theEvent modifierFlags] & NSAlphaShiftKeyMask) &&
!([theEvent modifierFlags] & NSFunctionKeyMask) &&
!([theEvent modifierFlags] & NSHelpKeyMask))
{
callRightMouseDown(mMousePos, [theEvent modifierFlags]);
mSimulatedRightClick = true;
} else {
if ([theEvent clickCount] == 2)
{
callDoubleClick(mMousePos, [theEvent modifierFlags]);
} else if ([theEvent clickCount] >= 1) {
callLeftMouseDown(mMousePos, [theEvent modifierFlags]);
}
}
}
- (void) mouseUp:(NSEvent *)theEvent
{
if (mSimulatedRightClick)
{
callRightMouseUp(mMousePos, [theEvent modifierFlags]);
mSimulatedRightClick = false;
} else {
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callLeftMouseUp(mMousePos, [theEvent modifierFlags]);
}
}
- (void) rightMouseDown:(NSEvent *)theEvent
{
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callRightMouseDown(mMousePos, [theEvent modifierFlags]);
}
- (void) rightMouseUp:(NSEvent *)theEvent
{
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callRightMouseUp(mMousePos, [theEvent modifierFlags]);
}
- (void)mouseMoved:(NSEvent *)theEvent
{
NSPoint dev_delta = gHiDPISupport ? [self convertPointToBacking:NSMakePoint([theEvent deltaX], [theEvent deltaY])] : NSMakePoint([theEvent deltaX], [theEvent deltaY]);
float mouseDeltas[] = {
float(dev_delta.x),
float(dev_delta.y)
};
callDeltaUpdate(mouseDeltas, 0);
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callMouseMoved(mMousePos, 0);
}
// NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged.
// Use mouseDragged for situations like this to trigger our movement callback instead.
- (void) mouseDragged:(NSEvent *)theEvent
{
// Trust the deltas supplied by NSEvent.
// The old CoreGraphics APIs we previously relied on are now flagged as obsolete.
// NSEvent isn't obsolete, and provides us with the correct deltas.
NSPoint dev_delta = gHiDPISupport ? [self convertPointToBacking:NSMakePoint([theEvent deltaX], [theEvent deltaY])] : NSMakePoint([theEvent deltaX], [theEvent deltaY]);
float mouseDeltas[] = {
float(dev_delta.x),
float(dev_delta.y)
};
callDeltaUpdate(mouseDeltas, 0);
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callMouseDragged(mMousePos, 0);
}
- (void) otherMouseDown:(NSEvent *)theEvent
{
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callOtherMouseDown(mMousePos, [theEvent modifierFlags], [theEvent buttonNumber]);
}
- (void) otherMouseUp:(NSEvent *)theEvent
{
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callOtherMouseUp(mMousePos, [theEvent modifierFlags], [theEvent buttonNumber]);
}
- (void) rightMouseDragged:(NSEvent *)theEvent
{
[self mouseDragged:theEvent];
}
- (void) otherMouseDragged:(NSEvent *)theEvent
{
[self mouseDragged:theEvent];
}
- (void) scrollWheel:(NSEvent *)theEvent
{
callScrollMoved(-[theEvent deltaX], -[theEvent deltaY]);
}
- (void) mouseExited:(NSEvent *)theEvent
{
callMouseExit();
}
- (void) keyUp:(NSEvent *)theEvent
{
NativeKeyEventData eventData = extractKeyDataFromKeyEvent(theEvent);
eventData.mKeyEvent = NativeKeyEventData::KEYUP;
callKeyUp(&eventData, [theEvent keyCode], [theEvent modifierFlags]);
}
- (void) keyDown:(NSEvent *)theEvent
{
NativeKeyEventData eventData = extractKeyDataFromKeyEvent(theEvent);
eventData.mKeyEvent = NativeKeyEventData::KEYDOWN;
uint keycode = [theEvent keyCode];
// We must not depend on flagsChange event to detect modifier flags changed,
// must depend on the modifire flags in the event parameter.
// Because flagsChange event handler misses event when other window is activated,
// e.g. OS Window for upload something or Input Window...
// mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit)
mModifiers = [theEvent modifierFlags];
NSString *str_no_modifiers = [theEvent charactersIgnoringModifiers];
unichar ch = 0;
if (str_no_modifiers.length)
{
ch = [str_no_modifiers characterAtIndex:0];
}
bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers, ch);
if (acceptsText &&
!mMarkedTextAllowed &&
!(mModifiers & (NSControlKeyMask | NSCommandKeyMask)) && // commands don't invoke InputWindow
![(LLAppDelegate*)[NSApp delegate] romanScript] &&
ch > ' ' &&
ch != NSDeleteCharacter &&
(ch < 0xF700 || ch > 0xF8FF)) // 0xF700-0xF8FF: reserved for function keys on the keyboard(from NSEvent.h)
{
[(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent];
} else
{
[[self inputContext] handleEvent:theEvent];
}
}
- (void)flagsChanged:(NSEvent *)theEvent
{
NativeKeyEventData eventData = extractKeyDataFromModifierEvent(theEvent);
mModifiers = [theEvent modifierFlags];
callModifier([theEvent modifierFlags]);
NSInteger mask = 0;
switch([theEvent keyCode])
{
case 56:
mask = NSShiftKeyMask;
break;
case 58:
mask = NSAlternateKeyMask;
break;
case 59:
mask = NSControlKeyMask;
break;
default:
return;
}
if (mModifiers & mask)
{
eventData.mKeyEvent = NativeKeyEventData::KEYDOWN;
wchar_t c = 0;
if([theEvent type] == NSEventTypeKeyDown)
{
// characters property is only valid when the event is of type KeyDown or KeyUp
// https://developer.apple.com/documentation/appkit/nsevent/1534183-characters?language=objc
c = [[theEvent characters] characterAtIndex:0];
}
callKeyDown(&eventData, [theEvent keyCode], 0, c);
}
else
{
eventData.mKeyEvent = NativeKeyEventData::KEYUP;
callKeyUp(&eventData, [theEvent keyCode], 0);
}
}
- (BOOL) acceptsFirstResponder
{
return YES;
}
- (NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender
{
NSPasteboard *pboard;
NSDragOperation sourceDragMask;
sourceDragMask = [sender draggingSourceOperationMask];
pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSURLPboardType])
{
if (sourceDragMask & NSDragOperationLink) {
NSURL *fileUrl = [[pboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:[NSDictionary dictionary]] objectAtIndex:0];
mLastDraggedUrl = [[fileUrl absoluteString] UTF8String];
return NSDragOperationLink;
}
}
return NSDragOperationNone;
}
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
callHandleDragUpdated(mLastDraggedUrl);
return NSDragOperationLink;
}
- (void) draggingExited:(id<NSDraggingInfo>)sender
{
callHandleDragExited(mLastDraggedUrl);
}
- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
{
return YES;
}
- (BOOL) performDragOperation:(id<NSDraggingInfo>)sender
{
callHandleDragDropped(mLastDraggedUrl);
return true;
}
- (BOOL)hasMarkedText
{
return mHasMarkedText;
}
- (NSRange)markedRange
{
int range[2];
getPreeditMarkedRange(&range[0], &range[1]);
return NSMakeRange(range[0], range[1]);
}
- (NSRange)selectedRange
{
int range[2];
getPreeditSelectionRange(&range[0], &range[1]);
return NSMakeRange(range[0], range[1]);
}
- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
{
// Apple says aString can be either an NSString or NSAttributedString instance.
// But actually it's NSConcreteMutableAttributedString or __NSCFConstantString.
// I observed aString was __NSCFConstantString only aString was null string(zero length).
// Apple also says when aString is an NSString object,
// the receiver is expected to render the marked text with distinguishing appearance.
// So I tried to make attributedStringInfo, but it won't be used... (Pell Smit)
if (mMarkedTextAllowed)
{
unsigned int selected[2] = {
unsigned(selectedRange.location),
unsigned(selectedRange.length)
};
unsigned int replacement[2] = {
unsigned(replacementRange.location),
unsigned(replacementRange.length)
};
int string_length = [aString length];
unichar text[string_length];
attributedStringInfo segments;
// I used 'respondsToSelector:@selector(string)'
// to judge aString is an attributed string or not.
if ([aString respondsToSelector:@selector(string)])
{
// aString is attibuted
[[aString string] getCharacters:text range:NSMakeRange(0, string_length)];
segments = getSegments((NSAttributedString *)aString);
}
else
{
// aString is not attributed
[aString getCharacters:text range:NSMakeRange(0, string_length)];
segments.seg_lengths.push_back(string_length);
segments.seg_standouts.push_back(true);
}
setMarkedText(text, selected, replacement, string_length, segments);
if (string_length > 0)
{
mHasMarkedText = TRUE;
mMarkedTextLength = string_length;
}
else
{
// we must clear the marked text when aString is null.
[self unmarkText];
}
} else {
if (mHasMarkedText)
{
[self unmarkText];
}
}
}
- (void)commitCurrentPreedit
{
if (mHasMarkedText)
{
if ([[self inputContext] respondsToSelector:@selector(commitEditing)])
{
[[self inputContext] commitEditing];
}
}
}
- (void)unmarkText
{
[[self inputContext] discardMarkedText];
resetPreedit();
mHasMarkedText = FALSE;
}
// We don't support attributed strings.
- (NSArray *)validAttributesForMarkedText
{
return [NSArray array];
}
// See above.
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
{
return nil;
}
- (void)insertText:(id)insertString
{
if (insertString != nil)
{
[self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])];
}
}
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
{
// SL-19801 Special workaround for system emoji picker
if ([aString length] == 2)
{
@try
{
uint32_t b0 = [aString characterAtIndex:0];
uint32_t b1 = [aString characterAtIndex:1];
if (((b0 & 0xF000) == 0xD000) && ((b1 & 0xF000) == 0xD000))
{
uint32_t b = 0x10000 | ((b0 & 0x3F) << 10) | (b1 & 0x3FF);
callUnicodeCallback(b, 0);
return;
}
}
@catch(NSException * e)
{
// One of the characters is an attribute string?
NSLog(@"Encountered an unsupported attributed character. Exception: %@ String: %@", e.name, aString);
return;
}
}
@try
{
if (!mHasMarkedText)
{
for (NSInteger i = 0; i < [aString length]; i++)
{
callUnicodeCallback([aString characterAtIndex:i], mModifiers);
}
} else {
resetPreedit();
// We may never get this point since unmarkText may be called before insertText ever gets called once we submit our text.
// But just in case...
for (NSInteger i = 0; i < [aString length]; i++)
{
handleUnicodeCharacter([aString characterAtIndex:i]);
}
mHasMarkedText = FALSE;
}
}
@catch(NSException * e)
{
NSLog(@"Failed to process an attributed string. Exception: %@ String: %@", e.name, aString);
}
}
- (void) insertNewline:(id)sender
{
if (!(mModifiers & NSCommandKeyMask) &&
!(mModifiers & NSShiftKeyMask) &&
!(mModifiers & NSAlternateKeyMask))
{
callUnicodeCallback(13, 0);
} else {
callUnicodeCallback(13, mModifiers);
}
}
- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
{
return NSNotFound;
}
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
{
float pos[4] = {0, 0, 0, 0};
getPreeditLocation(pos, mMarkedTextLength);
return NSMakeRect(pos[0], pos[1], pos[2], pos[3]);
}
- (void)doCommandBySelector:(SEL)aSelector
{
if (aSelector == @selector(insertNewline:))
{
[self insertNewline:self];
}
}
- (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex
{
return NO;
}
- (void) allowMarkedTextInput:(bool)allowed
{
mMarkedTextAllowed = allowed;
}
@end
@implementation LLUserInputWindow
- (void) close
{
[self orderOut:self];
}
@end
@implementation LLNonInlineTextView
/* Input Window is a legacy of 20 century, so we want to remove related classes.
But unfortunately, Viwer web browser has no support for modern inline input,
we need to leave these classes...
We will be back to get rid of Input Window after fixing viewer web browser.
How Input Window should work:
1) Input Window must not be empty.
It must close when it become empty result of edithing.
2) Input Window must not close when it still has input data.
It must keep open user types next char before commit. by Pell Smit
*/
- (void) setGLView:(LLOpenGLView *)view
{
glview = view;
}
- (void)keyDown:(NSEvent *)theEvent
{
// mKeyPressed is used later to determine whethere Input Window should close or not
mKeyPressed = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
// setMarkedText and insertText is called indirectly from inside keyDown: method
[super keyDown:theEvent];
}
// setMarkedText: is called for incomplete input(on the way to conversion).
- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
{
[super setMarkedText:aString selectedRange:selectedRange replacementRange:replacementRange];
if ([aString length] == 0) // this means Input Widow becomes empty
{
[self.window orderOut:self.window]; // Close this to avoid empty Input Window
}
}
// insertText: is called for inserting commited text.
// There are two ways to be called here:
// a) explicitly commited (must close)
// In case of user typed commit key(usually return key) or delete key or something
// b) automatically commited (must not close)
// In case of user typed next letter after conversion
- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange
{
[[self inputContext] discardMarkedText];
[self setString:@""];
[glview insertText:aString replacementRange:replacementRange];
if (mKeyPressed == NSEnterCharacter ||
mKeyPressed == NSBackspaceCharacter ||
mKeyPressed == NSTabCharacter ||
mKeyPressed == NSNewlineCharacter ||
mKeyPressed == NSCarriageReturnCharacter ||
mKeyPressed == NSDeleteCharacter ||
(mKeyPressed >= 0xF700 && mKeyPressed <= 0xF8FF))
{
// this is case a) of above comment
[self.window orderOut:self.window]; // to avoid empty Input Window
}
}
@end
@implementation LLNSWindow
- (id) init
{
return self;
}
- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view
{
NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation];
if(currentScreen)
{
NSPoint windowPoint = [view convertPoint:point toView:nil];
NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint];
NSPoint flippedScreenPoint = [currentScreen flipPoint:screenPoint];
flippedScreenPoint.y += [currentScreen frame].origin.y;
return flippedScreenPoint;
}
return NSZeroPoint;
}
- (NSPoint)flipPoint:(NSPoint)aPoint
{
return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y);
}
- (BOOL) becomeFirstResponder
{
callFocus();
return true;
}
- (BOOL) resignFirstResponder
{
callFocusLost();
return true;
}
- (void) close
{
callQuitHandler();
}
@end
+101
View File
@@ -0,0 +1,101 @@
/**
* @file llpreeditor.h
* @brief I believe this is used for languages like Japanese that require
* an "input method editor" to type Kanji.
* @author Open source patch, incorporated by Dave Simmons
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_PREEDITOR
#define LL_PREEDITOR
class LLPreeditor
{
public:
typedef std::vector<S32> segment_lengths_t;
typedef std::deque<bool> standouts_t;
// We don't delete against LLPreeditor, but compilers complain without this...
virtual ~LLPreeditor() {};
// Discard any preedit info. on this preeditor.
virtual void resetPreedit() = 0;
// Update the preedit feedback using specified details.
// Existing preedit is discarded and replaced with the new one. (I.e., updatePreedit is not cumulative.)
// All arguments are IN.
// preedit_count is the number of elements in arrays preedit_list and preedit_standouts.
// preedit list is an array of preedit texts (clauses.)
// preedit_standouts indicates whether each preedit text should be shown as standout clause.
// caret_position is the preedit-local position of text editing caret, in # of llwchar.
virtual void updatePreedit(const LLWString &preedit_string,
const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position) = 0;
// Turn the specified sub-contents into an active preedit.
// Both position and length are IN and count with UTF-32 (llwchar) characters.
// This method primarily facilitates reconversion.
virtual void markAsPreedit(S32 position, S32 length) = 0;
// Get the position and the length of the active preedit in the contents.
// Both position and length are OUT and count with UTF-32 (llwchar) characters.
// When this preeditor has no active preedit, position receives
// the caret position, and length receives 0.
virtual void getPreeditRange(S32 *position, S32 *length) const = 0;
// Get the position and the length of the current selection in the contents.
// Both position and length are OUT and count with UTF-32 (llwchar) characters.
// When this preeditor has no selection, position receives
// the caret position, and length receives 0.
virtual void getSelectionRange(S32 *position, S32 *length) const = 0;
// Get the locations where the preedit and related UI elements are displayed.
// Locations are relative to the app window and measured in GL coordinate space (before scaling.)
// query_position is IN argument, and other three are OUT.
virtual bool getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const = 0;
// Get the size (height) of the current font used in this preeditor.
virtual S32 getPreeditFontSize() const = 0;
// Get the contents of this preeditor as a LLWString. If there is an active preedit,
// the returned LLWString contains it.
virtual LLWString getPreeditString() const = 0;
// Handle a UTF-32 char on this preeditor, i.e., add the character
// to the contents.
// This is a back door of the method of same name of LLWindowCallback.
// called_from_parent should be set to false if calling through LLPreeditor.
virtual bool handleUnicodeCharHere(llwchar uni_char) = 0;
};
#endif
+522
View File
@@ -0,0 +1,522 @@
/**
* @file llwindow.cpp
* @brief Basic graphical window class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llwindowheadless.h"
#if LL_MESA_HEADLESS
#include "llwindowmesaheadless.h"
#elif LL_SDL
#include "llwindowsdl.h"
#elif LL_WINDOWS
#include "llwindowwin32.h"
#elif LL_DARWIN
#include "llwindowmacosx.h"
#endif
#include "llerror.h"
#include "llkeyboard.h"
#include "llwindowcallbacks.h"
//
// Globals
//
LLSplashScreen *gSplashScreenp = NULL;
bool gDebugClicks = false;
bool gDebugWindowProc = false;
// <FS:Zi> Allow file: links to open folders, chat history etc. on Linux systems
//const S32 gURLProtocolWhitelistCount = 5;
//const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:", "mailto:" };
#if LL_LINUX
const S32 gURLProtocolWhitelistCount = 7;
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "ftp:", "data:", "mailto:", "file:" };
#else
const S32 gURLProtocolWhitelistCount = 6;
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "ftp:", "data:", "mailto:" };
#endif
// </FS:Zi>
// CP: added a handler list - this is what's used to open the protocol and is based on registry entry
// only meaningful difference currently is that file: protocols are opened using http:
// since no protocol handler exists in registry for file:
// Important - these lists should match - protocol to handler
// Maestro: This list isn't referenced anywhere that I could find
//const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" };
S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
{
// Properly hide the splash screen when displaying the message box
bool was_visible = false;
if (LLSplashScreen::isVisible())
{
was_visible = true;
LLSplashScreen::hide();
}
S32 result = 0;
LL_WARNS() << "OSMessageBox: " << text << LL_ENDL;
#if LL_MESA_HEADLESS // !!! *FIX: (?)
return OSBTN_OK;
#elif LL_WINDOWS
result = OSMessageBoxWin32(text, caption, type);
#elif LL_DARWIN
result = OSMessageBoxMacOSX(text, caption, type);
#elif LL_SDL
result = OSMessageBoxSDL(text, caption, type);
#else
#error("OSMessageBox not implemented for this platform!")
#endif
if (was_visible)
{
LLSplashScreen::show();
}
return result;
}
//
// LLWindow
//
LLWindow::LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags)
: mCallbacks(callbacks),
mPostQuit(true),
mFullscreen(fullscreen),
mFullscreenWidth(0),
mFullscreenHeight(0),
mFullscreenBits(0),
mFullscreenRefresh(0),
mSupportedResolutions(NULL),
mNumSupportedResolutions(0),
mCurrentCursor(UI_CURSOR_ARROW),
mNextCursor(UI_CURSOR_ARROW),
mCursorHidden(false),
mBusyCount(0),
mIsMouseClipping(false),
mMinWindowWidth(0),
mMinWindowHeight(0),
mSwapMethod(SWAP_METHOD_UNDEFINED),
mHideCursorPermanent(false),
mFlags(flags),
mHighSurrogate(0),
mRefreshRate(0)
{
}
LLWindow::~LLWindow()
{
}
//virtual
bool LLWindow::isValid()
{
return true;
}
//virtual
bool LLWindow::canDelete()
{
return true;
}
//virtual
void LLWindow::setTitle(const std::string& title)
{
// the action happens in the platform specific impl
}
// virtual
void LLWindow::incBusyCount()
{
++mBusyCount;
}
// virtual
void LLWindow::decBusyCount()
{
if (mBusyCount > 0)
{
--mBusyCount;
}
}
//virtual
void LLWindow::resetBusyCount()
{
mBusyCount = 0;
}
//virtual
S32 LLWindow::getBusyCount() const
{
return mBusyCount;
}
//virtual
ECursorType LLWindow::getCursor() const
{
return mCurrentCursor;
}
//virtual
bool LLWindow::dialogColorPicker(F32 *r, F32 *g, F32 *b)
{
return false;
}
void *LLWindow::getMediaWindow()
{
// Default to returning the platform window.
return getPlatformWindow();
}
bool LLWindow::setSize(LLCoordScreen size)
{
if (!getMaximized())
{
size.mX = llmax(size.mX, mMinWindowWidth);
size.mY = llmax(size.mY, mMinWindowHeight);
}
return setSizeImpl(size);
}
bool LLWindow::setSize(LLCoordWindow size)
{
//HACK: we are inconsistently using minimum window dimensions
// in this case, we are constraining the inner "client" rect and other times
// we constrain the outer "window" rect
// There doesn't seem to be a good way to do this consistently without a bunch of platform
// specific code
if (!getMaximized())
{
size.mX = llmax(size.mX, mMinWindowWidth);
size.mY = llmax(size.mY, mMinWindowHeight);
}
return setSizeImpl(size);
}
// virtual
void LLWindow::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately)
{
mMinWindowWidth = min_width;
mMinWindowHeight = min_height;
if (enforce_immediately)
{
LLCoordScreen cur_size;
if (!getMaximized() && getSize(&cur_size))
{
if (cur_size.mX < mMinWindowWidth || cur_size.mY < mMinWindowHeight)
{
setSizeImpl(LLCoordScreen(llmin(cur_size.mX, mMinWindowWidth), llmin(cur_size.mY, mMinWindowHeight)));
}
}
}
}
//virtual
void LLWindow::processMiscNativeEvents()
{
// do nothing unless subclassed
}
//virtual
bool LLWindow::isPrimaryTextAvailable()
{
return false; // no
}
//virtual
bool LLWindow::pasteTextFromPrimary(LLWString &dst)
{
return false; // fail
}
// virtual
bool LLWindow::copyTextToPrimary(const LLWString &src)
{
return false; // fail
}
// static
std::vector<std::string> LLWindow::getDynamicFallbackFontList()
{
#if LL_WINDOWS
return LLWindowWin32::getDynamicFallbackFontList();
#elif LL_DARWIN
return LLWindowMacOSX::getDynamicFallbackFontList();
#elif LL_SDL
return LLWindowSDL::getDynamicFallbackFontList();
#else
return std::vector<std::string>();
#endif
}
// static
std::vector<std::string> LLWindow::getDisplaysResolutionList()
{
#if LL_WINDOWS
return LLWindowWin32::getDisplaysResolutionList();
#elif LL_DARWIN
return LLWindowMacOSX::getDisplaysResolutionList();
#else
return std::vector<std::string>();
#endif
}
#define UTF16_IS_HIGH_SURROGATE(U) ((U16)((U) - 0xD800) < 0x0400)
#define UTF16_IS_LOW_SURROGATE(U) ((U16)((U) - 0xDC00) < 0x0400)
#define UTF16_SURROGATE_PAIR_TO_UTF32(H,L) (((H) << 10) + (L) - (0xD800 << 10) - 0xDC00 + 0x00010000)
void LLWindow::handleUnicodeUTF16(U16 utf16, MASK mask)
{
// Note that we could discard unpaired surrogates, but I'm
// following the Unicode Consortium's recommendation here;
// that is, to preserve those unpaired surrogates in UTF-32
// values. _To_preserve_ means to pass to the callback in our
// context.
if (mHighSurrogate == 0)
{
if (UTF16_IS_HIGH_SURROGATE(utf16))
{
mHighSurrogate = utf16;
}
else
{
mCallbacks->handleUnicodeChar(utf16, mask);
}
}
else
{
if (UTF16_IS_LOW_SURROGATE(utf16))
{
/* A legal surrogate pair. */
mCallbacks->handleUnicodeChar(UTF16_SURROGATE_PAIR_TO_UTF32(mHighSurrogate, utf16), mask);
mHighSurrogate = 0;
}
else if (UTF16_IS_HIGH_SURROGATE(utf16))
{
/* Two consecutive high surrogates. */
mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
mHighSurrogate = utf16;
}
else
{
/* A non-low-surrogate preceeded by a high surrogate. */
mCallbacks->handleUnicodeChar(mHighSurrogate, mask);
mHighSurrogate = 0;
mCallbacks->handleUnicodeChar(utf16, mask);
}
}
}
//
// LLSplashScreen
//
// static
bool LLSplashScreen::isVisible()
{
return gSplashScreenp;
}
// static
LLSplashScreen *LLSplashScreen::create()
{
#if LL_MESA_HEADLESS || LL_SDL // !!! *FIX: (?)
return 0;
#elif LL_WINDOWS
return new LLSplashScreenWin32;
#elif LL_DARWIN
return new LLSplashScreenMacOSX;
#else
#error("LLSplashScreen not implemented on this platform!")
#endif
}
//static
void LLSplashScreen::show()
{
if (!gSplashScreenp)
{
#if LL_WINDOWS && !LL_MESA_HEADLESS
gSplashScreenp = new LLSplashScreenWin32;
#elif LL_DARWIN
gSplashScreenp = new LLSplashScreenMacOSX;
#endif
if (gSplashScreenp)
{
gSplashScreenp->showImpl();
}
}
}
//static
void LLSplashScreen::update(const std::string& str)
{
LLSplashScreen::show();
if (gSplashScreenp)
{
gSplashScreenp->updateImpl(str);
}
}
//static
void LLSplashScreen::hide()
{
if (gSplashScreenp)
{
gSplashScreenp->hideImpl();
}
delete gSplashScreenp;
gSplashScreenp = NULL;
}
//
// LLWindowManager
//
// TODO: replace with std::set
static std::set<LLWindow*> sWindowList;
LLWindow* LLWindowManager::createWindow(
LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags,
bool fullscreen,
bool clearBg,
bool enable_vsync,
bool use_gl,
bool ignore_pixel_depth,
U32 fsaa_samples,
U32 max_cores,
F32 max_gl_version,
bool useLegacyCursors) // <FS:LO> Legacy cursor setting from main program
{
LLWindow* new_window;
if (use_gl)
{
#if LL_MESA_HEADLESS
new_window = new LLWindowMesaHeadless(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth);
#elif LL_SDL
new_window = new LLWindowSDL(callbacks,
title, x, y, width, height, flags,
//fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples, useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
#elif LL_WINDOWS
new_window = new LLWindowWin32(callbacks,
title, name, x, y, width, height, flags,
//fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples, max_cores, max_gl_version);
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples, max_cores, max_gl_version, useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
#elif LL_DARWIN
new_window = new LLWindowMacOSX(callbacks,
title, name, x, y, width, height, flags,
//fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples, useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
#endif
}
else
{
new_window = new LLWindowHeadless(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth);
}
if (false == new_window->isValid())
{
delete new_window;
LL_WARNS() << "LLWindowManager::create() : Error creating window." << LL_ENDL;
return NULL;
}
sWindowList.insert(new_window);
return new_window;
}
bool LLWindowManager::destroyWindow(LLWindow* window)
{
if (sWindowList.find(window) == sWindowList.end())
{
LL_ERRS() << "LLWindowManager::destroyWindow() : Window pointer not valid, this window doesn't exist!"
<< LL_ENDL;
return false;
}
window->close();
sWindowList.erase(window);
delete window;
return true;
}
bool LLWindowManager::isWindowValid(LLWindow *window)
{
return sWindowList.find(window) != sWindowList.end();
}
//coordinate conversion utility funcs that forward to llwindow
LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const
{
const LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this);
LLCoordGL out;
LLWindow::instance_snapshot().begin()->convertCoords(self, &out);
return out.convert();
}
void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from)
{
LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this);
LLCoordGL from_gl(from);
LLWindow::instance_snapshot().begin()->convertCoords(from_gl, &self);
}
LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const
{
const LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this);
LLCoordGL out;
LLWindow::instance_snapshot().begin()->convertCoords(self, &out);
return out.convert();
}
void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from)
{
LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this);
LLCoordGL from_gl(from);
LLWindow::instance_snapshot().begin()->convertCoords(from_gl, &self);
}
+337
View File
@@ -0,0 +1,337 @@
/**
* @file llwindow.h
* @brief Basic graphical window class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOW_H
#define LL_LLWINDOW_H
#include "llrect.h"
#include "llcoord.h"
#include "llstring.h"
#include "llcursortypes.h"
#include "llinstancetracker.h"
#include "llsd.h"
class LLSplashScreen;
class LLPreeditor;
class LLWindowCallbacks;
// Refer to llwindow_test in test/common/llwindow for usage example
class LLWindow : public LLInstanceTracker<LLWindow>
{
public:
struct LLWindowResolution
{
S32 mWidth;
S32 mHeight;
};
enum ESwapMethod
{
SWAP_METHOD_UNDEFINED,
SWAP_METHOD_EXCHANGE,
SWAP_METHOD_COPY
};
enum EFlags
{
// currently unused
};
public:
virtual void show() = 0;
virtual void hide() = 0;
virtual void close() = 0;
virtual bool getVisible() = 0;
virtual bool getMinimized() = 0;
virtual bool getMaximized() = 0;
virtual bool maximize() = 0;
virtual void minimize() = 0;
virtual void restore() = 0;
bool getFullscreen() { return mFullscreen; };
virtual bool getPosition(LLCoordScreen *position) = 0;
virtual bool getSize(LLCoordScreen *size) = 0;
virtual bool getSize(LLCoordWindow *size) = 0;
virtual bool setPosition(LLCoordScreen position) = 0;
bool setSize(LLCoordScreen size);
bool setSize(LLCoordWindow size);
virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
virtual bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) = 0;
//create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread
// returns a pointer to be handed back to destroySharedConext/makeContextCurrent
virtual void* createSharedContext() = 0;
//make the given context current on the current thread
virtual void makeContextCurrent(void* context) = 0;
//destroy the given context that was retrieved by createSharedContext()
//Must be called on the same thread that called createSharedContext()
virtual void destroySharedContext(void* context) = 0;
virtual void toggleVSync(bool enable_vsync) = 0;
virtual bool setCursorPosition(LLCoordWindow position) = 0;
virtual bool getCursorPosition(LLCoordWindow *position) = 0;
#if LL_WINDOWS
virtual bool getCursorDelta(LLCoordCommon* delta) = 0;
#endif
virtual void showCursor() = 0;
virtual void hideCursor() = 0;
virtual bool isCursorHidden() = 0;
virtual void showCursorFromMouseMove() = 0;
virtual void hideCursorUntilMouseMove() = 0;
// Provide a way to set the Viewer window title after the
// windows has been created. The initial use case for this
// is described in SL-16102 (update window title with agent
// name, location etc. for non-interactive viewer) but it
// may also be useful in other cases.
virtual void setTitle(const std::string& title);
// These two functions create a way to make a busy cursor instead
// of an arrow when someone's busy doing something. Draw an
// arrow/hour if busycount > 0.
virtual void incBusyCount();
virtual void decBusyCount();
virtual void resetBusyCount();
virtual S32 getBusyCount() const;
// Sets cursor, may set to arrow+hourglass
virtual void setCursor(ECursorType cursor) { mNextCursor = cursor; };
virtual ECursorType getCursor() const;
virtual ECursorType getNextCursor() const { return mNextCursor; };
virtual void updateCursor() = 0;
virtual void captureMouse() = 0;
virtual void releaseMouse() = 0;
virtual void setMouseClipping( bool b ) = 0;
virtual bool isClipboardTextAvailable() = 0;
virtual bool pasteTextFromClipboard(LLWString &dst) = 0;
virtual bool copyTextToClipboard(const LLWString &src) = 0;
virtual bool isPrimaryTextAvailable();
virtual bool pasteTextFromPrimary(LLWString &dst);
virtual bool copyTextToPrimary(const LLWString &src);
virtual void flashIcon(F32 seconds) = 0;
virtual F32 getGamma() = 0;
virtual bool setGamma(const F32 gamma) = 0; // Set the gamma
virtual void setFSAASamples(const U32 fsaa_samples) = 0; //set number of FSAA samples
virtual U32 getFSAASamples() = 0;
virtual bool restoreGamma() = 0; // Restore original gamma table (before updating gamma)
virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
virtual void processMiscNativeEvents();
virtual void gatherInput() = 0;
virtual void delayInputProcessing() = 0;
virtual void swapBuffers() = 0;
virtual void bringToFront() = 0;
virtual void focusClient() { }; // this may not have meaning or be required on other platforms, therefore, it's not abstract
virtual void setOldResize(bool oldresize) { };
// handy coordinate space conversion routines
// NB: screen to window and vice verse won't work on width/height coordinate pairs,
// as the conversion must take into account left AND right border widths, etc.
virtual bool convertCoords( LLCoordScreen from, LLCoordWindow *to) = 0;
virtual bool convertCoords( LLCoordWindow from, LLCoordScreen *to) = 0;
virtual bool convertCoords( LLCoordWindow from, LLCoordGL *to) = 0;
virtual bool convertCoords( LLCoordGL from, LLCoordWindow *to) = 0;
virtual bool convertCoords( LLCoordScreen from, LLCoordGL *to) = 0;
virtual bool convertCoords( LLCoordGL from, LLCoordScreen *to) = 0;
// query supported resolutions
virtual LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) = 0;
virtual F32 getNativeAspectRatio() = 0;
virtual F32 getPixelAspectRatio() = 0;
virtual void setNativeAspectRatio(F32 aspect) = 0;
virtual void beforeDialog() {}; // prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)
virtual void afterDialog() {}; // undo whatever was done in beforeDialog()
// opens system default color picker, modally
// Returns true if valid color selected
virtual bool dialogColorPicker(F32 *r, F32 *g, F32 *b);
// return a platform-specific window reference (HWND on Windows, WindowRef on the Mac, Gtk window on Linux)
virtual void *getPlatformWindow() = 0;
// return the platform-specific window reference we use to initialize llmozlib (HWND on Windows, WindowRef on the Mac, Gtk window on Linux)
virtual void *getMediaWindow();
// control platform's Language Text Input mechanisms.
virtual void allowLanguageTextInput(LLPreeditor *preeditor, bool b) {}
virtual void setLanguageTextInput( const LLCoordGL & pos ) {};
virtual void updateLanguageTextInputArea() {}
virtual void interruptLanguageTextInput() {}
virtual void spawnWebBrowser(const std::string& escaped_url, bool async) {};
virtual void openFile(const std::string& file_name) {};
static std::vector<std::string> getDynamicFallbackFontList();
// Provide native key event data
virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); }
// Get system UI size based on DPI (for 96 DPI UI size should be 1.0)
virtual F32 getSystemUISize() { return 1.0f; }
static std::vector<std::string> getDisplaysResolutionList();
// windows only DirectInput8 for joysticks
virtual void* getDirectInput8() { return NULL; };
virtual bool getInputDevices(U32 device_type_filter,
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
void* win_callback,
void* userdata)
{
return false;
};
virtual S32 getRefreshRate() { return mRefreshRate; }
protected:
LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags);
virtual ~LLWindow();
// Defaults to true
virtual bool isValid();
// Defaults to true
virtual bool canDelete();
virtual bool setSizeImpl(LLCoordScreen size) = 0;
virtual bool setSizeImpl(LLCoordWindow size) = 0;
protected:
LLWindowCallbacks* mCallbacks;
bool mPostQuit; // should this window post a quit message when destroyed?
bool mFullscreen;
S32 mFullscreenWidth;
S32 mFullscreenHeight;
S32 mFullscreenBits;
S32 mFullscreenRefresh;
LLWindowResolution* mSupportedResolutions;
S32 mNumSupportedResolutions;
ECursorType mCurrentCursor;
ECursorType mNextCursor;
bool mCursorHidden;
S32 mBusyCount; // how deep is the "cursor busy" stack?
bool mIsMouseClipping; // Is this window currently clipping the mouse
ESwapMethod mSwapMethod;
bool mHideCursorPermanent;
U32 mFlags;
U16 mHighSurrogate;
S32 mMinWindowWidth;
S32 mMinWindowHeight;
S32 mRefreshRate;
// Handle a UTF-16 encoding unit received from keyboard.
// Converting the series of UTF-16 encoding units to UTF-32 data,
// this method passes the resulting UTF-32 data to mCallback's
// handleUnicodeChar. The mask should be that to be passed to the
// callback. This method uses mHighSurrogate as a dedicated work
// variable.
void handleUnicodeUTF16(U16 utf16, MASK mask);
friend class LLWindowManager;
// <FS:ND> Allow to query for window chrome sizes. Default it none, only win32 windows override this.
public:
virtual void getWindowChrome( U32 &aChromeW, U32 &aChromeH )
{ aChromeW = aChromeH = 0; }
// </FS:ND>
};
// LLSplashScreen
// A simple, OS-specific splash screen that we can display
// while initializing the application and before creating a GL
// window
class LLSplashScreen
{
public:
LLSplashScreen() { };
virtual ~LLSplashScreen() { };
// Call to display the window.
static LLSplashScreen * create();
static void show();
static void hide();
static void update(const std::string& string);
static bool isVisible();
protected:
// These are overridden by the platform implementation
virtual void showImpl() = 0;
virtual void updateImpl(const std::string& string) = 0;
virtual void hideImpl() = 0;
static bool sVisible;
};
// Platform-neutral for accessing the platform specific message box
S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type);
constexpr U32 OSMB_OK = 0;
constexpr U32 OSMB_OKCANCEL = 1;
constexpr U32 OSMB_YESNO = 2;
constexpr S32 OSBTN_YES = 0;
constexpr S32 OSBTN_NO = 1;
constexpr S32 OSBTN_OK = 2;
constexpr S32 OSBTN_CANCEL = 3;
//
// LLWindowManager
// Manages window creation and error checking
class LLWindowManager
{
public:
static LLWindow *createWindow(
LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags = 0,
bool fullscreen = false,
bool clearBg = false,
bool enable_vsync = false,
bool use_gl = true,
bool ignore_pixel_depth = false,
U32 fsaa_samples = 0,
U32 max_cores = 0,
F32 max_gl_version = 4.6f,
bool useLegacyCursors = false); // <FS:LO> Legacy cursor setting from main program
static bool destroyWindow(LLWindow* window);
static bool isWindowValid(LLWindow *window);
};
//
// helper funcs
//
extern bool gDebugWindowProc;
// Protocols, like "http" and "https" we support in URLs
extern const S32 gURLProtocolWhitelistCount;
extern const std::string gURLProtocolWhitelist[];
//extern const std::string gURLProtocolWhitelistHandler[];
#endif // _LL_window_h_
+232
View File
@@ -0,0 +1,232 @@
/**
* @file llwindowcallbacks.cpp
* @brief OS event callback class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llwindowcallbacks.h"
//
// LLWindowCallbacks
//
bool LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, bool repeated)
{
return false;
}
bool LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask)
{
return false;
}
void LLWindowCallbacks::handleScanKey(KEY key, bool key_down, bool key_up, bool key_level)
{
}
bool LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)
{
return false;
}
bool LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
{
return false;
}
bool LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
{
return false;
}
void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
{
return;
}
bool LLWindowCallbacks::handleCloseRequest(LLWindow *window)
{
//allow the window to close
return true;
}
void LLWindowCallbacks::handleQuit(LLWindow *window)
{
}
bool LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
{
return false;
}
bool LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
{
return false;
}
bool LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
{
return false;
}
bool LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
{
return false;
}
bool LLWindowCallbacks::handleOtherMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
{
return false;
}
bool LLWindowCallbacks::handleOtherMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
{
return false;
}
bool LLWindowCallbacks::handleActivate(LLWindow *window, bool activated)
{
return false;
}
bool LLWindowCallbacks::handleActivateApp(LLWindow *window, bool activating)
{
return false;
}
void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask)
{
}
void LLWindowCallbacks::handleMouseDragged(LLWindow *window, const LLCoordGL pos, MASK mask)
{
}
void LLWindowCallbacks::handleScrollWheel(LLWindow *window, S32 clicks)
{
}
void LLWindowCallbacks::handleScrollHWheel(LLWindow *window, S32 clicks)
{
}
void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S32 height)
{
}
void LLWindowCallbacks::handleFocus(LLWindow *window)
{
LL_WARNS("COCOA") << "Called handleFocus proto" << LL_ENDL;
}
void LLWindowCallbacks::handleFocusLost(LLWindow *window)
{
}
void LLWindowCallbacks::handleMenuSelect(LLWindow *window, const S32 menu_item)
{
}
bool LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y,
const S32 width, const S32 height)
{
return false;
}
bool LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask)
{
return false;
}
void LLWindowCallbacks::handleWindowBlock(LLWindow *window)
{
}
void LLWindowCallbacks::handleWindowUnblock(LLWindow *window)
{
}
void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *data)
{
}
LLWindowCallbacks::DragNDropResult LLWindowCallbacks::handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data )
{
return LLWindowCallbacks::DND_NONE;
}
bool LLWindowCallbacks::handleTimerEvent(LLWindow *window)
{
return false;
}
bool LLWindowCallbacks::handleDeviceChange(LLWindow *window, bool deviceRemoved) // <FS:Dax/> [FIRE-10419] Added deviceRemoved bool to prevent reinitialize on disconnect.
{
return false;
}
bool LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
{
return false;
}
bool LLWindowCallbacks::handleDisplayChanged()
{
return false;
}
bool LLWindowCallbacks::handleWindowDidChangeScreen(LLWindow *window)
{
return false;
}
void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg)
{
}
void LLWindowCallbacks::handlePauseWatchdog(LLWindow *window)
{
}
void LLWindowCallbacks::handleResumeWatchdog(LLWindow *window)
{
}
std::string LLWindowCallbacks::translateString(const char* tag)
{
return std::string();
}
//virtual
std::string LLWindowCallbacks::translateString(const char* tag,
const std::map<std::string, std::string>& args)
{
return std::string();
}
+101
View File
@@ -0,0 +1,101 @@
/**
* @file llwindowcallbacks.h
* @brief OS event callback class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLWINDOWCALLBACKS_H
#define LLWINDOWCALLBACKS_H
#include "llcoord.h"
class LLWindow;
class LLWindowCallbacks
{
public:
virtual ~LLWindowCallbacks() {}
virtual bool handleTranslatedKeyDown(KEY key, MASK mask, bool repeated);
virtual bool handleTranslatedKeyUp(KEY key, MASK mask);
virtual void handleScanKey(KEY key, bool key_down, bool key_up, bool key_level);
virtual bool handleUnicodeChar(llwchar uni_char, MASK mask);
virtual bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
virtual bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleMouseLeave(LLWindow *window);
// return true to allow window to close, which will then cause handleQuit to be called
virtual bool handleCloseRequest(LLWindow *window);
// window is about to be destroyed, clean up your business
virtual void handleQuit(LLWindow *window);
virtual bool handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
virtual bool handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual bool handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
virtual bool handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual bool handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
virtual bool handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
virtual bool handleActivate(LLWindow *window, bool activated);
virtual bool handleActivateApp(LLWindow *window, bool activating);
virtual void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleScrollWheel(LLWindow *window, S32 clicks);
virtual void handleScrollHWheel(LLWindow *window, S32 clicks);
virtual void handleResize(LLWindow *window, S32 width, S32 height);
virtual void handleFocus(LLWindow *window);
virtual void handleFocusLost(LLWindow *window);
virtual void handleMenuSelect(LLWindow *window, S32 menu_item);
virtual bool handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height);
virtual bool handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); // double-click of left mouse button
virtual void handleWindowBlock(LLWindow *window); // window is taking over CPU for a while
virtual void handleWindowUnblock(LLWindow *window); // window coming back after taking over CPU for a while
virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data);
virtual bool handleTimerEvent(LLWindow *window);
virtual bool handleDeviceChange(LLWindow *window, bool deviceRemoved); // <FS:Dax/> [FIRE-10419] Added deviceRemoved bool to prevent reinitialize on disconnect.
virtual bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
virtual bool handleDisplayChanged();
virtual bool handleWindowDidChangeScreen(LLWindow *window);
enum DragNDropAction {
DNDA_START_TRACKING = 0,// Start tracking an incoming drag
DNDA_TRACK, // User is dragging an incoming drag around the window
DNDA_STOP_TRACKING, // User is no longer dragging an incoming drag around the window (may have either cancelled or dropped on the window)
DNDA_DROPPED // User dropped an incoming drag on the window (this is the "commit" event)
};
enum DragNDropResult {
DND_NONE = 0, // No drop allowed
DND_MOVE, // Drop accepted would result in a "move" operation
DND_COPY, // Drop accepted would result in a "copy" operation
DND_LINK // Drop accepted would result in a "link" operation
};
virtual DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data);
virtual void handlePingWatchdog(LLWindow *window, const char * msg);
virtual void handlePauseWatchdog(LLWindow *window);
virtual void handleResumeWatchdog(LLWindow *window);
// Look up a localized string, usually for an error message
virtual std::string translateString(const char* tag);
virtual std::string translateString(const char* tag,
const std::map<std::string, std::string>& args);
};
#endif
+53
View File
@@ -0,0 +1,53 @@
/**
* @file llwindowheadless.cpp
* @brief Headless implementation of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "indra_constants.h"
#include "llwindowheadless.h"
#include "llkeyboardheadless.h"
//
// LLWindowHeadless
//
LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags, bool fullscreen, bool clear_background,
bool enable_vsync, bool use_gl, bool ignore_pixel_depth)
: LLWindow(callbacks, fullscreen, flags)
{
// Initialize a headless keyboard.
gKeyboard = new LLKeyboardHeadless();
gKeyboard->setCallbacks(callbacks);
}
LLWindowHeadless::~LLWindowHeadless()
{
}
void LLWindowHeadless::swapBuffers()
{
}
+131
View File
@@ -0,0 +1,131 @@
/**
* @file llwindowheadless.h
* @brief Headless definition of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOWHEADLESS_H
#define LL_LLWINDOWHEADLESS_H
#include "llwindow.h"
class LLWindowHeadless : public LLWindow
{
public:
/*virtual*/ void show() override {}
/*virtual*/ void hide() override {}
/*virtual*/ void close() override {}
/*virtual*/ bool getVisible() override {return false;}
/*virtual*/ bool getMinimized() override {return false;}
/*virtual*/ bool getMaximized() override {return false;}
/*virtual*/ bool maximize() override {return false;}
/*virtual*/ void minimize() override {}
/*virtual*/ void restore() override {}
// TODO: LLWindow::getFullscreen() is (intentionally?) NOT virtual.
// Apparently the coder of LLWindowHeadless didn't realize that. Is it a
// mistake to shadow the base-class method with an LLWindowHeadless
// override when called on the subclass, yet call the base-class method
// when indirecting through a polymorphic pointer or reference?
bool getFullscreen() {return false;}
/*virtual*/ bool getPosition(LLCoordScreen *position) override {return false;}
/*virtual*/ bool getSize(LLCoordScreen *size) override {return false;}
/*virtual*/ bool getSize(LLCoordWindow *size) override {return false;}
/*virtual*/ bool setPosition(LLCoordScreen position) override {return false;}
/*virtual*/ bool setSizeImpl(LLCoordScreen size) override {return false;}
/*virtual*/ bool setSizeImpl(LLCoordWindow size) override {return false;}
/*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override {return false;}
void* createSharedContext() override { return nullptr; }
void makeContextCurrent(void*) override {}
void destroySharedContext(void*) override {}
/*virtual*/ void toggleVSync(bool enable_vsync) override { }
/*virtual*/ bool setCursorPosition(LLCoordWindow position) override {return false;}
/*virtual*/ bool getCursorPosition(LLCoordWindow *position) override {return false;}
#if LL_WINDOWS
/*virtual*/ bool getCursorDelta(LLCoordCommon* delta) override { return false; }
#endif
/*virtual*/ void showCursor() override {}
/*virtual*/ void hideCursor() override {}
/*virtual*/ void showCursorFromMouseMove() override {}
/*virtual*/ void hideCursorUntilMouseMove() override {}
/*virtual*/ bool isCursorHidden() override {return false;}
/*virtual*/ void updateCursor() override {}
//virtual ECursorType getCursor() override { return mCurrentCursor; }
/*virtual*/ void captureMouse() override {}
/*virtual*/ void releaseMouse() override {}
/*virtual*/ void setMouseClipping( bool b ) override {}
/*virtual*/ bool isClipboardTextAvailable() override {return false; }
/*virtual*/ bool pasteTextFromClipboard(LLWString &dst) override {return false; }
/*virtual*/ bool copyTextToClipboard(const LLWString &src) override {return false; }
/*virtual*/ void flashIcon(F32 seconds) override {}
/*virtual*/ F32 getGamma() override {return 1.0f; }
/*virtual*/ bool setGamma(const F32 gamma) override {return false; } // Set the gamma
/*virtual*/ void setFSAASamples(const U32 fsaa_samples) override { }
/*virtual*/ U32 getFSAASamples() override { return 0; }
/*virtual*/ bool restoreGamma() override {return false; } // Restore original gamma table (before updating gamma)
//virtual ESwapMethod getSwapMethod() override { return mSwapMethod; }
/*virtual*/ void gatherInput() override {}
/*virtual*/ void delayInputProcessing() override {}
/*virtual*/ void swapBuffers() override;
// handy coordinate space conversion routines
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override { return false; }
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override { return false; }
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to) override { return false; }
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to) override { return false; }
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to) override { return false; }
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to) override { return false; }
/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; }
/*virtual*/ F32 getNativeAspectRatio() override { return 1.0f; }
/*virtual*/ F32 getPixelAspectRatio() override { return 1.0f; }
/*virtual*/ void setNativeAspectRatio(F32 ratio) override {}
/*virtual*/ void *getPlatformWindow() override { return 0; }
/*virtual*/ void bringToFront() override {}
LLWindowHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name,
S32 x, S32 y,
S32 width, S32 height,
U32 flags, bool fullscreen, bool clear_background,
bool enable_vsync, bool use_gl, bool ignore_pixel_depth);
virtual ~LLWindowHeadless();
private:
};
class LLSplashScreenHeadless : public LLSplashScreen
{
public:
LLSplashScreenHeadless() {}
virtual ~LLSplashScreenHeadless() {}
/*virtual*/ void showImpl() override {}
/*virtual*/ void updateImpl(const std::string& mesg) override {}
/*virtual*/ void hideImpl() override {}
};
#endif //LL_LLWINDOWHEADLESS_H
+187
View File
@@ -0,0 +1,187 @@
/**
* @file llwindowmacosx-objc.h
* @brief Prototypes for functions shared between llwindowmacosx.cpp
* and llwindowmacosx-objc.mm.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOWMACOSX_OBJC_H
#define LL_LLWINDOWMACOSX_OBJC_H
#include <map>
#include <vector>
#include <deque>
//fir CGSize
#include <CoreGraphics/CGGeometry.h>
typedef std::vector<std::pair<int, bool> > segment_t;
typedef std::vector<int> segment_lengths;
typedef std::deque<bool> segment_standouts;
struct attributedStringInfo {
segment_lengths seg_lengths;
segment_standouts seg_standouts;
};
// This will actually hold an NSCursor*, but that type is only available in objective C.
typedef void *CursorRef;
typedef void *NSWindowRef;
typedef void *GLViewRef;
struct NativeKeyEventData {
enum EventType {
KEYUNKNOWN,
KEYUP,
KEYDOWN,
KEYCHAR
};
EventType mKeyEvent = KEYUNKNOWN;
uint32_t mEventType = 0;
uint32_t mEventModifiers = 0;
uint32_t mEventKeyCode = 0;
uint32_t mEventChars = 0;
uint32_t mEventUnmodChars = 0;
bool mEventRepeat = false;
};
typedef const NativeKeyEventData * NSKeyEventRef;
// These are defined in llappviewermacosx.cpp.
bool initViewer();
void handleQuit();
bool pumpMainLoop();
void initMainLoop();
void cleanupViewer();
void handleUrl(const char* url);
void dispatchUrl(std::string url);
/* Defined in llwindowmacosx-objc.mm: */
int createNSApp(int argc, const char **argv);
void setupCocoa();
bool pasteBoardAvailable();
bool copyToPBoard(const unsigned short *str, unsigned int len);
unsigned short *copyFromPBoard();
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY);
short releaseImageCursor(CursorRef ref);
short setImageCursor(CursorRef ref);
void setArrowCursor();
void setIBeamCursor();
void setPointingHandCursor();
void setCopyCursor();
void setCrossCursor();
void setNotAllowedCursor();
void hideNSCursor();
void showNSCursor();
bool isCGCursorVisible();
void hideNSCursorTillMove(bool hide);
void requestUserAttention();
long showAlert(std::string title, std::string text, int type);
void setResizeMode(bool oldresize, void* glview);
void setTitleCocoa(NSWindowRef window, const std::string &title); // <FS:CR> Set Window title
NSWindowRef createNSWindow(int x, int y, int width, int height);
#include <OpenGL/OpenGL.h>
GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync);
void glSwapBuffers(void* context);
CGLContextObj getCGLContextObj(GLViewRef view);
unsigned long getVramSize(GLViewRef view);
float getDeviceUnitSize(GLViewRef view);
CGPoint getContentViewBoundsPosition(NSWindowRef window);
CGSize getContentViewBoundsSize(NSWindowRef window);
CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view);
void getWindowSize(NSWindowRef window, float* size);
void setWindowSize(NSWindowRef window, int width, int height);
void getCursorPos(NSWindowRef window, float* pos);
void makeWindowOrderFront(NSWindowRef window);
void convertScreenToWindow(NSWindowRef window, float *coord);
void convertWindowToScreen(NSWindowRef window, float *coord);
void convertScreenToView(NSWindowRef window, float *coord);
void convertRectToScreen(NSWindowRef window, float *coord);
void convertRectFromScreen(NSWindowRef window, float *coord);
void setWindowPos(NSWindowRef window, float* pos);
void closeWindow(NSWindowRef window);
void removeGLView(GLViewRef view);
void makeFirstResponder(NSWindowRef window, GLViewRef view);
void setupInputWindow(NSWindowRef window, GLViewRef view);
// These are all implemented in llwindowmacosx.cpp.
// This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict)
bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask);
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wchar_t character);
void callResetKeys();
bool callUnicodeCallback(wchar_t character, unsigned int mask);
void callRightMouseDown(float *pos, unsigned int mask);
void callRightMouseUp(float *pos, unsigned int mask);
void callLeftMouseDown(float *pos, unsigned int mask);
void callLeftMouseUp(float *pos, unsigned int mask);
void callDoubleClick(float *pos, unsigned int mask);
void callResize(unsigned int width, unsigned int height);
void callMouseMoved(float *pos, unsigned int mask);
void callMouseDragged(float *pos, unsigned int mask);
void callScrollMoved(float deltaX, float deltaY);
void callMouseExit();
void callWindowFocus();
void callWindowUnfocus();
void callWindowHide();
void callWindowUnhide();
void callWindowDidChangeScreen();
void callDeltaUpdate(float *delta, unsigned int mask);
void callOtherMouseDown(float *pos, unsigned int mask, int button);
void callOtherMouseUp(float *pos, unsigned int mask, int button);
void callFocus();
void callFocusLost();
void callModifier(unsigned int mask);
void callQuitHandler();
void commitCurrentPreedit(GLViewRef glView);
#include <string>
void callHandleDragEntered(std::string url);
void callHandleDragExited(std::string url);
void callHandleDragUpdated(std::string url);
void callHandleDragDropped(std::string url);
// LLPreeditor C bindings.
std::basic_string<wchar_t> getPreeditString();
void getPreeditSelectionRange(int *position, int *length);
void getPreeditMarkedRange(int *position, int *length);
bool handleUnicodeCharacter(wchar_t c);
void updatePreeditor(unsigned short *str);
void setPreeditMarkedRange(int position, int length);
void resetPreedit();
int wstring_length(const std::basic_string<wchar_t> & wstr, const int woffset, const int utf16_length, int *unaligned);
void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments);
void getPreeditLocation(float *location, unsigned int length);
void allowDirectMarkedTextInput(bool allow, GLViewRef glView);
NSWindowRef getMainAppWindow();
GLViewRef getGLView();
unsigned int getModifiers();
#endif // LL_LLWINDOWMACOSX_OBJC_H
+484
View File
@@ -0,0 +1,484 @@
/**
* @file llwindowmacosx-objc.mm
* @brief Definition of functions shared between llwindowmacosx.cpp
* and llwindowmacosx-objc.mm.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include <AppKit/AppKit.h>
#include <Cocoa/Cocoa.h>
#include <errno.h>
#include "llopenglview-objc.h"
#include "llwindowmacosx-objc.h"
#include "llappdelegate-objc.h"
/*
* These functions are broken out into a separate file because the
* objective-C typedef for 'BOOL' conflicts with the one in
* llcommon/stdtypes.h. This makes it impossible to use the standard
* linden headers with any objective-C++ source.
*/
int createNSApp(int argc, const char *argv[])
{
return NSApplicationMain(argc, argv);
}
void setupCocoa()
{
static bool inited = false;
if(!inited)
{
@autoreleasepool {
// The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
// ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
// when init'ing the Cocoa App window.
[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
}
inited = true;
}
}
bool copyToPBoard(const unsigned short *str, unsigned int len)
{
@autoreleasepool {
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
[pboard clearContents];
NSArray *contentsToPaste = [[[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil] autorelease];
return [pboard writeObjects:contentsToPaste];
}
}
bool pasteBoardAvailable()
{
NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
}
unsigned short *copyFromPBoard()
{
@autoreleasepool {
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
NSString *str = NULL;
BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
if (ok)
{
NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]];
str = [objToPaste objectAtIndex:0];
}
NSUInteger str_len = [str length];
unichar* temp = (unichar*)calloc(str_len+1, sizeof(unichar));
[str getCharacters:temp range:NSMakeRange(0, str_len)];
return temp;
}
}
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY)
{
NSCursor *cursor = nil;
@autoreleasepool {
// extra retain on the NSCursor since we want it to live for the lifetime of the app.
cursor =
[[[NSCursor alloc]
initWithImage:
[[[NSImage alloc] initWithContentsOfFile:
[NSString stringWithUTF8String:fullpath]
] autorelease]
hotSpot:NSMakePoint(hotspotX, hotspotY)
] retain];
}
return (CursorRef)cursor;
}
void setArrowCursor()
{
NSCursor *cursor = [NSCursor arrowCursor];
[NSCursor unhide];
[cursor set];
}
void setIBeamCursor()
{
NSCursor *cursor = [NSCursor IBeamCursor];
[cursor set];
}
void setPointingHandCursor()
{
NSCursor *cursor = [NSCursor pointingHandCursor];
[cursor set];
}
void setCopyCursor()
{
NSCursor *cursor = [NSCursor dragCopyCursor];
[cursor set];
}
void setCrossCursor()
{
NSCursor *cursor = [NSCursor crosshairCursor];
[cursor set];
}
void setNotAllowedCursor()
{
NSCursor *cursor = [NSCursor operationNotAllowedCursor];
[cursor set];
}
void hideNSCursor()
{
[NSCursor hide];
}
void showNSCursor()
{
[NSCursor unhide];
}
bool isCGCursorVisible()
{
return CGCursorIsVisible();
}
void hideNSCursorTillMove(bool hide)
{
[NSCursor setHiddenUntilMouseMoves:hide];
}
// This is currently unused, since we want all our cursors to persist for the life of the app, but I've included it for completeness.
OSErr releaseImageCursor(CursorRef ref)
{
if( ref != NULL )
{
@autoreleasepool {
NSCursor *cursor = (NSCursor*)ref;
[cursor autorelease];
}
}
else
{
return paramErr;
}
return noErr;
}
OSErr setImageCursor(CursorRef ref)
{
if( ref != NULL )
{
@autoreleasepool {
NSCursor *cursor = (NSCursor*)ref;
[cursor set];
}
}
else
{
return paramErr;
}
return noErr;
}
// Now for some unholy juggling between generic pointers and casting them to Obj-C objects!
// Note: things can get a bit hairy from here. This is not for the faint of heart.
NSWindowRef createNSWindow(int x, int y, int width, int height)
{
LLNSWindow *window = [[LLNSWindow alloc]initWithContentRect:NSMakeRect(x, y, width, height)
styleMask:NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTexturedBackgroundWindowMask backing:NSBackingStoreBuffered defer:NO];
[window makeKeyAndOrderFront:nil];
[window setAcceptsMouseMovedEvents:TRUE];
[window setRestorable:FALSE]; // Viewer manages state from own settings
return window;
}
GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync)
{
LLOpenGLView *glview = [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:samples andVsync:vsync];
[(LLNSWindow*)window setContentView:glview];
return glview;
}
void setResizeMode(bool oldresize, void* glview)
{
[(LLOpenGLView *)glview setOldResize:oldresize];
}
void glSwapBuffers(void* context)
{
[(NSOpenGLContext*)context flushBuffer];
}
CGLContextObj getCGLContextObj(GLViewRef view)
{
return [(LLOpenGLView *)view getCGLContextObj];
}
CGLPixelFormatObj* getCGLPixelFormatObj(NSWindowRef window)
{
LLOpenGLView *glview = [(LLNSWindow*)window contentView];
return [glview getCGLPixelFormatObj];
}
unsigned long getVramSize(GLViewRef view)
{
return [(LLOpenGLView *)view getVramSize];
}
float getDeviceUnitSize(GLViewRef view)
{
return [(LLOpenGLView*)view convertSizeToBacking:NSMakeSize(1, 1)].width;
}
CGPoint getContentViewBoundsPosition(NSWindowRef window)
{
return [[(LLNSWindow*)window contentView] bounds].origin;
}
CGSize getContentViewBoundsSize(NSWindowRef window)
{
return [[(LLNSWindow*)window contentView] bounds].size;
}
CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view)
{
return [(NSOpenGLView*)view convertRectToBacking:[[(LLNSWindow*)window contentView] bounds]].size;
}
void getWindowSize(NSWindowRef window, float* size)
{
NSRect frame = [(LLNSWindow*)window frame];
size[0] = frame.origin.x;
size[1] = frame.origin.y;
size[2] = frame.size.width;
size[3] = frame.size.height;
}
void setWindowSize(NSWindowRef window, int width, int height)
{
NSRect frame = [(LLNSWindow*)window frame];
frame.size.width = width;
frame.size.height = height;
[(LLNSWindow*)window setFrame:frame display:TRUE];
}
void setWindowPos(NSWindowRef window, float* pos)
{
NSPoint point;
point.x = pos[0];
point.y = pos[1];
[(LLNSWindow*)window setFrameOrigin:point];
}
void getCursorPos(NSWindowRef window, float* pos)
{
NSPoint mLoc;
mLoc = [(LLNSWindow*)window mouseLocationOutsideOfEventStream];
pos[0] = mLoc.x;
pos[1] = mLoc.y;
}
void makeWindowOrderFront(NSWindowRef window)
{
[(LLNSWindow*)window makeKeyAndOrderFront:nil];
}
void convertScreenToWindow(NSWindowRef window, float *coord)
{
NSRect point;
point.origin.x = coord[0];
point.origin.y = coord[1];
point = [(LLNSWindow*)window convertRectFromScreen:point];
coord[0] = point.origin.x;
coord[1] = point.origin.y;
}
void convertRectToScreen(NSWindowRef window, float *coord)
{
NSRect point;
point.origin.x = coord[0];
point.origin.y = coord[1];
point.size.width = coord[2];
point.size.height = coord[3];
point = [(LLNSWindow*)window convertRectToScreen:point];
coord[0] = point.origin.x;
coord[1] = point.origin.y;
coord[2] = point.size.width;
coord[3] = point.size.height;
}
void convertRectFromScreen(NSWindowRef window, float *coord)
{
NSRect point;
point.origin.x = coord[0];
point.origin.y = coord[1];
point.size.width = coord[2];
point.size.height = coord[3];
point = [(LLNSWindow*)window convertRectFromScreen:point];
coord[0] = point.origin.x;
coord[1] = point.origin.y;
coord[2] = point.size.width;
coord[3] = point.size.height;
}
void convertScreenToView(NSWindowRef window, float *coord)
{
NSRect point;
point.origin.x = coord[0];
point.origin.y = coord[1];
point.origin = [(LLNSWindow*)window convertScreenToBase:point.origin];
point.origin = [[(LLNSWindow*)window contentView] convertPoint:point.origin fromView:nil];
}
void convertWindowToScreen(NSWindowRef window, float *coord)
{
NSPoint point;
point.x = coord[0];
point.y = coord[1];
point = [(LLNSWindow*)window convertToScreenFromLocalPoint:point relativeToView:[(LLNSWindow*)window contentView]];
coord[0] = point.x;
coord[1] = point.y;
}
void closeWindow(NSWindowRef window)
{
[(LLNSWindow*)window close];
[(LLNSWindow*)window release];
}
void removeGLView(GLViewRef view)
{
[(LLOpenGLView*)view clearGLContext];
[(LLOpenGLView*)view removeFromSuperview];
}
void setupInputWindow(NSWindowRef window, GLViewRef glview)
{
[[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview];
}
void commitCurrentPreedit(GLViewRef glView)
{
[(LLOpenGLView*)glView commitCurrentPreedit];
}
void allowDirectMarkedTextInput(bool allow, GLViewRef glView)
{
[(LLOpenGLView*)glView allowMarkedTextInput:allow];
}
NSWindowRef getMainAppWindow()
{
LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window];
[winRef setAcceptsMouseMovedEvents:TRUE];
return winRef;
}
void makeFirstResponder(NSWindowRef window, GLViewRef view)
{
[(LLNSWindow*)window makeFirstResponder:(LLOpenGLView*)view];
}
void requestUserAttention()
{
[[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
}
long showAlert(std::string text, std::string title, int type)
{
long ret = 0;
@autoreleasepool {
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
[alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
if (type == 0)
{
[alert addButtonWithTitle:@"Okay"];
} else if (type == 1)
{
[alert addButtonWithTitle:@"Okay"];
[alert addButtonWithTitle:@"Cancel"];
} else if (type == 2)
{
[alert addButtonWithTitle:@"Yes"];
[alert addButtonWithTitle:@"No"];
}
ret = [alert runModal];
}
if (ret == NSAlertFirstButtonReturn)
{
if (type == 1)
{
ret = 3;
} else if (type == 2)
{
ret = 0;
}
} else if (ret == NSAlertSecondButtonReturn)
{
if (type == 0 || type == 1)
{
ret = 2;
} else if (type == 2)
{
ret = 1;
}
}
return ret;
}
/*
GLViewRef getGLView()
{
return [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] glview];
}
*/
unsigned int getModifiers()
{
return [NSEvent modifierFlags];
}
// <FS:CR> Set Window Title - sigh.
void setTitleCocoa(NSWindowRef window, const std::string &title)
{
NSString *str = [NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]];
[(LLNSWindow*)window setTitle:str];
}
// </FS:CR>
File diff suppressed because it is too large Load Diff
+271
View File
@@ -0,0 +1,271 @@
/**
* @file llwindowmacosx.h
* @brief Mac implementation of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOWMACOSX_H
#define LL_LLWINDOWMACOSX_H
#include "llwindow.h"
#include "llwindowcallbacks.h"
#include "llwindowmacosx-objc.h"
#include "lltimer.h"
#include <ApplicationServices/ApplicationServices.h>
#include <OpenGL/OpenGL.h>
// AssertMacros.h does bad things.
#include "fix_macros.h"
#undef verify
#undef require
class LLWindowMacOSX : public LLWindow
{
public:
void show() override;
void hide() override;
void close() override;
bool getVisible() override;
bool getMinimized() override;
bool getMaximized() override;
bool maximize() override;
void minimize() override;
void restore() override;
bool getFullscreen();
bool getPosition(LLCoordScreen *position) override;
bool getSize(LLCoordScreen *size) override;
bool getSize(LLCoordWindow *size) override;
bool setPosition(LLCoordScreen position) override;
bool setSizeImpl(LLCoordScreen size) override;
bool setSizeImpl(LLCoordWindow size) override;
bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override;
bool setCursorPosition(LLCoordWindow position) override;
bool getCursorPosition(LLCoordWindow *position) override;
void showCursor() override;
void hideCursor() override;
void showCursorFromMouseMove() override;
void hideCursorUntilMouseMove() override;
bool isCursorHidden() override;
void updateCursor() override;
ECursorType getCursor() const override;
void captureMouse() override;
void releaseMouse() override;
void setMouseClipping( bool b ) override;
bool isClipboardTextAvailable() override;
bool pasteTextFromClipboard(LLWString &dst) override;
bool copyTextToClipboard(const LLWString & src) override;
void flashIcon(F32 seconds) override;
F32 getGamma() override;
bool setGamma(const F32 gamma) override; // Set the gamma
U32 getFSAASamples() override;
void setFSAASamples(const U32 fsaa_samples) override;
bool restoreGamma() override; // Restore original gamma table (before updating gamma)
ESwapMethod getSwapMethod() override { return mSwapMethod; }
void gatherInput() override;
void delayInputProcessing() override {};
void swapBuffers() override;
// handy coordinate space conversion routines
bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override;
bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override;
bool convertCoords(LLCoordWindow from, LLCoordGL *to) override;
bool convertCoords(LLCoordGL from, LLCoordWindow *to) override;
bool convertCoords(LLCoordScreen from, LLCoordGL *to) override;
bool convertCoords(LLCoordGL from, LLCoordScreen *to) override;
LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override;
F32 getNativeAspectRatio() override;
F32 getPixelAspectRatio() override;
void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; }
void beforeDialog() override;
void afterDialog() override;
bool dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
void *getPlatformWindow() override;
void bringToFront() override {};
void allowLanguageTextInput(LLPreeditor *preeditor, bool b) override;
void interruptLanguageTextInput() override;
void spawnWebBrowser(const std::string& escaped_url, bool async) override;
F32 getSystemUISize() override;
void openFile(const std::string& file_name) override;
void setTitle(const std::string& title) override;
bool getInputDevices(U32 device_type_filter,
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
void* win_callback,
void* userdata) override;
static std::vector<std::string> getDisplaysResolutionList();
static std::vector<std::string> getDynamicFallbackFontList();
// Provide native key event data
LLSD getNativeKeyData() override;
void* getWindow() { return mWindow; }
LLWindowCallbacks* getCallbacks() { return mCallbacks; }
LLPreeditor* getPreeditor() { return mPreeditor; }
void updateMouseDeltas(float* deltas);
void getMouseDeltas(float* delta);
void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action);
bool allowsLanguageInput() { return mLanguageTextInputAllowed; }
//create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread
// returns a pointer to be handed back to destroySharedConext/makeContextCurrent
void* createSharedContext() override;
//make the given context current on the current thread
void makeContextCurrent(void* context) override;
//destroy the given context that was retrieved by createSharedContext()
//Must be called on the same thread that called createSharedContext()
void destroySharedContext(void* context) override;
void toggleVSync(bool enable_vsync) override;
// enable or disable multithreaded GL
static void setUseMultGL(bool use_mult_gl);
protected:
LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl,
bool ignore_pixel_depth,
U32 fsaa_samples,
bool useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
~LLWindowMacOSX();
//void initCursors();
void initCursors(bool useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
bool isValid() override;
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
// Changes display resolution. Returns true if successful
bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
// Go back to last fullscreen display resolution.
bool setFullscreenResolution();
// Restore the display resolution to its value before we ran the app.
bool resetDisplayResolution();
bool shouldPostQuit() { return mPostQuit; }
//Satisfy MAINT-3135 and MAINT-3288 with a flag.
/*virtual */ void setOldResize(bool oldresize) override {setResizeMode(oldresize, mGLView); }
private:
void restoreGLContext();
protected:
//
// Platform specific methods
//
// create or re-create the GL context/window. Called from the constructor and switchContext().
bool createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_vsync);
void destroyContext();
void setupFailure(const std::string& text, const std::string& caption, U32 type);
void adjustCursorDecouple(bool warpingMouse = false);
static MASK modifiersToMask(S16 modifiers);
#if LL_OS_DRAGDROP_ENABLED
//static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
//static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
#endif // LL_OS_DRAGDROP_ENABLED
//
// Platform specific variables
//
// Use generic pointers here. This lets us do some funky Obj-C interop using Obj-C objects without having to worry about any compilation problems that may arise.
NSWindowRef mWindow;
GLViewRef mGLView;
CGLContextObj mContext;
CGLPixelFormatObj mPixelFormat;
CGDirectDisplayID mDisplay;
LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
std::string mWindowTitle;
double mOriginalAspectRatio;
bool mSimulatedRightClick;
U32 mLastModifiers;
bool mHandsOffEvents; // When true, temporarially disable CarbonEvent processing.
// Used to allow event processing when putting up dialogs in fullscreen mode.
bool mCursorDecoupled;
S32 mCursorLastEventDeltaX;
S32 mCursorLastEventDeltaY;
bool mCursorIgnoreNextDelta;
bool mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
LLCoordScreen mNeedsResizeSize;
F32 mOverrideAspectRatio;
bool mMaximized;
bool mMinimized;
U32 mFSAASamples;
bool mForceRebuild;
S32 mDragOverrideCursor;
// Input method management through Text Service Manager.
bool mLanguageTextInputAllowed;
LLPreeditor* mPreeditor;
public:
static bool sUseMultGL;
friend class LLWindowManager;
public:
bool mUseLegacyCursors; // <FS:LO> Legacy cursor setting from main program
};
class LLSplashScreenMacOSX : public LLSplashScreen
{
public:
LLSplashScreenMacOSX();
virtual ~LLSplashScreenMacOSX();
void showImpl();
void updateImpl(const std::string& mesg);
void hideImpl();
private:
WindowRef mWindow;
};
S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type);
void load_url_external(const char* url);
#endif //LL_LLWINDOWMACOSX_H
+78
View File
@@ -0,0 +1,78 @@
/**
* @file llwindowmesaheadless.cpp
* @brief Platform-dependent implementation of llwindow
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "indra_constants.h"
#include "llwindowmesaheadless.h"
#include "llgl.h"
#define MESA_CHANNEL_TYPE GL_UNSIGNED_SHORT
#define MESA_CHANNEL_SIZE 2
U16 *gMesaBuffer = NULL;
//
// LLWindowMesaHeadless
//
LLWindowMesaHeadless::LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags, bool fullscreen, bool clearBg,
bool disable_vsync, bool use_gl, bool ignore_pixel_depth)
: LLWindow(callbacks, fullscreen, flags)
{
if (use_gl)
{
LL_INFOS() << "MESA Init" << LL_ENDL;
mMesaContext = OSMesaCreateContextExt( GL_RGBA, 32, 0, 0, NULL );
/* Allocate the image buffer */
mMesaBuffer = new unsigned char [width * height * 4 * MESA_CHANNEL_SIZE];
llassert(mMesaBuffer);
gMesaBuffer = (U16*)mMesaBuffer;
/* Bind the buffer to the context and make it current */
if (!OSMesaMakeCurrent( mMesaContext, mMesaBuffer, MESA_CHANNEL_TYPE, width, height ))
{
LL_ERRS() << "MESA: OSMesaMakeCurrent failed!" << LL_ENDL;
}
llverify(gGLManager.initGL());
}
}
LLWindowMesaHeadless::~LLWindowMesaHeadless()
{
delete mMesaBuffer;
OSMesaDestroyContext( mMesaContext );
}
void LLWindowMesaHeadless::swapBuffers()
{
glFinish();
}
+123
View File
@@ -0,0 +1,123 @@
/**
* @file llwindowmesaheadless.h
* @brief Windows implementation of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOWMESAHEADLESS_H
#define LL_LLWINDOWMESAHEADLESS_H
#if LL_MESA_HEADLESS
#include "llwindow.h"
#include "GL/glu.h"
#include "GL/osmesa.h"
class LLWindowMesaHeadless : public LLWindow
{
public:
/*virtual*/ void show() {};
/*virtual*/ void hide() {};
/*virtual*/ void close() {};
/*virtual*/ bool getVisible() {return false;};
/*virtual*/ bool getMinimized() {return false;};
/*virtual*/ bool getMaximized() {return false;};
/*virtual*/ bool maximize() {return false;};
/*virtual*/ void minimize() {};
/*virtual*/ void restore() {};
/*virtual*/ bool getFullscreen() {return false;};
/*virtual*/ bool getPosition(LLCoordScreen *position) {return false;};
/*virtual*/ bool getSize(LLCoordScreen *size) {return false;};
/*virtual*/ bool getSize(LLCoordWindow *size) {return false;};
/*virtual*/ bool setPosition(LLCoordScreen position) {return false;};
/*virtual*/ bool setSizeImpl(LLCoordScreen size) {return false;};
/*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, const LLCoordScreen * const posp = NULL) {return false;};
/*virtual*/ bool setCursorPosition(LLCoordWindow position) {return false;};
/*virtual*/ bool getCursorPosition(LLCoordWindow *position) {return false;};
/*virtual*/ void showCursor() {};
/*virtual*/ void hideCursor() {};
/*virtual*/ void showCursorFromMouseMove() {};
/*virtual*/ void hideCursorUntilMouseMove() {};
/*virtual*/ bool isCursorHidden() {return false;};
/*virtual*/ void updateCursor() {};
//virtual ECursorType getCursor() { return mCurrentCursor; };
/*virtual*/ void captureMouse() {};
/*virtual*/ void releaseMouse() {};
/*virtual*/ void setMouseClipping( bool b ) {};
/*virtual*/ bool isClipboardTextAvailable() {return false; };
/*virtual*/ bool pasteTextFromClipboard(LLWString &dst) {return false; };
/*virtual*/ bool copyTextToClipboard(const LLWString &src) {return false; };
/*virtual*/ void flashIcon(F32 seconds) {};
/*virtual*/ F32 getGamma() {return 1.0f; };
/*virtual*/ bool setGamma(const F32 gamma) {return false; }; // Set the gamma
/*virtual*/ bool restoreGamma() {return false; }; // Restore original gamma table (before updating gamma)
/*virtual*/ void setFSAASamples(const U32 fsaa_samples) { /* FSAA not supported yet on Mesa headless.*/ }
/*virtual*/ U32 getFSAASamples() { return 0; }
//virtual ESwapMethod getSwapMethod() { return mSwapMethod; }
/*virtual*/ void gatherInput() {};
/*virtual*/ void delayInputProcessing() {};
/*virtual*/ void swapBuffers();
/*virtual*/ void restoreGLContext() {};
// handy coordinate space conversion routines
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) { return false; };
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) { return false; };
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to) { return false; };
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to) { return false; };
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to) { return false; };
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to) { return false; };
/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) { return NULL; };
/*virtual*/ F32 getNativeAspectRatio() { return 1.0f; };
/*virtual*/ F32 getPixelAspectRatio() { return 1.0f; };
/*virtual*/ void setNativeAspectRatio(F32 ratio) {}
/*virtual*/ void *getPlatformWindow() { return 0; };
/*virtual*/ void bringToFront() {};
LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags, bool fullscreen, bool clearBg,
bool disable_vsync, bool use_gl, bool ignore_pixel_depth);
~LLWindowMesaHeadless();
private:
OSMesaContext mMesaContext;
unsigned char * mMesaBuffer;
};
class LLSplashScreenMesaHeadless : public LLSplashScreen
{
public:
LLSplashScreenMesaHeadless() {};
virtual ~LLSplashScreenMesaHeadless() {};
/*virtual*/ void showImpl() {};
/*virtual*/ void updateImpl(const std::string& mesg) {};
/*virtual*/ void hideImpl() {};
};
#endif
#endif //LL_LLWINDOWMESAHEADLESS_H
File diff suppressed because it is too large Load Diff
+266
View File
@@ -0,0 +1,266 @@
/**
* @file llwindowsdl.h
* @brief SDL implementation of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifdef LL_SDL2
#include "llwindowsdl2.h"
#else
#ifndef LL_LLWINDOWSDL_H
#define LL_LLWINDOWSDL_H
// Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class
#include "llwindow.h"
#include "lltimer.h"
#include "SDL/SDL.h"
#include "SDL/SDL_endian.h"
#if LL_X11
// get X11-specific headers for use in low-level stuff like copy-and-paste support
#include "SDL/SDL_syswm.h"
#endif
// AssertMacros.h does bad things.
#include "fix_macros.h"
#undef verify
#undef require
class LLWindowSDL : public LLWindow
{
public:
/*virtual*/ void show();
/*virtual*/ void hide();
/*virtual*/ void close();
/*virtual*/ bool getVisible();
/*virtual*/ bool getMinimized();
/*virtual*/ bool getMaximized();
/*virtual*/ bool maximize();
/*virtual*/ void minimize();
/*virtual*/ void restore();
/*virtual*/ bool getFullscreen();
/*virtual*/ bool getPosition(LLCoordScreen *position);
/*virtual*/ bool getSize(LLCoordScreen *size);
/*virtual*/ bool getSize(LLCoordWindow *size);
/*virtual*/ bool setPosition(LLCoordScreen position);
/*virtual*/ bool setSizeImpl(LLCoordScreen size);
/*virtual*/ bool setSizeImpl(LLCoordWindow size);
/*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL);
/*virtual*/ bool setCursorPosition(LLCoordWindow position);
/*virtual*/ bool getCursorPosition(LLCoordWindow *position);
/*virtual*/ void showCursor();
/*virtual*/ void hideCursor();
/*virtual*/ void showCursorFromMouseMove();
/*virtual*/ void hideCursorUntilMouseMove();
/*virtual*/ bool isCursorHidden();
/*virtual*/ void updateCursor();
/*virtual*/ void captureMouse();
/*virtual*/ void releaseMouse();
/*virtual*/ void setMouseClipping( bool b );
/*virtual*/ void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
/*virtual*/ bool isClipboardTextAvailable();
/*virtual*/ bool pasteTextFromClipboard(LLWString &dst);
/*virtual*/ bool copyTextToClipboard(const LLWString & src);
/*virtual*/ bool isPrimaryTextAvailable();
/*virtual*/ bool pasteTextFromPrimary(LLWString &dst);
/*virtual*/ bool copyTextToPrimary(const LLWString & src);
/*virtual*/ void flashIcon(F32 seconds);
/*virtual*/ F32 getGamma();
/*virtual*/ bool setGamma(const F32 gamma); // Set the gamma
/*virtual*/ U32 getFSAASamples();
/*virtual*/ void setFSAASamples(const U32 samples);
/*virtual*/ bool restoreGamma(); // Restore original gamma table (before updating gamma)
/*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
/*virtual*/ void processMiscNativeEvents();
/*virtual*/ void gatherInput();
/*virtual*/ void swapBuffers();
/*virtual*/ void restoreGLContext() {};
/*virtual*/ void delayInputProcessing() { };
// handy coordinate space conversion routines
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to);
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to);
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to);
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to);
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to);
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to);
/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
/*virtual*/ F32 getNativeAspectRatio();
/*virtual*/ F32 getPixelAspectRatio();
/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
/*virtual*/ void beforeDialog();
/*virtual*/ void afterDialog();
/*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b);
/*virtual*/ void *getPlatformWindow();
/*virtual*/ void bringToFront();
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
/*virtual*/ void openFile(const std::string& file_name);
/*virtual*/ void setTitle(const std::string& title);
static std::vector<std::string> getDynamicFallbackFontList();
// Not great that these are public, but they have to be accessible
// by non-class code and it's better than making them global.
#if LL_X11
Window mSDL_XWindowID;
Display *mSDL_Display;
#endif
void (*Lock_Display)(void);
void (*Unlock_Display)(void);
#if LL_GTK
// Lazily initialize and check the runtime GTK version for goodness.
static bool ll_try_gtk_init(void);
#endif // LL_GTK
#if LL_X11
static Window get_SDL_XWindowID(void);
static Display* get_SDL_Display(void);
#endif // LL_X11
void* createSharedContext() override;
void makeContextCurrent(void* context) override;
void destroySharedContext(void* context) override;
void toggleVSync(bool enable_vsync) override;
protected:
LLWindowSDL(LLWindowCallbacks* callbacks,
const std::string& title, int x, int y, int width, int height, U32 flags,
bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl,
//boolOL ignore_pixel_depth, U32 fsaa_samples);
bool ignore_pixel_depth, U32 fsaa_samples, bool useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
~LLWindowSDL();
/*virtual*/ bool isValid();
/*virtual*/ LLSD getNativeKeyData();
//void initCursors();
void initCursors(bool useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
void quitCursors();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
// Changes display resolution. Returns true if successful
bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
// Go back to last fullscreen display resolution.
bool setFullscreenResolution();
bool shouldPostQuit() { return mPostQuit; }
protected:
//
// Platform specific methods
//
// create or re-create the GL context/window. Called from the constructor and switchContext().
bool createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_vsync);
void destroyContext();
void setupFailure(const std::string& text, const std::string& caption, U32 type);
void fixWindowSize(void);
U32 SDLCheckGrabbyKeys(SDLKey keysym, bool gain);
bool SDLReallyCaptureInput(bool capture);
//
// Platform specific variables
//
U32 mGrabbyKeyFlags;
int mReallyCapturedCount;
SDL_Surface * mWindow;
std::string mWindowTitle;
double mOriginalAspectRatio;
bool mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
LLCoordScreen mNeedsResizeSize;
F32 mOverrideAspectRatio;
F32 mGamma;
U32 mFSAASamples;
int mSDLFlags;
SDL_Cursor* mSDLCursors[UI_CURSOR_COUNT];
int mHaveInputFocus; /* 0=no, 1=yes, else unknown */
int mIsMinimized; /* 0=no, 1=yes, else unknown */
friend class LLWindowManager;
private:
#if LL_X11
void x11_set_urgent(bool urgent);
bool mFlashing;
LLTimer mFlashTimer;
#endif //LL_X11
U32 mKeyScanCode;
U32 mKeyVirtualKey;
SDLMod mKeyModifiers;
U32 mSDLSym; // <FS:ND/> Store the SDL Keysym too.
bool mUseLegacyCursors; // <FS:LO> Legacy cursor setting from main program
public:
#if LL_X11
static Display* getSDLDisplay();
LLWString const& getPrimaryText() const { return mPrimaryClipboard; }
LLWString const& getSecondaryText() const { return mSecondaryClipboard; }
void clearPrimaryText() { mPrimaryClipboard.clear(); }
void clearSecondaryText() { mSecondaryClipboard.clear(); }
private:
void initialiseX11Clipboard();
bool getSelectionText(Atom selection, LLWString& text);
bool getSelectionText( Atom selection, Atom type, LLWString &text );
bool setSelectionText(Atom selection, const LLWString& text);
#endif
LLWString mPrimaryClipboard;
LLWString mSecondaryClipboard;
};
class LLSplashScreenSDL : public LLSplashScreen
{
public:
LLSplashScreenSDL();
virtual ~LLSplashScreenSDL();
/*virtual*/ void showImpl();
/*virtual*/ void updateImpl(const std::string& mesg);
/*virtual*/ void hideImpl();
};
S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type);
#endif //LL_LLWINDOWSDL_H
#endif
File diff suppressed because it is too large Load Diff
+274
View File
@@ -0,0 +1,274 @@
/**
* @file llwindowsdl.h
* @brief SDL implementation of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOWSDL2_H
#define LL_LLWINDOWSDL2_H
// Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class
#include "llwindow.h"
#include "lltimer.h"
#include "SDL2/SDL.h"
#include "SDL2/SDL_endian.h"
#if LL_X11
// get X11-specific headers for use in low-level stuff like copy-and-paste support
#include "SDL2/SDL_syswm.h"
#endif
// AssertMacros.h does bad things.
#include "fix_macros.h"
#undef verify
#undef require
class LLWindowSDL : public LLWindow
{
public:
/*virtual*/ void show();
/*virtual*/ void hide();
/*virtual*/ void close();
/*virtual*/ bool getVisible();
/*virtual*/ bool getMinimized();
/*virtual*/ bool getMaximized();
/*virtual*/ bool maximize();
/*virtual*/ void minimize();
/*virtual*/ void restore();
/*virtual*/ bool getFullscreen();
/*virtual*/ bool getPosition(LLCoordScreen *position);
/*virtual*/ bool getSize(LLCoordScreen *size);
/*virtual*/ bool getSize(LLCoordWindow *size);
/*virtual*/ bool setPosition(LLCoordScreen position);
/*virtual*/ bool setSizeImpl(LLCoordScreen size);
/*virtual*/ bool setSizeImpl(LLCoordWindow size);
/*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL);
// <FS:Zi> Make shared context work on Linux for multithreaded OpenGL
void* createSharedContext() override;
void makeContextCurrent(void* context) override;
void destroySharedContext(void* context) override;
/*virtual*/ void toggleVSync(bool enable_vsync);
// </FS:Zi>
/*virtual*/ bool setCursorPosition(LLCoordWindow position);
/*virtual*/ bool getCursorPosition(LLCoordWindow *position);
/*virtual*/ void showCursor();
/*virtual*/ void hideCursor();
/*virtual*/ void showCursorFromMouseMove();
/*virtual*/ void hideCursorUntilMouseMove();
/*virtual*/ bool isCursorHidden();
/*virtual*/ void updateCursor();
/*virtual*/ void captureMouse();
/*virtual*/ void releaseMouse();
/*virtual*/ void setMouseClipping( bool b );
/*virtual*/ void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
/*virtual*/ bool isClipboardTextAvailable();
/*virtual*/ bool pasteTextFromClipboard(LLWString &dst);
/*virtual*/ bool copyTextToClipboard(const LLWString & src);
/*virtual*/ bool isPrimaryTextAvailable();
/*virtual*/ bool pasteTextFromPrimary(LLWString &dst);
/*virtual*/ bool copyTextToPrimary(const LLWString & src);
/*virtual*/ void flashIcon(F32 seconds);
/*virtual*/ F32 getGamma();
/*virtual*/ bool setGamma(const F32 gamma); // Set the gamma
/*virtual*/ U32 getFSAASamples();
/*virtual*/ void setFSAASamples(const U32 samples);
/*virtual*/ bool restoreGamma(); // Restore original gamma table (before updating gamma)
/*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
/*virtual*/ void processMiscNativeEvents();
/*virtual*/ void gatherInput();
/*virtual*/ void swapBuffers();
/*virtual*/ void restoreGLContext() {};
/*virtual*/ void delayInputProcessing() { };
// handy coordinate space conversion routines
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to);
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to);
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to);
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to);
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to);
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to);
/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
/*virtual*/ F32 getNativeAspectRatio();
/*virtual*/ F32 getPixelAspectRatio();
/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
/*virtual*/ void beforeDialog();
/*virtual*/ void afterDialog();
/*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b);
/*virtual*/ void *getPlatformWindow();
/*virtual*/ void bringToFront();
/*virtual*/ void allowLanguageTextInput(LLPreeditor* preeditor, bool b);
/*virtual*/ void setLanguageTextInput(const LLCoordGL& pos);
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
/*virtual*/ void openFile(const std::string& file_name);
/*virtual*/ void setTitle(const std::string& title);
void enableIME(bool b);
static std::vector<std::string> getDynamicFallbackFontList();
// Not great that these are public, but they have to be accessible
// by non-class code and it's better than making them global.
#if LL_X11
Window mSDL_XWindowID;
Display *mSDL_Display;
#endif
void (*Lock_Display)(void);
void (*Unlock_Display)(void);
#if LL_GTK
// Lazily initialize and check the runtime GTK version for goodness.
static bool ll_try_gtk_init(void);
#endif // LL_GTK
#if LL_X11
static Window get_SDL_XWindowID(void);
static Display* get_SDL_Display(void);
#endif // LL_X11
protected:
LLWindowSDL(LLWindowCallbacks* callbacks,
const std::string& title, int x, int y, int width, int height, U32 flags,
bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl,
//bool ignore_pixel_depth, U32 fsaa_samples);
bool ignore_pixel_depth, U32 fsaa_samples, bool useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
~LLWindowSDL();
/*virtual*/ bool isValid();
/*virtual*/ LLSD getNativeKeyData();
//void initCursors();
void initCursors(bool useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
void quitCursors();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
// Changes display resolution. Returns true if successful
bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
// Go back to last fullscreen display resolution.
bool setFullscreenResolution();
bool shouldPostQuit() { return mPostQuit; }
protected:
//
// Platform specific methods
//
// create or re-create the GL context/window. Called from the constructor and switchContext().
bool createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_vsync);
void destroyContext();
void setupFailure(const std::string& text, const std::string& caption, U32 type);
void fixWindowSize(void);
U32 SDLCheckGrabbyKeys(U32 keysym, bool gain);
bool SDLReallyCaptureInput(bool capture);
//
// Platform specific variables
//
U32 mGrabbyKeyFlags;
int mReallyCapturedCount;
SDL_Window* mWindow;
SDL_Surface* mSurface;
SDL_GLContext mContext;
SDL_Cursor* mSDLCursors[UI_CURSOR_COUNT];
LLPreeditor* mPreeditor;
bool mIMEEnabled;
std::string mWindowTitle;
double mOriginalAspectRatio;
bool mNeedsResize; // Constructor figured out the window is too big, it needs a resize.
LLCoordScreen mNeedsResizeSize;
F32 mOverrideAspectRatio;
F32 mGamma;
U32 mFSAASamples;
int mSDLFlags;
int mHaveInputFocus; /* 0=no, 1=yes, else unknown */
int mIsMinimized; /* 0=no, 1=yes, else unknown */
friend class LLWindowManager;
private:
#if LL_X11
void x11_set_urgent(bool urgent);
bool mFlashing;
LLTimer mFlashTimer;
#endif //LL_X11
U32 mKeyVirtualKey;
U32 mKeyModifiers;
std::string mInputType;
bool mUseLegacyCursors; // <FS:LO> Legacy cursor setting from main program
public:
#if LL_X11
static Display* getSDLDisplay();
LLWString const& getPrimaryText() const { return mPrimaryClipboard; }
LLWString const& getSecondaryText() const { return mSecondaryClipboard; }
void clearPrimaryText() { mPrimaryClipboard.clear(); }
void clearSecondaryText() { mSecondaryClipboard.clear(); }
private:
void tryFindFullscreenSize( int &aWidth, int &aHeight );
void initialiseX11Clipboard();
bool getSelectionText(Atom selection, LLWString& text);
bool getSelectionText( Atom selection, Atom type, LLWString &text );
bool setSelectionText(Atom selection, const LLWString& text);
#endif
LLWString mPrimaryClipboard;
LLWString mSecondaryClipboard;
};
class LLSplashScreenSDL : public LLSplashScreen
{
public:
LLSplashScreenSDL();
virtual ~LLSplashScreenSDL();
/*virtual*/ void showImpl();
/*virtual*/ void updateImpl(const std::string& mesg);
/*virtual*/ void hideImpl();
};
S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type);
#endif //LL_LLWINDOWSDL_H
File diff suppressed because it is too large Load Diff
+294
View File
@@ -0,0 +1,294 @@
/**
* @file llwindowwin32.h
* @brief Windows implementation of LLWindow class
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLWINDOWWIN32_H
#define LL_LLWINDOWWIN32_H
// Limit Windows API to small and manageable set.
#include "llwin32headers.h"
#include "llwindow.h"
#include "llwindowcallbacks.h"
#include "lldragdropwin32.h"
#include "llthread.h"
#include "llthreadsafequeue.h"
#include "llmutex.h"
#include "workqueue.h"
// Hack for async host by name
#define LL_WM_HOST_RESOLVED (WM_APP + 1)
typedef void (*LLW32MsgCallback)(const MSG &msg);
class LLWindowWin32 : public LLWindow
{
public:
/*virtual*/ void show();
/*virtual*/ void hide();
/*virtual*/ void close();
/*virtual*/ bool getVisible();
/*virtual*/ bool getMinimized();
/*virtual*/ bool getMaximized();
/*virtual*/ bool maximize();
/*virtual*/ void minimize();
/*virtual*/ void restore();
/*virtual*/ bool getFullscreen();
/*virtual*/ bool getPosition(LLCoordScreen *position);
/*virtual*/ bool getSize(LLCoordScreen *size);
/*virtual*/ bool getSize(LLCoordWindow *size);
/*virtual*/ bool setPosition(LLCoordScreen position);
/*virtual*/ bool setSizeImpl(LLCoordScreen size);
/*virtual*/ bool setSizeImpl(LLCoordWindow size);
/*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL);
/*virtual*/ void setTitle(const std::string& title);
void* createSharedContext() override;
void makeContextCurrent(void* context) override;
void destroySharedContext(void* context) override;
/*virtual*/ void toggleVSync(bool enable_vsync);
/*virtual*/ bool setCursorPosition(LLCoordWindow position);
/*virtual*/ bool getCursorPosition(LLCoordWindow *position);
/*virtual*/ bool getCursorDelta(LLCoordCommon* delta);
/*virtual*/ void showCursor();
/*virtual*/ void hideCursor();
/*virtual*/ void showCursorFromMouseMove();
/*virtual*/ void hideCursorUntilMouseMove();
/*virtual*/ bool isCursorHidden();
/*virtual*/ void updateCursor();
/*virtual*/ ECursorType getCursor() const;
/*virtual*/ void captureMouse();
/*virtual*/ void releaseMouse();
/*virtual*/ void setMouseClipping( bool b );
/*virtual*/ bool isClipboardTextAvailable();
/*virtual*/ bool pasteTextFromClipboard(LLWString &dst);
/*virtual*/ bool copyTextToClipboard(const LLWString &src);
/*virtual*/ void flashIcon(F32 seconds);
/*virtual*/ F32 getGamma();
/*virtual*/ bool setGamma(const F32 gamma); // Set the gamma
/*virtual*/ void setFSAASamples(const U32 fsaa_samples);
/*virtual*/ U32 getFSAASamples();
/*virtual*/ bool restoreGamma(); // Restore original gamma table (before updating gamma)
/*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
/*virtual*/ void gatherInput();
/*virtual*/ void delayInputProcessing();
/*virtual*/ void swapBuffers();
/*virtual*/ void restoreGLContext() {};
// handy coordinate space conversion routines
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to);
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to);
/*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to);
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to);
/*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to);
/*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to);
/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
/*virtual*/ F32 getNativeAspectRatio();
/*virtual*/ F32 getPixelAspectRatio();
/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
/*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b );
/*virtual*/ void *getPlatformWindow();
/*virtual*/ void bringToFront();
/*virtual*/ void focusClient();
/*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, bool b);
/*virtual*/ void setLanguageTextInput( const LLCoordGL & pos );
/*virtual*/ void updateLanguageTextInputArea();
/*virtual*/ void interruptLanguageTextInput();
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
void openFile(const std::string& file_name);
/*virtual*/ F32 getSystemUISize();
LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
static std::vector<std::string> getDisplaysResolutionList();
static std::vector<std::string> getDynamicFallbackFontList();
static void setDPIAwareness();
/*virtual*/ void* getDirectInput8();
/*virtual*/ bool getInputDevices(U32 device_type_filter,
std::function<bool(std::string&, LLSD&, void*)> osx_callback,
void* win_callback,
void* userdata);
U32 getRawWParam() { return mRawWParam; }
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl,
//bool ignore_pixel_depth, U32 fsaa_samples, U32 max_cores, F32 max_gl_version);
bool ignore_pixel_depth, U32 fsaa_samples, U32 max_cores, F32 max_gl_version, bool useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
~LLWindowWin32();
//void initCursors();
void initCursors(bool useLegacyCursors); // <FS:LO> Legacy cursor setting from main program
HCURSOR loadColorCursor(LPCTSTR name);
bool isValid();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
virtual LLSD getNativeKeyData();
// Changes display resolution. Returns true if successful
bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
// Go back to last fullscreen display resolution.
bool setFullscreenResolution();
// Restore the display resolution to its value before we ran the app.
bool resetDisplayResolution();
bool shouldPostQuit() { return mPostQuit; }
void fillCandidateForm(const LLCoordGL& caret, const LLRect& bounds, CANDIDATEFORM *form);
void fillCharPosition(const LLCoordGL& caret, const LLRect& bounds, const LLRect& control, IMECHARPOSITION *char_position);
void fillCompositionLogfont(LOGFONT *logfont);
U32 fillReconvertString(const LLWString &text, S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string);
void handleStartCompositionMessage();
void handleCompositionMessage(U32 indexes);
bool handleImeRequests(WPARAM request, LPARAM param, LRESULT *result);
protected:
//
// Platform specific methods
//
bool getClientRectInScreenSpace(RECT* rectp);
static LRESULT CALLBACK mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param);
//
// Platform specific variables
//
WCHAR *mWindowTitle;
WCHAR *mWindowClassName;
HWND mWindowHandle = 0; // window handle
HGLRC mhRC = 0; // OpenGL rendering context
HDC mhDC = 0; // Windows Device context handle
HINSTANCE mhInstance; // handle to application instance
RECT mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
WPARAM mLastSizeWParam;
F32 mOverrideAspectRatio;
F32 mNativeAspectRatio;
HCURSOR mCursor[ UI_CURSOR_COUNT ]; // Array of all mouse cursors
LLCoordWindow mCursorPosition; // mouse cursor position, should only be mutated on main thread
LLMutex mRawMouseMutex;
RAWINPUTDEVICE mRawMouse;
LLCoordWindow mLastCursorPosition; // mouse cursor position from previous frame
LLCoordCommon mRawMouseDelta; // raw mouse delta according to window thread
LLCoordCommon mMouseFrameDelta; // how much the mouse moved between the last two calls to gatherInput
MASK mMouseMask;
static bool sIsClassRegistered; // has the window class been registered?
F32 mCurrentGamma;
U32 mFSAASamples;
U32 mMaxCores; // for debugging only -- maximum number of CPU cores to use, or 0 for no limit
F32 mMaxGLVersion; // maximum OpenGL version to attempt to use (clamps to 3.2 - 4.6)
WORD mPrevGammaRamp[3][256];
WORD mCurrentGammaRamp[3][256];
bool mCustomGammaSet;
LPWSTR mIconResource;
bool mInputProcessingPaused;
// The following variables are for Language Text Input control.
// They are all static, since one context is shared by all LLWindowWin32
// instances.
static bool sLanguageTextInputAllowed;
static bool sWinIMEOpened;
static HKL sWinInputLocale;
static DWORD sWinIMEConversionMode;
static DWORD sWinIMESentenceMode;
static LLCoordWindow sWinIMEWindowPosition;
LLCoordGL mLanguageTextInputPointGL;
LLRect mLanguageTextInputAreaGL;
LLPreeditor *mPreeditor;
LLDragDropWin32* mDragDrop;
U32 mKeyCharCode;
U32 mKeyScanCode;
U32 mKeyVirtualKey;
U32 mRawMsg;
U32 mRawWParam;
U32 mRawLParam;
bool mMouseVanish;
// Cached values of GetWindowRect and GetClientRect to be used by app thread
void updateWindowRect();
RECT mRect;
RECT mClientRect;
struct LLWindowWin32Thread;
LLWindowWin32Thread* mWindowThread = nullptr;
LLThreadSafeQueue<std::function<void()>> mFunctionQueue;
LLThreadSafeQueue<std::function<void()>> mMouseQueue;
void post(const std::function<void()>& func);
void postMouseButtonEvent(const std::function<void()>& func);
void recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style);
void kickWindowThread(HWND windowHandle=0);
friend class LLWindowManager;
// <FS:ND> Allow to query for window chrome sizes.
public:
virtual void getWindowChrome( U32 &aChromeW, U32 &aChromeH );
// </FS:ND>
};
class LLSplashScreenWin32 : public LLSplashScreen
{
public:
LLSplashScreenWin32();
virtual ~LLSplashScreenWin32();
/*virtual*/ void showImpl();
/*virtual*/ void updateImpl(const std::string& mesg);
/*virtual*/ void hideImpl();
#if LL_WINDOWS
static LRESULT CALLBACK windowProc(HWND h_wnd, UINT u_msg,
WPARAM w_param, LPARAM l_param);
#endif
private:
#if LL_WINDOWS
HWND mWindow;
#endif
};
extern LLW32MsgCallback gAsyncMsgCallback;
extern LPWSTR gIconResource;
S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type);
#endif //LL_LLWINDOWWIN32_H