IDE & LCL: Move focus to editor after hitting breakpoint. Patch from August Klein, issue #15967

git-svn-id: trunk@31087 -
This commit is contained in:
juha 2011-06-05 06:22:54 +00:00
parent 8f85c6d37a
commit 4b57ac797b
11 changed files with 193 additions and 12 deletions

View File

@ -96,6 +96,7 @@ type
FDebugger: TDebugger;
FDialogs: array[TDebugDialogType] of TDebuggerDlg;
FPrevShownWindow: HWND;
FStepping: Boolean;
// keep track of the last reported location
FCurrentLocation: TDBGLocationRec;
FIgnoreSourceFiles: TStringList; // a list of unfindable sourcefiles, that should not be prompted anymore
@ -868,10 +869,10 @@ begin
if (FDebugger.State in [dsRun])
then begin
// hide IDE during run
if EnvironmentOptions.HideIDEOnRun and (MainIDE.ToolStatus=itDebugger)
if EnvironmentOptions.HideIDEOnRun and (MainIDE.ToolStatus=itDebugger) and not FStepping
then MainIDE.HideIDE;
if FPrevShownWindow <> 0 then
if (FPrevShownWindow <> 0) and not FStepping then
begin
SetForegroundWindow(FPrevShownWindow);
FPrevShownWindow := 0;
@ -887,10 +888,14 @@ begin
end
else if (OldState in [dsRun]) then
begin
if EnvironmentOptions.HideIDEOnRun
then MainIDE.UnhideIDE;
FPrevShownWindow := GetForegroundWindow;
Application.BringToFront;
if not FStepping then
begin
FPrevShownWindow := GetForegroundWindow;
if EnvironmentOptions.HideIDEOnRun then
MainIDE.UnhideIDE;
if not EnvironmentOptions.SingleTaskBarButton then
Application.BringToFront;
end;
end;
end;
@ -932,6 +937,7 @@ begin
FDebugger.ErrorStateInfo, ftError, [frStop]);
end;
dsStop: begin
FPrevShownWindow:=0;
if (OldState<>dsIdle)
then begin
if EnvironmentOptions.DebuggerShowStopMessage
@ -1956,6 +1962,7 @@ begin
Exit;
end;
FStepping:=True;
FDebugger.StepInto;
Result := mrOk;
end;
@ -1970,6 +1977,7 @@ begin
Exit;
end;
FStepping:=True;
FDebugger.StepOver;
Result := mrOk;
end;
@ -1984,6 +1992,7 @@ begin
Exit;
end;
FStepping:=True;
FDebugger.StepIntoInstr;
Result := mrOk;
// Todo: move to DebuggerChangeState (requires the last run-command-type to be avail)
@ -2000,6 +2009,7 @@ begin
Exit;
end;
FStepping:=True;
FDebugger.StepOverInstr;
Result := mrOk;
// Todo: move to DebuggerChangeState (requires the last run-command-type to be avail)
@ -2016,6 +2026,7 @@ begin
Exit;
end;
FStepping:=True;
FDebugger.StepOut;
Result := mrOk;
end;
@ -2152,6 +2163,7 @@ begin
exit;
end;
Include(FManagerStates,dmsRunning);
FStepping:=False;
try
FDebugger.Run;
finally

View File

@ -168,6 +168,8 @@ procedure gdk_draw_pixbuf(drawable : PGdkDrawable; gc : PGdkGC; pixbuf : PGdkPix
dither : TGdkRgbDither; x_dither, y_dither : gint); cdecl; external gdklib;
function gdk_screen_get_default: PGdkScreen; cdecl; external gdklib;
function gdk_screen_get_rgb_colormap(screen: PGdkScreen): PGdkColormap; cdecl; external gdklib;
function gdk_x11_get_default_xdisplay: pointer; cdecl; external gdklib;
function gdk_x11_get_default_root_xwindow: guint; cdecl; external gdklib;
// gdk 2.4
function gdk_cursor_new_from_pixbuf(display: PGdkDisplay; pixbuf: PGdkPixbuf; x, y: gint): PGdkCursor; cdecl; external gdklib name 'gdk_cursor_new_from_pixbuf';

View File

@ -298,6 +298,10 @@ type
{$I gtk2winapih.inc}
{$I gtk2lclintfh.inc}
public
{$IFDEF HASX}
function X11Raise(AHandle: HWND): boolean;
function X11GetActiveWindow: HWND;
{$ENDIF}
procedure StartFocusTimer;
property AppActive: Boolean read GetAppActive write SetAppActive;
property LastFocusIn: PGtkWidget read FLastFocusIn write FLastFocusIn;

View File

@ -1156,6 +1156,8 @@ procedure TGtk2WidgetSet.AppBringToFront;
begin
if Assigned(Application.MainForm) and Application.MainForm.HandleAllocated then
gdk_window_raise(PGtkWidget(Application.MainForm.Handle)^.window);
gdk_window_focus(PGtkWidget(Application.MainForm.Handle)^.window,
gtk_get_current_event_time);
end;
procedure TGtk2WidgetSet.AppMinimize;
@ -4251,6 +4253,74 @@ begin
then gdk_pixmap_unref(TempMaskBitmap);
end;
{$IFDEF HASX}
function TGtk2WidgetSet.X11Raise(AHandle: HWND): boolean;
var
Display: PDisplay;
RootWin: TWindow;
ScreenNum: Integer;
XClient: TXClientMessageEvent;
WMAtom: TAtom;
screen: PGdkScreen;
begin
Result:=false;
screen:=gdk_screen_get_default;
Display := gdk_x11_get_default_xdisplay;
if Display = nil then
exit;
ScreenNum := gdk_screen_get_number(screen);
RootWin := gdk_x11_get_default_root_xwindow;
XClient._type := ClientMessage;
XClient.window := AHandle;
WMAtom := XInternAtom(Display,'_NET_ACTIVE_WINDOW', False);
XClient.message_type := WMATom;
XClient.format := 32;
XClient.data.l[0] := 1;
XClient.data.l[1] := 0;
XClient.data.l[2] := 0;
Result:=XSendEvent (Display, RootWin, False,
SubstructureRedirectMask or SubstructureNotifyMask,
@XClient)<>0;
end;
function TGtk2WidgetSet.X11GetActivewindow: HWND;
var
Display: PDisplay;
RootWin: TWindow;
ScreenNum: Integer;
WMAtom: TAtom;
ActualTypeReturn: TAtom;
ActualFormatReturn: LongInt;
NItemsReturn, BytesAfterReturn: Cardinal;
Ptr: PByte;
screen: PGdkScreen;
Valid: Boolean;
begin
screen:=gdk_screen_get_default;
Display := gdk_x11_get_default_xdisplay;
if Display = nil then
exit;
ScreenNum := gdk_screen_get_number(screen);
RootWin := gdk_x11_get_default_root_xwindow;
WMAtom := XInternAtom(Display,'_NET_ACTIVE_WINDOW', False);
Valid:=XGetWindowProperty(Display, RootWin, WMAtom, 0, 1, False,
AnyPropertyType, @ActualTypeReturn,
@ActualFormatReturn, @NItemsReturn,
@BytesAfterReturn, @Ptr)=0;
if Valid then
try
if (ActualTypeReturn = None) or (ActualFormatReturn <> 32) or not Assigned(Ptr) then
Valid := False;
if Valid then Result := PCardinal(Ptr)^;
finally
if Assigned(Ptr) then
XFree(Ptr);
end;
end;
{$ENDIF}
{------------------------------------------------------------------------------
procedure TGtk2WidgetSet.BringFormToFront(Sender: TObject);
------------------------------------------------------------------------------}

View File

@ -3719,6 +3719,14 @@ begin
then g_list_free(TopList);
end;
function TGtk2WidgetSet.GetForegroundWindow: HWND;
begin
Result:=0;
{$IFDEF HASX}
Result:=X11GetActiveWindow;
{$ENDIF}
end;
{------------------------------------------------------------------------------
Function: GetDIBits
Params:
@ -8114,6 +8122,7 @@ var
GdkWindow: PGdkWindow;
AForm: TCustomForm;
begin
try
{$IFDEF VerboseFocus}
DbgOut('TGtk2WidgetSet.SetForegroundWindow hWnd=',DbgS(hWnd));
LCLObject:=TControl(GetLCLObject(Pointer(hWnd)));
@ -8152,6 +8161,7 @@ begin
{$ENDIF}
gdk_window_show(GdkWindow);
gdk_window_raise(GdkWindow);
gdk_window_focus(GdkWindow, gtk_get_current_event_time);
{$IFDEF DebugGDKTraps}
EndGDKErrorTrap;
{$ENDIF}
@ -8159,6 +8169,11 @@ begin
gtk_window_present(PGtkWindow(hWnd));
end;
end;
except
{$IFDEF HASX}
Result:=X11Raise(hWnd);
{$ENDIF}
end;
end;
function TGtk2WidgetSet.SetMapMode(DC: HDC; fnMapMode : Integer): Integer;

View File

@ -124,6 +124,7 @@ function GetDeviceSize(DC: HDC; var p: TPoint): boolean; override;
function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer; override;
function GetFocus: HWND; override;
function GetFontLanguageInfo(DC: HDC): DWord; override;
function GetForegroundWindow: HWND; override;
function GetKeyState(nVirtKey: Integer): Smallint; override;
function GetMapMode(DC: HDC): Integer; override;
function GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo): Boolean; override;

View File

@ -203,6 +203,8 @@ type
function QtVersionCheck(const AMajor, AMinor, AMicro: Integer): Boolean;
{$IFDEF HASX11}
function IsCurrentDesktop(AWidget: QWidgetH): Boolean;
function X11Raise(AHandle: HWND): boolean;
function X11GetActiveWindow: HWND;
function GetWindowManager: String;
procedure SetSkipX11Taskbar(Widget: QWidgetH; const ASkipTaskBar: Boolean);
{check if we are running under kde3 installation}

View File

@ -4958,11 +4958,8 @@ begin
else
inherited Activate;
{$IFDEF HASX11}
// qt X11 bug ? activates window but it's not in
// front of others.
{$note TQtWidget.Activate: Check this with next qt version (>=4.7)}
if not QWidget_isModal(Widget) then
QWidget_raise(Widget);
X11Raise(QWidget_winId(Widget));
{$ENDIF}
end;

View File

@ -4972,13 +4972,27 @@ begin
end;
end;
function TQtWidgetSet.GetForegroundWindow: HWND;
begin
Result:=0;
{$IFDEF HASX11}
Result:=X11GetActivewindow;
{$ENDIF}
end;
function TQtWidgetSet.SetForegroundWindow(HWnd: HWND): boolean;
begin
Result := False;
if HWND <> 0 then
begin
Result := TQtWidget(HWND).IsActiveWindow;
TQtWidget(HWnd).Activate;
try
Result := TQtWidget(HWND).IsActiveWindow;
TQtWidget(HWnd).Activate;
except
{$IFDEF HASX11}
Result:=X11Raise(HWnd);
{$ENDIF}
end;
end;
end;

View File

@ -111,6 +111,7 @@ function GetDeviceSize(DC: HDC; var P: TPoint): Boolean; Override;
function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: BitmapInfo; Usage: UINT): Integer; Override;
function GetDoubleClickTime: UINT; override;
function GetFocus: HWND; override;
function GetForegroundWindow: HWND; override;
function GetKeyState(nVirtKey: Integer): Smallint; override;
function GetMapMode(DC: HDC): Integer; override;
function GetMonitorInfo(Monitor: HMONITOR; lpmi: PMonitorInfo): Boolean; override;

View File

@ -81,6 +81,69 @@ begin
end;
end;
function X11Raise(AHandle: HWND): boolean;
var
Display: PDisplay;
RootWin: TWindow;
ScreenNum: Integer;
XClient: TXClientMessageEvent;
WMAtom: TAtom;
begin
Result:=false;
Display := QX11Info_display();
if Display = nil then
exit;
ScreenNum := QX11Info_appScreen();
RootWin := XRootWindow(Display, ScreenNum);
XClient._type := ClientMessage;
XClient.window := AHandle;
WMAtom := XInternAtom(Display,'_NET_ACTIVE_WINDOW', False);
XClient.message_type := WMATom;
XClient.format := 32;
XClient.data.l[0] := 1;
XClient.data.l[1] := 0;
XClient.data.l[2] := 0;
Result:=XSendEvent (Display, RootWin, False,
SubstructureRedirectMask or SubstructureNotifyMask,
@XClient)<>0;
end;
function X11GetActivewindow: HWND;
var
Display: PDisplay;
RootWin: TWindow;
ScreenNum: Integer;
WMAtom: TAtom;
ActualTypeReturn: TAtom;
ActualFormatReturn: LongInt;
NItemsReturn, BytesAfterReturn: Cardinal;
Ptr: PByte;
Valid: Boolean;
begin
Display := QX11Info_display();
if Display = nil then
exit;
ScreenNum := QX11Info_appScreen();
RootWin := XRootWindow(Display, ScreenNum);
WMAtom := XInternAtom(Display,'_NET_ACTIVE_WINDOW', False);
Valid:=XGetWindowProperty(Display, RootWin, WMAtom, 0, 1, False,
AnyPropertyType, @ActualTypeReturn,
@ActualFormatReturn, @NItemsReturn,
@BytesAfterReturn, @Ptr)=0;
if Valid then
try
if (ActualTypeReturn = None) or (ActualFormatReturn <> 32) or not Assigned(Ptr) then
Valid := False;
if Valid then Result := PCardinal(Ptr)^;
finally
if Assigned(Ptr) then
XFree(Ptr);
end;
end;
function GetWindowManager: String;
{used to get window manager name, so we can handle different wm's behaviour
eg. kde vs. gnome}