Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
1a809219
Commit
1a809219
authored
Sep 18, 2002
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support for the take focus protocol.
parent
876fecf3
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
148 additions
and
77 deletions
+148
-77
event.c
dlls/x11drv/event.c
+136
-72
window.c
dlls/x11drv/window.c
+3
-5
x11drv_main.c
dlls/x11drv/x11drv_main.c
+5
-0
config
documentation/samples/config
+2
-0
x11drv.h
include/x11drv.h
+2
-0
No files found.
dlls/x11drv/event.c
View file @
1a809219
...
...
@@ -48,7 +48,6 @@
#include "shellapi.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
event
);
WINE_DECLARE_DEBUG_CHANNEL
(
win
);
/* X context to associate a hwnd to an X window */
extern
XContext
winContext
;
...
...
@@ -72,9 +71,6 @@ extern Atom dndSelection;
#define DndURL 128
/* KDE drag&drop */
/* The last X window which had the focus */
static
Window
glastXFocusWin
=
0
;
static
const
char
*
const
event_names
[]
=
{
""
,
""
,
"KeyPress"
,
"KeyRelease"
,
"ButtonPress"
,
"ButtonRelease"
,
...
...
@@ -89,7 +85,6 @@ static const char * const event_names[] =
static
void
EVENT_ProcessEvent
(
XEvent
*
event
);
static
BOOL
X11DRV_CheckFocus
(
void
);
/* Event handlers */
static
void
EVENT_FocusIn
(
HWND
hWnd
,
XFocusChangeEvent
*
event
);
...
...
@@ -368,90 +363,164 @@ static void EVENT_ProcessEvent( XEvent *event )
/**********************************************************************
* EVENT_FocusIn
* set_focus_error_handler
*
* Handler for X errors happening during XSetInputFocus call.
*/
static
void
EVENT_FocusIn
(
HWND
hWnd
,
XFocusChangeEvent
*
event
)
static
int
set_focus_error_handler
(
Display
*
display
,
XErrorEvent
*
event
,
void
*
arg
)
{
WND
*
pWndLastFocus
;
XWindowAttributes
win_attr
;
BOOL
bIsDisabled
;
return
(
event
->
error_code
==
BadValue
);
}
if
(
!
hWnd
)
return
;
bIsDisabled
=
GetWindowLongA
(
hWnd
,
GWL_STYLE
)
&
WS_DISABLED
;
/**********************************************************************
* set_focus
*/
static
void
set_focus
(
HWND
hwnd
,
Time
time
)
{
HWND
focus
=
GetFocus
();
Window
win
;
/* If the window has been disabled, revert the X focus back to the last
* focus window. This is to disallow the window manager from switching
* focus away while the app is in a modal state.
*/
if
(
bIsDisabled
&&
glastXFocusWin
)
if
(
hwnd
!=
focus
&&
!
IsChild
(
hwnd
,
focus
))
{
/* Change focus only if saved focus window is registered and viewable */
wine_tsx11_lock
();
if
(
XFindContext
(
event
->
display
,
glastXFocusWin
,
winContext
,
(
char
**
)
&
pWndLastFocus
)
==
0
)
{
if
(
XGetWindowAttributes
(
event
->
display
,
glastXFocusWin
,
&
win_attr
)
&&
(
win_attr
.
map_state
==
IsViewable
)
)
{
XSetInputFocus
(
event
->
display
,
glastXFocusWin
,
RevertToParent
,
CurrentTime
);
wine_tsx11_unlock
();
return
;
}
}
wine_tsx11_unlock
();
TRACE
(
"changing window focus to %x
\n
"
,
hwnd
);
SetFocus
(
hwnd
);
}
if
(
event
->
detail
!=
NotifyPointer
&&
hWnd
!=
GetForegroundWindow
())
SetForegroundWindow
(
hWnd
);
/* focus window might be changed by the above SetFocus() call */
focus
=
GetFocus
();
win
=
X11DRV_get_whole_window
(
focus
);
if
(
win
)
{
Display
*
display
=
thread_display
();
TRACE
(
"setting focus to %x (%lx) time=%ld
\n
"
,
focus
,
win
,
time
);
X11DRV_expect_error
(
display
,
set_focus_error_handler
,
NULL
);
XSetInputFocus
(
display
,
win
,
RevertToParent
,
time
);
if
(
X11DRV_check_error
())
ERR
(
"got BadMatch, ignoring
\n
"
);
}
}
/**********************************************************************
* EVENT_FocusOut
*
* Note: only top-level override-redirect windows get FocusOut events.
* handle_wm_protocols_message
*/
static
void
EVENT_FocusOut
(
HWND
hWnd
,
XFocusChan
geEvent
*
event
)
static
void
handle_wm_protocols_message
(
HWND
hwnd
,
XClientMessa
geEvent
*
event
)
{
/* Save the last window which had the focus */
glastXFocusWin
=
event
->
window
;
if
(
!
hWnd
)
return
;
if
(
GetWindowLongA
(
hWnd
,
GWL_STYLE
)
&
WS_DISABLED
)
glastXFocusWin
=
0
;
Atom
protocol
=
(
Atom
)
event
->
data
.
l
[
0
];
if
(
!
protocol
)
return
;
if
(
event
->
detail
!=
NotifyPointer
&&
hWnd
==
GetForegroundWindow
())
if
(
protocol
==
wmDeleteWindow
)
{
/* Ignore the delete window request if the window has been disabled
* and we are in managed mode. This is to disallow applications from
* being closed by the window manager while in a modal state.
*/
if
(
IsWindowEnabled
(
hwnd
))
PostMessageW
(
hwnd
,
WM_SYSCOMMAND
,
SC_CLOSE
,
0
);
}
else
if
(
protocol
==
wmTakeFocus
)
{
/* don't reset the foreground window, if the window which is
getting the focus is a Wine window */
if
(
!
X11DRV_CheckFocus
())
Time
event_time
=
(
Time
)
event
->
data
.
l
[
1
];
HWND
last_focus
=
x11drv_thread_data
()
->
last_focus
;
TRACE
(
"got take focus msg for %x, enabled=%d, focus=%x, active=%x, fg=%x, last=%x
\n
"
,
hwnd
,
IsWindowEnabled
(
hwnd
),
GetFocus
(),
GetActiveWindow
(),
GetForegroundWindow
(),
last_focus
);
if
(
IsWindowEnabled
(
hwnd
))
{
SendMessageA
(
hWnd
,
WM_CANCELMODE
,
0
,
0
);
/* Abey : 6-Oct-99. Check again if the focus out window is the
Foreground window, because in most cases the messages sent
above must have already changed the foreground window, in which
case we don't have to change the foreground window to 0 */
if
(
hWnd
==
GetForegroundWindow
())
SetForegroundWindow
(
0
);
/* simulate a mouse click on the caption to find out
* whether the window wants to be activated */
LRESULT
ma
=
SendMessageW
(
hwnd
,
WM_MOUSEACTIVATE
,
GetAncestor
(
hwnd
,
GA_ROOT
),
MAKELONG
(
HTCAPTION
,
WM_LBUTTONDOWN
)
);
if
(
ma
!=
MA_NOACTIVATEANDEAT
&&
ma
!=
MA_NOACTIVATE
)
set_focus
(
hwnd
,
event_time
);
else
TRACE
(
"not setting focus to %x (%lx), ma=%ld
\n
"
,
hwnd
,
event
->
window
,
ma
);
}
else
{
hwnd
=
GetFocus
();
if
(
!
hwnd
)
hwnd
=
GetActiveWindow
();
if
(
!
hwnd
)
hwnd
=
last_focus
;
if
(
hwnd
&&
IsWindowEnabled
(
hwnd
))
set_focus
(
hwnd
,
event_time
);
}
}
}
static
const
char
*
const
focus_details
[]
=
{
"NotifyAncestor"
,
"NotifyVirtual"
,
"NotifyInferior"
,
"NotifyNonlinear"
,
"NotifyNonlinearVirtual"
,
"NotifyPointer"
,
"NotifyPointerRoot"
,
"NotifyDetailNone"
};
/**********************************************************************
* EVENT_FocusIn
*/
static
void
EVENT_FocusIn
(
HWND
hwnd
,
XFocusChangeEvent
*
event
)
{
if
(
!
hwnd
)
return
;
TRACE
(
"win %x xwin %lx detail=%s
\n
"
,
hwnd
,
event
->
window
,
focus_details
[
event
->
detail
]
);
if
(
wmTakeFocus
)
return
;
/* ignore FocusIn if we are using take focus */
if
(
event
->
detail
==
NotifyPointer
)
return
;
if
(
!
IsWindowEnabled
(
hwnd
))
{
HWND
hwnd
=
GetFocus
();
if
(
!
hwnd
)
hwnd
=
GetActiveWindow
();
if
(
!
hwnd
)
hwnd
=
x11drv_thread_data
()
->
last_focus
;
if
(
hwnd
&&
IsWindowEnabled
(
hwnd
))
set_focus
(
hwnd
,
CurrentTime
);
}
else
if
(
hwnd
!=
GetForegroundWindow
())
{
SetForegroundWindow
(
hwnd
);
}
}
/**********************************************************************
* CheckFocus (X11DRV.@)
* EVENT_FocusOut
*
* Note: only top-level windows get FocusOut events.
*/
static
BOOL
X11DRV_CheckFocus
(
void
)
static
void
EVENT_FocusOut
(
HWND
hwnd
,
XFocusChangeEvent
*
event
)
{
Display
*
display
=
thread_display
();
HWND
hWnd
;
Window
xW
;
int
state
;
TSXGetInputFocus
(
display
,
&
xW
,
&
state
);
if
(
xW
==
None
||
TSXFindContext
(
display
,
xW
,
winContext
,
(
char
**
)
&
hWnd
)
)
return
FALSE
;
return
TRUE
;
HWND
hwnd_tmp
;
Window
focus_win
;
int
revert
;
TRACE
(
"win %x xwin %lx detail=%s
\n
"
,
hwnd
,
event
->
window
,
focus_details
[
event
->
detail
]
);
if
(
event
->
detail
==
NotifyPointer
)
return
;
if
(
hwnd
!=
GetForegroundWindow
())
return
;
SendMessageA
(
hwnd
,
WM_CANCELMODE
,
0
,
0
);
/* don't reset the foreground window, if the window which is
getting the focus is a Wine window */
TSXGetInputFocus
(
thread_display
(),
&
focus_win
,
&
revert
);
if
(
!
focus_win
||
TSXFindContext
(
thread_display
(),
focus_win
,
winContext
,
(
char
**
)
&
hwnd_tmp
))
{
/* Abey : 6-Oct-99. Check again if the focus out window is the
Foreground window, because in most cases the messages sent
above must have already changed the foreground window, in which
case we don't have to change the foreground window to 0 */
if
(
hwnd
==
GetForegroundWindow
())
{
TRACE
(
"lost focus, setting fg to 0
\n
"
);
x11drv_thread_data
()
->
last_focus
=
hwnd
;
SetForegroundWindow
(
0
);
}
}
}
...
...
@@ -1257,13 +1326,8 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
static
void
EVENT_ClientMessage
(
HWND
hWnd
,
XClientMessageEvent
*
event
)
{
if
(
event
->
message_type
!=
None
&&
event
->
format
==
32
)
{
if
((
event
->
message_type
==
wmProtocols
)
&&
(((
Atom
)
event
->
data
.
l
[
0
])
==
wmDeleteWindow
))
{
/* Ignore the delete window request if the window has been disabled */
if
(
!
(
GetWindowLongA
(
hWnd
,
GWL_STYLE
)
&
WS_DISABLED
))
PostMessageA
(
hWnd
,
WM_SYSCOMMAND
,
SC_CLOSE
,
0
);
}
if
(
event
->
message_type
==
wmProtocols
)
handle_wm_protocols_message
(
hWnd
,
event
);
else
if
(
event
->
message_type
==
dndProtocol
)
{
/* query window (drag&drop event contains only drag window) */
...
...
dlls/x11drv/window.c
View file @
1a809219
...
...
@@ -404,9 +404,7 @@ void X11DRV_set_wm_hints( Display *display, WND *win )
if
((
wm_hints
=
TSXAllocWMHints
()))
{
wm_hints
->
flags
=
InputHint
|
StateHint
|
WindowGroupHint
;
/* use globally active model if take focus is supported,
* passive model otherwise (cf. ICCCM) */
wm_hints
->
input
=
!
wmTakeFocus
;
wm_hints
->
input
=
!
(
win
->
dwStyle
&
WS_DISABLED
);
set_icon_hints
(
display
,
win
,
wm_hints
);
...
...
@@ -621,8 +619,7 @@ static void create_desktop( Display *display, WND *wndPtr, CREATESTRUCTA *cs )
winContext
=
XUniqueContext
();
wmProtocols
=
XInternAtom
(
display
,
"WM_PROTOCOLS"
,
False
);
wmDeleteWindow
=
XInternAtom
(
display
,
"WM_DELETE_WINDOW"
,
False
);
/* wmTakeFocus = XInternAtom( display, "WM_TAKE_FOCUS", False );*/
wmTakeFocus
=
0
;
/* not yet */
if
(
use_take_focus
)
wmTakeFocus
=
XInternAtom
(
display
,
"WM_TAKE_FOCUS"
,
False
);
dndProtocol
=
XInternAtom
(
display
,
"DndProtocol"
,
False
);
dndSelection
=
XInternAtom
(
display
,
"DndSelection"
,
False
);
wmChangeState
=
XInternAtom
(
display
,
"WM_CHANGE_STATE"
,
False
);
...
...
@@ -825,6 +822,7 @@ BOOL X11DRV_DestroyWindow( HWND hwnd )
{
TRACE
(
"win %x xwin %lx/%lx
\n
"
,
hwnd
,
data
->
whole_window
,
data
->
client_window
);
if
(
thread_data
->
cursor_window
==
data
->
whole_window
)
thread_data
->
cursor_window
=
None
;
if
(
thread_data
->
last_focus
==
hwnd
)
thread_data
->
last_focus
=
0
;
wine_tsx11_lock
();
XSync
(
gdi_display
,
False
);
/* flush any reference to this drawable in GDI queue */
XDeleteContext
(
display
,
data
->
whole_window
,
winContext
);
...
...
dlls/x11drv/x11drv_main.c
View file @
1a809219
...
...
@@ -64,6 +64,7 @@ unsigned int screen_height;
unsigned
int
screen_depth
;
Window
root_window
;
int
dxgrab
,
usedga
,
usexvidmode
;
int
use_take_focus
=
1
;
int
managed_mode
=
1
;
unsigned
int
X11DRV_server_startticks
;
...
...
@@ -247,6 +248,9 @@ static void setup_options(void)
if
(
!
get_config_key
(
hkey
,
appkey
,
"UseXVidMode"
,
buffer
,
sizeof
(
buffer
)
))
usexvidmode
=
IS_OPTION_TRUE
(
buffer
[
0
]
);
if
(
!
get_config_key
(
hkey
,
appkey
,
"UseTakeFocus"
,
buffer
,
sizeof
(
buffer
)
))
use_take_focus
=
IS_OPTION_TRUE
(
buffer
[
0
]
);
screen_depth
=
0
;
if
(
!
get_config_key
(
hkey
,
appkey
,
"ScreenDepth"
,
buffer
,
sizeof
(
buffer
)
))
screen_depth
=
atoi
(
buffer
);
...
...
@@ -461,6 +465,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
data
->
process_event_count
=
0
;
data
->
cursor
=
None
;
data
->
cursor_window
=
None
;
data
->
last_focus
=
0
;
NtCurrentTeb
()
->
driver_data
=
data
;
return
data
;
}
...
...
documentation/samples/config
View file @
1a809219
...
...
@@ -141,6 +141,8 @@ WINE REGISTRY Version 2
"UseXShm" = "Y"
; Use XVidMode extension if present
"UseXVidMode" = "Y"
; Use the take focus protocol
"UseTakeFocus" = "Y"
; Enable DirectX mouse grab
"DXGrab" = "N"
; Create the desktop window with a double-buffered visual
...
...
include/x11drv.h
View file @
1a809219
...
...
@@ -329,6 +329,7 @@ struct x11drv_thread_data
int
process_event_count
;
/* recursion count for event processing */
Cursor
cursor
;
/* current cursor */
Window
cursor_window
;
/* current window that contains the cursor */
HWND
last_focus
;
/* last window that had focus */
};
extern
struct
x11drv_thread_data
*
x11drv_init_thread_data
(
void
);
...
...
@@ -348,6 +349,7 @@ extern unsigned int screen_width;
extern
unsigned
int
screen_height
;
extern
unsigned
int
screen_depth
;
extern
unsigned
int
text_caps
;
extern
int
use_take_focus
;
extern
int
managed_mode
;
extern
Atom
wmProtocols
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment